1 //******************************************************************************
2 //
3 // File: Hex.java
4 // Package: edu.rit.util
5 // Unit: Class edu.rit.util.Hex
6 //
7 // This Java source file is copyright (C) 2006 by Alan Kaminsky. All rights
8 // reserved. For further information, contact the author, Alan Kaminsky, at
9 // ark@cs.rit.edu.
10 //
11 // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12 // software; you can redistribute it and/or modify it under the terms of the GNU
13 // General Public License as published by the Free Software Foundation; either
14 // version 3 of the License, or (at your option) any later version.
15 //
16 // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 //
20 // Linking this library statically or dynamically with other modules is making a
21 // combined work based on this library. Thus, the terms and conditions of the GNU
22 // General Public License cover the whole combination.
23 //
24 // As a special exception, the copyright holders of this library give you
25 // permission to link this library with independent modules to produce an
26 // executable, regardless of the license terms of these independent modules, and
27 // to copy and distribute the resulting executable under terms of your choice,
28 // provided that you also meet, for each linked independent module, the terms
29 // and conditions of the license of that module. An independent module is a module
30 // which is not derived from or based on this library. If you modify this library,
31 // you may extend this exception to your version of the library, but you are not
32 // obligated to do so. If you do not wish to do so, delete this exception
33 // statement from your version.
34 //
35 // A copy of the GNU General Public License is provided in the file gpl.txt. You
36 // may also obtain a copy of the GNU General Public License on the World Wide
37 // Web at http://www.gnu.org/licenses/gpl.html.
38 //
39 //******************************************************************************
40 package edu.rit.util;
41
42 /**
43 * Class Hex provides static methods for converting between hexadecimal strings
44 * and numbers of various kinds.
45 *
46 * @author Alan Kaminsky
47 * @version 22-Apr-2006
48 */
49 public class Hex {
50
51 // Hidden data members.
52 private static final char[] int2hex = new char[]{'0', '1', '2', '3', '4', '5', '6', '7',
53 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
54
55 // Prevent construction.
56 private Hex() {
57 }
58
59 // Exported operations.
60 /**
61 * Convert the given <code>byte</code> value to a two-digit hexadecimal string.
62 *
63 * @param val Value.
64 * @return Hexadecimal string.
65 */
66 public static String toString(byte val) {
67 StringBuilder buf = new StringBuilder(2);
68 buf.append(int2hex[(val >> 4) & 0xF]);
69 buf.append(int2hex[(val) & 0xF]);
70 return buf.toString();
71 }
72
73 /**
74 * Convert the given <code>char</code> value to a four-digit hexadecimal string.
75 *
76 * @param val Value.
77 * @return Hexadecimal string.
78 */
79 public static String toString(char val) {
80 StringBuilder buf = new StringBuilder(4);
81 buf.append(int2hex[(val >> 12) & 0xF]);
82 buf.append(int2hex[(val >> 8) & 0xF]);
83 buf.append(int2hex[(val >> 4) & 0xF]);
84 buf.append(int2hex[(val) & 0xF]);
85 return buf.toString();
86 }
87
88 /**
89 * Convert the given <code>short</code> value to a four-digit hexadecimal
90 * string.
91 *
92 * @param val Value.
93 * @return Hexadecimal string.
94 */
95 public static String toString(short val) {
96 StringBuilder buf = new StringBuilder(4);
97 buf.append(int2hex[(val >> 12) & 0xF]);
98 buf.append(int2hex[(val >> 8) & 0xF]);
99 buf.append(int2hex[(val >> 4) & 0xF]);
100 buf.append(int2hex[(val) & 0xF]);
101 return buf.toString();
102 }
103
104 /**
105 * Convert the given <code>int</code> value to an eight-digit hexadecimal
106 * string.
107 *
108 * @param val Value.
109 * @return Hexadecimal string.
110 */
111 public static String toString(int val) {
112 StringBuilder buf = new StringBuilder(8);
113 buf.append(int2hex[(val >> 28) & 0xF]);
114 buf.append(int2hex[(val >> 24) & 0xF]);
115 buf.append(int2hex[(val >> 20) & 0xF]);
116 buf.append(int2hex[(val >> 16) & 0xF]);
117 buf.append(int2hex[(val >> 12) & 0xF]);
118 buf.append(int2hex[(val >> 8) & 0xF]);
119 buf.append(int2hex[(val >> 4) & 0xF]);
120 buf.append(int2hex[(val) & 0xF]);
121 return buf.toString();
122 }
123
124 /**
125 * Convert the given <code>long</code> value to a sixteen-digit hexadecimal
126 * string.
127 *
128 * @param val Value.
129 * @return Hexadecimal string.
130 */
131 public static String toString(long val) {
132 StringBuilder buf = new StringBuilder(16);
133 buf.append(int2hex[(int) (val >> 60) & 0xF]);
134 buf.append(int2hex[(int) (val >> 56) & 0xF]);
135 buf.append(int2hex[(int) (val >> 52) & 0xF]);
136 buf.append(int2hex[(int) (val >> 48) & 0xF]);
137 buf.append(int2hex[(int) (val >> 44) & 0xF]);
138 buf.append(int2hex[(int) (val >> 40) & 0xF]);
139 buf.append(int2hex[(int) (val >> 36) & 0xF]);
140 buf.append(int2hex[(int) (val >> 32) & 0xF]);
141 buf.append(int2hex[(int) (val >> 28) & 0xF]);
142 buf.append(int2hex[(int) (val >> 24) & 0xF]);
143 buf.append(int2hex[(int) (val >> 20) & 0xF]);
144 buf.append(int2hex[(int) (val >> 16) & 0xF]);
145 buf.append(int2hex[(int) (val >> 12) & 0xF]);
146 buf.append(int2hex[(int) (val >> 8) & 0xF]);
147 buf.append(int2hex[(int) (val >> 4) & 0xF]);
148 buf.append(int2hex[(int) (val) & 0xF]);
149 return buf.toString();
150 }
151
152 /**
153 * Convert the given <code>byte</code> array to a hexadecimal string. Each byte
154 * is converted to two hexadecimal digits.
155 *
156 * @param val Byte array.
157 * @return Hexadecimal string.
158 * @exception NullPointerException (unchecked exception) Thrown if
159 * <code>val</code> is null.
160 */
161 public static String toString(byte[] val) {
162 return toString(val, 0, val.length);
163 }
164
165 /**
166 * Convert a portion of the given <code>byte</code> array to a hexadecimal
167 * string. Each byte is converted to two hexadecimal digits.
168 *
169 * @param val Byte array.
170 * @param off Index of first byte to convert.
171 * @param len Number of bytes to convert.
172 * @return Hexadecimal string.
173 * @exception NullPointerException (unchecked exception) Thrown if
174 * <code>val</code> is null.
175 * @exception IndexOutOfBoundsException (unchecked exception) Thrown if
176 * <code>off</code> < 0, <code>len</code>
177 * < 0, or <code>off+len</code> > <code>val.length</code>.
178 */
179 public static String toString(byte[] val,
180 int off,
181 int len) {
182 if (off < 0 || len < 0 || off + len > val.length) {
183 throw new IndexOutOfBoundsException();
184 }
185 StringBuilder buf = new StringBuilder(2 * len);
186 while (len > 0) {
187 buf.append(int2hex[(val[off] >> 4) & 0xF]);
188 buf.append(int2hex[(val[off]) & 0xF]);
189 ++off;
190 --len;
191 }
192 return buf.toString();
193 }
194
195 /**
196 * Convert the given hexadecimal string to a <code>byte</code> value. Characters
197 * of the string from the highest index to the lowest index give the
198 * hexadecimal digits of the value from least significant digit to most
199 * significant digit. Any extra high-order digits in the string are omitted.
200 *
201 * @param str Hexadecimal string.
202 * @return Value.
203 * @exception NullPointerException (unchecked exception) Thrown if
204 * <code>str</code> is null.
205 * @exception IllegalArgumentException (unchecked exception) Thrown if any
206 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
207 * <code>'9'</code>, <code>'a'</code> ..
208 * <code>'f'</code>, or <code>'A'</code> .. <code>'F'</code>).
209 */
210 public static byte toByte(String str) {
211 return (byte) toInt(str);
212 }
213
214 /**
215 * Convert the given hexadecimal string to a <code>char</code> value. Characters
216 * of the string from the highest index to the lowest index give the
217 * hexadecimal digits of the value from least significant digit to most
218 * significant digit. Any extra high-order digits in the string are omitted.
219 *
220 * @param str Hexadecimal string.
221 * @return Value.
222 * @exception NullPointerException (unchecked exception) Thrown if
223 * <code>str</code> is null.
224 * @exception IllegalArgumentException (unchecked exception) Thrown if any
225 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
226 * <code>'9'</code>, <code>'a'</code> ..
227 * <code>'f'</code>, or <code>'A'</code> .. <code>'F'</code>).
228 */
229 public static char toChar(String str) {
230 return (char) toInt(str);
231 }
232
233 /**
234 * Convert the given hexadecimal string to a <code>short</code> value.
235 * Characters of the string from the highest index to the lowest index give
236 * the hexadecimal digits of the value from least significant digit to most
237 * significant digit. Any extra high-order digits in the string are omitted.
238 *
239 * @param str Hexadecimal string.
240 * @return Value.
241 * @exception NullPointerException (unchecked exception) Thrown if
242 * <code>str</code> is null.
243 * @exception IllegalArgumentException (unchecked exception) Thrown if any
244 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
245 * <code>'9'</code>, <code>'a'</code> ..
246 * <code>'f'</code>, or <code>'A'</code> .. <code>'F'</code>).
247 */
248 public static short toShort(String str) {
249 return (short) toInt(str);
250 }
251
252 /**
253 * Convert the given hexadecimal string to an <code>int</code> value. Characters
254 * of the string from the highest index to the lowest index give the
255 * hexadecimal digits of the value from least significant digit to most
256 * significant digit. Any extra high-order digits in the string are omitted.
257 *
258 * @param str Hexadecimal string.
259 * @return Value.
260 * @exception NullPointerException (unchecked exception) Thrown if
261 * <code>str</code> is null.
262 * @exception IllegalArgumentException (unchecked exception) Thrown if any
263 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
264 * <code>'9'</code>, <code>'a'</code> ..
265 * <code>'f'</code>, or <code>'A'</code> .. <code>'F'</code>).
266 */
267 public static int toInt(String str) {
268 int result = 0;
269 int n = str.length();
270 for (int i = 0; i < n; ++i) {
271 result = (result << 4) + hex2int(str.charAt(i));
272 }
273 return result;
274 }
275
276 /**
277 * Convert the given hexadecimal string to a <code>long</code> value. Characters
278 * of the string from the highest index to the lowest index give the
279 * hexadecimal digits of the value from least significant digit to most
280 * significant digit. Any extra high-order digits in the string are omitted.
281 *
282 * @param str Hexadecimal string.
283 * @return Value.
284 * @exception NullPointerException (unchecked exception) Thrown if
285 * <code>str</code> is null.
286 * @exception IllegalArgumentException (unchecked exception) Thrown if any
287 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
288 * <code>'9'</code>, <code>'a'</code> ..
289 * <code>'f'</code>, or <code>'A'</code> .. <code>'F'</code>).
290 */
291 public static long toLong(String str) {
292 long result = 0L;
293 int n = str.length();
294 for (int i = 0; i < n; ++i) {
295 result = (result << 4) + hex2int(str.charAt(i));
296 }
297 return result;
298 }
299
300 /**
301 * Convert the given hexadecimal string to a sequence of bytes stored in a
302 * new <code>byte</code> array. Characters of the string from the highest index
303 * to the lowest index give the hexadecimal digits of the value from least
304 * significant digit to most significant digit. The value is stored in a
305 * newly allocated byte array, with the least significant byte stored at the
306 * highest index and the most significant byte stored at the lowest index.
307 * The array's length is sufficient to hold the entire converted string. The
308 * newly allocated byte array is returned.
309 *
310 * @param str Hexadecimal string.
311 * @return Value (byte array).
312 * @exception NullPointerException (unchecked exception) Thrown if
313 * <code>str</code> is null.
314 * @exception IllegalArgumentException (unchecked exception) Thrown if any
315 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
316 * <code>'9'</code>, <code>'a'</code> ..
317 * <code>'f'</code>, or <code>'A'</code> .. <code>'F'</code>).
318 */
319 public static byte[] toByteArray(String str) {
320 int n = (str.length() + 1) / 2;
321 byte[] val = new byte[n];
322 toByteArray(str, val, 0, val.length);
323 return val;
324 }
325
326 /**
327 * Convert the given hexadecimal string to a sequence of bytes stored in the
328 * given <code>byte</code> array. Characters of the string from the highest
329 * index to the lowest index give the hexadecimal digits of the value from
330 * least significant digit to most significant digit. The value is stored in
331 * <code>val</code> from highest index to lowest index, with the least
332 * significant byte stored at index <code>val.length-1</code>. If the converted
333 * string requires more than <code>val.length</code> bytes, the extra digits at
334 * the beginning of the string are not converted. If the converted string
335 * requires fewer than <code>val.length</code> bytes, the extra bytes at the
336 * beginning of <code>val</code> are set to 0.
337 *
338 * @param str Hexadecimal string.
339 * @param val Byte array in which to store converted value.
340 * @exception NullPointerException (unchecked exception) Thrown if
341 * <code>str</code> is null or <code>val</code>
342 * is null.
343 * @exception IllegalArgumentException (unchecked exception) Thrown if any
344 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
345 * <code>'9'</code>, <code>'a'</code> ..
346 * <code>'f'</code>, or <code>'A'</code> .. <code>'F'</code>).
347 */
348 public static void toByteArray(String str,
349 byte[] val) {
350 toByteArray(str, val, 0, val.length);
351 }
352
353 /**
354 * Convert the given hexadecimal string to a sequence of bytes stored in a
355 * portion of the given <code>byte</code> array. Characters of the string from
356 * the highest index to the lowest index give the hexadecimal digits of the
357 * value from least significant digit to most significant digit. The value
358 * is stored in <code>val</code> from highest index to lowest index, with the
359 * least significant byte stored at index <code>off+len-1</code>. If the
360 * converted string requires more than <code>len</code> bytes, the extra digits
361 * at the beginning of the string are not converted. If the converted string
362 * requires fewer than <code>len</code> bytes, the extra bytes starting at index
363 * <code>off</code> of <code>val</code> are set to 0.
364 *
365 * @param str Hexadecimal string.
366 * @param val Byte array in which to store converted value.
367 * @param off Index of first byte to store.
368 * @param len Number of bytes to store.
369 * @exception NullPointerException (unchecked exception) Thrown if
370 * <code>str</code> is null or <code>val</code>
371 * is null.
372 * @exception IllegalArgumentException (unchecked exception) Thrown if
373 * <code>off</code> < 0, <code>len</code>
374 * < 0, or <code>off+len</code> > <code>val.length</code>. Thrown if any
375 * character of the string is not a hexadecimal digit (<code>'0'</code> ..
376 * <code>'9'</code>, <code>'a'</code> .. <code>'f'</code>, or <code>'A'</code> ..
377 * <code>'F'</code>).
378 */
379 public static void toByteArray(String str,
380 byte[] val,
381 int off,
382 int len) {
383 if (off < 0 || len < 0 || off + len > val.length) {
384 throw new IndexOutOfBoundsException();
385 }
386 int stroff = str.length() - 1;
387 int valoff = off + len - 1;
388 int result;
389 while (len > 0 && stroff >= 0) {
390 result = hex2int(str.charAt(stroff));
391 --stroff;
392 if (stroff >= 0) {
393 result += hex2int(str.charAt(stroff)) << 4;
394 }
395 --stroff;
396 val[valoff] = (byte) result;
397 --valoff;
398 --len;
399 }
400 while (len > 0) {
401 val[valoff] = (byte) 0;
402 --valoff;
403 --len;
404 }
405 }
406
407 // Hidden operations.
408 /**
409 * Convert the given hexadecimal digit to an <code>int</code> value.
410 *
411 * @param digit Hexadecimal digit.
412 *
413 * @return Value.
414 *
415 * @exception IllegalArgumentException (unchecked exception) Thrown if
416 * <code>digit</code> is not a hexadecimal digit (<code>'0'</code> .. <code>'9'</code>,
417 * <code>'a'</code> .. <code>'f'</code>, or
418 * <code>'A'</code> .. <code>'F'</code>).
419 */
420 private static int hex2int(char digit) {
421 switch (digit) {
422 case '0':
423 case '1':
424 case '2':
425 case '3':
426 case '4':
427 case '5':
428 case '6':
429 case '7':
430 case '8':
431 case '9':
432 return digit - '0';
433 case 'a':
434 case 'b':
435 case 'c':
436 case 'd':
437 case 'e':
438 case 'f':
439 return digit - 'a' + 10;
440 case 'A':
441 case 'B':
442 case 'C':
443 case 'D':
444 case 'E':
445 case 'F':
446 return digit - 'A' + 10;
447 default:
448 throw new IllegalArgumentException("Not a hexadecimal digit: '" + digit + "'");
449 }
450 }
451
452 }