MD5Stream.st
changeset 7042 dbb7898901e3
parent 7041 1c0516e1f72d
child 7197 a68adb223592
--- a/MD5Stream.st	Wed Feb 19 14:01:49 2003 +0100
+++ b/MD5Stream.st	Wed Feb 19 18:10:44 2003 +0100
@@ -171,56 +171,6 @@
     Transcript show:(n*50/1024 / t); showCR:' Kb/s'
                                                                 [exEnd]
 "
-!
-
-testVectors
-"
-  Test Vectors:
-        'abc'
-
-          #[90 1 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72]
-
-        'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'
-          #[82 15 EF 7 96 A2 B CA AA E1 16 D3 87 6C 66 4A]
-
-        A million repetitions of 'a'
-          #[77 7 D6 AE 4E 2 7C 70 EE A2 A9 35 C2 29 6F 21]
-"
-    |hashStream result stream|
-
-    stream := WriteStream on:''.
-    hashStream := MD5Stream new.
-    hashStream nextPut:'abc'.
-    result := hashStream hashValue.
-    result printOn:stream base:16.
-    stream contents = '#[90 1 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72]' ifFalse:[
-        self error.
-    ].
-    stream reset.
-    hashStream := MD5Stream new.
-    hashStream nextPut:'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'.
-    result := hashStream hashValue.
-    result printOn:stream base:16.
-    stream contents = '#[82 15 EF 7 96 A2 B CA AA E1 16 D3 87 6C 66 4A]' ifFalse:[
-        self error.
-    ].
-    stream reset.
-    hashStream := MD5Stream new.
-    1000000 timesRepeat:[ hashStream nextPut:$a ].
-    result := hashStream hashValue.
-    result printOn:stream base:16.
-    stream contents = '#[77 7 D6 AE 4E 2 7C 70 EE A2 A9 35 C2 29 6F 21]' ifFalse:[
-        self error.
-    ].
-    stream reset.
-    result := MD5Stream hashValueOf:'abc'.
-    result printOn:stream base:16.
-    stream contents = '#[90 1 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72]' ifFalse:[
-        self error.
-    ].
-"
-self testVectors
-"
 ! !
 
 !MD5Stream class methodsFor:'initialization'!
@@ -260,6 +210,26 @@
     "Created: / 18.3.1999 / 08:02:16 / stefan"
 ! !
 
+!MD5Stream class methodsFor:'testing'!
+
+testVector
+
+    ^ #( 
+            ('abc'
+              #[16r90 16r01 16r50 16r98 16r3C 16rD2 16r4F 16rB0 16rD6 16r96 16r3F 16r7D 16r28 16rE1 16r7F 16r72])
+
+            ('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'
+             #[16r82 16r15 16rEF 16r07 16r96 16rA2 16r0B 16rCA 16rAA 16rE1 16r16 16rD3 16r87 16r6C 16r66 16r4A])
+        ) copyWith: 
+        (Array with:(String new:1000000 withAll:$a)
+               with:#[16r77 16r07 16rD6 16rAE 16r4E 16r02 16r7C 16r70 16rEE 16rA2 16rA9 16r35 16rC2 16r29 16r6F 16r21])
+
+
+    "
+      self test
+    "
+! !
+
 !MD5Stream methodsFor:'initialization'!
 
 initialize
@@ -331,8 +301,7 @@
 nextPut:anObject
   "update our hash value for anObject.
    anObject may be a String, a Character, a Smallinteger or an Array of primitive
-   types like ByteArray.
-  "
+   types like ByteArray"
 
   |ret|
 
@@ -341,71 +310,135 @@
        __qClass(__INST(hashContext)) == @global(ByteArray) &&
        __byteArraySize(__INST(hashContext)) == sizeof(MD5_CTX)
    ) {
-	MD5_CTX *ctx = 
-	    (MD5_CTX *)__ByteArrayInstPtr(__INST(hashContext))->ba_element;
+        MD5_CTX *ctx = 
+            (MD5_CTX *)__ByteArrayInstPtr(__INST(hashContext))->ba_element;
 
-	if (__isNonNilObject(anObject)) {
-	    OBJ cls =__qClass(anObject);
-	    INT mask = (INT)(__ClassInstPtr(cls)->c_flags) & __MASKSMALLINT(ARRAYMASK);
+        if (__isNonNilObject(anObject)) {
+            OBJ cls =__qClass(anObject);
+            INT mask = (INT)(__ClassInstPtr(cls)->c_flags) & __MASKSMALLINT(ARRAYMASK);
 
-	    if (cls == @global(String) || cls == @global(Symbol)) {
-		/* String: omit leading '\0' */
+            if (cls == @global(String) || cls == @global(Symbol)) {
+                /* String: omit leading '\0' */
 
-		MD5Update(ctx, __StringInstPtr(anObject)->s_element, __stringSize(anObject));
-	    } else if (mask != __MASKSMALLINT(POINTERARRAY) &&
-		mask != __MASKSMALLINT(WKPOINTERARRAY) &&
-		mask != __MASKSMALLINT(0)
-	    ) {
-		/* Byte|Integer|.... Array */
+                MD5Update(ctx, __StringInstPtr(anObject)->s_element, __stringSize(anObject));
+            } else if (mask != __MASKSMALLINT(POINTERARRAY) &&
+                mask != __MASKSMALLINT(WKPOINTERARRAY) &&
+                mask != __MASKSMALLINT(0)
+            ) {
+                /* Byte|Integer|.... Array */
 
-		register int n;
-		char *pFirst;
+                register int n;
+                char *pFirst;
 
-		n /* nInstVars */  = __intVal(__ClassInstPtr(cls)->c_ninstvars);
-		n /* nInstBytes */ = OHDR_SIZE + __OBJS2BYTES__(n /* nInstVars */);
-		pFirst = (char *)(__InstPtr(anObject)) + n /* nInstBytes */;
-		n /* nbytes */     = __qSize(anObject) - n /* nInstBytes */;
-		MD5Update(ctx, pFirst, n);
-	    } else if (cls == @global(Character)) {
-		/* Character */
+                n /* nInstVars */  = __intVal(__ClassInstPtr(cls)->c_ninstvars);
+                n /* nInstBytes */ = OHDR_SIZE + __OBJS2BYTES__(n /* nInstVars */);
+                pFirst = (char *)(__InstPtr(anObject)) + n /* nInstBytes */;
+                n /* nbytes */     = __qSize(anObject) - n /* nInstBytes */;
+                MD5Update(ctx, pFirst, n);
+            } else if (cls == @global(Character)) {
+                /* Character */
         
-		INT val = __intVal(_characterVal(anObject));
-		if (val > 255) {
-		    /* Two byte character */
-		    short s = val;
-		    MD5Update(ctx, &s, 2);
-		} else {
-		    char c = val;
-		    MD5Update(ctx, &c, 1);
-		}
-	    } else {
-		ret = false;
-	    }
-	} else {
-	    if (anObject == nil) {
-		ret = false;
-	    } else {
-		/* SmallInteger */
+                INT val = __intVal(_characterVal(anObject));
+                if (val > 255) {
+                    /* Two byte character */
+                    short s = val;
+                    MD5Update(ctx, &s, 2);
+                } else {
+                    char c = val;
+                    MD5Update(ctx, &c, 1);
+                }
+            } else {
+                ret = false;
+            }
+        } else {
+            if (anObject == nil) {
+                ret = false;
+            } else {
+                /* SmallInteger */
                 
-		INT i = __intVal(anObject);
-		MD5Update(ctx, &i, sizeof(INT));
-	    }
-	}
+                INT i = __intVal(anObject);
+                MD5Update(ctx, &i, sizeof(INT));
+            }
+        }
     }
 %}.
 
     ret notNil ifTrue:[
-	^ self primitiveFailed
+        ^ self primitiveFailed
     ].
                 
 
     "Created: 22.10.1996 / 21:53:24 / stefan"
