1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.util;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Utilities for formatting numbers as hexadecimal.
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class Hex {
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * This class is uninstantiable.
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private Hex() {
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // This space intentionally left blank.
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats a {@code long} as an 8-byte unsigned hex value.
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String u8(long v) {
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[16];
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 16; i++) {
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[15 - i] = Character.forDigit((int) v & 0x0f, 16);
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 4-byte unsigned hex value.
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String u4(int v) {
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[8];
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 8; i++) {
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[7 - i] = Character.forDigit(v & 0x0f, 16);
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 3-byte unsigned hex value.
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String u3(int v) {
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[6];
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 6; i++) {
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[5 - i] = Character.forDigit(v & 0x0f, 16);
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 2-byte unsigned hex value.
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String u2(int v) {
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[4];
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 4; i++) {
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[3 - i] = Character.forDigit(v & 0x0f, 16);
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as either a 2-byte unsigned hex value
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * (if the value is small enough) or a 4-byte unsigned hex value (if
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * not).
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String u2or4(int v) {
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (v == (char) v) {
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return u2(v);
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return u4(v);
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 1-byte unsigned hex value.
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String u1(int v) {
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[2];
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 2; i++) {
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[1 - i] = Character.forDigit(v & 0x0f, 16);
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 4-bit unsigned hex nibble.
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String uNibble(int v) {
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[1];
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        result[0] = Character.forDigit(v & 0x0f, 16);
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats a {@code long} as an 8-byte signed hex value.
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String s8(long v) {
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[17];
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (v < 0) {
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '-';
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v = -v;
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '+';
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 16; i++) {
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[16 - i] = Character.forDigit((int) v & 0x0f, 16);
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 4-byte signed hex value.
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String s4(int v) {
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[9];
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (v < 0) {
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '-';
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v = -v;
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '+';
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 8; i++) {
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[8 - i] = Character.forDigit(v & 0x0f, 16);
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 2-byte signed hex value.
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String s2(int v) {
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[5];
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (v < 0) {
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '-';
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v = -v;
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '+';
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 4; i++) {
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[4 - i] = Character.forDigit(v & 0x0f, 16);
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats an {@code int} as a 1-byte signed hex value.
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param v value to format
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} formatted form
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String s1(int v) {
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        char[] result = new char[3];
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (v < 0) {
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '-';
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v = -v;
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[0] = '+';
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < 2; i++) {
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result[2 - i] = Character.forDigit(v & 0x0f, 16);
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            v >>= 4;
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return new String(result);
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Formats a hex dump of a portion of a {@code byte[]}. The result
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is always newline-terminated, unless the passed-in length was zero,
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * in which case the result is always the empty string ({@code ""}).
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param arr {@code non-null;} array to format
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param offset {@code >= 0;} offset to the part to dump
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param length {@code >= 0;} number of bytes to dump
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param outOffset {@code >= 0;} first output offset to print
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param bpl {@code >= 0;} number of bytes of output per line
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param addressLength {@code {2,4,6,8};} number of characters for each address
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * header
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} a string of the dump
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String dump(byte[] arr, int offset, int length,
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                              int outOffset, int bpl, int addressLength) {
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int end = offset + length;
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // twos-complement math trick: ((x < 0) || (y < 0)) <=> ((x|y) < 0)
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (((offset | length | end) < 0) || (end > arr.length)) {
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IndexOutOfBoundsException("arr.length " +
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                                arr.length + "; " +
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                                offset + "..!" + end);
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (outOffset < 0) {
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("outOffset < 0");
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (length == 0) {
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return "";
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuffer sb = new StringBuffer(length * 4 + 6);
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean bol = true;
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int col = 0;
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        while (length > 0) {
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (col == 0) {
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                String astr;
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                switch (addressLength) {
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    case 2:  astr = Hex.u1(outOffset); break;
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    case 4:  astr = Hex.u2(outOffset); break;
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    case 6:  astr = Hex.u3(outOffset); break;
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    default: astr = Hex.u4(outOffset); break;
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(astr);
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(": ");
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            } else if ((col & 1) == 0) {
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(' ');
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(Hex.u1(arr[offset]));
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            outOffset++;
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            offset++;
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            col++;
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (col == bpl) {
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append('\n');
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                col = 0;
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            length--;
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (col != 0) {
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append('\n');
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
304