All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ardikars.common.util.Hexs Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2017-2019 the original author or authors.
 *
 * 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.ardikars.common.util;

import com.ardikars.common.annotation.Helper;

import java.nio.ByteBuffer;
import java.util.regex.Pattern;

/**
 * Hexs utility.
 *
 * @author Ardika Rommy Sanjaya
 * @since 1.0.0
 */
@Helper
public final class Hexs {

    private static final Pattern NO_SEPARATOR_HEX_STRING_PATTERN
            = Pattern.compile("\\A([0-9a-fA-F][0-9a-fA-F])+\\z");

    private static final String HEXDUMP_PRETTY_HEADER = ""
            + "         +-------------------------------------------------+\n"
            + "         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |\n"
            + "+--------+-------------------------------------------------+--------+\n";

    private static final String HEXDUMP_PRETTY_FOOTER = ""
            + "+--------+---------------------------------"
            + "----------------+--------+";

    private static final char[] HEXDUMP_TABLE;


    /**
     * {@link ByteBuffer} to hex string.
     * @param buffer buffer.
     * @return returns hex string.
     */
    public static String toHexString(final ByteBuffer buffer) {
        return toHexString(buffer, 0, buffer.capacity());
    }

    /**
     * {@link ByteBuffer} to hex string.
     * @param buffer buffer.
     * @param offset offset.
     * @param length length.
     * @return returns hex string.
     */
    public static String toHexString(final ByteBuffer buffer, final int offset, final int length) {
        if (length == 0) {
            return "";
        }
        int endIndex = offset + length;
        char[] buf = new char[length << 1];

        int srcIdx = offset;
        int dstIdx = 0;
        for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) {
            System.arraycopy(
                    HEXDUMP_TABLE, (buffer.get(srcIdx) & 0xFF) << 1,
                    buf, dstIdx, 2);
        }
        return new String(buf);
    }

    /**
     * {@link ByteBuffer} to hex string.
     * @param buffer buffer.
     * @return returns hex string.
     */
    public static String toHexString(final byte[] buffer) {
        return toHexString(buffer, 0, buffer.length);
    }

    /**
     * {@link ByteBuffer} to hex string.
     * @param buffer buffer.
     * @param offset offset.
     * @param length length.
     * @return returns hex string.
     */
    public static String toHexString(final byte[] buffer, final int offset, final int length) {
        if (length == 0) {
            return "";
        }
        int endIndex = offset + length;
        char[] buf = new char[length << 1];

        int srcIdx = offset;
        int dstIdx = 0;
        for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) {
            System.arraycopy(
                    HEXDUMP_TABLE, (buffer[srcIdx] & 0xFF) << 1,
                    buf, dstIdx, 2);
        }
        return new String(buf);
    }

    /**
     * Byte array to hex dump format.
     * @param data byte array.
     * @return hex dump format.
     * @since 1.0.0
     */
    public static String toPrettyHexDump(final byte[] data) {
        return toPrettyHexDump(data, 0, data.length);
    }

    /**
     * Byte array to hex dump format.
     * @param data byte array.
     * @param offset offset.
     * @param length length.
     * @return hex dump format.
     * @since 1.0.0
     */
    public static String toPrettyHexDump(final byte[] data, final int offset, final int length) {
        Validate.notInBounds(data, offset, length);
        StringBuilder result = new StringBuilder();
        StringBuilder builder = new StringBuilder();
        int pos = offset;
        int max = length;
        int lineNumber = 0;
        builder.append(HEXDUMP_PRETTY_HEADER);
        while (pos < max) {
            builder.append(String.format("%08d", lineNumber++) + " | ");
            int lineMax = Math.min(max - pos, 16);
            for (int i = 0; i < lineMax; i++) {
                int index = (data[pos + i] & 0xFF) << 1;
                builder.append(new String(new char[] {HEXDUMP_TABLE[index], HEXDUMP_TABLE[++index]}));
                builder.append(" ");
            }
            while (builder.length() < 48) {
                builder.append(" ");
            }
            builder.append("| ");
            for (int i = 0; i < lineMax; i++) {
                char c = (char) data[pos + i];
                if (c < 32 || c > 127) {
                    c = '.';
                }
                builder.append(c);
            }
            builder.append("\n");
            result.append(builder);
            builder.setLength(0);
            pos += 16;
        }
        result.append(HEXDUMP_PRETTY_FOOTER);
        return result.toString();
    }

    /**
     * Byte buffer to hex dump format.
     * @param buffer byte buffer.
     * @param offset offset.
     * @param length length.
     * @return hex dump format.
     * @since 1.1.0
     */
    public static String toPrettyHexDump(ByteBuffer buffer, int offset, int length) {
        Validate.notInBounds(buffer.capacity(), offset, length);
        StringBuilder result = new StringBuilder();
        StringBuilder builder = new StringBuilder();
        int pos = offset;
        int max = length;
        int lineNumber = 0;
        builder.append(HEXDUMP_PRETTY_HEADER);
        while (pos < max) {
            builder.append(String.format("%08d", lineNumber++) + " | ");
            int lineMax = Math.min(max - pos, 16);
            for (int i = 0; i < lineMax; i++) {
                int index = (buffer.get(pos + i) & 0xFF) << 1;
                builder.append(new String(new char[] {HEXDUMP_TABLE[index], HEXDUMP_TABLE[++index]}));
                builder.append(" ");
            }
            while (builder.length() < 48) {
                builder.append(" ");
            }
            builder.append("| ");
            for (int i = 0; i < lineMax; i++) {
                char c = buffer.getChar(pos + i);
                if (c < 32 || c > 127) {
                    c = '.';
                }
                builder.append(c);
            }
            builder.append("\n");
            result.append(builder);
            builder.setLength(0);
            pos += 16;
        }
        result.append(HEXDUMP_PRETTY_FOOTER);
        return result.toString();
    }

    /**
     * Hex stream to byte array.
     * @param hexStream hex stream.
     * @return byte array.
     * @since 1.0.0
     */
    public static byte[] parseHex(String hexStream) {
        Validate.nullPointer(hexStream);
        if (hexStream.startsWith("0x")) {
            hexStream = hexStream.substring(2);
        }
        hexStream = hexStream.replaceAll("\\s+", "").trim();
        if (!NO_SEPARATOR_HEX_STRING_PATTERN.matcher(hexStream).matches()) {
            throw new IllegalArgumentException();
        }
        int len = hexStream.length();
        byte[] data = new byte[len >> 1];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexStream.charAt(i), 16) << 4)
                    + Character.digit(hexStream.charAt(i + 1), 16));
        }
        return data;
    }

    static {
        HEXDUMP_TABLE = new char[256 * 4];
        final char[] digits = "0123456789abcdef".toCharArray();
        for (int i = 0; i < 256; i++) {
            HEXDUMP_TABLE[ i << 1     ] = digits[i >>> 4 & 0x0F];
            HEXDUMP_TABLE[(i << 1) + 1] = digits[i       & 0x0F];
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy