From c0c6a6a55afddae84aa55b8903f0614a4ff8722d Mon Sep 17 00:00:00 2001 From: "John B. Matthews" Date: Tue, 17 Jun 2008 01:22:41 +0000 Subject: [PATCH] Add CRC16. --- src/com/webcodepro/shrinkit/CRC16.java | 91 +++++++++++++++++++ .../com/webcodepro/shrinkit/CRC16Test.java | 33 +++++++ 2 files changed, 124 insertions(+) create mode 100644 src/com/webcodepro/shrinkit/CRC16.java create mode 100644 test_src/com/webcodepro/shrinkit/CRC16Test.java diff --git a/src/com/webcodepro/shrinkit/CRC16.java b/src/com/webcodepro/shrinkit/CRC16.java new file mode 100644 index 0000000..8e7f09f --- /dev/null +++ b/src/com/webcodepro/shrinkit/CRC16.java @@ -0,0 +1,91 @@ +package com.webcodepro.shrinkit; + +import java.util.zip.Checksum; + +/** + * Crc16: Calculate 16-bit Cyclic Redundancy Check. + * License: GPL, incorporated by reference. + * + * @author John B. Matthews + */ +public class CRC16 implements Checksum { + + /** CCITT polynomial: x^16 + x^12 + x^5 + 1 -> 0x1021 (1000000100001) */ + private static final int poly = 0x1021; + private static final int[] table = new int[256]; + private int value = 0; + + static { // initialize static lookup table + for (int i = 0; i < 256; i++) { + int crc = i << 8; + for (int j = 0; j < 8; j++) { + if ((crc & 0x8000) == 0x8000) { + crc = (crc << 1) ^ poly; + } else { + crc = (crc << 1); + } + } + table[i] = crc & 0xffff; + } + } + + /** + * Update 16-bit CRC. + * + * @param crc starting CRC value + * @param bytes input byte array + * @param off start offset to data + * @param len number of bytes to process + * @return 16-bit unsigned CRC + */ + private int update(int crc, byte[] bytes, int off, int len) { + for (int i = off; i < (off + len); i++) { + byte b = bytes[i]; + crc = (table[((crc >> 8) & 0xff) ^ b] ^ (crc << 8)) & 0xffff; + } + return crc; + } + + public static int[] getTable() { + return table; + } + + public long getValue() { + return value; + } + + public void reset() { + value = 0; + } + + /** + * Update 16-bit CRC. + * + * @param b input byte + */ + public void update(int b) { + byte[] ba = { (byte) b }; + value = update(value, ba, 0, 1); + } + + /** + * Update 16-bit CRC. + * + * @param b input byte array + */ + public void update(byte[] b) { + value = update(value, b, 0, b.length); + } + + /** + * Update 16-bit CRC. + * + * @param b input byte array + * @param off starting offset to data + * @param len number of bytes to process + */ + public void update(byte[] b, int off, int len) { + value = update(value, b, off, len); + } + +} \ No newline at end of file diff --git a/test_src/com/webcodepro/shrinkit/CRC16Test.java b/test_src/com/webcodepro/shrinkit/CRC16Test.java new file mode 100644 index 0000000..3b99010 --- /dev/null +++ b/test_src/com/webcodepro/shrinkit/CRC16Test.java @@ -0,0 +1,33 @@ +package com.webcodepro.shrinkit; + +import java.io.UnsupportedEncodingException; + +import junit.framework.TestCase; + +public class CRC16Test extends TestCase { + + public void testTable() { + int[] table = CRC16.getTable(); + assertEquals(0, table[0]); + assertEquals(0x1ef0, table[0xff]); + System.out.println("CRC16 lookup table:"); + for (int i = 0; i < 256; i++) { + System.out.print(Integer.toHexString(table[i]) + " "); + if ((i + 1) % 8 == 0) System.out.println(); + } + } + + public void testUpdate() throws UnsupportedEncodingException { + CRC16 crc16 = new CRC16(); + crc16.update("123456789".getBytes("UTF-8")); + assertEquals(0x31c3, crc16.getValue()); + crc16.update("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes("UTF-8")); + assertEquals(0x92cc, crc16.getValue()); + crc16.update("abcdefghijklmnopqrstuvwxyz".getBytes("UTF-8")); + assertEquals(0xfc85, crc16.getValue()); + crc16.reset(); + crc16.update("xxx123456789xxx".getBytes("UTF-8"), 3, 9); + assertEquals(0x31c3, crc16.getValue()); + } + +} \ No newline at end of file