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 
17 package com.android.internal.util;
18 
19 import android.annotation.Nullable;
20 import android.compat.annotation.UnsupportedAppUsage;
21 
22 public class HexDump
23 {
24     private final static char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
25     private final static char[] HEX_LOWER_CASE_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
26 
dumpHexString(@ullable byte[] array)27     public static String dumpHexString(@Nullable byte[] array) {
28         if (array == null) return "(null)";
29         return dumpHexString(array, 0, array.length);
30     }
31 
dumpHexString(@ullable byte[] array, int offset, int length)32     public static String dumpHexString(@Nullable byte[] array, int offset, int length)
33     {
34         if (array == null) return "(null)";
35         StringBuilder result = new StringBuilder();
36 
37         byte[] line = new byte[16];
38         int lineIndex = 0;
39 
40         result.append("\n0x");
41         result.append(toHexString(offset));
42 
43         for (int i = offset ; i < offset + length ; i++)
44         {
45             if (lineIndex == 16)
46             {
47                 result.append(" ");
48 
49                 for (int j = 0 ; j < 16 ; j++)
50                 {
51                     if (line[j] > ' ' && line[j] < '~')
52                     {
53                         result.append(new String(line, j, 1));
54                     }
55                     else
56                     {
57                         result.append(".");
58                     }
59                 }
60 
61                 result.append("\n0x");
62                 result.append(toHexString(i));
63                 lineIndex = 0;
64             }
65 
66             byte b = array[i];
67             result.append(" ");
68             result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
69             result.append(HEX_DIGITS[b & 0x0F]);
70 
71             line[lineIndex++] = b;
72         }
73 
74         if (lineIndex != 16)
75         {
76             int count = (16 - lineIndex) * 3;
77             count++;
78             for (int i = 0 ; i < count ; i++)
79             {
80                 result.append(" ");
81             }
82 
83             for (int i = 0 ; i < lineIndex ; i++)
84             {
85                 if (line[i] > ' ' && line[i] < '~')
86                 {
87                     result.append(new String(line, i, 1));
88                 }
89                 else
90                 {
91                     result.append(".");
92                 }
93             }
94         }
95 
96         return result.toString();
97     }
98 
toHexString(byte b)99     public static String toHexString(byte b)
100     {
101         return toHexString(toByteArray(b));
102     }
103 
104     @UnsupportedAppUsage
toHexString(byte[] array)105     public static String toHexString(byte[] array)
106     {
107         return toHexString(array, 0, array.length, true);
108     }
109 
110     @UnsupportedAppUsage
toHexString(byte[] array, boolean upperCase)111     public static String toHexString(byte[] array, boolean upperCase)
112     {
113         return toHexString(array, 0, array.length, upperCase);
114     }
115 
116     @UnsupportedAppUsage
toHexString(byte[] array, int offset, int length)117     public static String toHexString(byte[] array, int offset, int length)
118     {
119         return toHexString(array, offset, length, true);
120     }
121 
toHexString(byte[] array, int offset, int length, boolean upperCase)122     public static String toHexString(byte[] array, int offset, int length, boolean upperCase)
123     {
124         char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS;
125         char[] buf = new char[length * 2];
126 
127         int bufIndex = 0;
128         for (int i = offset ; i < offset + length; i++)
129         {
130             byte b = array[i];
131             buf[bufIndex++] = digits[(b >>> 4) & 0x0F];
132             buf[bufIndex++] = digits[b & 0x0F];
133         }
134 
135         return new String(buf);
136     }
137 
138     @UnsupportedAppUsage
toHexString(int i)139     public static String toHexString(int i)
140     {
141         return toHexString(toByteArray(i));
142     }
143 
toByteArray(byte b)144     public static byte[] toByteArray(byte b)
145     {
146         byte[] array = new byte[1];
147         array[0] = b;
148         return array;
149     }
150 
toByteArray(int i)151     public static byte[] toByteArray(int i)
152     {
153         byte[] array = new byte[4];
154 
155         array[3] = (byte)(i & 0xFF);
156         array[2] = (byte)((i >> 8) & 0xFF);
157         array[1] = (byte)((i >> 16) & 0xFF);
158         array[0] = (byte)((i >> 24) & 0xFF);
159 
160         return array;
161     }
162 
toByte(char c)163     private static int toByte(char c)
164     {
165         if (c >= '0' && c <= '9') return (c - '0');
166         if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
167         if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
168 
169         throw new RuntimeException ("Invalid hex char '" + c + "'");
170     }
171 
172     @UnsupportedAppUsage
hexStringToByteArray(String hexString)173     public static byte[] hexStringToByteArray(String hexString)
174     {
175         int length = hexString.length();
176         byte[] buffer = new byte[length / 2];
177 
178         for (int i = 0 ; i < length ; i += 2)
179         {
180             buffer[i / 2] = (byte)((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i+1)));
181         }
182 
183         return buffer;
184     }
185 
appendByteAsHex(StringBuilder sb, byte b, boolean upperCase)186     public static StringBuilder appendByteAsHex(StringBuilder sb, byte b, boolean upperCase) {
187         char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS;
188         sb.append(digits[(b >> 4) & 0xf]);
189         sb.append(digits[b & 0xf]);
190         return sb;
191     }
192 
193 }
194