com.l2jfree.util.HexUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.l2jfree.util.HexUtil.java

Source

/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jfree.util;

import java.math.BigInteger;
import java.nio.ByteBuffer;

import org.apache.commons.lang3.ArrayUtils;

/**
 * This class provides functions to manipulate byte arrays in the programmer-friendly hexadecimal
 * octet format.
 */
public final class HexUtil {
    private HexUtil() {
        // utility class
    }

    /**
     * Randomly generates <TT>size</TT> bytes.
     * 
     * @param size bytes to generate
     * @return randomly generated byte array
     */
    public static byte[] generateHex(int size) {
        byte[] array = new byte[size];
        for (int i = 0; i < size; i++)
            array[i] = (byte) Rnd.nextInt(256);
        return array;
    }

    /**
     * Transforms a legacy HexID into a byte array.
     * 
     * @param string HexID
     * @return decoded byte array
     */
    public static byte[] stringToHex(String string) {
        return new BigInteger(string, 16).toByteArray();
    }

    /**
     * Converts a byte array to a legacy HexID.
     * 
     * @param hex a byte array
     * @return HexID
     */
    public static String hexToString(byte[] hex) {
        if (hex == null)
            return "null";

        return new BigInteger(hex).toString(16);
    }

    /**
     * Encodes a byte array to a string of hex octets.
     * 
     * @param hex a byte array
     * @return encoded string
     */
    public static String bytesToHexString(byte[] hex) {
        return bytesToHexString(hex, null);
    }

    /**
     * Encodes a byte array to a string of hex octets.
     * 
     * @param hex a byte array
     * @param delimiter byte delimiter
     * @return encoded string
     */
    public static String bytesToHexString(byte[] hex, CharSequence delimiter) {
        return bytesToHexString(hex, 0, delimiter);
    }

    public static String bytesToHexString(byte[] hex, int off, CharSequence delimiter) {
        if (ArrayUtils.isEmpty(hex) || off >= hex.length)
            return "";

        final StringBuilder bytes = new StringBuilder(fillHex(hex[off] & 0xFF, 2));
        for (int i = off + 1; i < hex.length; i++) {
            if (delimiter != null)
                bytes.append(delimiter);
            bytes.append(fillHex(hex[i] & 0xFF, 2));
        }
        return bytes.toString().toUpperCase();
    }

    /**
     * Decodes a string of hex octets to a byte array.
     * 
     * @param hex a byte array
     * @return decoded byte array
     */
    public static byte[] hexStringToBytes(String hex) {
        if (hex == null)
            return null;
        hex = hex.replace(" ", "");
        if (hex.length() % 2 == 1)
            return null;

        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            String byte_ = hex.substring(i * 2, (i + 1) * 2);
            bytes[i] = (byte) (Integer.parseInt(byte_, 16) & 0xFF);
        }
        return bytes;
    }

    @Deprecated
    public static byte[] HexStringToBytes(String hex) {
        return hexStringToBytes(hex);
    }

    public static String printData(ByteBuffer buf, int offset, int len) {
        byte[] tmp = new byte[len];
        int pos = buf.position();
        buf.position(offset);
        buf.get(tmp);
        buf.position(pos);
        return printData(tmp, len);
    }

    /**
     * This method is equivalent to <TT>printData(raw, raw.length)</TT>.
     * 
     * @param raw a byte array
     * @return converted byte array
     * @see #printData(byte[], int)
     */
    public static String printData(byte[] raw) {
        return printData(raw, raw.length);
    }

    /**
     * Converts a byte array to string in a special form. <BR>
     * <BR>
     * On the left side of the generated string, each byte is printed as a hex octet with a trailing
     * space.<BR>
     * On the right side of the generated string, each byte is printed as an ASCII char, unless it's
     * a non-printing character (the same is done to extended ASCII characters): then a period is
     * printed instead.
     * 
     * @param data a byte array
     * @param len number of bytes to print
     * @return converted byte array
     * @see #printData(byte[], int)
     */
    public static String printData(byte[] data, int len) {
        String eol = System.getProperty("line.separator", "\r\n");
        final StringBuilder result = new StringBuilder(eol);

        int counter = 0;

        for (int i = 0; i < len; i++) {
            if (counter % 16 == 0) {
                result.append(fillHex(i, 4));
                result.append(": ");
            }

            result.append(fillHex(data[i] & 0xff, 2));
            result.append(' ');
            counter++;
            if (counter == 16) {
                result.append("   ");

                int charpoint = i - 15;
                for (int a = 0; a < 16; a++) {
                    int t1 = data[charpoint++];
                    if (t1 > 0x1f && t1 < 0x80) {
                        result.append((char) t1);
                    } else {
                        result.append('.');
                    }
                }

                result.append(eol);
                counter = 0;
            }
        }

        int rest = data.length % 16;
        if (rest > 0) {
            for (int i = 0; i < 17 - rest; i++) {
                result.append("   ");
            }

            int charpoint = data.length - rest;
            for (int a = 0; a < rest; a++) {
                int t1 = data[charpoint++];
                if (t1 > 0x1f && t1 < 0x80) {
                    result.append((char) t1);
                } else {
                    result.append('.');
                }
            }

            result.append(eol);
        }

        return result.toString();
    }

    /**
     * Converts a number to hexadecimal format and adds leading zeros if necessary.
     * 
     * @param data a number
     * @param digits minimum hexadecimal digit count
     * @return given number in hexadecimal format
     */
    public static String fillHex(int data, int digits) {
        String hex = Integer.toHexString(data);

        StringBuilder number = new StringBuilder(Math.max(hex.length(), digits));
        for (int i = hex.length(); i < digits; i++)
            number.append(0);
        number.append(hex);

        return number.toString();
    }
}