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 }