Untitled

 avatar
unknown
plain_text
7 days ago
3.0 kB
3
Indexable
public class CrcCalculator {

    private final AlgorithmParams parameters;
    private final byte hashSize;
    private long mask = 0xFFFFFFFFFFFFFFFFL;
    private final long[] table = new long[256];

    public CrcCalculator(CrcAlgorithm algorithm) {
        this(algorithm.getParams());
    }

    public CrcCalculator(AlgorithmParams parameters) {
        this.parameters = parameters;

        this.hashSize = (byte) parameters.getHashSize();
        if (this.hashSize < 64) {
            mask = (1L << this.hashSize) - 1;
        }
        createTable();
    }

    public long calc(byte[] data) {
        return calc(data, 0, data.length);
    }

    public long calc(byte[] data, int offset, int length) {
        long init = parameters.isRefOut() ?
                reverseBits(parameters.getInit(), hashSize) :
                parameters.getInit();
        long hash = computeCrc(init, data, offset, length);
        return (hash ^ parameters.getXorOut()) & mask;
    }

    private long computeCrc(long init, byte[] data, int offset, int length) {
        long crc = init;
        if (parameters.isRefOut()) {
            for (int i = offset; i < offset + length; i++) {
                crc = (table[(int) ((crc ^ data[i]) & 0xFF)] ^ (crc >>> 8));
                crc &= mask;
            }
        } else {
            int toRight = (hashSize - 8);
            toRight = Math.max(toRight, 0);
            for (int i = offset; i < offset + length; i++) {
                crc = (table[(int) (((crc >> toRight) ^ data[i]) & 0xFF)] ^ (crc << 8));
                crc &= mask;
            }
        }
        return crc;
    }

    private void createTable() {
        for (int i = 0; i < table.length; i++)
            table[i] = createTableEntry(i);
    }

    private long createTableEntry(int index) {
        long r = index;

        if (parameters.isRefIn())
            r = reverseBits(r, hashSize);
        else if (hashSize > 8)
            r <<= (hashSize - 8);

        long lastBit = (1L << (hashSize - 1));

        for (int i = 0; i < 8; i++) {
            if ((r & lastBit) != 0)
                r = ((r << 1) ^ parameters.getPoly());
            else
                r <<= 1;
        }

        if (parameters.isRefOut())
            r = reverseBits(r, hashSize);

        return r & mask;
    }

    private long reverseBits(long ul, int valueLength) {
        long newValue = 0;
        for (int i = valueLength - 1; i >= 0; i--) {
            newValue |= (ul & 1) << i;
            ul >>= 1;
        }
        return newValue;
    }

    public static byte[] hexStringToByteArray(String hex) {
        int length = hex.length();
        byte[] data = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
Leave a Comment