1 /******************************************************************************* 2 3 copyright: Copyright (c) 2006 James Pelcis. All rights reserved 4 5 license: BSD style: $(LICENSE) 6 7 version: Initial release: August 2006 8 9 author: James Pelcis 10 11 *******************************************************************************/ 12 13 module tango.util.digest.Crc32; 14 15 public import tango.util.digest.Digest; 16 17 18 /** This class implements the CRC-32 checksum algorithm. 19 The digest returned is a little-endian 4 byte string. */ 20 final class Crc32 : Digest 21 { 22 private uint[256] table; 23 private uint result = 0xffffffff; 24 25 /** 26 * Create a cloned CRC32 27 */ 28 this (Crc32 crc32) 29 { 30 this.table[] = crc32.table[]; 31 this.result = crc32.result; 32 } 33 34 /** 35 * Prepare Crc32 to checksum the data with a given polynomial. 36 * 37 * Params: 38 * polynomial = The magic CRC number to base calculations on. The 39 * default compatible with ZIP, PNG, ethernet and others. Note: This 40 * default value has poor error correcting properties. 41 */ 42 this (uint polynomial = 0xEDB88320U) 43 { 44 for (int i = 0; i < 256; i++) 45 { 46 uint value = i; 47 for (int j = 8; j > 0; j--) 48 { 49 version (Gim) 50 { 51 if (value & 1) 52 { 53 value >>>= 1; 54 value ^= polynomial; 55 } 56 else 57 value >>>= 1; 58 } 59 else 60 { 61 if (value & 1) { 62 value &= 0xFFFFFFFE; 63 value /= 2; 64 value &= 0x7FFFFFFF; 65 value ^= polynomial; 66 } 67 else 68 { 69 value &= 0xFFFFFFFE; 70 value /= 2; 71 value &= 0x7FFFFFFF; 72 } 73 } 74 } 75 table[i] = value; 76 } 77 } 78 79 /** */ 80 override Crc32 update (const(void[]) input) 81 { 82 uint r = result; // DMD optimization 83 foreach (ubyte value; cast(const(ubyte[])) input) 84 { 85 auto i = cast(ubyte) r;// & 0xff; 86 i ^= value; 87 version (Gim) 88 { 89 r >>>= 8; 90 } 91 else 92 { 93 r &= 0xFFFFFF00; 94 r /= 0x100; 95 r &= 16777215; 96 } 97 r ^= table[i]; 98 } 99 result = r; 100 return this; 101 } 102 103 /** The Crc32 digestSize is 4 */ 104 override uint digestSize () 105 { 106 return 4; 107 } 108 109 /** */ 110 override ubyte[] binaryDigest(ubyte[] buf = null) { 111 if (buf.length < 4) 112 buf.length = 4; 113 uint v = ~result; 114 buf[3] = cast(ubyte) (v >> 24); 115 buf[2] = cast(ubyte) (v >> 16); 116 buf[1] = cast(ubyte) (v >> 8); 117 buf[0] = cast(ubyte) (v); 118 result = 0xffffffff; 119 return buf; 120 } 121 122 /** Returns the Crc32 digest as a uint */ 123 uint crc32Digest() { 124 uint ret = ~result; 125 result = 0xffffffff; 126 return ret; 127 } 128 } 129 130 debug(UnitTest) 131 { 132 unittest 133 { 134 scope c = new Crc32(); 135 static ubyte[] data = [1,2,3,4,5,6,7,8,9,10]; 136 c.update(data); 137 assert(c.binaryDigest() == cast(ubyte[]) "\x7b\x57\x20\x25".dup); 138 c.update(data); 139 assert(c.crc32Digest() == 0x2520577b); 140 c.update(data); 141 assert(c.hexDigest() == "7b572025".dup); 142 } 143 }