• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &gt;= 0; offset to the part to dump
254      * @param length &gt;= 0; number of bytes to dump
255      * @param outOffset &gt;= 0; first output offset to print
256      * @param bpl &gt;= 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 }