Statistics
| Revision:

root / org.gvsig.dgn / trunk / org.gvsig.dgn / org.gvsig.dgn.provider / src / main / java / org / gvsig / fmap / dal / store / dgn / lib / ByteUtils.java @ 6

History | View | Annotate | Download (23.6 KB)

1
/*
2
 * Created on 21-jul-2003
3
 *
4
 * Copyright (c) 2003
5
 * Francisco Jos? Pe?arrubia Mart?nez
6
 * IVER Tecnolog?as de la Informaci?n S.A.
7
 * Salamanca 50
8
 * 46005 Valencia (        SPAIN )
9
 * +34 963163400
10
 * mailto:fran@iver.es
11
 * http://www.iver.es
12
 */
13
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
14
 *
15
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
16
 *
17
 * This program is free software; you can redistribute it and/or
18
 * modify it under the terms of the GNU General Public License
19
 * as published by the Free Software Foundation; either version 2
20
 * of the License, or (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program; if not, write to the Free Software
29
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
30
 *
31
 * For more information, contact:
32
 *
33
 *  Generalitat Valenciana
34
 *   Conselleria d'Infraestructures i Transport
35
 *   Av. Blasco Ib??ez, 50
36
 *   46010 VALENCIA
37
 *   SPAIN
38
 *
39
 *      +34 963862235
40
 *   gvsig@gva.es
41
 *      www.gvsig.gva.es
42
 *
43
 *    or
44
 *
45
 *   IVER T.I. S.A
46
 *   Salamanca 50
47
 *   46005 Valencia
48
 *   Spain
49
 *
50
 *   +34 963163400
51
 *   dac@iver.es
52
 */
53
package org.gvsig.fmap.dal.store.dgn.lib;
54

    
55
import java.math.BigInteger;
56

    
57

    
58
/**
59
 * Clase que engloba m?todos para trabajar con bytes.
60
 *
61
 * @author Vicente Caballero Navarro
62
 */
63
public class ByteUtils {
64
        public static final int SIZE_BOOL = 1;
65
        public static final int SIZE_SHORT = 2;
66
        public static final int SIZE_INT = 4;
67
        public static final int SIZE_LONG = 8;
68
        public static final int SIZE_DOUBLE = 8;
69

    
70
        /** A nibble->char mapping for printing out bytes. */
71
        public static final char[] digits = {
72
                        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
73
                        'e', 'f'
74
                };
75

    
76
        /**
77
         * Return the <code>int</code> represented by the bytes in
78
         * <code>data</code> staring at offset <code>offset[0]</code>.
79
         *
80
         * @param data the array from which to read
81
         * @param offset A single element array whose first element is the index in
82
         *                   data from which to begin reading on function entry, and which on
83
         *                   function exit has been incremented by the number of bytes read.
84
         *
85
         * @return the value of the <code>int</code> decoded
86
         */
87
        public static final int bytesToInt(byte[] data, int[] offset) {
88
                /**
89
                 * TODO: We use network-order within OceanStore, but temporarily
90
                 * supporting intel-order to work with some JNI code until JNI code is
91
                 * set to interoperate with network-order.
92
                 */
93
                int result = 0;
94

    
95
                for (int i = 0; i < SIZE_INT; ++i) {
96
                        result <<= 8;
97
                        result |= byteToUnsignedInt(data[offset[0]++]);
98
                }
99

    
100
                return result;
101
        }
102

    
103
        /**
104
         * Write the bytes representing <code>i</code> into the byte array
105
         * <code>data</code>, starting at index <code>offset [0]</code>, and
106
         * increment <code>offset [0]</code> by the number of bytes written; if
107
         * <code>data == null</code>, increment <code>offset [0]</code> by the
108
         * number of bytes that would have been written otherwise.
109
         *
110
         * @param i the <code>int</code> to encode
111
         * @param data The byte array to store into, or <code>null</code>.
112
         * @param offset A single element array whose first element is the index in
113
         *                   data to begin writing at on function entry, and which on
114
         *                   function exit has been incremented by the number of bytes
115
         *                   written.
116
         */
117
        public static final void intToBytes(int i, byte[] data, int[] offset) {
118
                /**
119
                 * TODO: We use network-order within OceanStore, but temporarily
120
                 * supporting intel-order to work with some JNI code until JNI code is
121
                 * set to interoperate with network-order.
122
                 */
123
                if (data != null) {
124
                        for (int j = (offset[0] + SIZE_INT) - 1; j >= offset[0]; --j) {
125
                                data[j] = (byte) i;
126
                                i >>= 8;
127
                        }
128
                }
129

    
130
                offset[0] += SIZE_INT;
131
        }
132

    
133
        /**
134
         * Return the <code>short</code> represented by the bytes in
135
         * <code>data</code> staring at offset <code>offset[0]</code>.
136
         *
137
         * @param data the array from which to read
138
         * @param offset A single element array whose first element is the index in
139
         *                   data from which to begin reading on function entry, and which on
140
         *                   function exit has been incremented by the number of bytes read.
141
         *
142
         * @return the value of the <code>short</code> decoded
143
         */
144
        public static final short bytesToShort(byte[] data, int[] offset) {
145
                /**
146
                 * TODO: We use network-order within OceanStore, but temporarily
147
                 * supporting intel-order to work with some JNI code until JNI code is
148
                 * set to interoperate with network-order.
149
                 */
150
                short result = 0;
151

    
152
                for (int i = 0; i < SIZE_SHORT; ++i) {
153
                        result <<= 8;
154
                        result |= (short) byteToUnsignedInt(data[offset[0]++]);
155
                }
156

    
157
                return result;
158
        }
159

    
160
        /**
161
         * Write the bytes representing <code>s</code> into the byte array
162
         * <code>data</code>, starting at index <code>offset [0]</code>, and
163
         * increment <code>offset [0]</code> by the number of bytes written; if
164
         * <code>data == null</code>, increment <code>offset [0]</code> by the
165
         * number of bytes that would have been written otherwise.
166
         *
167
         * @param s the <code>short</code> to encode
168
         * @param data The byte array to store into, or <code>null</code>.
169
         * @param offset A single element array whose first element is the index in
170
         *                   data to begin writing at on function entry, and which on
171
         *                   function exit has been incremented by the number of bytes
172
         *                   written.
173
         */
174
        public static final void shortToBytes(short s, byte[] data, int[] offset) {
175
                /**
176
                 * TODO: We use network-order within OceanStore, but temporarily
177
                 * supporting intel-order to work with some JNI code until JNI code is
178
                 * set to interoperate with network-order.
179
                 */
180
                if (data != null) {
181
                        data[offset[0] + 1] = (byte) s;
182
                        data[offset[0]] = (byte) (s >> 8);
183
                }
184

    
185
                offset[0] += SIZE_SHORT;
186
        }
187

    
188
        /**
189
         * Return the <code>long</code> represented by the bytes in
190
         * <code>data</code> staring at offset <code>offset[0]</code>.
191
         *
192
         * @param data the array from which to read
193
         * @param offset A single element array whose first element is the index in
194
         *                   data from which to begin reading on  function entry, and which
195
         *                   on function exit has been incremented by the number of bytes
196
         *                   read.
197
         *
198
         * @return the value of the <code>long</code> decoded
199
         */
200
        public static final long bytesToLong(byte[] data, int[] offset) {
201
                long result = 0;
202

    
203
                for (int i = 0; i < SIZE_LONG; ++i) {
204
                        result <<= 8;
205

    
206
                        int res = byteToUnsignedInt(data[offset[0]++]);
207
                        result = result | res;
208
                }
209

    
210
                return result;
211
        }
212

    
213
        /**
214
         * Write the bytes representing <code>l</code> into the byte array
215
         * <code>data</code>, starting at index <code>offset [0]</code>, and
216
         * increment <code>offset [0]</code> by the number of bytes written; if
217
         * <code>data == null</code>, increment <code>offset [0]</code> by the
218
         * number of bytes that would have been written otherwise.
219
         *
220
         * @param l the <code>long</code> to encode
221
         * @param data The byte array to store into, or <code>null</code>.
222
         * @param offset A single element array whose first element is the index in
223
         *                   data to begin writing at on function entry, and which on
224
         *                   function exit has been incremented by the number of bytes
225
         *                   written.
226
         */
227
        public static final void longToBytes(long l, byte[] data, int[] offset) {
228
                /**
229
                 * TODO: We use network-order within OceanStore, but temporarily
230
                 * supporting intel-order to work with some JNI code until JNI code is
231
                 * set to interoperate with network-order.
232
                 */
233
                if (data != null) {
234
                        for (int j = (offset[0] + SIZE_LONG) - 1; j >= offset[0]; --j) {
235
                                data[j] = (byte) l;
236
                                l >>= 8;
237
                        }
238
                }
239

    
240
                offset[0] += SIZE_LONG;
241
        }
242

    
243
        /**
244
         * Return the <code>double</code> represented by the bytes in
245
         * <code>data</code> staring at offset <code>offset[0]</code>.
246
         *
247
         * @param data the array from which to read
248
         * @param offset A single element array whose first element is the index in
249
         *                   data from which to begin reading on  function entry, and which
250
         *                   on function exit has been incremented by the number of bytes
251
         *                   read.
252
         *
253
         * @return the value of the <code>double</code> decoded
254
         */
255
        public static final double bytesToDouble(byte[] data, int[] offset) {
256
                long bits = bytesToLong(data, offset);
257

    
258
                return Double.longBitsToDouble(bits);
259
        }
260

    
261
        /**
262
         * Write the bytes representing <code>d</code> into the byte array
263
         * <code>data</code>, starting at index <code>offset [0]</code>, and
264
         * increment <code>offset [0]</code> by the number of bytes written; if
265
         * <code>data == null</code>, increment <code>offset [0]</code> by the
266
         * number of bytes that would have been written otherwise.
267
         *
268
         * @param d the <code>double</code> to encode
269
         * @param data The byte array to store into, or <code>null</code>.
270
         * @param offset A single element array whose first element is the index in
271
         *                   data to begin writing at on function entry, and which on
272
         *                   function exit has been incremented by the number of bytes
273
         *                   written.
274
         */
275
        public static final void doubleToBytes(double d, byte[] data, int[] offset) {
276
                long bits = Double.doubleToLongBits(d);
277
                longToBytes(bits, data, offset);
278
        }
279

    
280
        /**
281
         * Return the <code>String</code> represented by the bytes in
282
         * <code>data</code> staring at offset <code>offset[0]</code>. This method
283
         * relies on the user using the corresponding <code>stringToBytes</code>
284
         * method to encode the <code>String</code>, so that it may properly
285
         * retrieve the <code>String</code> length.
286
         *
287
         * @param data the array from which to read
288
         * @param offset A single element array whose first element is the index in
289
         *                   data from which to begin reading on function entry, and which on
290
         *                   function exit has been incremented by the number of bytes read.
291
         *
292
         * @return the value of the <code>String</code> decoded
293
         */
294
        public static final String bytesToString(byte[] data, int[] offset) {
295
                offset[0] = 0;
296

    
297
                int length = bytesToInt(data, offset);
298
                String st = null;
299

    
300
                if ((length < 0) || (length > data.length)) {
301
                        st = new String(data);
302
                } else {
303
                        st = new String(data, offset[0], length);
304
                }
305

    
306
                offset[0] += length;
307

    
308
                return st;
309
        }
310

    
311
        /**
312
         * Write the bytes representing <code>s</code> into the byte array
313
         * <code>data</code>, starting at index <code>offset [0]</code>, and
314
         * increment <code>offset [0]</code> by the number of bytes written; if
315
         * <code>data == null</code>, increment <code>offset [0]</code> by the
316
         * number of bytes that would have been written otherwise.
317
         *
318
         * @param s the <code>String</code> to encode
319
         * @param data The byte array to store into, or <code>null</code>.
320
         * @param offset A single element array whose first element is the index in
321
         *                   data to begin writing at on function entry, and which on
322
         *                   function exit has been incremented by the number of bytes
323
         *                   written.
324
         */
325
        public static final void stringToBytes(String s, byte[] data, int[] offset) {
326
                byte[] s_bytes = s.getBytes();
327

    
328
                if (data != null) {
329
                        intToBytes(s_bytes.length, data, offset);
330
                        memcpy(data, offset[0], s_bytes, 0, s_bytes.length);
331
                } else {
332
                        offset[0] += SIZE_INT;
333
                }
334

    
335
                offset[0] += s_bytes.length;
336
        }
337

    
338
        /**
339
         * Return the <code>boolean</code> represented by the bytes in
340
         * <code>data</code> staring at offset <code>offset[0]</code>.
341
         *
342
         * @param data the array from which to read
343
         * @param offset A single element array whose first element is the index in
344
         *                   data from which to begin reading on  function entry, and which
345
         *                   on function exit has been incremented by the number of bytes
346
         *                   read.
347
         *
348
         * @return the value of the <code>boolean</code> decoded
349
         */
350
        public static final boolean bytesToBool(byte[] data, int[] offset) {
351
                boolean result = true;
352

    
353
                if (data[offset[0]] == 0) {
354
                        result = false;
355
                }
356

    
357
                offset[0] += SIZE_BOOL;
358

    
359
                return result;
360
        }
361

    
362
        /**
363
         * Write the bytes representing <code>b</code> into the byte array
364
         * <code>data</code>, starting at index <code>offset [0]</code>, and
365
         * increment <code>offset [0]</code> by the number of bytes written; if
366
         * <code>data == null</code>, increment <code>offset [0]</code> by the
367
         * number of bytes that would have been written otherwise.
368
         *
369
         * @param b the <code>boolean</code> to encode
370
         * @param data The byte array to store into, or <code>null</code>.
371
         * @param offset A single element array whose first element is the index in
372
         *                   data to begin writing at on function entry, and which on
373
         *                   function exit has been incremented by the number of bytes
374
         *                   written.
375
         */
376
        public static final void boolToBytes(boolean b, byte[] data, int[] offset) {
377
                if (data != null) {
378
                        data[offset[0]] = (byte) (b ? 1 : 0);
379
                }
380

    
381
                offset[0] += SIZE_BOOL;
382
        }
383

    
384
        /**
385
         * Return the <code>BigInteger</code> represented by the bytes in
386
         * <code>data</code> staring at offset <code>offset[0]</code>.
387
         *
388
         * @param data the array from which to read
389
         * @param offset A single element array whose first element is the index in
390
         *                   data from which to begin reading on  function entry, and which
391
         *                   on function exit has been incremented by the number of bytes
392
         *                   read.
393
         *
394
         * @return the <code>BigInteger</code> decoded
395
         */
396
        public static final BigInteger bytesToBigInteger(byte[] data, int[] offset) {
397
                int length = bytesToInt(data, offset);
398
                byte[] bytes = new byte[length];
399
                offset[0] += memcpy(bytes, 0, data, offset[0], length);
400

    
401
                return new BigInteger(bytes);
402
        }
403

    
404
        /**
405
         * Write the bytes representing <code>n</code> into the byte array
406
         * <code>data</code>, starting at index <code>offset [0]</code>, and
407
         * increment <code>offset [0]</code> by the number of bytes written; if
408
         * <code>data == null</code>, increment <code>offset [0]</code> by the
409
         * number of bytes that would have been written otherwise.
410
         *
411
         * @param n the <code>BigInteger</code> to encode
412
         * @param data The byte array to store into, or <code>null</code>.
413
         * @param offset A single element array whose first element is the index in
414
         *                   data to begin writing at on function entry, and which on
415
         *                   function exit has been incremented by the number of bytes
416
         *                   written.
417
         */
418
        public static final void bigIntegerToBytes(BigInteger n, byte[] data,
419
                int[] offset) {
420
                byte[] bytes = n.toByteArray();
421
                intToBytes(bytes.length, data, offset);
422
                offset[0] += memcpy(data, offset[0], bytes, 0, bytes.length);
423
        }
424

    
425
        /**
426
         * Convert an array of <code>bytes</code>s into an array of
427
         * <code>ints</code>.
428
         *
429
         * @param dst the array to write
430
         * @param dst_offset the start offset in <code>dst</code>, times 4. This
431
         *                   measures the offset as if <code>dst</code> were an array of
432
         *                   <code>byte</code>s (rather than <code>int</code>s).
433
         * @param src the array to read
434
         * @param src_offset the start offset in <code>src</code>
435
         * @param length the number of <code>byte</code>s to copy.
436
         */
437
        public static final void bytesToInts(int[] dst, int dst_offset, byte[] src,
438
                int src_offset, int length) {
439
                if ((src == null) || (dst == null) ||
440
                                ((src_offset + length) > src.length) ||
441
                                ((dst_offset + length) > (dst.length * 4)) ||
442
                                ((dst_offset % 4) != 0) || ((length % 4) != 0)) {
443
                        croak("bytesToInts parameters are invalid" + " src==" + src +
444
                                " dst==" + dst +
445
                                (((src == null) || (dst == null)) ? " "
446
                                                                                                  : (" (src_offset+length)>src.length==" +
447
                                (src_offset + length) + ">" + src.length +
448
                                " (dst_offset+length)>(dst.length*4)==" +
449
                                (dst_offset + length) + ">" + (dst.length * 4) +
450
                                " (dst_offset%4)==" + (dst_offset % 4) + " (length%4)==" +
451
                                (length % 4) + " dest.length==" + dst.length + " length==" +
452
                                length)));
453
                }
454

    
455
                // Convert parameters to normal format
456
                int[] offset = new int[1];
457
                offset[0] = src_offset;
458

    
459
                int int_dst_offset = dst_offset / 4;
460

    
461
                for (int i = 0; i < (length / 4); ++i) {
462
                        dst[int_dst_offset++] = bytesToInt(src, offset);
463
                }
464
        }
465

    
466
        /**
467
         * Convert an array of <code>int</code>s into an array of
468
         * <code>bytes</code>.
469
         *
470
         * @param dst the array to write
471
         * @param dst_offset the start offset in <code>dst</code>
472
         * @param src the array to read
473
         * @param src_offset the start offset in <code>src</code>, times 4. This
474
         *                   measures the offset as if <code>src</code> were an array of
475
         *                   <code>byte</code>s (rather than <code>int</code>s).
476
         * @param length the number of <code>byte</code>s to copy.
477
         */
478
        public static final void intsToBytes(byte[] dst, int dst_offset, int[] src,
479
                int src_offset, int length) {
480
                if ((src == null) || (dst == null) ||
481
                                ((dst_offset + length) > dst.length) ||
482
                                ((src_offset + length) > (src.length * 4)) ||
483
                                ((src_offset % 4) != 0) || ((length % 4) != 0)) {
484
                        croak("intsToBytes parameters are invalid:" + " src=" + src +
485
                                " dst=" + dst + " (dst_offset=" + dst_offset + " + length=" +
486
                                length + ")=" + (dst_offset + length) + " > dst.length=" +
487
                                ((dst == null) ? 0 : dst.length) + " (src_offset=" +
488
                                src_offset + " + length=" + length + ")=" +
489
                                (src_offset + length) + " > (src.length=" +
490
                                ((src == null) ? 0 : src.length) + "*4)=" +
491
                                ((src == null) ? 0 : (src.length * 4)) + " (src_offset=" +
492
                                src_offset + " % 4)=" + (src_offset % 4) + " != 0" +
493
                                " (length=" + length + " % 4)=" + (length % 4) + " != 0");
494
                }
495

    
496
                // Convert parameters to normal format
497
                int[] offset = new int[1];
498
                offset[0] = dst_offset;
499

    
500
                int int_src_offset = src_offset / 4;
501

    
502
                for (int i = 0; i < (length / 4); ++i) {
503
                        intToBytes(src[int_src_offset++], dst, offset);
504
                }
505
        }
506

    
507
        /**
508
         * Convert a <code>byte</code> into an unsigned integer.
509
         *
510
         * @param b the <code>byte</code> to cast
511
         *
512
         * @return a postiive <code>int</code> whose lowest byte contains the bits
513
         *                    of <code>b</code>.
514
         */
515
        public static final int byteToUnsignedInt(byte b) {
516
                return (b) & 0xff;
517
        }
518

    
519
        /**
520
         * Copy contents of one array of <code>bytes</code> into another. If either
521
         * array is <code>null</code>, simply return the <code>length</code>
522
         * parameter directly.
523
         *
524
         * @param dst the array to write, or <code>null</code>
525
         * @param dst_offset the start offset in <code>dst</code>
526
         * @param src the array to read, or <code>null</code>
527
         * @param src_offset the start offset in <code>src</code>
528
         * @param length the number of <code>byte</code>s to copy.
529
         *
530
         * @return DOCUMENT ME!
531
         */
532
        public static int memcpy(byte[] dst, int dst_offset, byte[] src,
533
                int src_offset, int length) {
534
                if ((dst != null) && (src != null)) {
535
                        if (dst.length < (dst_offset + length)) {
536
                                croak("dst.length = " + dst.length + ", but " +
537
                                        "dst_offset = " + dst_offset + " and length = " + length +
538
                                        ".");
539
                        }
540

    
541
                        if (src.length < (src_offset + length)) {
542
                                croak("src.length = " + src.length + ", but " +
543
                                        "src_offset = " + src_offset + " and length = " + length +
544
                                        ".");
545
                        }
546

    
547
                        for (int i = 0; i < length; ++i, ++dst_offset, ++src_offset) {
548
                                dst[dst_offset] = src[src_offset];
549
                        }
550
                }
551

    
552
                return length;
553
        }
554

    
555
        /**
556
         * Compare the contents of one array of <code>bytes</code> to another.
557
         *
558
         * @param a the first array
559
         * @param a_offset the start offset in <code>a</code>
560
         * @param b the second array
561
         * @param b_offset the start offset in <code>b</code>
562
         * @param length the number of <code>byte</code>s to compare.
563
         *
564
         * @return DOCUMENT ME!
565
         */
566
        public static boolean memcmp(byte[] a, int a_offset, byte[] b,
567
                int b_offset, int length) {
568
                if ((a == null) && (b == null)) {
569
                        return true;
570
                }
571

    
572
                if ((a == null) || (b == null)) {
573
                        return false;
574
                }
575

    
576
                for (int i = 0; i < length; ++i, ++a_offset, ++b_offset) {
577
                        if (a[a_offset] != b[b_offset]) {
578
                                return false;
579
                        }
580
                }
581

    
582
                return true;
583
        }
584

    
585
        /**
586
         * Fill the given array with zeros.
587
         *
588
         * @param array the array to clear
589
         * @param offset the start offset
590
         * @param length the number of <code>byte</code>s to clear.
591
         */
592
        public static void memclr(byte[] array, int offset, int length) {
593
                for (int i = 0; i < length; ++i, ++offset) {
594
                        array[offset] = 0;
595
                }
596
        }
597

    
598
        /**
599
         * Round a number up to a given multiple.
600
         *
601
         * @param value the number to be rounded
602
         * @param multiple the number to which to be rounded
603
         *
604
         * @return the smallest <code>int</code> greater than or equal to
605
         *                    <code>value</code> which divides <code>multiple</code> exactly.
606
         */
607
        public static int round_up(int value, int multiple) {
608
                return (((value - 1) / multiple) + 1) * multiple;
609
        }
610

    
611
        /**
612
         * Return a new array equal to original except zero-padded to an integral
613
         * mulitple of blocks.  If the original is already an integral multiple of
614
         * blocks, just return it.
615
         *
616
         * @param original the array of <code>byte</code>s to be padded
617
         * @param block_size the size of the blocks
618
         *
619
         * @return an array whose size divides <code>block_size</code> exactly. The
620
         *                    array is either <code>original</code> itself, or a copy whose
621
         *                    first <code>original.length</code> bytes are equal to
622
         *                    <code>original</code>.
623
         */
624
        public static byte[] zero_pad(byte[] original, int block_size) {
625
                if ((original.length % block_size) == 0) {
626
                        return original;
627
                }
628

    
629
                byte[] result = new byte[round_up(original.length, block_size)];
630
                memcpy(result, 0, original, 0, original.length);
631

    
632
                // Unnecessary - jvm sets bytes to 0.
633
                // memclr (result, original.length, result.length - original.length);
634
                return result;
635
        }
636

    
637
        /**
638
         * Determines whether two arrays of <code>byte</code>s contain the same
639
         * contents.
640
         *
641
         * @param b1 The first array
642
         * @param b2 The second array
643
         *
644
         * @return <code>true</code> if both arrays are <code>null</code>, both
645
         *                    empty, or both of the same length with equal contents.
646
         */
647
        public static boolean equals(byte[] b1, byte[] b2) {
648
                if (b1 == b2) {
649
                        return true;
650
                }
651

    
652
                if ((b1 == null) || (b2 == null)) { // only one is null
653

    
654
                        return false;
655
                }
656

    
657
                if (b1.length != b2.length) {
658
                        return false;
659
                }
660

    
661
                for (int i = 0; i < b1.length; ++i) {
662
                        if (b1[i] != b2[i]) {
663
                                return false;
664
                        }
665
                }
666

    
667
                return true;
668
        }
669

    
670
        /**
671
         * Produce a <code>String</code> representation for the specified array of
672
         * <code>byte</code>s.  Print each <code>byte</code> as two hexadecimal
673
         * digits.
674
         *
675
         * @param data The array to print
676
         * @param offset the start offset in <code>data</code>
677
         * @param length the number of <code>byte</code>s to print
678
         *
679
         * @return DOCUMENT ME!
680
         */
681
        public static String print_bytes(byte[] data, int offset, int length) {
682
                int size = 2 * length;
683
                size += ((size / 8) + (size / 64));
684

    
685
                char[] buf = new char[size];
686
                int low_mask = 0x0f;
687
                int high_mask = 0xf0;
688
                int buf_pos = 0;
689
                byte b;
690

    
691
                int j = 0;
692

    
693
                for (int i = offset; i < (offset + length); ++i) {
694
                        b = data[i];
695
                        buf[buf_pos++] = digits[(high_mask & b) >> 4];
696
                        buf[buf_pos++] = digits[(low_mask & b)];
697

    
698
                        if ((j % 4) == 3) {
699
                                buf[buf_pos++] = ' ';
700
                        }
701

    
702
                        if ((j % 32) == 31) {
703
                                buf[buf_pos++] = '\n';
704
                        }
705

    
706
                        ++j;
707
                }
708

    
709
                return new String(buf);
710
        }
711

    
712
        /**
713
         * DOCUMENT ME!
714
         *
715
         * @param data DOCUMENT ME!
716
         * @param offset DOCUMENT ME!
717
         * @param length DOCUMENT ME!
718
         *
719
         * @return DOCUMENT ME!
720
         */
721
        public static String print_bytes_exact(byte[] data, int offset, int length) {
722
                int size = 2 * length;
723
                char[] buf = new char[size];
724
                int low_mask = 0x0f;
725
                int high_mask = 0xf0;
726
                int buf_pos = 0;
727
                byte b;
728

    
729
                int j = 0;
730

    
731
                for (int i = offset; i < (offset + length); ++i) {
732
                        b = data[i];
733
                        buf[buf_pos++] = digits[(high_mask & b) >> 4];
734
                        buf[buf_pos++] = digits[(low_mask & b)];
735
                        ++j;
736
                }
737

    
738
                return new String(buf);
739
        }
740

    
741
        /**
742
         * DOCUMENT ME!
743
         *
744
         * @param data DOCUMENT ME!
745
         *
746
         * @return DOCUMENT ME!
747
         */
748
        public static String print_bytes(byte[] data) {
749
                return print_bytes(data, 0, data.length);
750
        }
751

    
752
        /**
753
         * DOCUMENT ME!
754
         *
755
         * @param msg DOCUMENT ME!
756
         */
757
        private static void croak(String msg) {
758
                // throw new java.AssertionViolatedException(msg);
759
        }
760

    
761
        /**
762
         * DOCUMENT ME!
763
         *
764
         * @param b DOCUMENT ME!
765
         *
766
         * @return DOCUMENT ME!
767
         */
768
        public static int getUnsigned(byte b) {
769
                return ((b & 0xff)); // >> 8);
770
        }
771
}