+!
+
+nextPutBytes:count from:anObject startingAt:start
+    "update the hash value with count bytes from an object starting at index start.
+     The object must have non-pointer indexed instvars 
+     (i.e. be a ByteArray, String, Float- or DoubleArray),
+     or an externalBytes object (with known size)"
+
+%{
+    int len, offs;
+    int objSize, nInstVars, nInstBytes;
+    char *extPtr;
+    OBJ oClass;
+
+   if (__isNonNilObject(__INST(hashContext))
+       &&__qClass(__INST(hashContext)) == @global(ByteArray)
+       &&__byteArraySize(__INST(hashContext)) == sizeof(MD5_CTX)
+       && __bothSmallInteger(count, start)
+   ) {
+        MD5_CTX *ctx = 
+            (MD5_CTX *)__ByteArrayInstPtr(__INST(hashContext))->ba_element;
+
+        len = __intVal(count);
+        offs = __intVal(start) - 1;
+
+        oClass = __Class(anObject);
+        if (oClass == ExternalBytes) {
+            OBJ sz;
+
+            nInstBytes = 0;
+            extPtr = (char *)__externalBytesAddress(anObject);
+            sz = __externalBytesSize(anObject);
+            if (__isSmallInteger(sz)) {
+                objSize = __intVal(sz);
+            } else {
+                objSize = 0; /* unknown */
+            }
+        } else {
+            switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+                case BYTEARRAY:
+                case WORDARRAY:
+                case LONGARRAY:
+                case SWORDARRAY:
+                case SLONGARRAY:
+                case FLOATARRAY:
+                case DOUBLEARRAY:
+                    break;
+                default:
+                    goto bad;
+            }
+            nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+            nInstBytes = OHDR_SIZE + __OBJS2BYTES__(nInstVars);
+            objSize = __Size(anObject) - nInstBytes;
+            extPtr = (char *)__byteArrayVal(anObject);
+        }
+        if ((offs >= 0) && (len >= 0) && (objSize >= (len + offs))) {
+            MD5Update(ctx, extPtr+offs, len);
+            RETURN (count);
+        }
+    }
+bad: ;
+%}.
+
+    ^ self primitiveFailed
 ! !
 
 !MD5Stream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/MD5Stream.st,v 1.2 2003-02-19 13:01:49 penk Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/MD5Stream.st,v 1.3 2003-02-19 17:09:46 stefan Exp $'
 ! !
 
 MD5Stream initialize!