View Javadoc
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> &lt; 0, <code>len</code>
177      * &lt; 0, or <code>off+len</code> &gt; <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> &lt; 0, <code>len</code>
374      * &lt; 0, or <code>off+len</code> &gt; <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 }