CRC32Stream.st
changeset 2570 55ce3e8bd7dc
parent 2569 abfbf6f1682b
child 2571 12d5e280eea1
--- a/CRC32Stream.st	Fri May 13 12:42:54 2011 +0200
+++ b/CRC32Stream.st	Fri May 13 17:21:46 2011 +0200
@@ -12,8 +12,8 @@
 "{ Package: 'stx:libbasic2' }"
 
 HashStream subclass:#CRC32Stream
-	instanceVariableNames:'crc'
-	classVariableNames:'CrcTable'
+	instanceVariableNames:'crc generatorPolynom crcTable'
+	classVariableNames:'CrcTables'
 	poolDictionaries:''
 	category:'System-Crypt-Hashing'
 !
@@ -37,11 +37,18 @@
 documentation
 "
     Standard CRC method as defined by ISO 3309 [ISO-3309] or ITU-T V.42 [ITU-T-V42]. 
-    The CRC polynomial employed is
+    The default CRC polynomial employed is
 
         x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
         (or 16r04C11DB7)
 
+    You can also create an instace perforing the Castagnioli CRC-32C 
+    (used in iSCSI & SCTP, G.hn payload, SSE4.2):
+
+        self newCrc32c
+
+        x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1 
+
     Use CRC to protect against communication errors;
     do NOT use CRC for cryptography - use SHA1Stream or MD5Stream instead.
 
@@ -126,25 +133,56 @@
 
 !CRC32Stream class methodsFor:'initialization'!
 
-initialize
+crcTableFor:generatorPolynomInteger
+    |crcTable|
 
-    CrcTable := IntegerArray new:256.
+    crcTable := (CrcTables at:generatorPolynomInteger ifAbsent:nil). 
+    crcTable isNil ifTrue:[
+        crcTable := IntegerArray new:256.
 
-    0 to:255 do:[:count| |i|
-        i := count.
-        8 timesRepeat:[
-            (i bitTest:1) ifTrue:[
-"/                i := 16r1EDC6F41 bitXor:(i bitShift:-1)
-                i := 16rEDB88320 bitXor:(i bitShift:-1)
-            ] ifFalse:[
-                i := i bitShift:-1
-            ]
+        0 to:255 do:[:count| |i|
+            i := count.
+            8 timesRepeat:[
+                (i bitTest:1) ifTrue:[
+                    i := generatorPolynomInteger bitXor:(i bitShift:-1)
+                ] ifFalse:[
+                    i := i bitShift:-1
+                ]
+            ].
+            crcTable at:count+1 put:i.
         ].
-        CrcTable at:count+1 put:i.
+        CrcTables at:generatorPolynomInteger put:crcTable.
     ].
+    ^ crcTable.
+!
+
+initialize
+    CrcTables := Dictionary new.
+! !
+
+!CRC32Stream class methodsFor:'instance creation'!
+
+generatorPolynom:anInteger
+    ^ self basicNew generatorPolynom:anInteger
 
     "
-      self initialize
+       self assert:((self generatorPolynom:16r82F63B78)
+                                nextPut:'123456789';
+                                hashValue)    = 16rE3069283
+    "
+!
+
+newCrc32C
+    "return an instance of the Castagnoli CRC-32
+        x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1 
+     (used in iSCSI & SCTP, G.hn payload, SSE4.2)"
+
+    ^ self basicNew generatorPolynom:16r82F63B78
+
+    "
+       self assert:((self newCrc32C)
+                                nextPut:'123456789';
+                                hashValue)    = 16rE3069283
     "
 ! !
 
@@ -180,12 +218,27 @@
     "
 ! !
 
+!CRC32Stream methodsFor:'accessing'!
+
+generatorPolynom
+    "answer the generator polynom"
+
+    ^ generatorPolynom
+!
+
+generatorPolynom:anInteger
+    generatorPolynom := anInteger.
+    crc := 16rFFFFFFFF.
+    crcTable := self class crcTableFor:generatorPolynom.
+! !
+
 !CRC32Stream methodsFor:'initialization'!
 
 initialize
-    "initialize the CRC"
+    "initialize the CRC to CRC-32 ITU-T:
+        x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1"
 
-    crc := 16rFFFFFFFF.
+    self generatorPolynom:16rEDB88320
 ! !
 
 !CRC32Stream methodsFor:'queries'!
@@ -232,7 +285,7 @@
                 _crc = __unsignedLongIntVal( __INST(crc) );
             }
 
-            _crcTable = __integerArrayVal( @global(CrcTable) );
+            _crcTable = __integerArrayVal( __INST(crcTable) );
 
             while (n > 3) {
                 unsigned _idx;
@@ -277,7 +330,7 @@
         argSize := arg size.
         1 to:argSize do:[:n|
             byte := arg byteAt:n.
-            crc := (CrcTable at:((crc bitXor:byte) bitAnd:16rFF)+1) 
+            crc := (crcTable at:((crc bitXor:byte) bitAnd:16rFF)+1) 
                    bitXor:(crc bitShift:-8).
         ].
         ^ self.
@@ -286,12 +339,12 @@
     arg isCharacter ifTrue:[
         byte := arg codePoint.
         byte < 256 ifTrue:[
-            crc := (CrcTable at:((crc bitXor:byte) bitAnd:16rFF)+1) 
+            crc := (crcTable at:((crc bitXor:byte) bitAnd:16rFF)+1) 
                    bitXor:(crc bitShift:-8).
             ^ self.
         ].
         byte digitBytes do:[:eachByte|
-            crc := (CrcTable at:((crc bitXor:eachByte) bitAnd:16rFF)+1) 
+            crc := (crcTable at:((crc bitXor:eachByte) bitAnd:16rFF)+1) 
                    bitXor:(crc bitShift:-8).
         ].
         ^ self.
@@ -299,12 +352,12 @@
 
     arg isInteger ifTrue:[
         arg < 256 ifTrue:[
-            crc := (CrcTable at:((crc bitXor:arg) bitAnd:16rFF)+1) 
+            crc := (crcTable at:((crc bitXor:arg) bitAnd:16rFF)+1) 
                    bitXor:(crc bitShift:-8).
             ^ self.
         ].
         arg digitBytes do:[:eachByte|
-            crc := (CrcTable at:((crc bitXor:eachByte) bitAnd:16rFF)+1) 
+            crc := (crcTable at:((crc bitXor:eachByte) bitAnd:16rFF)+1) 
                    bitXor:(crc bitShift:-8).
         ].
         ^ self.
@@ -323,11 +376,11 @@
 !CRC32Stream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic2/CRC32Stream.st,v 1.14 2011-05-13 10:42:54 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/CRC32Stream.st,v 1.15 2011-05-13 15:21:46 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic2/CRC32Stream.st,v 1.14 2011-05-13 10:42:54 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/CRC32Stream.st,v 1.15 2011-05-13 15:21:46 stefan Exp $'
 ! !
 
 CRC32Stream initialize!