package net.i2p.util;
/*
* free (adj.): unencumbered; not under the control of others
* Written by human in 2004 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.data.DataHelper;
/**
* Hexdump class (well, it's actually a namespace with some functions,
* but let's stick with java terminology :-). These methods generate
* an output that resembles `hexdump -C` (Windows users: do you
* remember `debug` in the DOS age?).
*
* @author human
*/
public class HexDump {
private static final int FORMAT_OFFSET_PADDING = 8;
private static final int FORMAT_BYTES_PER_ROW = 16;
private static final byte[] HEXCHARS = DataHelper.getASCII("0123456789abcdef");
/**
* Dump a byte array in a String.
*
* @param data Data to be dumped
*/
public static String dump(byte[] data) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
dump(data, 0, data.length, out);
return out.toString("ISO-8859-1");
} catch (IOException e) {
throw new RuntimeException("no 8859?", e);
}
}
/**
* Dump a byte array in a String.
*
* @param data Data to be dumped
* @param off Offset from the beginning of <code>data</code>
* @param len Number of bytes of <code>data</code> to be dumped
*/
public static String dump(byte[] data, int off, int len) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
dump(data, off, len, out);
return out.toString("ISO-8859-1");
} catch (IOException e) {
throw new RuntimeException("no 8859?", e);
}
}
/**
* Dump a byte array through a stream.
*
* @param data Data to be dumped
* @param out Output stream
*/
public static void dump(byte data[], OutputStream out) throws IOException {
dump(data, 0, data.length, out);
}
/**
* Dump a byte array through a stream.
*
* @param data Data to be dumped
* @param off Offset from the beginning of <code>data</code>
* @param len Number of bytes of <code>data</code> to be dumped
* @param out Output stream
*/
public static void dump(byte[] data, int off, int len, OutputStream out) throws IOException {
String hexoff;
int dumpoff, hexofflen, i, nextbytes, end = len + off;
int val;
for (dumpoff = off; dumpoff < end; dumpoff += FORMAT_BYTES_PER_ROW) {
// Pad the offset with 0's (i miss my beloved sprintf()...)
hexoff = Integer.toString(dumpoff, 16);
hexofflen = hexoff.length();
for (i = 0; i < FORMAT_OFFSET_PADDING - hexofflen; ++i) {
out.write('0');
}
out.write(DataHelper.getASCII(hexoff));
out.write(' ');
// Bytes to be printed in the current line
nextbytes = (FORMAT_BYTES_PER_ROW < (end - dumpoff) ? FORMAT_BYTES_PER_ROW : (end - dumpoff));
for (i = 0; i < FORMAT_BYTES_PER_ROW; ++i) {
// Put two spaces to separate 8-bytes blocks
if ((i % 8) == 0) {
out.write(' ');
}
if (i >= nextbytes) {
out.write(DataHelper.getASCII(" "));
} else {
val = data[dumpoff + i] & 0xff;
out.write(HEXCHARS[val >>> 4]);
out.write(HEXCHARS[val & 0xf]);
out.write(' ');
}
}
out.write(DataHelper.getASCII(" |"));
for (i = 0; i < FORMAT_BYTES_PER_ROW; ++i) {
if (i >= nextbytes) {
out.write(' ');
} else {
val = data[i + dumpoff];
// Is it a printable character?
if ((val > 31) && (val < 127)) {
out.write(val);
} else {
out.write('.');
}
}
}
out.write('|');
out.write('\n');
}
}
/**
* @since 0.9.21
*/
/****
public static void main(String[] args) {
byte[] b = new byte[9993];
RandomSource.getInstance().nextBytes(b);
System.out.println(dump(b));
System.out.println(dump("test test test abcde xyz !!!".getBytes()));
}
****/
}