001: /* encdec - encode and decode integers, times, and
002: * internationalized strings to and from popular binary formats
003: * http://www.ioplex.com/~miallen/encdec/
004: * Copyright (c) 2003 Michael B. Allen <mballen@erols.com>
005: *
006: * The GNU Library General Public License
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
021: * MA 02111-1307, USA
022: */
023:
024: package jcifs.util;
025:
026: import java.util.Date;
027: import java.io.IOException;
028:
029: public class Encdec {
030:
031: public static final long MILLISECONDS_BETWEEN_1970_AND_1601 = 11644473600000L;
032: public static final long SEC_BETWEEEN_1904_AND_1970 = 2082844800L;
033: public static final int TIME_1970_SEC_32BE = 1;
034: public static final int TIME_1970_SEC_32LE = 2;
035: public static final int TIME_1904_SEC_32BE = 3;
036: public static final int TIME_1904_SEC_32LE = 4;
037: public static final int TIME_1601_NANOS_64LE = 5;
038: public static final int TIME_1601_NANOS_64BE = 6;
039: public static final int TIME_1970_MILLIS_64BE = 7;
040: public static final int TIME_1970_MILLIS_64LE = 8;
041:
042: /* Encode integers
043: */
044:
045: public static int enc_uint16be(short s, byte[] dst, int di) {
046: dst[di++] = (byte) ((s >> 8) & 0xFF);
047: dst[di] = (byte) (s & 0xFF);
048: return 2;
049: }
050:
051: public static int enc_uint32be(int i, byte[] dst, int di) {
052: dst[di++] = (byte) ((i >> 24) & 0xFF);
053: dst[di++] = (byte) ((i >> 16) & 0xFF);
054: dst[di++] = (byte) ((i >> 8) & 0xFF);
055: dst[di] = (byte) (i & 0xFF);
056: return 4;
057: }
058:
059: public static int enc_uint16le(short s, byte[] dst, int di) {
060: dst[di++] = (byte) (s & 0xFF);
061: dst[di] = (byte) ((s >> 8) & 0xFF);
062: return 2;
063: }
064:
065: public static int enc_uint32le(int i, byte[] dst, int di) {
066: dst[di++] = (byte) (i & 0xFF);
067: dst[di++] = (byte) ((i >> 8) & 0xFF);
068: dst[di++] = (byte) ((i >> 16) & 0xFF);
069: dst[di] = (byte) ((i >> 24) & 0xFF);
070: return 4;
071: }
072:
073: /* Decode integers
074: */
075:
076: public static short dec_uint16be(byte[] src, int si) {
077: return (short) (((src[si] & 0xFF) << 8) | (src[si + 1] & 0xFF));
078: }
079:
080: public static int dec_uint32be(byte[] src, int si) {
081: return ((src[si] & 0xFF) << 24) | ((src[si + 1] & 0xFF) << 16)
082: | ((src[si + 2] & 0xFF) << 8) | (src[si + 3] & 0xFF);
083: }
084:
085: public static short dec_uint16le(byte[] src, int si) {
086: return (short) ((src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8));
087: }
088:
089: public static int dec_uint32le(byte[] src, int si) {
090: return (src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8)
091: | ((src[si + 2] & 0xFF) << 16)
092: | ((src[si + 3] & 0xFF) << 24);
093: }
094:
095: /* Encode and decode 64 bit integers
096: */
097:
098: public static int enc_uint64be(long l, byte[] dst, int di) {
099: enc_uint32be((int) (l & 0xFFFFFFFFL), dst, di + 4);
100: enc_uint32be((int) ((l >> 32L) & 0xFFFFFFFFL), dst, di);
101: return 8;
102: }
103:
104: public static int enc_uint64le(long l, byte[] dst, int di) {
105: enc_uint32le((int) (l & 0xFFFFFFFFL), dst, di);
106: enc_uint32le((int) ((l >> 32L) & 0xFFFFFFFFL), dst, di + 4);
107: return 8;
108: }
109:
110: public static long dec_uint64be(byte[] src, int si) {
111: long l;
112: l = dec_uint32be(src, si) & 0xFFFFFFFFL;
113: l <<= 32L;
114: l |= dec_uint32be(src, si + 4) & 0xFFFFFFFFL;
115: return l;
116: }
117:
118: public static long dec_uint64le(byte[] src, int si) {
119: long l;
120: l = dec_uint32le(src, si + 4) & 0xFFFFFFFFL;
121: l <<= 32L;
122: l |= dec_uint32le(src, si) & 0xFFFFFFFFL;
123: return l;
124: }
125:
126: /* Encode floats
127: */
128:
129: public static int enc_floatle(float f, byte[] dst, int di) {
130: return enc_uint32le(Float.floatToIntBits(f), dst, di);
131: }
132:
133: public static int enc_floatbe(float f, byte[] dst, int di) {
134: return enc_uint32be(Float.floatToIntBits(f), dst, di);
135: }
136:
137: /* Decode floating point numbers
138: */
139:
140: public static float dec_floatle(byte[] src, int si) {
141: return Float.intBitsToFloat(dec_uint32le(src, si));
142: }
143:
144: public static float dec_floatbe(byte[] src, int si) {
145: return Float.intBitsToFloat(dec_uint32be(src, si));
146: }
147:
148: /* Encode and decode doubles
149: */
150:
151: public static int enc_doublele(double d, byte[] dst, int di) {
152: return enc_uint64le(Double.doubleToLongBits(d), dst, di);
153: }
154:
155: public static int enc_doublebe(double d, byte[] dst, int di) {
156: return enc_uint64be(Double.doubleToLongBits(d), dst, di);
157: }
158:
159: public static double dec_doublele(byte[] src, int si) {
160: return Double.longBitsToDouble(dec_uint64le(src, si));
161: }
162:
163: public static double dec_doublebe(byte[] src, int si) {
164: return Double.longBitsToDouble(dec_uint64be(src, si));
165: }
166:
167: /* Encode times
168: */
169:
170: public static int enc_time(Date date, byte[] dst, int di, int enc) {
171: long t;
172:
173: switch (enc) {
174: case TIME_1970_SEC_32BE:
175: return enc_uint32be((int) (date.getTime() / 1000L), dst, di);
176: case TIME_1970_SEC_32LE:
177: return enc_uint32le((int) (date.getTime() / 1000L), dst, di);
178: case TIME_1904_SEC_32BE:
179: return enc_uint32be(
180: (int) ((date.getTime() / 1000L + SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF),
181: dst, di);
182: case TIME_1904_SEC_32LE:
183: return enc_uint32le(
184: (int) ((date.getTime() / 1000L + SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF),
185: dst, di);
186: case TIME_1601_NANOS_64BE:
187: t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
188: return enc_uint64be(t, dst, di);
189: case TIME_1601_NANOS_64LE:
190: t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
191: return enc_uint64le(t, dst, di);
192: case TIME_1970_MILLIS_64BE:
193: return enc_uint64be(date.getTime(), dst, di);
194: case TIME_1970_MILLIS_64LE:
195: return enc_uint64le(date.getTime(), dst, di);
196: default:
197: throw new IllegalArgumentException(
198: "Unsupported time encoding");
199: }
200: }
201:
202: /* Decode times
203: */
204:
205: public static Date dec_time(byte[] src, int si, int enc) {
206: long t;
207:
208: switch (enc) {
209: case TIME_1970_SEC_32BE:
210: return new Date(dec_uint32be(src, si) * 1000L);
211: case TIME_1970_SEC_32LE:
212: return new Date(dec_uint32le(src, si) * 1000L);
213: case TIME_1904_SEC_32BE:
214: return new Date(
215: ((dec_uint32be(src, si) & 0xFFFFFFFFL) - SEC_BETWEEEN_1904_AND_1970) * 1000L);
216: case TIME_1904_SEC_32LE:
217: return new Date(
218: ((dec_uint32le(src, si) & 0xFFFFFFFFL) - SEC_BETWEEEN_1904_AND_1970) * 1000L);
219: case TIME_1601_NANOS_64BE:
220: t = dec_uint64be(src, si);
221: return new Date(t / 10000L
222: - MILLISECONDS_BETWEEN_1970_AND_1601);
223: case TIME_1601_NANOS_64LE:
224: t = dec_uint64le(src, si);
225: return new Date(t / 10000L
226: - MILLISECONDS_BETWEEN_1970_AND_1601);
227: case TIME_1970_MILLIS_64BE:
228: return new Date(dec_uint64be(src, si));
229: case TIME_1970_MILLIS_64LE:
230: return new Date(dec_uint64le(src, si));
231: default:
232: throw new IllegalArgumentException(
233: "Unsupported time encoding");
234: }
235: }
236:
237: public static int enc_utf8(String str, byte[] dst, int di, int dlim)
238: throws IOException {
239: int start = di, ch;
240: int strlen = str.length();
241:
242: for (int i = 0; di < dlim && i < strlen; i++) {
243: ch = str.charAt(i);
244: if ((ch >= 0x0001) && (ch <= 0x007F)) {
245: dst[di++] = (byte) ch;
246: } else if (ch > 0x07FF) {
247: if ((dlim - di) < 3) {
248: break;
249: }
250: dst[di++] = (byte) (0xE0 | ((ch >> 12) & 0x0F));
251: dst[di++] = (byte) (0x80 | ((ch >> 6) & 0x3F));
252: dst[di++] = (byte) (0x80 | ((ch >> 0) & 0x3F));
253: } else {
254: if ((dlim - di) < 2) {
255: break;
256: }
257: dst[di++] = (byte) (0xC0 | ((ch >> 6) & 0x1F));
258: dst[di++] = (byte) (0x80 | ((ch >> 0) & 0x3F));
259: }
260: }
261:
262: return di - start;
263: }
264:
265: public static String dec_utf8(byte[] src, int si, int slim)
266: throws IOException {
267: char[] uni = new char[slim - si];
268: int ui, ch;
269:
270: for (ui = 0; si < slim && (ch = src[si++] & 0xFF) != 0; ui++) {
271: if (ch < 0x80) {
272: uni[ui] = (char) ch;
273: } else if ((ch & 0xE0) == 0xC0) {
274: if ((slim - si) < 2) {
275: break;
276: }
277: uni[ui] = (char) ((ch & 0x1F) << 6);
278: ch = src[si++] & 0xFF;
279: uni[ui] |= ch & 0x3F;
280: if ((ch & 0xC0) != 0x80 || uni[ui] < 0x80) {
281: throw new IOException("Invalid UTF-8 sequence");
282: }
283: } else if ((ch & 0xF0) == 0xE0) {
284: if ((slim - si) < 3) {
285: break;
286: }
287: uni[ui] = (char) ((ch & 0x0F) << 12);
288: ch = src[si++] & 0xFF;
289: if ((ch & 0xC0) != 0x80) {
290: throw new IOException("Invalid UTF-8 sequence");
291: } else {
292: uni[ui] |= (ch & 0x3F) << 6;
293: ch = src[si++] & 0xFF;
294: uni[ui] |= ch & 0x3F;
295: if ((ch & 0xC0) != 0x80 || uni[ui] < 0x800) {
296: throw new IOException("Invalid UTF-8 sequence");
297: }
298: }
299: } else {
300: throw new IOException("Unsupported UTF-8 sequence");
301: }
302: }
303:
304: return new String(uni, 0, ui);
305: }
306:
307: public static String dec_ucs2le(byte[] src, int si, int slim,
308: char[] buf) throws IOException {
309: int bi;
310:
311: for (bi = 0; (si + 1) < slim; bi++, si += 2) {
312: buf[bi] = (char) dec_uint16le(src, si);
313: if (buf[bi] == '\0') {
314: break;
315: }
316: }
317:
318: return new String(buf, 0, bi);
319: }
320: }
|