1 /* 2 * [The "BSD licence"] 3 * Copyright (c) 2010 Ben Gruver (JesusFreke) 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 package org.jf.util; 30 31 /** 32 * Utilities for formatting numbers as hexadecimal. 33 */ 34 public final class Hex { 35 /** 36 * This class is uninstantiable. 37 */ Hex()38 private Hex() { 39 // This space intentionally left blank. 40 } 41 42 /** 43 * Formats a <code>long</code> as an 8-byte unsigned hex value. 44 * 45 * @param v value to format 46 * @return non-null; formatted form 47 */ u8(long v)48 public static String u8(long v) { 49 char[] result = new char[16]; 50 for (int i = 0; i < 16; i++) { 51 result[15 - i] = Character.forDigit((int) v & 0x0f, 16); 52 v >>= 4; 53 } 54 55 return new String(result); 56 } 57 58 /** 59 * Formats an <code>int</code> as a 4-byte unsigned hex value. 60 * 61 * @param v value to format 62 * @return non-null; formatted form 63 */ u4(int v)64 public static String u4(int v) { 65 char[] result = new char[8]; 66 for (int i = 0; i < 8; i++) { 67 result[7 - i] = Character.forDigit(v & 0x0f, 16); 68 v >>= 4; 69 } 70 71 return new String(result); 72 } 73 74 /** 75 * Formats an <code>int</code> as a 3-byte unsigned hex value. 76 * 77 * @param v value to format 78 * @return non-null; formatted form 79 */ u3(int v)80 public static String u3(int v) { 81 char[] result = new char[6]; 82 for (int i = 0; i < 6; i++) { 83 result[5 - i] = Character.forDigit(v & 0x0f, 16); 84 v >>= 4; 85 } 86 87 return new String(result); 88 } 89 90 /** 91 * Formats an <code>int</code> as a 2-byte unsigned hex value. 92 * 93 * @param v value to format 94 * @return non-null; formatted form 95 */ u2(int v)96 public static String u2(int v) { 97 char[] result = new char[4]; 98 for (int i = 0; i < 4; i++) { 99 result[3 - i] = Character.forDigit(v & 0x0f, 16); 100 v >>= 4; 101 } 102 103 return new String(result); 104 } 105 106 /** 107 * Formats an <code>int</code> as either a 2-byte unsigned hex value 108 * (if the value is small enough) or a 4-byte unsigned hex value (if 109 * not). 110 * 111 * @param v value to format 112 * @return non-null; formatted form 113 */ u2or4(int v)114 public static String u2or4(int v) { 115 if (v == (char) v) { 116 return u2(v); 117 } else { 118 return u4(v); 119 } 120 } 121 122 /** 123 * Formats an <code>int</code> as a 1-byte unsigned hex value. 124 * 125 * @param v value to format 126 * @return non-null; formatted form 127 */ u1(int v)128 public static String u1(int v) { 129 char[] result = new char[2]; 130 for (int i = 0; i < 2; i++) { 131 result[1 - i] = Character.forDigit(v & 0x0f, 16); 132 v >>= 4; 133 } 134 135 return new String(result); 136 } 137 138 /** 139 * Formats an <code>int</code> as a 4-bit unsigned hex nibble. 140 * 141 * @param v value to format 142 * @return non-null; formatted form 143 */ uNibble(int v)144 public static String uNibble(int v) { 145 char[] result = new char[1]; 146 147 result[0] = Character.forDigit(v & 0x0f, 16); 148 return new String(result); 149 } 150 151 /** 152 * Formats a <code>long</code> as an 8-byte signed hex value. 153 * 154 * @param v value to format 155 * @return non-null; formatted form 156 */ s8(long v)157 public static String s8(long v) { 158 char[] result = new char[17]; 159 160 if (v < 0) { 161 result[0] = '-'; 162 v = -v; 163 } else { 164 result[0] = '+'; 165 } 166 167 for (int i = 0; i < 16; i++) { 168 result[16 - i] = Character.forDigit((int) v & 0x0f, 16); 169 v >>= 4; 170 } 171 172 return new String(result); 173 } 174 175 /** 176 * Formats an <code>int</code> as a 4-byte signed hex value. 177 * 178 * @param v value to format 179 * @return non-null; formatted form 180 */ s4(int v)181 public static String s4(int v) { 182 char[] result = new char[9]; 183 184 if (v < 0) { 185 result[0] = '-'; 186 v = -v; 187 } else { 188 result[0] = '+'; 189 } 190 191 for (int i = 0; i < 8; i++) { 192 result[8 - i] = Character.forDigit(v & 0x0f, 16); 193 v >>= 4; 194 } 195 196 return new String(result); 197 } 198 199 /** 200 * Formats an <code>int</code> as a 2-byte signed hex value. 201 * 202 * @param v value to format 203 * @return non-null; formatted form 204 */ s2(int v)205 public static String s2(int v) { 206 char[] result = new char[5]; 207 208 if (v < 0) { 209 result[0] = '-'; 210 v = -v; 211 } else { 212 result[0] = '+'; 213 } 214 215 for (int i = 0; i < 4; i++) { 216 result[4 - i] = Character.forDigit(v & 0x0f, 16); 217 v >>= 4; 218 } 219 220 return new String(result); 221 } 222 223 /** 224 * Formats an <code>int</code> as a 1-byte signed hex value. 225 * 226 * @param v value to format 227 * @return non-null; formatted form 228 */ s1(int v)229 public static String s1(int v) { 230 char[] result = new char[3]; 231 232 if (v < 0) { 233 result[0] = '-'; 234 v = -v; 235 } else { 236 result[0] = '+'; 237 } 238 239 for (int i = 0; i < 2; i++) { 240 result[2 - i] = Character.forDigit(v & 0x0f, 16); 241 v >>= 4; 242 } 243 244 return new String(result); 245 } 246 247 /** 248 * Formats a hex dump of a portion of a <code>byte[]</code>. The result 249 * is always newline-terminated, unless the passed-in length was zero, 250 * in which case the result is always the empty string (<code>""</code>). 251 * 252 * @param arr non-null; array to format 253 * @param offset >= 0; offset to the part to dump 254 * @param length >= 0; number of bytes to dump 255 * @param outOffset >= 0; first output offset to print 256 * @param bpl >= 0; number of bytes of output per line 257 * @param addressLength {2,4,6,8}; number of characters for each address 258 * header 259 * @return non-null; a string of the dump 260 */ dump(byte[] arr, int offset, int length, int outOffset, int bpl, int addressLength)261 public static String dump(byte[] arr, int offset, int length, 262 int outOffset, int bpl, int addressLength) { 263 int end = offset + length; 264 265 // twos-complement math trick: ((x < 0) || (y < 0)) <=> ((x|y) < 0) 266 if (((offset | length | end) < 0) || (end > arr.length)) { 267 throw new IndexOutOfBoundsException("arr.length " + 268 arr.length + "; " + 269 offset + "..!" + end); 270 } 271 272 if (outOffset < 0) { 273 throw new IllegalArgumentException("outOffset < 0"); 274 } 275 276 if (length == 0) { 277 return ""; 278 } 279 280 StringBuffer sb = new StringBuffer(length * 4 + 6); 281 boolean bol = true; 282 int col = 0; 283 284 while (length > 0) { 285 if (col == 0) { 286 String astr; 287 switch (addressLength) { 288 case 2: astr = Hex.u1(outOffset); break; 289 case 4: astr = Hex.u2(outOffset); break; 290 case 6: astr = Hex.u3(outOffset); break; 291 default: astr = Hex.u4(outOffset); break; 292 } 293 sb.append(astr); 294 sb.append(": "); 295 } else if ((col & 1) == 0) { 296 sb.append(' '); 297 } 298 sb.append(Hex.u1(arr[offset])); 299 outOffset++; 300 offset++; 301 col++; 302 if (col == bpl) { 303 sb.append('\n'); 304 col = 0; 305 } 306 length--; 307 } 308 309 if (col != 0) { 310 sb.append('\n'); 311 } 312 313 return sb.toString(); 314 } 315 }