String.st
branchjv
changeset 18487 8735bd9eee2f
parent 18470 9e4db770f8f5
child 18488 cb7a21f38b77
--- a/String.st	Sat Jun 13 07:00:29 2015 +0200
+++ b/String.st	Wed Jun 17 06:22:00 2015 +0100
@@ -1822,20 +1822,39 @@
     long h = me.hash_fnv1a();
     return __c__._RETURN(STInteger._new(h));
 #else
-    extern unsigned int __symbolHash(char *);
-    unsigned char *cp;
-    unsigned int h;
+    /* Following code is inlined FNV1a hash. 
+     * Inlined for speed (to avoid send).
+     * DO NOT use __symbolHash() here as it 
+     * does not handle characters with codepoint 0
+     * properly - see
+     * https://swing.fit.cvut.cz/projects/stx-jv/ticket/65
+     */
+    REGISTER unsigned int h;
+    REGISTER unsigned char *cp;
+    int l;
 
     cp = __stringVal(self);
+    l = __stringSize(self);
     if (!__qIsStringLike(self)) {
 	int n = __OBJS2BYTES__(__intVal(__ClassInstPtr(__qClass(self))->c_ninstvars));
 
 	cp += n;
+    }    
+    h = 2166136261U;
+    while (l >= 4) {
+	l -= 4;
+	h = (h ^ cp[0]) * 16777619;
+	h = (h ^ cp[1]) * 16777619;
+	h = (h ^ cp[2]) * 16777619;
+	h = (h ^ cp[3]) * 16777619;
+	cp += 4;
     }
-    h = __symbolHash(cp);
-    // make sure, it fits into a smallInt
+    while (l--) {
+	h = (h ^ *cp++) * 16777619;
+    }
+    // make it a smallInteger
     h = (h ^ (h >> 30)) & 0x3FFFFFFF;
-    RETURN(__mkSmallInteger(h));
+    RETURN ( __mkSmallInteger(h));
 #endif /* not SCHTEAM */
 %}.
     ^ self primitiveFailed
@@ -1932,7 +1951,7 @@
 	l -= n;
     }
 
-    h = 2166136261;
+    h = 2166136261U;
     while (l >= 4) {
 	l -= 4;
 	h = (h ^ cp[0]) * 16777619;