1 /* encdec - encode and decode integers, times, and
2  * internationalized strings to and from popular binary formats
3  * http://www.ioplex.com/~miallen/encdec/
4  * Copyright (c) 2003 Michael B. Allen <mballen@erols.com>
5  *
6  * The GNU Library General Public License
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21  * MA 02111-1307, USA
22  */
23 
24 package jcifs.util;
25 
26 import java.util.Date;
27 import java.io.IOException;
28 
29 public class Encdec {
30 
31     public static final long MILLISECONDS_BETWEEN_1970_AND_1601 = 11644473600000L;
32     public static final long SEC_BETWEEEN_1904_AND_1970 = 2082844800L;
33     public static final int TIME_1970_SEC_32BE = 1;
34     public static final int TIME_1970_SEC_32LE = 2;
35     public static final int TIME_1904_SEC_32BE = 3;
36     public static final int TIME_1904_SEC_32LE = 4;
37     public static final int TIME_1601_NANOS_64LE = 5;
38     public static final int TIME_1601_NANOS_64BE = 6;
39     public static final int TIME_1970_MILLIS_64BE = 7;
40     public static final int TIME_1970_MILLIS_64LE = 8;
41 
42     /* Encode integers
43      */
44 
enc_uint16be( short s, byte[] dst, int di )45     public static int enc_uint16be( short s, byte[] dst, int di ) {
46         dst[di++] = (byte)((s >> 8) & 0xFF);
47         dst[di] = (byte)(s & 0xFF);
48         return 2;
49     }
enc_uint32be( int i, byte[] dst, int di )50     public static int enc_uint32be( int i, byte[] dst, int di ) {
51         dst[di++] = (byte)((i >> 24) & 0xFF);
52         dst[di++] = (byte)((i >> 16) & 0xFF);
53         dst[di++] = (byte)((i >> 8) & 0xFF);
54         dst[di] = (byte)(i & 0xFF);
55         return 4;
56     }
enc_uint16le( short s, byte[] dst, int di )57     public static int enc_uint16le( short s, byte[] dst, int di )
58     {
59         dst[di++] = (byte)(s & 0xFF);
60         dst[di] = (byte)((s >> 8) & 0xFF);
61         return 2;
62     }
enc_uint32le( int i, byte[] dst, int di )63     public static int enc_uint32le( int i, byte[] dst, int di )
64     {
65         dst[di++] = (byte)(i & 0xFF);
66         dst[di++] = (byte)((i >> 8) & 0xFF);
67         dst[di++] = (byte)((i >> 16) & 0xFF);
68         dst[di] = (byte)((i >> 24) & 0xFF);
69         return 4;
70     }
71 
72     /* Decode integers
73      */
74 
dec_uint16be( byte[] src, int si )75     public static short dec_uint16be( byte[] src, int si )
76     {
77         return (short)(((src[si] & 0xFF) << 8) | (src[si + 1] & 0xFF));
78     }
dec_uint32be( byte[] src, int si )79     public static int dec_uint32be( byte[] src, int si )
80     {
81         return ((src[si] & 0xFF) << 24) | ((src[si + 1] & 0xFF) << 16) |
82                ((src[si + 2] & 0xFF) << 8) | (src[si + 3] & 0xFF);
83     }
dec_uint16le( byte[] src, int si )84     public static short dec_uint16le( byte[] src, int si )
85     {
86         return (short)((src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8));
87     }
dec_uint32le( byte[] src, int si )88     public static int dec_uint32le( byte[] src, int si )
89     {
90         return (src[si] & 0xFF) | ((src[si + 1] & 0xFF) << 8) |
91                ((src[si + 2] & 0xFF) << 16) | ((src[si + 3] & 0xFF) << 24);
92     }
93 
94     /* Encode and decode 64 bit integers
95      */
96 
enc_uint64be( long l, byte[] dst, int di )97     public static int enc_uint64be( long l, byte[] dst, int di )
98     {
99         enc_uint32be( (int)(l & 0xFFFFFFFFL), dst, di + 4 );
100         enc_uint32be( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di );
101         return 8;
102     }
enc_uint64le( long l, byte[] dst, int di )103     public static int enc_uint64le( long l, byte[] dst, int di )
104     {
105         enc_uint32le( (int)(l & 0xFFFFFFFFL), dst, di );
106         enc_uint32le( (int)(( l >> 32L ) & 0xFFFFFFFFL), dst, di + 4 );
107         return 8;
108     }
dec_uint64be( byte[] src, int si )109     public static long dec_uint64be( byte[] src, int si )
110     {
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     }
dec_uint64le( byte[] src, int si )117     public static long dec_uint64le( byte[] src, int si )
118     {
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 
enc_floatle( float f, byte[] dst, int di )129     public static int enc_floatle( float f, byte[] dst, int di )
130     {
131         return enc_uint32le( Float.floatToIntBits( f ), dst, di );
132     }
enc_floatbe( float f, byte[] dst, int di )133     public static int enc_floatbe( float f, byte[] dst, int di )
134     {
135         return enc_uint32be( Float.floatToIntBits( f ), dst, di );
136     }
137 
138     /* Decode floating point numbers
139      */
140 
dec_floatle( byte[] src, int si )141     public static float dec_floatle( byte[] src, int si )
142     {
143         return Float.intBitsToFloat( dec_uint32le( src, si ));
144     }
dec_floatbe( byte[] src, int si )145     public static float dec_floatbe( byte[] src, int si )
146     {
147         return Float.intBitsToFloat( dec_uint32be( src, si ));
148     }
149 
150     /* Encode and decode doubles
151      */
152 
enc_doublele( double d, byte[] dst, int di )153     public static int enc_doublele( double d, byte[] dst, int di )
154     {
155         return enc_uint64le( Double.doubleToLongBits( d ), dst, di );
156     }
enc_doublebe( double d, byte[] dst, int di )157     public static int enc_doublebe( double d, byte[] dst, int di )
158     {
159         return enc_uint64be( Double.doubleToLongBits( d ), dst, di );
160     }
dec_doublele( byte[] src, int si )161     public static double dec_doublele( byte[] src, int si )
162     {
163         return Double.longBitsToDouble( dec_uint64le( src, si ));
164     }
dec_doublebe( byte[] src, int si )165     public static double dec_doublebe( byte[] src, int si )
166     {
167         return Double.longBitsToDouble( dec_uint64be( src, si ));
168     }
169 
170     /* Encode times
171      */
172 
enc_time( Date date, byte[] dst, int di, int enc )173     public static int enc_time( Date date, byte[] dst, int di, int enc )
174     {
175         long t;
176 
177         switch( enc ) {
178             case TIME_1970_SEC_32BE:
179                 return enc_uint32be( (int)(date.getTime() / 1000L), dst, di );
180             case TIME_1970_SEC_32LE:
181                 return enc_uint32le( (int)(date.getTime() / 1000L), dst, di );
182             case TIME_1904_SEC_32BE:
183                 return enc_uint32be( (int)((date.getTime() / 1000L +
184                     SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di );
185             case TIME_1904_SEC_32LE:
186                 return enc_uint32le( (int)((date.getTime() / 1000L +
187                     SEC_BETWEEEN_1904_AND_1970) & 0xFFFFFFFF), dst, di );
188             case TIME_1601_NANOS_64BE:
189                 t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
190                 return enc_uint64be( t, dst, di );
191             case TIME_1601_NANOS_64LE:
192                 t = (date.getTime() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
193                 return enc_uint64le( t, dst, di );
194             case TIME_1970_MILLIS_64BE:
195                 return enc_uint64be( date.getTime(), dst, di );
196             case TIME_1970_MILLIS_64LE:
197                 return enc_uint64le( date.getTime(), dst, di );
198             default:
199                 throw new IllegalArgumentException( "Unsupported time encoding" );
200         }
201     }
202 
203     /* Decode times
204      */
205 
dec_time( byte[] src, int si, int enc )206     public static Date dec_time( byte[] src, int si, int enc )
207     {
208         long t;
209 
210         switch( enc ) {
211             case TIME_1970_SEC_32BE:
212                 return new Date( dec_uint32be( src, si ) * 1000L );
213             case TIME_1970_SEC_32LE:
214                 return new Date( dec_uint32le( src, si ) * 1000L );
215             case TIME_1904_SEC_32BE:
216                 return new Date((( dec_uint32be( src, si ) & 0xFFFFFFFFL) -
217                     SEC_BETWEEEN_1904_AND_1970 ) * 1000L );
218             case TIME_1904_SEC_32LE:
219                 return new Date((( dec_uint32le( src, si ) & 0xFFFFFFFFL) -
220                     SEC_BETWEEEN_1904_AND_1970 ) * 1000L );
221             case TIME_1601_NANOS_64BE:
222                 t = dec_uint64be( src, si );
223                 return new Date( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601);
224             case TIME_1601_NANOS_64LE:
225                 t = dec_uint64le( src, si );
226                 return new Date( t / 10000L - 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( "Unsupported time encoding" );
233         }
234     }
235 
enc_utf8( String str, byte[] dst, int di, int dlim )236     public static int enc_utf8( String str, byte[] dst, int di, int dlim ) throws IOException {
237         int start = di, ch;
238         int strlen = str.length();
239 
240         for( int i = 0; di < dlim && i < strlen; i++ ) {
241             ch = str.charAt( i );
242             if ((ch >= 0x0001) && (ch <= 0x007F)) {
243                 dst[di++] = (byte)ch;
244             } else if (ch > 0x07FF) {
245                 if((dlim - di) < 3 ) {
246                     break;
247                 }
248                 dst[di++] = (byte)(0xE0 | ((ch >> 12) & 0x0F));
249                 dst[di++] = (byte)(0x80 | ((ch >>  6) & 0x3F));
250                 dst[di++] = (byte)(0x80 | ((ch >>  0) & 0x3F));
251             } else {
252                 if((dlim - di) < 2 ) {
253                     break;
254                 }
255                 dst[di++] = (byte)(0xC0 | ((ch >>  6) & 0x1F));
256                 dst[di++] = (byte)(0x80 | ((ch >>  0) & 0x3F));
257             }
258         }
259 
260         return di - start;
261     }
dec_utf8( byte[] src, int si, int slim )262     public static String dec_utf8( byte[] src, int si, int slim ) throws IOException {
263         char[] uni = new char[slim - si];
264         int ui, ch;
265 
266         for( ui = 0; si < slim && (ch = src[si++] & 0xFF) != 0; ui++ ) {
267             if( ch < 0x80 ) {
268                 uni[ui] = (char)ch;
269             } else if((ch & 0xE0) == 0xC0 ) {
270                 if((slim - si) < 2 ) {
271                     break;
272                 }
273                 uni[ui] = (char)((ch & 0x1F) << 6);
274                 ch = src[si++] & 0xFF;
275                 uni[ui] |= ch & 0x3F;
276                 if ((ch & 0xC0) != 0x80 || uni[ui] < 0x80 ) {
277                     throw new IOException( "Invalid UTF-8 sequence" );
278                 }
279             } else if((ch & 0xF0) == 0xE0 ) {
280                 if((slim - si) < 3 ) {
281                     break;
282                 }
283                 uni[ui]  = (char)((ch & 0x0F) << 12);
284                 ch = src[si++] & 0xFF;
285                 if ((ch & 0xC0) != 0x80 ) {
286                     throw new IOException( "Invalid UTF-8 sequence" );
287                 } else {
288                     uni[ui] |= (ch & 0x3F) << 6;
289                     ch = src[si++] & 0xFF;
290                     uni[ui] |=  ch & 0x3F;
291                     if ((ch & 0xC0) != 0x80 || uni[ui] < 0x800) {
292                         throw new IOException( "Invalid UTF-8 sequence" );
293                     }
294                 }
295             } else {
296                 throw new IOException( "Unsupported UTF-8 sequence" );
297             }
298         }
299 
300         return new String( uni, 0, ui );
301     }
dec_ucs2le( byte[] src, int si, int slim, char[] buf )302     public static String dec_ucs2le( byte[] src, int si, int slim, char[] buf ) throws IOException {
303         int bi;
304 
305         for( bi = 0; (si + 1) < slim; bi++, si += 2 ) {
306             buf[bi] = (char)dec_uint16le( src, si );
307             if( buf[bi] == '\0' ) {
308                 break;
309             }
310         }
311 
312         return new String( buf, 0, bi );
313     }
314 }
315