svn-gvsig-desktop / tags / v1_0_2_Build_896 / libraries / libDwg / src / com / iver / cit / javacad / util / ByteUtils.java @ 10391
History | View | Annotate | Download (23.4 KB)
1 | 7660 | fjp | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
18 | *
|
||
19 | * For more information, contact:
|
||
20 | *
|
||
21 | * Generalitat Valenciana
|
||
22 | * Conselleria d'Infraestructures i Transport
|
||
23 | * Av. Blasco Ib??ez, 50
|
||
24 | * 46010 VALENCIA
|
||
25 | * SPAIN
|
||
26 | *
|
||
27 | * +34 963862235
|
||
28 | * gvsig@gva.es
|
||
29 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * IVER T.I. S.A
|
||
34 | * Salamanca 50
|
||
35 | * 46005 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963163400
|
||
39 | * dac@iver.es
|
||
40 | */
|
||
41 | package com.iver.cit.javacad.util; |
||
42 | import java.math.BigInteger; |
||
43 | |||
44 | |||
45 | /**
|
||
46 | * Clase que engloba m?todos para trabajar con bytes.
|
||
47 | *
|
||
48 | * @author Vicente Caballero Navarro
|
||
49 | */
|
||
50 | public class ByteUtils { |
||
51 | public static final int SIZE_BOOL = 1; |
||
52 | public static final int SIZE_SHORT = 2; |
||
53 | public static final int SIZE_INT = 4; |
||
54 | public static final int SIZE_LONG = 8; |
||
55 | public static final int SIZE_DOUBLE = 8; |
||
56 | |||
57 | /** A nibble->char mapping for printing out bytes. */
|
||
58 | public static final char[] digits = { |
||
59 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', |
||
60 | 'e', 'f' |
||
61 | }; |
||
62 | |||
63 | /**
|
||
64 | * Return the <code>int</code> represented by the bytes in
|
||
65 | * <code>data</code> staring at offset <code>offset[0]</code>.
|
||
66 | *
|
||
67 | * @param data the array from which to read
|
||
68 | * @param offset A single element array whose first element is the index in
|
||
69 | * data from which to begin reading on function entry, and which on
|
||
70 | * function exit has been incremented by the number of bytes read.
|
||
71 | *
|
||
72 | * @return the value of the <code>int</code> decoded
|
||
73 | */
|
||
74 | public static final int bytesToInt(byte[] data, int[] offset) { |
||
75 | /**
|
||
76 | * TODO: We use network-order within OceanStore, but temporarily
|
||
77 | * supporting intel-order to work with some JNI code until JNI code is
|
||
78 | * set to interoperate with network-order.
|
||
79 | */
|
||
80 | int result = 0; |
||
81 | |||
82 | for (int i = 0; i < SIZE_INT; ++i) { |
||
83 | result <<= 8;
|
||
84 | result |= byteToUnsignedInt(data[offset[0]++]);
|
||
85 | } |
||
86 | |||
87 | return result;
|
||
88 | } |
||
89 | |||
90 | /**
|
||
91 | * Write the bytes representing <code>i</code> into the byte array
|
||
92 | * <code>data</code>, starting at index <code>offset [0]</code>, and
|
||
93 | * increment <code>offset [0]</code> by the number of bytes written; if
|
||
94 | * <code>data == null</code>, increment <code>offset [0]</code> by the
|
||
95 | * number of bytes that would have been written otherwise.
|
||
96 | *
|
||
97 | * @param i the <code>int</code> to encode
|
||
98 | * @param data The byte array to store into, or <code>null</code>.
|
||
99 | * @param offset A single element array whose first element is the index in
|
||
100 | * data to begin writing at on function entry, and which on
|
||
101 | * function exit has been incremented by the number of bytes
|
||
102 | * written.
|
||
103 | */
|
||
104 | public static final void intToBytes(int i, byte[] data, int[] offset) { |
||
105 | /**
|
||
106 | * TODO: We use network-order within OceanStore, but temporarily
|
||
107 | * supporting intel-order to work with some JNI code until JNI code is
|
||
108 | * set to interoperate with network-order.
|
||
109 | */
|
||
110 | if (data != null) { |
||
111 | for (int j = (offset[0] + SIZE_INT) - 1; j >= offset[0]; --j) { |
||
112 | data[j] = (byte) i;
|
||
113 | i >>= 8;
|
||
114 | } |
||
115 | } |
||
116 | |||
117 | offset[0] += SIZE_INT;
|
||
118 | } |
||
119 | |||
120 | /**
|
||
121 | * Return the <code>short</code> represented by the bytes in
|
||
122 | * <code>data</code> staring at offset <code>offset[0]</code>.
|
||
123 | *
|
||
124 | * @param data the array from which to read
|
||
125 | * @param offset A single element array whose first element is the index in
|
||
126 | * data from which to begin reading on function entry, and which on
|
||
127 | * function exit has been incremented by the number of bytes read.
|
||
128 | *
|
||
129 | * @return the value of the <code>short</code> decoded
|
||
130 | */
|
||
131 | public static final short bytesToShort(byte[] data, int[] offset) { |
||
132 | /**
|
||
133 | * TODO: We use network-order within OceanStore, but temporarily
|
||
134 | * supporting intel-order to work with some JNI code until JNI code is
|
||
135 | * set to interoperate with network-order.
|
||
136 | */
|
||
137 | short result = 0; |
||
138 | |||
139 | for (int i = 0; i < SIZE_SHORT; ++i) { |
||
140 | result <<= 8;
|
||
141 | result |= (short) byteToUnsignedInt(data[offset[0]++]); |
||
142 | } |
||
143 | |||
144 | return result;
|
||
145 | } |
||
146 | |||
147 | /**
|
||
148 | * Write the bytes representing <code>s</code> into the byte array
|
||
149 | * <code>data</code>, starting at index <code>offset [0]</code>, and
|
||
150 | * increment <code>offset [0]</code> by the number of bytes written; if
|
||
151 | * <code>data == null</code>, increment <code>offset [0]</code> by the
|
||
152 | * number of bytes that would have been written otherwise.
|
||
153 | *
|
||
154 | * @param s the <code>short</code> to encode
|
||
155 | * @param data The byte array to store into, or <code>null</code>.
|
||
156 | * @param offset A single element array whose first element is the index in
|
||
157 | * data to begin writing at on function entry, and which on
|
||
158 | * function exit has been incremented by the number of bytes
|
||
159 | * written.
|
||
160 | */
|
||
161 | public static final void shortToBytes(short s, byte[] data, int[] offset) { |
||
162 | /**
|
||
163 | * TODO: We use network-order within OceanStore, but temporarily
|
||
164 | * supporting intel-order to work with some JNI code until JNI code is
|
||
165 | * set to interoperate with network-order.
|
||
166 | */
|
||
167 | if (data != null) { |
||
168 | data[offset[0] + 1] = (byte) s; |
||
169 | data[offset[0]] = (byte) (s >> 8); |
||
170 | } |
||
171 | |||
172 | offset[0] += SIZE_SHORT;
|
||
173 | } |
||
174 | |||
175 | /**
|
||
176 | * Return the <code>long</code> represented by the bytes in
|
||
177 | * <code>data</code> staring at offset <code>offset[0]</code>.
|
||
178 | *
|
||
179 | * @param data the array from which to read
|
||
180 | * @param offset A single element array whose first element is the index in
|
||
181 | * data from which to begin reading on function entry, and which
|
||
182 | * on function exit has been incremented by the number of bytes
|
||
183 | * read.
|
||
184 | *
|
||
185 | * @return the value of the <code>long</code> decoded
|
||
186 | */
|
||
187 | public static final long bytesToLong(byte[] data, int[] offset) { |
||
188 | long result = 0; |
||
189 | |||
190 | for (int i = 0; i < SIZE_LONG; ++i) { |
||
191 | result <<= 8;
|
||
192 | |||
193 | int res = byteToUnsignedInt(data[offset[0]++]); |
||
194 | result = result | res; |
||
195 | } |
||
196 | |||
197 | return result;
|
||
198 | } |
||
199 | |||
200 | /**
|
||
201 | * Write the bytes representing <code>l</code> into the byte array
|
||
202 | * <code>data</code>, starting at index <code>offset [0]</code>, and
|
||
203 | * increment <code>offset [0]</code> by the number of bytes written; if
|
||
204 | * <code>data == null</code>, increment <code>offset [0]</code> by the
|
||
205 | * number of bytes that would have been written otherwise.
|
||
206 | *
|
||
207 | * @param l the <code>long</code> to encode
|
||
208 | * @param data The byte array to store into, or <code>null</code>.
|
||
209 | * @param offset A single element array whose first element is the index in
|
||
210 | * data to begin writing at on function entry, and which on
|
||
211 | * function exit has been incremented by the number of bytes
|
||
212 | * written.
|
||
213 | */
|
||
214 | public static final void longToBytes(long l, byte[] data, int[] offset) { |
||
215 | /**
|
||
216 | * TODO: We use network-order within OceanStore, but temporarily
|
||
217 | * supporting intel-order to work with some JNI code until JNI code is
|
||
218 | * set to interoperate with network-order.
|
||
219 | */
|
||
220 | if (data != null) { |
||
221 | for (int j = (offset[0] + SIZE_LONG) - 1; j >= offset[0]; --j) { |
||
222 | data[j] = (byte) l;
|
||
223 | l >>= 8;
|
||
224 | } |
||
225 | } |
||
226 | |||
227 | offset[0] += SIZE_LONG;
|
||
228 | } |
||
229 | |||
230 | /**
|
||
231 | * Return the <code>double</code> represented by the bytes in
|
||
232 | * <code>data</code> staring at offset <code>offset[0]</code>.
|
||
233 | *
|
||
234 | * @param data the array from which to read
|
||
235 | * @param offset A single element array whose first element is the index in
|
||
236 | * data from which to begin reading on function entry, and which
|
||
237 | * on function exit has been incremented by the number of bytes
|
||
238 | * read.
|
||
239 | *
|
||
240 | * @return the value of the <code>double</code> decoded
|
||
241 | */
|
||
242 | public static final double bytesToDouble(byte[] data, int[] offset) { |
||
243 | long bits = bytesToLong(data, offset);
|
||
244 | |||
245 | return Double.longBitsToDouble(bits); |
||
246 | } |
||
247 | |||
248 | /**
|
||
249 | * Write the bytes representing <code>d</code> into the byte array
|
||
250 | * <code>data</code>, starting at index <code>offset [0]</code>, and
|
||
251 | * increment <code>offset [0]</code> by the number of bytes written; if
|
||
252 | * <code>data == null</code>, increment <code>offset [0]</code> by the
|
||
253 | * number of bytes that would have been written otherwise.
|
||
254 | *
|
||
255 | * @param d the <code>double</code> to encode
|
||
256 | * @param data The byte array to store into, or <code>null</code>.
|
||
257 | * @param offset A single element array whose first element is the index in
|
||
258 | * data to begin writing at on function entry, and which on
|
||
259 | * function exit has been incremented by the number of bytes
|
||
260 | * written.
|
||
261 | */
|
||
262 | public static final void doubleToBytes(double d, byte[] data, int[] offset) { |
||
263 | long bits = Double.doubleToLongBits(d); |
||
264 | longToBytes(bits, data, offset); |
||
265 | } |
||
266 | |||
267 | /**
|
||
268 | * Return the <code>String</code> represented by the bytes in
|
||
269 | * <code>data</code> staring at offset <code>offset[0]</code>. This method
|
||
270 | * relies on the user using the corresponding <code>stringToBytes</code>
|
||
271 | * method to encode the <code>String</code>, so that it may properly
|
||
272 | * retrieve the <code>String</code> length.
|
||
273 | *
|
||
274 | * @param data the array from which to read
|
||
275 | * @param offset A single element array whose first element is the index in
|
||
276 | * data from which to begin reading on function entry, and which on
|
||
277 | * function exit has been incremented by the number of bytes read.
|
||
278 | *
|
||
279 | * @return the value of the <code>String</code> decoded
|
||
280 | */
|
||
281 | public static final String bytesToString(byte[] data, int[] offset) { |
||
282 | offset[0] = 0; |
||
283 | |||
284 | int length = bytesToInt(data, offset);
|
||
285 | String st = null; |
||
286 | |||
287 | if ((length < 0) || (length > data.length)) { |
||
288 | st = new String(data); |
||
289 | } else {
|
||
290 | st = new String(data, offset[0], length); |
||
291 | } |
||
292 | |||
293 | offset[0] += length;
|
||
294 | |||
295 | return st;
|
||
296 | } |
||
297 | |||
298 | /**
|
||
299 | * Write the bytes representing <code>s</code> into the byte array
|
||
300 | * <code>data</code>, starting at index <code>offset [0]</code>, and
|
||
301 | * increment <code>offset [0]</code> by the number of bytes written; if
|
||
302 | * <code>data == null</code>, increment <code>offset [0]</code> by the
|
||
303 | * number of bytes that would have been written otherwise.
|
||
304 | *
|
||
305 | * @param s the <code>String</code> to encode
|
||
306 | * @param data The byte array to store into, or <code>null</code>.
|
||
307 | * @param offset A single element array whose first element is the index in
|
||
308 | * data to begin writing at on function entry, and which on
|
||
309 | * function exit has been incremented by the number of bytes
|
||
310 | * written.
|
||
311 | */
|
||
312 | public static final void stringToBytes(String s, byte[] data, int[] offset) { |
||
313 | byte[] s_bytes = s.getBytes(); |
||
314 | |||
315 | if (data != null) { |
||
316 | intToBytes(s_bytes.length, data, offset); |
||
317 | memcpy(data, offset[0], s_bytes, 0, s_bytes.length); |
||
318 | } else {
|
||
319 | offset[0] += SIZE_INT;
|
||
320 | } |
||
321 | |||
322 | offset[0] += s_bytes.length;
|
||
323 | } |
||
324 | |||
325 | /**
|
||
326 | * Return the <code>boolean</code> represented by the bytes in
|
||
327 | * <code>data</code> staring at offset <code>offset[0]</code>.
|
||
328 | *
|
||
329 | * @param data the array from which to read
|
||
330 | * @param offset A single element array whose first element is the index in
|
||
331 | * data from which to begin reading on function entry, and which
|
||
332 | * on function exit has been incremented by the number of bytes
|
||
333 | * read.
|
||
334 | *
|
||
335 | * @return the value of the <code>boolean</code> decoded
|
||
336 | */
|
||
337 | public static final boolean bytesToBool(byte[] data, int[] offset) { |
||
338 | boolean result = true; |
||
339 | |||
340 | if (data[offset[0]] == 0) { |
||
341 | result = false;
|
||
342 | } |
||
343 | |||
344 | offset[0] += SIZE_BOOL;
|
||
345 | |||
346 | return result;
|
||
347 | } |
||
348 | |||
349 | /**
|
||
350 | * Write the bytes representing <code>b</code> into the byte array
|
||
351 | * <code>data</code>, starting at index <code>offset [0]</code>, and
|
||
352 | * increment <code>offset [0]</code> by the number of bytes written; if
|
||
353 | * <code>data == null</code>, increment <code>offset [0]</code> by the
|
||
354 | * number of bytes that would have been written otherwise.
|
||
355 | *
|
||
356 | * @param b the <code>boolean</code> to encode
|
||
357 | * @param data The byte array to store into, or <code>null</code>.
|
||
358 | * @param offset A single element array whose first element is the index in
|
||
359 | * data to begin writing at on function entry, and which on
|
||
360 | * function exit has been incremented by the number of bytes
|
||
361 | * written.
|
||
362 | */
|
||
363 | public static final void boolToBytes(boolean b, byte[] data, int[] offset) { |
||
364 | if (data != null) { |
||
365 | data[offset[0]] = (byte) (b ? 1 : 0); |
||
366 | } |
||
367 | |||
368 | offset[0] += SIZE_BOOL;
|
||
369 | } |
||
370 | |||
371 | /**
|
||
372 | * Return the <code>BigInteger</code> represented by the bytes in
|
||
373 | * <code>data</code> staring at offset <code>offset[0]</code>.
|
||
374 | *
|
||
375 | * @param data the array from which to read
|
||
376 | * @param offset A single element array whose first element is the index in
|
||
377 | * data from which to begin reading on function entry, and which
|
||
378 | * on function exit has been incremented by the number of bytes
|
||
379 | * read.
|
||
380 | *
|
||
381 | * @return the <code>BigInteger</code> decoded
|
||
382 | */
|
||
383 | public static final BigInteger bytesToBigInteger(byte[] data, int[] offset) { |
||
384 | int length = bytesToInt(data, offset);
|
||
385 | byte[] bytes = new byte[length]; |
||
386 | offset[0] += memcpy(bytes, 0, data, offset[0], length); |
||
387 | |||
388 | return new BigInteger(bytes); |
||
389 | } |
||
390 | |||
391 | /**
|
||
392 | * Write the bytes representing <code>n</code> into the byte array
|
||
393 | * <code>data</code>, starting at index <code>offset [0]</code>, and
|
||
394 | * increment <code>offset [0]</code> by the number of bytes written; if
|
||
395 | * <code>data == null</code>, increment <code>offset [0]</code> by the
|
||
396 | * number of bytes that would have been written otherwise.
|
||
397 | *
|
||
398 | * @param n the <code>BigInteger</code> to encode
|
||
399 | * @param data The byte array to store into, or <code>null</code>.
|
||
400 | * @param offset A single element array whose first element is the index in
|
||
401 | * data to begin writing at on function entry, and which on
|
||
402 | * function exit has been incremented by the number of bytes
|
||
403 | * written.
|
||
404 | */
|
||
405 | public static final void bigIntegerToBytes(BigInteger n, byte[] data, |
||
406 | int[] offset) { |
||
407 | byte[] bytes = n.toByteArray(); |
||
408 | intToBytes(bytes.length, data, offset); |
||
409 | offset[0] += memcpy(data, offset[0], bytes, 0, bytes.length); |
||
410 | } |
||
411 | |||
412 | /**
|
||
413 | * Convert an array of <code>bytes</code>s into an array of
|
||
414 | * <code>ints</code>.
|
||
415 | *
|
||
416 | * @param dst the array to write
|
||
417 | * @param dst_offset the start offset in <code>dst</code>, times 4. This
|
||
418 | * measures the offset as if <code>dst</code> were an array of
|
||
419 | * <code>byte</code>s (rather than <code>int</code>s).
|
||
420 | * @param src the array to read
|
||
421 | * @param src_offset the start offset in <code>src</code>
|
||
422 | * @param length the number of <code>byte</code>s to copy.
|
||
423 | */
|
||
424 | public static final void bytesToInts(int[] dst, int dst_offset, byte[] src, |
||
425 | int src_offset, int length) { |
||
426 | if ((src == null) || (dst == null) || |
||
427 | ((src_offset + length) > src.length) || |
||
428 | ((dst_offset + length) > (dst.length * 4)) ||
|
||
429 | ((dst_offset % 4) != 0) || ((length % 4) != 0)) { |
||
430 | croak("bytesToInts parameters are invalid" + " src==" + src + |
||
431 | " dst==" + dst +
|
||
432 | (((src == null) || (dst == null)) ? " " |
||
433 | : (" (src_offset+length)>src.length==" +
|
||
434 | (src_offset + length) + ">" + src.length +
|
||
435 | " (dst_offset+length)>(dst.length*4)==" +
|
||
436 | (dst_offset + length) + ">" + (dst.length * 4) + |
||
437 | " (dst_offset%4)==" + (dst_offset % 4) + " (length%4)==" + |
||
438 | (length % 4) + " dest.length==" + dst.length + " length==" + |
||
439 | length))); |
||
440 | } |
||
441 | |||
442 | // Convert parameters to normal format
|
||
443 | int[] offset = new int[1]; |
||
444 | offset[0] = src_offset;
|
||
445 | |||
446 | int int_dst_offset = dst_offset / 4; |
||
447 | |||
448 | for (int i = 0; i < (length / 4); ++i) { |
||
449 | dst[int_dst_offset++] = bytesToInt(src, offset); |
||
450 | } |
||
451 | } |
||
452 | |||
453 | /**
|
||
454 | * Convert an array of <code>int</code>s into an array of
|
||
455 | * <code>bytes</code>.
|
||
456 | *
|
||
457 | * @param dst the array to write
|
||
458 | * @param dst_offset the start offset in <code>dst</code>
|
||
459 | * @param src the array to read
|
||
460 | * @param src_offset the start offset in <code>src</code>, times 4. This
|
||
461 | * measures the offset as if <code>src</code> were an array of
|
||
462 | * <code>byte</code>s (rather than <code>int</code>s).
|
||
463 | * @param length the number of <code>byte</code>s to copy.
|
||
464 | */
|
||
465 | public static final void intsToBytes(byte[] dst, int dst_offset, int[] src, |
||
466 | int src_offset, int length) { |
||
467 | if ((src == null) || (dst == null) || |
||
468 | ((dst_offset + length) > dst.length) || |
||
469 | ((src_offset + length) > (src.length * 4)) ||
|
||
470 | ((src_offset % 4) != 0) || ((length % 4) != 0)) { |
||
471 | croak("intsToBytes parameters are invalid:" + " src=" + src + |
||
472 | " dst=" + dst + " (dst_offset=" + dst_offset + " + length=" + |
||
473 | length + ")=" + (dst_offset + length) + " > dst.length=" + |
||
474 | ((dst == null) ? 0 : dst.length) + " (src_offset=" + |
||
475 | src_offset + " + length=" + length + ")=" + |
||
476 | (src_offset + length) + " > (src.length=" +
|
||
477 | ((src == null) ? 0 : src.length) + "*4)=" + |
||
478 | ((src == null) ? 0 : (src.length * 4)) + " (src_offset=" + |
||
479 | src_offset + " % 4)=" + (src_offset % 4) + " != 0" + |
||
480 | " (length=" + length + " % 4)=" + (length % 4) + " != 0"); |
||
481 | } |
||
482 | |||
483 | // Convert parameters to normal format
|
||
484 | int[] offset = new int[1]; |
||
485 | offset[0] = dst_offset;
|
||
486 | |||
487 | int int_src_offset = src_offset / 4; |
||
488 | |||
489 | for (int i = 0; i < (length / 4); ++i) { |
||
490 | intToBytes(src[int_src_offset++], dst, offset); |
||
491 | } |
||
492 | } |
||
493 | |||
494 | /**
|
||
495 | * Convert a <code>byte</code> into an unsigned integer.
|
||
496 | *
|
||
497 | * @param b the <code>byte</code> to cast
|
||
498 | *
|
||
499 | * @return a postiive <code>int</code> whose lowest byte contains the bits
|
||
500 | * of <code>b</code>.
|
||
501 | */
|
||
502 | public static final int byteToUnsignedInt(byte b) { |
||
503 | return ((int) b) & 0xff; |
||
504 | } |
||
505 | |||
506 | /**
|
||
507 | * Copy contents of one array of <code>bytes</code> into another. If either
|
||
508 | * array is <code>null</code>, simply return the <code>length</code>
|
||
509 | * parameter directly.
|
||
510 | *
|
||
511 | * @param dst the array to write, or <code>null</code>
|
||
512 | * @param dst_offset the start offset in <code>dst</code>
|
||
513 | * @param src the array to read, or <code>null</code>
|
||
514 | * @param src_offset the start offset in <code>src</code>
|
||
515 | * @param length the number of <code>byte</code>s to copy.
|
||
516 | *
|
||
517 | * @return DOCUMENT ME!
|
||
518 | */
|
||
519 | public static int memcpy(byte[] dst, int dst_offset, byte[] src, |
||
520 | int src_offset, int length) { |
||
521 | if ((dst != null) && (src != null)) { |
||
522 | if (dst.length < (dst_offset + length)) {
|
||
523 | croak("dst.length = " + dst.length + ", but " + |
||
524 | "dst_offset = " + dst_offset + " and length = " + length + |
||
525 | ".");
|
||
526 | } |
||
527 | |||
528 | if (src.length < (src_offset + length)) {
|
||
529 | croak("src.length = " + src.length + ", but " + |
||
530 | "src_offset = " + src_offset + " and length = " + length + |
||
531 | ".");
|
||
532 | } |
||
533 | |||
534 | for (int i = 0; i < length; ++i, ++dst_offset, ++src_offset) |
||
535 | dst[dst_offset] = src[src_offset]; |
||
536 | } |
||
537 | |||
538 | return length;
|
||
539 | } |
||
540 | |||
541 | /**
|
||
542 | * Compare the contents of one array of <code>bytes</code> to another.
|
||
543 | *
|
||
544 | * @param a the first array
|
||
545 | * @param a_offset the start offset in <code>a</code>
|
||
546 | * @param b the second array
|
||
547 | * @param b_offset the start offset in <code>b</code>
|
||
548 | * @param length the number of <code>byte</code>s to compare.
|
||
549 | *
|
||
550 | * @return DOCUMENT ME!
|
||
551 | */
|
||
552 | public static boolean memcmp(byte[] a, int a_offset, byte[] b, |
||
553 | int b_offset, int length) { |
||
554 | if ((a == null) && (b == null)) { |
||
555 | return true; |
||
556 | } |
||
557 | |||
558 | if ((a == null) || (b == null)) { |
||
559 | return false; |
||
560 | } |
||
561 | |||
562 | for (int i = 0; i < length; ++i, ++a_offset, ++b_offset) |
||
563 | if (a[a_offset] != b[b_offset]) {
|
||
564 | return false; |
||
565 | } |
||
566 | |||
567 | return true; |
||
568 | } |
||
569 | |||
570 | /**
|
||
571 | * Fill the given array with zeros.
|
||
572 | *
|
||
573 | * @param array the array to clear
|
||
574 | * @param offset the start offset
|
||
575 | * @param length the number of <code>byte</code>s to clear.
|
||
576 | */
|
||
577 | public static void memclr(byte[] array, int offset, int length) { |
||
578 | for (int i = 0; i < length; ++i, ++offset) |
||
579 | array[offset] = 0;
|
||
580 | } |
||
581 | |||
582 | /**
|
||
583 | * Round a number up to a given multiple.
|
||
584 | *
|
||
585 | * @param value the number to be rounded
|
||
586 | * @param multiple the number to which to be rounded
|
||
587 | *
|
||
588 | * @return the smallest <code>int</code> greater than or equal to
|
||
589 | * <code>value</code> which divides <code>multiple</code> exactly.
|
||
590 | */
|
||
591 | public static int round_up(int value, int multiple) { |
||
592 | return (((value - 1) / multiple) + 1) * multiple; |
||
593 | } |
||
594 | |||
595 | /**
|
||
596 | * Return a new array equal to original except zero-padded to an integral
|
||
597 | * mulitple of blocks. If the original is already an integral multiple of
|
||
598 | * blocks, just return it.
|
||
599 | *
|
||
600 | * @param original the array of <code>byte</code>s to be padded
|
||
601 | * @param block_size the size of the blocks
|
||
602 | *
|
||
603 | * @return an array whose size divides <code>block_size</code> exactly. The
|
||
604 | * array is either <code>original</code> itself, or a copy whose
|
||
605 | * first <code>original.length</code> bytes are equal to
|
||
606 | * <code>original</code>.
|
||
607 | */
|
||
608 | public static byte[] zero_pad(byte[] original, int block_size) { |
||
609 | if ((original.length % block_size) == 0) { |
||
610 | return original;
|
||
611 | } |
||
612 | |||
613 | byte[] result = new byte[round_up(original.length, block_size)]; |
||
614 | memcpy(result, 0, original, 0, original.length); |
||
615 | |||
616 | // Unnecessary - jvm sets bytes to 0.
|
||
617 | // memclr (result, original.length, result.length - original.length);
|
||
618 | return result;
|
||
619 | } |
||
620 | |||
621 | /**
|
||
622 | * Determines whether two arrays of <code>byte</code>s contain the same
|
||
623 | * contents.
|
||
624 | *
|
||
625 | * @param b1 The first array
|
||
626 | * @param b2 The second array
|
||
627 | *
|
||
628 | * @return <code>true</code> if both arrays are <code>null</code>, both
|
||
629 | * empty, or both of the same length with equal contents.
|
||
630 | */
|
||
631 | public static boolean equals(byte[] b1, byte[] b2) { |
||
632 | if (b1 == b2) {
|
||
633 | return true; |
||
634 | } |
||
635 | |||
636 | if ((b1 == null) || (b2 == null)) { // only one is null |
||
637 | |||
638 | return false; |
||
639 | } |
||
640 | |||
641 | if (b1.length != b2.length) {
|
||
642 | return false; |
||
643 | } |
||
644 | |||
645 | for (int i = 0; i < b1.length; ++i) |
||
646 | if (b1[i] != b2[i]) {
|
||
647 | return false; |
||
648 | } |
||
649 | |||
650 | return true; |
||
651 | } |
||
652 | |||
653 | /**
|
||
654 | * Produce a <code>String</code> representation for the specified array of
|
||
655 | * <code>byte</code>s. Print each <code>byte</code> as two hexadecimal
|
||
656 | * digits.
|
||
657 | *
|
||
658 | * @param data The array to print
|
||
659 | * @param offset the start offset in <code>data</code>
|
||
660 | * @param length the number of <code>byte</code>s to print
|
||
661 | *
|
||
662 | * @return DOCUMENT ME!
|
||
663 | */
|
||
664 | public static String print_bytes(byte[] data, int offset, int length) { |
||
665 | int size = 2 * length; |
||
666 | size += ((size / 8) + (size / 64)); |
||
667 | |||
668 | char[] buf = new char[size]; |
||
669 | int low_mask = 0x0f; |
||
670 | int high_mask = 0xf0; |
||
671 | int buf_pos = 0; |
||
672 | byte b;
|
||
673 | |||
674 | int j = 0; |
||
675 | |||
676 | for (int i = offset; i < (offset + length); ++i) { |
||
677 | b = data[i]; |
||
678 | buf[buf_pos++] = digits[(high_mask & b) >> 4];
|
||
679 | buf[buf_pos++] = digits[(low_mask & b)]; |
||
680 | |||
681 | if ((j % 4) == 3) { |
||
682 | buf[buf_pos++] = ' ';
|
||
683 | } |
||
684 | |||
685 | if ((j % 32) == 31) { |
||
686 | buf[buf_pos++] = '\n';
|
||
687 | } |
||
688 | |||
689 | ++j; |
||
690 | } |
||
691 | |||
692 | return new String(buf); |
||
693 | } |
||
694 | |||
695 | /**
|
||
696 | * DOCUMENT ME!
|
||
697 | *
|
||
698 | * @param data DOCUMENT ME!
|
||
699 | * @param offset DOCUMENT ME!
|
||
700 | * @param length DOCUMENT ME!
|
||
701 | *
|
||
702 | * @return DOCUMENT ME!
|
||
703 | */
|
||
704 | public static String print_bytes_exact(byte[] data, int offset, int length) { |
||
705 | int size = 2 * length; |
||
706 | char[] buf = new char[size]; |
||
707 | int low_mask = 0x0f; |
||
708 | int high_mask = 0xf0; |
||
709 | int buf_pos = 0; |
||
710 | byte b;
|
||
711 | |||
712 | int j = 0; |
||
713 | |||
714 | for (int i = offset; i < (offset + length); ++i) { |
||
715 | b = data[i]; |
||
716 | buf[buf_pos++] = digits[(high_mask & b) >> 4];
|
||
717 | buf[buf_pos++] = digits[(low_mask & b)]; |
||
718 | ++j; |
||
719 | } |
||
720 | |||
721 | return new String(buf); |
||
722 | } |
||
723 | |||
724 | /**
|
||
725 | * DOCUMENT ME!
|
||
726 | *
|
||
727 | * @param data DOCUMENT ME!
|
||
728 | *
|
||
729 | * @return DOCUMENT ME!
|
||
730 | */
|
||
731 | public static String print_bytes(byte[] data) { |
||
732 | return print_bytes(data, 0, data.length); |
||
733 | } |
||
734 | |||
735 | /**
|
||
736 | * DOCUMENT ME!
|
||
737 | *
|
||
738 | * @param msg DOCUMENT ME!
|
||
739 | */
|
||
740 | private static void croak(String msg) { |
||
741 | // throw new java.AssertionViolatedException(msg);
|
||
742 | } |
||
743 | |||
744 | /**
|
||
745 | * DOCUMENT ME!
|
||
746 | *
|
||
747 | * @param b DOCUMENT ME!
|
||
748 | *
|
||
749 | * @return DOCUMENT ME!
|
||
750 | */
|
||
751 | public static int getUnsigned(byte b) { |
||
752 | return ((b & 0xff)); // >> 8); |
||
753 | } |
||
754 | } |