cn.meteor.module.util.check.CRCUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of meteor-util Show documentation
Show all versions of meteor-util Show documentation
A Java Framework for JavaEE application reference architecture.
The newest version!
package cn.meteor.module.util.check;
// Package crc implements generic CRC calculations up to 64 bits wide.
// It aims to be fairly complete, allowing users to match pretty much
// any CRC algorithm used in the wild by choosing appropriate Parameters.
// And it's also fairly fast for everyday use.
//
// This package has been largely inspired by Ross Williams' 1993 paper "A Painless Guide to CRC Error Detection Algorithms".
// A good list of parameter sets for various CRC algorithms can be found at http://reveng.sourceforge.net/crc-catalogue/.
/**
* This class provides utility functions for CRC calculation using either canonical straight forward approach
* or using "fast" table-driven implementation. Note, that even though table-driven implementation is much faster
* for processing large amounts of data and is commonly referred as fast algorithm, sometimes it might be quicker to
* calculate CRC using canonical algorithm then to prepare the table for table-driven implementation.
* */
public class CRCUtils
{
/**
* Parameters represents set of parameters defining a particular CRC algorithm.
* */
public static class Parameters
{
private int width; // Width of the CRC expressed in bits
private long polynomial; // Polynomial used in this CRC calculation
private boolean reflectIn; // Refin indicates whether input bytes should be reflected
private boolean reflectOut; // Refout indicates whether input bytes should be reflected
private long init; // Init is initial value for CRC calculation
private long finalXor; // Xor is a value for final xor to be applied before returning result
public Parameters(int width, long polynomial, long init, boolean reflectIn, boolean reflectOut, long finalXor)
{
this.width = width;
this.polynomial = polynomial;
this.reflectIn = reflectIn;
this.reflectOut = reflectOut;
this.init = init;
this.finalXor = finalXor;
}
public Parameters(Parameters orig)
{
width = orig.width;
polynomial = orig.polynomial;
reflectIn = orig.reflectIn;
reflectOut = orig.reflectOut;
init = orig.init;
finalXor = orig.finalXor;
}
public int getWidth()
{
return width;
}
public long getPolynomial()
{
return polynomial;
}
public boolean isReflectIn()
{
return reflectIn;
}
public boolean isReflectOut()
{
return reflectOut;
}
public long getInit()
{
return init;
}
public long getFinalXor()
{
return finalXor;
}
/** CCITT CRC parameters */
public static final Parameters CCITT = new Parameters(16, 0x1021, 0x00FFFF, false, false, 0x0);
/** CRC16 CRC parameters, also known as ARC */
/** CRC16-IBM 宽度:16 多项式(Hex):8005 初始值(Hex):0000 结果异或值(Hex):0000 */
public static final Parameters CRC16_IBM = new Parameters(16, 0x8005, 0x0000, true, true, 0x0);
/** CRC16-MAXIM 宽度:16 多项式(Hex):8005 初始值(Hex):0000 结果异或值(Hex):FFFF */
public static final Parameters CRC16_MAXIM = new Parameters(16, 0x8005, 0x0000, true, true, 0xFFFF);
/** CRC16-USB 宽度:16 多项式(Hex):8005 初始值(Hex):FFFF 结果异或值(Hex):FFFF */
public static final Parameters CRC16_USB = new Parameters(16, 0x8005, 0xFFFF, true, true, 0xFFFF);
/** CRC16-MODBUS 宽度:16 多项式(Hex):8005 初始值(Hex):FFFF 结果异或值(Hex):0000 */
public static final Parameters CRC16_MODBUS = new Parameters(16, 0x8005, 0xFFFF, true, true, 0x0);
/** XMODEM is a set of CRC parameters commonly referred as "XMODEM" */
public static final Parameters XMODEM = new Parameters(16, 0x1021, 0x0000, false, false, 0x0);
/** XMODEM2 is another set of CRC parameters commonly referred as "XMODEM" */
public static final Parameters XMODEM2 = new Parameters(16, 0x8408, 0x0000, true, true, 0x0);
/** CRC32 is by far the the most commonly used CRC-32 polynom and set of parameters */
public static final Parameters CRC32 = new Parameters(32, 0x04C11DB7, 0x00FFFFFFFFL, true, true, 0x00FFFFFFFFL);
/** IEEE is an alias to CRC32 */
public static final Parameters IEEE = CRC32;
/** Castagnoli polynomial. used in iSCSI. And also provided by hash/crc32 package. */
public static final Parameters Castagnoli = new Parameters(32, 0x1EDC6F41L, 0x00FFFFFFFFL, true, true, 0x00FFFFFFFFL);
/** CRC32C is an alias to Castagnoli */
public static final Parameters CRC32C = Castagnoli;
/** Koopman polynomial */
public static final Parameters Koopman = new Parameters(32, 0x741B8CD7L, 0x00FFFFFFFFL, true, true, 0x00FFFFFFFFL);
/** CRC64ISO is set of parameters commonly known as CRC64-ISO */
public static final Parameters CRC64ISO = new Parameters(64, 0x000000000000001BL, 0xFFFFFFFFFFFFFFFFL, true, true, 0xFFFFFFFFFFFFFFFFL);
/** CRC64ECMA is set of parameters commonly known as CRC64-ECMA */
public static final Parameters CRC64ECMA = new Parameters(64, 0x42F0E1EBA9EA3693L, 0xFFFFFFFFFFFFFFFFL, true, true, 0xFFFFFFFFFFFFFFFFL);
}
/**
* Reverses order of last count bits.
* @param in value wich bits need to be reversed
* @param count indicates how many bits be rearranged
* @return the value with specified bits order reversed
*/
private static long reflect(long in, int count)
{
long ret = in;
for (int idx = 0; idx < count; idx++)
{
long srcbit = 1L << idx;
long dstbit = 1L << (count - idx - 1);
if ((in & srcbit) != 0)
{
ret |= dstbit;
}
else
{
ret = ret & (~dstbit);
}
}
return ret;
}
/**
* This method implements simple straight forward bit by bit calculation.
* It is relatively slow for large amounts of data, but does not require
* any preparation steps. As a result, it might be faster in some cases
* then building a table required for faster calculation.
* @param crcParams CRC algorithm parameters
* @param data data for the CRC calculation
* @return the CRC value of the data provided
*/
public static long calculateCRC(Parameters crcParams, byte[] data)
{
long curValue =crcParams.init;
long topBit = 1L << (crcParams.width - 1);
long mask = (topBit << 1) - 1;
for (int i=0; i< data.length; i++)
{
long curByte = ((long)(data[i])) & 0x00FFL;
if (crcParams.reflectIn)
{
curByte = reflect(curByte, 8);
}
curValue ^= (curByte << (crcParams.width - 8));
for (int j=0; j< 8; j++)
{
if ((curValue & topBit)!=0)
{
curValue = (curValue << 1) ^ crcParams.polynomial;
}
else
{
curValue = (curValue << 1);
}
}
}
if (crcParams.reflectOut)
{
curValue = reflect(curValue, crcParams.width);
}
curValue = curValue ^ crcParams.finalXor;
return curValue & mask;
}
private Parameters crcParams;
private long initValue;
private long[] crctable;
private long mask;
/**
* Returns initial value for this CRC intermediate value
* This method is used when starting a new iterative CRC calculation (using init, update
* and finalCRC methods, possibly supplying data in chunks).
* @return initial value for this CRC intermediate value
*/
public long init()
{
return initValue;
}
/**
* This method is used to feed data when performing iterative CRC calculation (using init, update
* and finalCRC methods, possibly supplying data in chunks). It can be called multiple times per
* CRC calculation to feed data to be processed in chunks.
* @param curValue CRC intermediate value so far
* @param chunk data chunk to b processed by this call
* @param offset is 0-based offset of the data to be processed in the array supplied
* @param length indicates number of bytes to be processed.
* @return updated intermediate value for this CRC
* */
public long update (long curValue, byte[] chunk, int offset, int length)
{
if (crcParams.reflectIn)
{
for (int i=0; i < length; i++)
{
byte v = chunk[offset+i];
curValue = crctable[(((byte)curValue) ^ v)&0x00FF]^(curValue >>> 8);
}
}
else
{
for (int i=0; i < length; i++)
{
byte v = chunk[offset+i];
curValue = crctable[((((byte)(curValue >>> (crcParams.width - 8))) ^ v)&0xFF)]^(curValue << 8);
}
}
return curValue;
}
/**
* A convenience method for feeding a complete byte array of data.
* @param curValue CRC intermediate value so far
* @param chunk data chunk to b processed by this call
* @return updated intermediate value for this CRC
* */
public long update (long curValue, byte[] chunk)
{
return update(curValue, chunk, 0, chunk.length);
}
/**
* This method should be called to retrieve actual CRC for the data processed so far.
* @param curValue CRC intermediate value so far
* @return calculated CRC
* */
public long finalCRC(long curValue)
{
long ret=curValue;
if (crcParams.reflectOut != crcParams.reflectIn)
{
ret = reflect(ret, crcParams.width);
}
return (ret ^ crcParams.finalXor) & mask;
}
/**
* A convenience method allowing to calculate CRC in one call.
* @param data is data to calculate CRC on
* @return calculated CRC
* */
public long calculateCRC(byte[] data)
{
long crc = init();
crc = update(crc, data);
return finalCRC(crc);
}
/**
* Constructs a new CRC processor for table based CRC calculations.
* Underneath, it just calls finalCRC() method.
* @param crcParams CRC algorithm parameters
*/
public CRCUtils(Parameters crcParams)
{
this.crcParams = new Parameters(crcParams); // TODO: implement copy constructor;
initValue = (crcParams.reflectIn) ? reflect(crcParams.init, crcParams.width) : crcParams.init;
this.mask = ((crcParams.width>=64) ? 0 : (1L << crcParams.width)) - 1;
this.crctable = new long[256];
byte[] tmp = new byte[1];
Parameters tableParams = new Parameters(crcParams);
tableParams.init = 0;
tableParams.reflectOut = tableParams.reflectIn;
tableParams.finalXor = 0;
for (int i=0; i< 256; i++)
{
tmp[0] = (byte)i;
crctable[i] = CRCUtils.calculateCRC(tableParams, tmp);
}
}
/**
* Is a convenience method to spare end users from explicit type conversion every time this package is used.
* Underneath, it just calls finalCRC() method.
* @param curValue current intermediate crc state value
* @return the final CRC value
* @throws RuntimeException if crc being calculated is not 8-bit
*/
public byte finalCRC8 (long curValue)
{
if (crcParams.width != 8)
throw new RuntimeException("CRC width mismatch");
return (byte) finalCRC(curValue);
}
/**
* Is a convenience method to spare end users from explicit type conversion every time this package is used.
* Underneath, it just calls finalCRC() method.
* @param curValue current intermediate crc state value
* @return the final CRC value
* @throws RuntimeException if crc being calculated is not 16-bit
*/
public short finalCRC16 (long curValue)
{
if (crcParams.width != 16)
throw new RuntimeException("CRC width mismatch");
return (short) finalCRC(curValue);
}
/**
* Is a convenience method to spare end users from explicit type conversion every time this package is used.
* Underneath, it just calls finalCRC() method.
* @param curValue current intermediate crc state value
* @return the final CRC value
* @throws RuntimeException if crc being calculated is not 32-bit
*/
public int finalCRC32(long curValue)
{
if (crcParams.width != 32)
throw new RuntimeException("CRC width mismatch");
return (int) finalCRC(curValue);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy