removed a debug
[lwes-java.git] / src / main / java / org / lwes / util / NumberCodec.java
blobc8d4afadadd833fb82284fade63aea0a8d019ff5
1 /*======================================================================*
2 * Copyright (c) 2008, Yahoo! Inc. All rights reserved. *
3 * *
4 * Licensed under the New BSD License (the "License"); you may not use *
5 * this file except in compliance with the License. Unless required *
6 * by applicable law or agreed to in writing, software distributed *
7 * under the License is distributed on an "AS IS" BASIS, WITHOUT *
8 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
9 * See the License for the specific language governing permissions and *
10 * limitations under the License. See accompanying LICENSE file. *
11 *======================================================================*/
13 package org.lwes.util;
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
18 import java.math.BigInteger;
20 /**
21 * This is a class to efficiently encode built-in primitive types into
22 * byte arrays and decode them back. While this can be done with a
23 * combination of ByteArrayOutputStreams, DataOutputStreams,
24 * ByteArrayInputStreams, DataInputStreams, merely creating those
25 * objects is quite costly and it is difficult to make them persistent.
26 * As such, this contains code lifted from the guts of the Data*Stream
27 * classes.
28 * <p/>
29 * Also, this class defines functions to convert primitive types and
30 * byte arrays to and from hexadecimal strings.
31 * <p/>
32 * Hopefully, support for these operations will be added to
33 * the standard Java API and this class can be retired.
35 * @author Preston Pfarner
36 * @author Michael P. Lum
37 * @version %I%, %G%
38 * @since 0.0.1
40 public final class NumberCodec {
41 private static transient Log log = LogFactory.getLog(NumberCodec.class);
43 public static final int BYTE_BYTES = 1;
44 public static final int SHORT_BYTES = 2;
45 public static final int INT_BYTES = 4;
46 public static final int LONG_BYTES = 8;
48 public static final int BYTE_BITS = 8;
49 public static final int SHORT_BITS = SHORT_BYTES * BYTE_BITS;
50 public static final int INT_BITS = INT_BYTES * BYTE_BITS;
51 public static final int LONG_BITS = LONG_BYTES * BYTE_BITS;
53 public static final short BYTE_MASK = 0xFF;
54 public static final int SHORT_MASK = 0xFFFF;
55 public static final long INT_MASK = 0xFFFFFFFFL;
57 private static final char[] hexCharMap = {
58 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
61 private static final byte[] hexByteMap = {
62 (byte) '0', (byte) '1', (byte) '2', (byte) '3',
63 (byte) '4', (byte) '5', (byte) '6', (byte) '7',
64 (byte) '8', (byte) '9', (byte) 'A', (byte) 'B',
65 (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
68 /**
69 * Prohibited constructor; this is an uninstantiable class.
71 private NumberCodec() {
75 /* ***********************************************************************
76 * ENCODING TO BYTE ARRAYS
77 * ***********************************************************************/
79 /**
80 * Encode a byte into a byte-array buffer. <br>
81 * This version does not perform any null or range checks!
83 * @param b the byte to be encoded
84 * @param buffer the byte array into which the encoding should be written
85 * @param offset the position in the array to start writing the encoding
87 public static void encodeByteUnchecked(byte b, byte[] buffer, int offset) {
88 buffer[offset] = b;
91 /**
92 * Encode a byte into a byte-array buffer.
94 * @param b the byte to be encoded
95 * @param buffer the byte array into which the encoding should be written
96 * @param offset the position in the array to start writing the encoding
97 * @param length the maximum number of bytes that may be written
99 public static void encodeByte(byte b, byte[] buffer, int offset, int length)
100 throws IllegalArgumentException {
101 checkRange(BYTE_BYTES, buffer, offset, length);
102 encodeByteUnchecked(b, buffer, offset);
106 * Encode a short into a byte-array buffer. <br>
107 * This version does not perform any null or range checks!
109 * @param s the short to be encoded
110 * @param buffer the byte array into which the encoding should be written
111 * @param offset the position in the array to start writing the encoding
113 public static void encodeShortUnchecked(short s, byte[] buffer, int offset) {
114 buffer[offset++] = (byte) ((s >>> (1 * BYTE_BITS)) & BYTE_MASK);
115 buffer[offset] = (byte) ((s >>> (0 * BYTE_BITS)) & BYTE_MASK);
119 * Encode a short into a byte-array buffer.
121 * @param s the short to be encoded
122 * @param buffer the byte array into which the encoding should be written
123 * @param offset the position in the array to start writing the encoding
124 * @param length the maximum number of bytes that may be written
126 public static void encodeShort(short s, byte[] buffer, int offset, int length)
127 throws IllegalArgumentException {
128 checkRange(SHORT_BYTES, buffer, offset, length);
129 encodeShortUnchecked(s, buffer, offset);
133 * Encode an int into a byte-array buffer. <br>
134 * This version does not perform any null or range checks!
136 * @param i the int to be encoded
137 * @param buffer the byte array into which the encoding should be written
138 * @param offset the position in the array to start writing the encoding
140 public static void encodeIntUnchecked(int i, byte[] buffer, int offset) {
141 buffer[offset++] = (byte) ((i >>> (3 * BYTE_BITS)) & BYTE_MASK);
142 buffer[offset++] = (byte) ((i >>> (2 * BYTE_BITS)) & BYTE_MASK);
143 buffer[offset++] = (byte) ((i >>> (1 * BYTE_BITS)) & BYTE_MASK);
144 buffer[offset] = (byte) ((i >>> (0 * BYTE_BITS)) & BYTE_MASK);
148 * Encode an int into a byte-array buffer.
150 * @param i the int to be encoded
151 * @param buffer the byte array into which the encoding should be written
152 * @param offset the position in the array to start writing the encoding
153 * @param length the maximum number of bytes that may be written
155 public static void encodeInt(int i, byte[] buffer, int offset, int length)
156 throws IllegalArgumentException {
157 checkRange(INT_BYTES, buffer, offset, length);
158 encodeIntUnchecked(i, buffer, offset);
162 * Encode a long into a byte-array buffer.
164 * @param l the long to be encoded
165 * @param buffer the byte array into which the encoding should be written
166 * @param offset the position in the array to start writing the encoding
168 public static void encodeLongUnchecked(long l, byte[] buffer, int offset) {
169 buffer[offset++] = (byte) ((l >>> (7 * BYTE_BITS)) & BYTE_MASK);
170 buffer[offset++] = (byte) ((l >>> (6 * BYTE_BITS)) & BYTE_MASK);
171 buffer[offset++] = (byte) ((l >>> (5 * BYTE_BITS)) & BYTE_MASK);
172 buffer[offset++] = (byte) ((l >>> (4 * BYTE_BITS)) & BYTE_MASK);
173 buffer[offset++] = (byte) ((l >>> (3 * BYTE_BITS)) & BYTE_MASK);
174 buffer[offset++] = (byte) ((l >>> (2 * BYTE_BITS)) & BYTE_MASK);
175 buffer[offset++] = (byte) ((l >>> (1 * BYTE_BITS)) & BYTE_MASK);
176 buffer[offset] = (byte) ((l >>> (0 * BYTE_BITS)) & BYTE_MASK);
180 * Encode a long into a byte-array buffer.
182 * @param l the long to be encoded
183 * @param buffer the byte array into which the encoding should be written
184 * @param offset the position in the array to start writing the encoding
185 * @param length the maximum number of bytes that may be written
187 public static void encodeLong(long l, byte[] buffer, int offset, int length)
188 throws IllegalArgumentException {
189 checkRange(LONG_BYTES, buffer, offset, length);
190 encodeLongUnchecked(l, buffer, offset);
193 /* ***********************************************************************
194 * DECODING FROM BYTE ARRAYS
195 * ***********************************************************************/
198 * Extract and decode a byte out of a byte-array buffer. <br>
199 * This version does not perform any null or range checks!
201 * @param buffer the byte array from which the encoded form should be read
202 * @param offset the position in the array to start reading the encoded form
204 public static final byte decodeByteUnchecked(byte[] buffer, int offset) {
205 return buffer[offset];
209 * Decode a byte out of a byte-array buffer.
211 * @param buffer the byte array from which the encoded form should be read
212 * @param offset the position in the array to start reading the encoded form
213 * @param length the maximum number of bytes that may be read
215 public static final byte decodeByte(byte[] buffer, int offset, int length)
216 throws IllegalArgumentException {
217 checkRange(BYTE_BYTES, buffer, offset, length);
218 return decodeByteUnchecked(buffer, offset);
222 * Extract and decode a short out of a byte-array buffer. <br>
223 * This version does not perform any null or range checks!
225 * @param buffer the byte array from which the encoded form should be read
226 * @param offset the position in the array to start reading the encoded form
228 public static short decodeShortUnchecked(byte[] buffer, int offset) {
229 return
230 (short) ((decodeByteUnchecked(buffer, offset) << BYTE_BITS) +
231 (decodeByteUnchecked(buffer, offset + BYTE_BYTES) & BYTE_MASK));
235 * Decode a short out of a byte-array buffer.
237 * @param buffer the byte array from which the encoded form should be read
238 * @param offset the position in the array to start reading the encoded form
239 * @param length the maximum number of bytes that may be read
241 public static short decodeShort(byte[] buffer, int offset, int length)
242 throws IllegalArgumentException {
243 checkRange(SHORT_BYTES, buffer, offset, length);
244 return decodeShortUnchecked(buffer, offset);
248 * Extract and decode an int out of a byte-array buffer. <br>
249 * This version does not perform any null or range checks!
251 * @param buffer the byte array from which the encoded form should be read
252 * @param offset the position in the array to start reading the encoded form
254 public static int decodeIntUnchecked(byte[] buffer, int offset) {
255 return ((decodeShortUnchecked(buffer, offset) << SHORT_BITS) +
256 (decodeShortUnchecked(buffer, offset + SHORT_BYTES) & SHORT_MASK));
260 * Decode an int out of a byte-array buffer.
262 * @param buffer the byte array from which the encoded form should be read
263 * @param offset the position in the array to start reading the encoded form
264 * @param length the maximum number of bytes that may be read
266 public static int decodeInt(byte[] buffer, int offset, int length)
267 throws IllegalArgumentException {
268 checkRange(INT_BYTES, buffer, offset, length);
269 return decodeIntUnchecked(buffer, offset);
273 * Extract and decode a long out of a byte-array buffer. <br>
274 * This version does not perform any null or range checks!
276 * @param buffer the byte array from which the encoded form should be read
277 * @param offset the position in the array to start reading the encoded form
279 public static long decodeLongUnchecked(byte[] buffer, int offset) {
280 return ((((long) decodeIntUnchecked(buffer, offset)) << INT_BITS) +
281 (decodeIntUnchecked(buffer, offset + INT_BYTES) & INT_MASK));
285 * Decode a long out of a byte-array buffer.
287 * @param buffer the byte array from which the encoded form should be read
288 * @param offset the position in the array to start reading the encoded form
289 * @param length the maximum number of bytes that may be read
291 public static long decodeLong(byte[] buffer, int offset, int length)
292 throws IllegalArgumentException {
293 checkRange(LONG_BYTES, buffer, offset, length);
294 return decodeLongUnchecked(buffer, offset);
298 * Verifies that the buffer exists, that the writeable region fits into
299 * the buffer, and that the writeable length is long enough.
301 * @param minLength the length that will be written
302 * @param buffer the destination array
303 * @param offset the first position that should be written
304 * @param length the number of bytes that may be written
305 * @throws IllegalArgumentException if the check fails
307 public static void checkRange(int minLength,
308 byte[] buffer, int offset, int length)
309 throws IllegalArgumentException {
310 if (buffer == null) {
311 throw new IllegalArgumentException("Buffer is null.");
313 if ((offset < 0) || (length < 0) || (offset + length > buffer.length)) {
314 throw new IllegalArgumentException("Writeable region does not fit: " +
315 offset + "," + length + "," + buffer.length);
317 if (minLength > length) {
318 throw new IllegalArgumentException("Writeable region is too small: " +
319 minLength + ">" + length);
323 /* ***********************************************************************
324 * WRITING TO STRINGS (IN HEX)
325 * ***********************************************************************/
328 * Output a number in unsigned hexadecimal form, padding with zeroes,
329 * with a fixed result size. Extra opening "f"'s are removed.
331 * @param num the number to convert
332 * @param numBytes the number of bytes to write (each is two hex digits)
333 * @return a String representing the number.
335 private static String toHexString(long num, int numBytes) {
336 final StringBuffer buf = new StringBuffer(2 * numBytes);
337 writeHexString(num, numBytes, buf);
338 return buf.toString();
342 * Write a number in unsigned hexadecimal form, padding with zeroes,
343 * with a fixed result size. Extra opening "f"'s are removed.
345 * @param num the number to convert
346 * @param numBytes the number of bytes to write (each is two hex digits)
347 * @param buf the StringBuffer into which to write
349 private static void writeHexString(long num, int numBytes, StringBuffer buf) {
350 final int startLen = buf.length();
351 int numNibbles = numBytes << 1;
352 int pos = startLen + numNibbles;
353 buf.setLength(pos);
354 while (numNibbles != 0) {
355 --pos;
356 final byte masked = (byte) (num & 0xf);
357 buf.setCharAt(pos, hexCharMap[masked]);
358 num >>>= 4;
359 --numNibbles;
364 * Write a number in unsigned hexadecimal form, padding with zeroes,
365 * with a fixed result size. Extra opening "f"'s are removed.
367 * @param value the number to convert
368 * @param bytes the byte array into which to write
369 * @param offset the offset into <code>bytes</code> to start
370 * @param numBytes the number of bytes to write (each is two hex digits)
372 private static void writeHexString
373 (long value, byte[] bytes, int offset, int numBytes) {
374 int numNibbles = numBytes << 1;
375 int pos = offset + numNibbles;
376 while (numNibbles != 0) {
377 --pos;
378 final byte masked = (byte) (value & 0xf);
379 bytes[pos] = hexByteMap[masked];
380 value >>>= 4;
381 --numNibbles;
385 /* ***********************************************************************
386 * Convert numbers to hex strings
387 * ***********************************************************************/
390 * Output a byte in unsigned hexadecimal form, padding with zeroes.
392 * @param b the byte
393 * @return a String representing the byte.
395 public static String toHexString(byte b) {
396 return toHexString(b, BYTE_BYTES);
400 * Output a short in unsigned hexadecimal form, padding with zeroes.
402 * @param s the short
403 * @return a String representing the short.
405 public static String toHexString(short s) {
406 return toHexString(s, SHORT_BYTES);
410 * Output an int in unsigned hexadecimal form, padding with zeroes.
412 * @param i the int
413 * @return a String representing the int.
415 public static String toHexString(int i) {
416 return toHexString(i, INT_BYTES);
420 * Output a long in unsigned hexadecimal form, padding with zeroes.
422 * @param l the long
423 * @return a String representing the long.
425 public static String toHexString(long l) {
426 return toHexString(l, LONG_BYTES);
430 * Output a BigInteger in unsigned hexadecimal form, padding with zeroes.
432 * @param bi the BigInteger
433 * @return a String representing the BigInteger.
435 public static String toHexString(BigInteger bi) {
436 if (bi == null) {
437 return "";
439 return bi.toString(16); // 16-bit radix
442 /* ***********************************************************************
443 * Write hex strings into string buffers
444 * ***********************************************************************/
447 * Write a byte in unsigned hexadecimal form, padding with zeroes.
449 * @param buf the StringBuffer into which to write
450 * @param b the byte
452 public static void writeHexString(byte b, StringBuffer buf) {
453 writeHexString(b, BYTE_BYTES, buf);
457 * Write a short in unsigned hexadecimal form, padding with zeroes.
459 * @param buf the StringBuffer into which to write
460 * @param s the short
462 public static void writeHexString(short s, StringBuffer buf) {
463 writeHexString(s, SHORT_BYTES, buf);
467 * Write a int in unsigned hexadecimal form, padding with zeroes.
469 * @param buf the StringBuffer into which to write
470 * @param i the int
472 public static void writeHexString(int i, StringBuffer buf) {
473 writeHexString(i, INT_BYTES, buf);
477 * Write a long in unsigned hexadecimal form, padding with zeroes.
479 * @param buf the StringBuffer into which to write
480 * @param l the long
482 public static void writeHexString(long l, StringBuffer buf) {
483 writeHexString(l, LONG_BYTES, buf);
486 /* ***********************************************************************
487 * Write hex strings into byte arrays
488 * (with each byte representing a nibble in ASCII)
489 * ***********************************************************************/
492 * Write a byte in unsigned hexadecimal form, padding with zeroes.
494 * @param b the byte
495 * @param bytes the byte array into which to write
496 * @param offset the index in the byte array to start writing
498 public static void writeHexString(byte b, byte[] bytes, int offset) {
499 writeHexString(b, bytes, offset, BYTE_BYTES);
503 * Write a short in unsigned hexadecimal form, padding with zeroes.
505 * @param value the value to write
506 * @param bytes the byte array into which to write
507 * @param offset the index in the byte array to start writing
509 public static void writeHexString(short value, byte[] bytes, int offset) {
510 writeHexString(value, bytes, offset, SHORT_BYTES);
514 * Write a int in unsigned hexadecimal form, padding with zeroes.
516 * @param value the value to write
517 * @param bytes the byte array into which to write
518 * @param offset the index in the byte array to start writing
520 public static void writeHexString(int value, byte[] bytes, int offset) {
521 writeHexString(value, bytes, offset, INT_BYTES);
525 * Write a long in unsigned hexadecimal form, padding with zeroes.
527 * @param value the value to write
528 * @param bytes the byte array into which to write
529 * @param offset the index in the byte array to start writing
531 public static void writeHexString(long value, byte[] bytes, int offset) {
532 writeHexString(value, bytes, offset, LONG_BYTES);
537 * Return a String encoding the bytes from a portion of a byte array
538 * in hex form.
540 * @param bytes the byte array
541 * @param offset the first byte to output
542 * @param length the number of bytes to output
543 * @return the hex dump of the byte array
545 public static String byteArrayToHexString(byte[] bytes,
546 int offset, int length) {
547 StringBuffer buf = new StringBuffer(2 * length);
548 for (int i = offset; i < offset + length; i++) {
549 buf.append(Character.forDigit(((bytes[i] >>> 4) & 0x0f), 16));
550 buf.append(Character.forDigit((bytes[i] & 0x0f), 16));
552 return buf.toString();
555 public static byte[] hexStringToByteArray(String aString) {
556 int length = aString.length();
557 if ((length % 2) != 0) {
558 log.error("ERROR: Odd Number, can't convert to byte array");
559 return null;
561 byte[] bytes = new byte[(length / 2)];
562 for (int k = 0; k < (length / 2); k++) {
563 bytes[k] = (byte) 0;
565 byte[] str_bytes = aString.getBytes();
566 if (str_bytes.length != length) {
567 log.error("ERROR: Mismatching lengths");
568 return null;
570 int count = 0;
571 boolean waitingForSecondNibble = false;
572 for (int i = 0; i < length; i++) {
573 switch (str_bytes[i]) {
574 case ((byte) '0'):
575 if (waitingForSecondNibble) {
576 bytes[count] |= (byte) 0x0;
577 count++;
578 waitingForSecondNibble = false;
580 else {
581 bytes[count] |= (byte) ((byte) 0x0 << 4);
582 waitingForSecondNibble = true;
584 break;
585 case ((byte) '1'):
586 if (waitingForSecondNibble) {
587 bytes[count] |= (byte) 0x1;
588 count++;
589 waitingForSecondNibble = false;
591 else {
592 bytes[count] |= (byte) ((byte) 0x1 << 4);
593 waitingForSecondNibble = true;
595 break;
596 case ((byte) '2'):
597 if (waitingForSecondNibble) {
598 bytes[count] |= (byte) 0x2;
599 count++;
600 waitingForSecondNibble = false;
602 else {
603 bytes[count] |= (byte) ((byte) 0x2 << 4);
604 waitingForSecondNibble = true;
606 break;
607 case ((byte) '3'):
608 if (waitingForSecondNibble) {
609 bytes[count] |= (byte) 0x3;
610 count++;
611 waitingForSecondNibble = false;
613 else {
614 bytes[count] |= (byte) ((byte) 0x3 << 4);
615 waitingForSecondNibble = true;
617 break;
618 case ((byte) '4'):
619 if (waitingForSecondNibble) {
620 bytes[count] |= (byte) 0x4;
621 count++;
622 waitingForSecondNibble = false;
624 else {
625 bytes[count] |= (byte) ((byte) 0x4 << 4);
626 waitingForSecondNibble = true;
628 break;
629 case ((byte) '5'):
630 if (waitingForSecondNibble) {
631 bytes[count] |= (byte) 0x5;
632 count++;
633 waitingForSecondNibble = false;
635 else {
636 bytes[count] |= (byte) ((byte) 0x5 << 4);
637 waitingForSecondNibble = true;
639 break;
640 case ((byte) '6'):
641 if (waitingForSecondNibble) {
642 bytes[count] |= (byte) 0x6;
643 count++;
644 waitingForSecondNibble = false;
646 else {
647 bytes[count] |= (byte) ((byte) 0x6 << 4);
648 waitingForSecondNibble = true;
650 break;
651 case ((byte) '7'):
652 if (waitingForSecondNibble) {
653 bytes[count] |= (byte) 0x7;
654 count++;
655 waitingForSecondNibble = false;
657 else {
658 bytes[count] |= (byte) ((byte) 0x7 << 4);
659 waitingForSecondNibble = true;
661 break;
662 case ((byte) '8'):
663 if (waitingForSecondNibble) {
664 bytes[count] |= (byte) 0x8;
665 count++;
666 waitingForSecondNibble = false;
668 else {
669 bytes[count] |= (byte) ((byte) 0x8 << 4);
670 waitingForSecondNibble = true;
672 break;
673 case ((byte) '9'):
674 if (waitingForSecondNibble) {
675 bytes[count] |= (byte) 0x9;
676 count++;
677 waitingForSecondNibble = false;
679 else {
680 bytes[count] |= (byte) ((byte) 0x9 << 4);
681 waitingForSecondNibble = true;
683 break;
684 case ((byte) 'a'):
685 case ((byte) 'A'):
686 if (waitingForSecondNibble) {
687 bytes[count] |= (byte) 0xa;
688 count++;
689 waitingForSecondNibble = false;
691 else {
692 bytes[count] |= (byte) ((byte) 0xa << 4);
693 waitingForSecondNibble = true;
695 break;
696 case ((byte) 'b'):
697 case ((byte) 'B'):
698 if (waitingForSecondNibble) {
699 bytes[count] |= (byte) 0xb;
700 count++;
701 waitingForSecondNibble = false;
703 else {
704 bytes[count] |= (byte) ((byte) 0xb << 4);
705 waitingForSecondNibble = true;
707 break;
708 case ((byte) 'c'):
709 case ((byte) 'C'):
710 if (waitingForSecondNibble) {
711 bytes[count] |= (byte) 0xc;
712 count++;
713 waitingForSecondNibble = false;
715 else {
716 bytes[count] |= (byte) ((byte) 0xc << 4);
717 waitingForSecondNibble = true;
719 break;
721 case ((byte) 'd'):
722 case ((byte) 'D'):
723 if (waitingForSecondNibble) {
724 bytes[count] |= (byte) 0xd;
725 count++;
726 waitingForSecondNibble = false;
728 else {
729 bytes[count] |= (byte) ((byte) 0xd << 4);
730 waitingForSecondNibble = true;
732 break;
734 case ((byte) 'e'):
735 case ((byte) 'E'):
736 if (waitingForSecondNibble) {
737 bytes[count] |= (byte) 0xe;
738 count++;
739 waitingForSecondNibble = false;
741 else {
742 bytes[count] |= (byte) ((byte) 0xe << 4);
743 waitingForSecondNibble = true;
745 break;
747 case ((byte) 'f'):
748 case ((byte) 'F'):
749 if (waitingForSecondNibble) {
750 bytes[count] |= (byte) 0xf;
751 count++;
752 waitingForSecondNibble = false;
754 else {
755 bytes[count] |= (byte) ((byte) 0xf << 4);
756 waitingForSecondNibble = true;
758 break;
760 default:
761 log.error("ERROR: non-hex character");
762 return null;
765 return bytes;
769 * Return a String encoding the bytes in a byte array in hex form. <br>
770 * This is equivalent to
771 * <code>byteArrayToHexString(bytes,0,bytes.length);</code>
773 * @param bytes the byte array
774 * @return the hex dump of the byte array
776 public static String byteArrayToHexString(byte[] bytes) {
777 return byteArrayToHexString(bytes, 0, bytes.length);
781 * Turn an unsigned hex string into a long. This whole thing is here
782 * to replace Long.parseLong(str,16) because it fails with large unsigned
783 * hex strings (ones that denote negative values). When they work out
784 * the signed hex vs. unsigned hex issue in the Java API, this can be
785 * retired.
787 * @param str the String to parse
788 * @return the long that was written in <code>str</code>
790 private static long fromHexString(String str, long min) {
791 final int hex = 16;
792 final char firstChar = str.charAt(0);
793 final int digit = Character.digit(firstChar, hex);
794 if (digit < hex / 2) {
795 return Long.parseLong(str, hex);
797 else {
798 /* Subtract <code>hex/2</code> from the first digit and flip the sign. */
799 final String posStr = (Character.forDigit(digit - hex / 2, hex) +
800 str.substring(1, str.length()));
801 final long offsetLong = Long.parseLong(posStr, hex);
802 return offsetLong + min;
807 * Output a byte in unsigned hexadecimal form, padding with zeroes.
809 * @param s the String representing the byte.
810 * @return the parsed byte
812 public static byte byteFromHexString(String s) {
813 return (byte) fromHexString(s, Byte.MIN_VALUE);
817 * Output a short in unsigned hexadecimal form, padding with zeroes.
819 * @param s the String representing the short
820 * @return the parsed short
822 public static short shortFromHexString(String s) {
823 return (short) fromHexString(s, Short.MIN_VALUE);
827 * Output an int in unsigned hexadecimal form, padding with zeroes.
829 * @param s the String representing the int.
830 * @return the parsed int
832 public static int intFromHexString(String s) {
833 return (int) fromHexString(s, Integer.MIN_VALUE);
837 * Output a long in unsigned hexadecimal form, padding with zeroes.
839 * @param s the String representing the long.
840 * @return the parsed long
842 public static long longFromHexString(String s) {
843 return fromHexString(s, Long.MIN_VALUE);
847 * Decode a long out of a byte-array buffer. (convienience method)
849 * @param pBytes the byte array from which the encoded form should be read
850 * @return long decoded from bytes
852 public static long decodeLong(byte[] pBytes)
853 throws NumberFormatException {
854 if (pBytes == null) {
855 throw new NumberFormatException("null byte array passed");
857 if (pBytes.length != NumberCodec.LONG_BYTES) {
858 throw new NumberFormatException("expecting byte array length of: " +
859 NumberCodec.LONG_BYTES + " got: " + pBytes.length);
861 return NumberCodec.decodeLong(pBytes, 0, pBytes.length);
865 * Encode a long into a byte-array buffer. (convienience method)
867 * @param pLong the long to be encoded
868 * @return encoded bytes of the long
870 public static byte[] encodeLong(long pLong) {
871 byte[] bytes = new byte[NumberCodec.LONG_BYTES];
872 NumberCodec.encodeLong(pLong, bytes, 0, bytes.length);
873 return bytes;
877 * Decode a int out of a byte-array buffer. (convienience method)
879 * @param pBytes the byte array from which the encoded form should be read
880 * @return int decoded from bytes
882 public static int decodeInt (byte[] pBytes)
883 throws NumberFormatException
885 if (pBytes == null)
887 throw new NumberFormatException("null byte array passed");
889 if (pBytes.length != NumberCodec.LONG_BYTES)
891 throw new NumberFormatException("expecting byte array length of: " +
892 NumberCodec.INT_BYTES + " got: " + pBytes.length);
894 return NumberCodec.decodeInt(pBytes, 0, pBytes.length);
898 * Encode a int into a byte-array buffer. (convienience method)
900 * @param pInt the int to be encoded
901 * @return encoded bytes of the int
903 public static byte[] encodeInt (int pInt)
904 throws NumberFormatException
906 byte[] bytes = new byte[NumberCodec.INT_BYTES];
907 NumberCodec.encodeInt(pInt, bytes, 0, bytes.length);
908 return bytes;