1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.util;
18
19public class HexDump
20{
21    private final static char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
22    private final static char[] HEX_LOWER_CASE_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
23
24    public static String dumpHexString(byte[] array)
25    {
26        return dumpHexString(array, 0, array.length);
27    }
28
29    public static String dumpHexString(byte[] array, int offset, int length)
30    {
31        StringBuilder result = new StringBuilder();
32
33        byte[] line = new byte[16];
34        int lineIndex = 0;
35
36        result.append("\n0x");
37        result.append(toHexString(offset));
38
39        for (int i = offset ; i < offset + length ; i++)
40        {
41            if (lineIndex == 16)
42            {
43                result.append(" ");
44
45                for (int j = 0 ; j < 16 ; j++)
46                {
47                    if (line[j] > ' ' && line[j] < '~')
48                    {
49                        result.append(new String(line, j, 1));
50                    }
51                    else
52                    {
53                        result.append(".");
54                    }
55                }
56
57                result.append("\n0x");
58                result.append(toHexString(i));
59                lineIndex = 0;
60            }
61
62            byte b = array[i];
63            result.append(" ");
64            result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
65            result.append(HEX_DIGITS[b & 0x0F]);
66
67            line[lineIndex++] = b;
68        }
69
70        if (lineIndex != 16)
71        {
72            int count = (16 - lineIndex) * 3;
73            count++;
74            for (int i = 0 ; i < count ; i++)
75            {
76                result.append(" ");
77            }
78
79            for (int i = 0 ; i < lineIndex ; i++)
80            {
81                if (line[i] > ' ' && line[i] < '~')
82                {
83                    result.append(new String(line, i, 1));
84                }
85                else
86                {
87                    result.append(".");
88                }
89            }
90        }
91
92        return result.toString();
93    }
94
95    public static String toHexString(byte b)
96    {
97        return toHexString(toByteArray(b));
98    }
99
100    public static String toHexString(byte[] array)
101    {
102        return toHexString(array, 0, array.length, true);
103    }
104
105    public static String toHexString(byte[] array, boolean upperCase)
106    {
107        return toHexString(array, 0, array.length, upperCase);
108    }
109
110    public static String toHexString(byte[] array, int offset, int length)
111    {
112        return toHexString(array, offset, length, true);
113    }
114
115    public static String toHexString(byte[] array, int offset, int length, boolean upperCase)
116    {
117        char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS;
118        char[] buf = new char[length * 2];
119
120        int bufIndex = 0;
121        for (int i = offset ; i < offset + length; i++)
122        {
123            byte b = array[i];
124            buf[bufIndex++] = digits[(b >>> 4) & 0x0F];
125            buf[bufIndex++] = digits[b & 0x0F];
126        }
127
128        return new String(buf);
129    }
130
131    public static String toHexString(int i)
132    {
133        return toHexString(toByteArray(i));
134    }
135
136    public static byte[] toByteArray(byte b)
137    {
138        byte[] array = new byte[1];
139        array[0] = b;
140        return array;
141    }
142
143    public static byte[] toByteArray(int i)
144    {
145        byte[] array = new byte[4];
146
147        array[3] = (byte)(i & 0xFF);
148        array[2] = (byte)((i >> 8) & 0xFF);
149        array[1] = (byte)((i >> 16) & 0xFF);
150        array[0] = (byte)((i >> 24) & 0xFF);
151
152        return array;
153    }
154
155    private static int toByte(char c)
156    {
157        if (c >= '0' && c <= '9') return (c - '0');
158        if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
159        if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
160
161        throw new RuntimeException ("Invalid hex char '" + c + "'");
162    }
163
164    public static byte[] hexStringToByteArray(String hexString)
165    {
166        int length = hexString.length();
167        byte[] buffer = new byte[length / 2];
168
169        for (int i = 0 ; i < length ; i += 2)
170        {
171            buffer[i / 2] = (byte)((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i+1)));
172        }
173
174        return buffer;
175    }
176
177    public static StringBuilder appendByteAsHex(StringBuilder sb, byte b, boolean upperCase) {
178        char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS;
179        sb.append(digits[(b >> 4) & 0xf]);
180        sb.append(digits[b & 0xf]);
181        return sb;
182    }
183
184}
185