class Hex {

    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();
    }

    private  Hex();

}