public static String
dump(String description, byte [] b, int offset, int length) {
	StringBuffer sb = new StringBuffer();
	sb.append(length);
	sb.append(" bytes");
	if (description != null) {
		sb.append(" (");
		sb.append(description);
		sb.append(')');
	}
	sb.append(':');
	int prefixlen = sb.toString().length();
	prefixlen = (prefixlen + 8) & ~ 7;
	sb.append('\t');
	int perline = (80 - prefixlen) / 3;
	for (int i = 0; i < length; i++) {
		if (i != 0 && i % perline == 0) {
			for (int j = 0; j < prefixlen; j+=8)
				sb.append("\n\t");
		}
		int value = (int)(b[i + offset]) & 0xFF;
		if (value < 16)
			sb.append('0');
		sb.append(Integer.toHexString(value));
		sb.append(' ');
	}
	sb.append('\n');
	return sb.toString();
}

public static String
dump(String description, byte [] b, int offset, int length) {
	StringBuffer sb = new StringBuffer();
	sb.append(length);
	sb.append("b");
	if (description != null) {
		sb.append(" (");
		sb.append(description);
		sb.append(')');
	}
	sb.append(':');
	int prefixlen = sb.toString().length();
	prefixlen = (prefixlen + 8) & ~ 7;
	sb.append('\t');
	int perline = (80 - prefixlen) / 3;
	for (int i = 0; i < length; i++) {
		if (i != 0 && i % perline == 0) {
			sb.append('\n');
			for (int j = 0; j < prefixlen; j+=8)
				sb.append('\t');
		}
		int value = (int)(b[i + offset]) & 0xFF;
		if (value < 16)
			sb.append('0');
		sb.append(Integer.toHexString(value));
		sb.append(' ');
	}
	sb.append('\n');
	return sb.toString();
}
