blob: e95669c91a25490220746c24f1486a71975475f5 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.util;
/**
* Utilities for formatting numbers as hexadecimal.
*/
public final class Hex {
/**
* This class is uninstantiable.
*/
private Hex() {
// This space intentionally left blank.
}
/**
* Formats a {@code long} as an 8-byte unsigned hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String u8(long v) {
char[] result = new char[16];
for (int i = 0; i < 16; i++) {
result[15 - i] = Character.forDigit((int) v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as a 4-byte unsigned hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String u4(int v) {
char[] result = new char[8];
for (int i = 0; i < 8; i++) {
result[7 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as a 3-byte unsigned hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String u3(int v) {
char[] result = new char[6];
for (int i = 0; i < 6; i++) {
result[5 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as a 2-byte unsigned hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String u2(int v) {
char[] result = new char[4];
for (int i = 0; i < 4; i++) {
result[3 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as either a 2-byte unsigned hex value
* (if the value is small enough) or a 4-byte unsigned hex value (if
* not).
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String u2or4(int v) {
if (v == (char) v) {
return u2(v);
} else {
return u4(v);
}
}
/**
* Formats an {@code int} as a 1-byte unsigned hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String u1(int v) {
char[] result = new char[2];
for (int i = 0; i < 2; i++) {
result[1 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as a 4-bit unsigned hex nibble.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String uNibble(int v) {
char[] result = new char[1];
result[0] = Character.forDigit(v & 0x0f, 16);
return new String(result);
}
/**
* Formats a {@code long} as an 8-byte signed hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String s8(long v) {
char[] result = new char[17];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 16; i++) {
result[16 - i] = Character.forDigit((int) v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as a 4-byte signed hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String s4(int v) {
char[] result = new char[9];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 8; i++) {
result[8 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as a 2-byte signed hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String s2(int v) {
char[] result = new char[5];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 4; i++) {
result[4 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats an {@code int} as a 1-byte signed hex value.
*
* @param v value to format
* @return {@code non-null;} formatted form
*/
public static String s1(int v) {
char[] result = new char[3];
if (v < 0) {
result[0] = '-';
v = -v;
} else {
result[0] = '+';
}
for (int i = 0; i < 2; i++) {
result[2 - i] = Character.forDigit(v & 0x0f, 16);
v >>= 4;
}
return new String(result);
}
/**
* Formats a hex dump of a portion of a {@code byte[]}. The result
* is always newline-terminated, unless the passed-in length was zero,
* in which case the result is always the empty string ({@code ""}).
*
* @param arr {@code non-null;} array to format
* @param offset {@code >= 0;} offset to the part to dump
* @param length {@code >= 0;} number of bytes to dump
* @param outOffset {@code >= 0;} first output offset to print
* @param bpl {@code >= 0;} number of bytes of output per line
* @param addressLength {@code {2,4,6,8};} number of characters for each address
* header
* @return {@code non-null;} a string of the dump
*/
public static String dump(byte[] arr, int offset, int length,
int outOffset, int bpl, int addressLength) {
int end = offset + length;
// twos-complement math trick: ((x < 0) || (y < 0)) <=> ((x|y) < 0)
if (((offset | length | end) < 0) || (end > arr.length)) {
throw new IndexOutOfBoundsException("arr.length " +
arr.length + "; " +
offset + "..!" + end);
}
if (outOffset < 0) {
throw new IllegalArgumentException("outOffset < 0");
}
if (length == 0) {
return "";
}
StringBuffer sb = new StringBuffer(length * 4 + 6);
boolean bol = true;
int col = 0;
while (length > 0) {
if (col == 0) {
String astr;
switch (addressLength) {
case 2: astr = Hex.u1(outOffset); break;
case 4: astr = Hex.u2(outOffset); break;
case 6: astr = Hex.u3(outOffset); break;
default: astr = Hex.u4(outOffset); break;
}
sb.append(astr);
sb.append(": ");
} else if ((col & 1) == 0) {
sb.append(' ');
}
sb.append(Hex.u1(arr[offset]));
outOffset++;
offset++;
col++;
if (col == bpl) {
sb.append('\n');
col = 0;
}
length--;
}
if (col != 0) {
sb.append('\n');
}
return sb.toString();
}
}