001: package uk.org.ponder.hashutil;
002:
003: import uk.org.ponder.byteutil.ByteWrap;
004:
005: /** This class implements the CRC32 algorithm, used to compute integer hash values from
006: * a byte stream. Felix thinks it doesn't work correctly due to its use of non-logical
007: * right shifts in several of the eat methods.
008: */
009:
010: public class CRC32 implements Hasher {
011: public static final int P = 0xEDB88320; // number of considerable magicity!
012: public static final int init = 0xffffffff;
013: public static int[] bytetable;
014: static {
015: bytetable = new int[256];
016: for (int i = 0; i < 256; ++i) {
017: bytetable[i] = checkbyte(i);
018: }
019: }
020: int checksum;
021:
022: public CRC32() {
023: checksum = init;
024: }
025:
026: public void reset() {
027: checksum = init;
028: }
029:
030: public static int checkbyte(int v) {
031: for (int i = 8; i > 0; i--) {
032: v = (v & 1) != 0 ? (v >>> 1) ^ P : v >>> 1;
033: }
034: return v;
035: }
036:
037: public static int eatquick(char[] buffer, int start, int length) {
038: int lcheck = init;
039: for (int i = start; i < start + length; ++i) {
040: lcheck = (lcheck >> 8)
041: ^ bytetable[(lcheck ^ ((int) buffer[i] >> 8)) & 0xff];
042: lcheck = (lcheck >> 8)
043: ^ bytetable[(lcheck ^ (int) buffer[i]) & 0xff];
044: }
045: return lcheck;
046: }
047:
048: public static int eatquick(byte[] buffer, int start, int length) {
049: int lcheck = init;
050: for (int i = start; i < start + length; ++i) {
051: lcheck = (lcheck >> 8)
052: ^ bytetable[(lcheck ^ (int) buffer[i]) & 0xff];
053: }
054: return lcheck;
055: }
056:
057: public static int eatquick(String s) {
058: int lcheck = init;
059: for (int i = 0; i < s.length(); ++i) {
060: lcheck = (lcheck >> 8)
061: ^ checkbyte((lcheck ^ ((int) s.charAt(i) >> 8)) & 0xff);
062: lcheck = (lcheck >> 8)
063: ^ checkbyte((lcheck ^ (int) s.charAt(i)) & 0xff);
064: }
065: return lcheck;
066: }
067:
068: public int eat(char[] buffer, int start, int length) {
069: for (int i = start; i < start + length; ++i) {
070: checksum = (checksum >> 8)
071: ^ bytetable[(checksum ^ ((int) buffer[i] >> 8)) & 0xff];
072: checksum = (checksum >> 8)
073: ^ bytetable[(checksum ^ (int) buffer[i]) & 0xff];
074: }
075: return checksum;
076: }
077:
078: // nb - semantics of eat changed to match eatquick for thread-safety!
079: public int eat(ByteWrap b) {
080: int lcheck = init;
081: for (int i = 0; i < b.size(); ++i) {
082: lcheck = (lcheck >> 8)
083: ^ checkbyte((lcheck ^ b.read_at1(i)) & 0xff);
084: }
085: return lcheck;
086: }
087:
088: public int eat(String s) {
089: for (int i = 0; i < s.length(); ++i) {
090: checksum = (checksum >> 8)
091: ^ checkbyte((checksum ^ ((int) s.charAt(i) >> 8)) & 0xff);
092: checksum = (checksum >> 8)
093: ^ checkbyte((checksum ^ (int) s.charAt(i)) & 0xff);
094: }
095: return checksum;
096:
097: }
098:
099: public static void main(String[] args) {
100: ByteWrap temphash = new ByteWrap(4);
101: for (int i = 0; i < 10; ++i) {
102: temphash.write_at4(0, checkbyte(i));
103: System.out.println("Hash of byte " + i + " is " + temphash);
104: }
105: }
106: }
|