#include "EXTERN.h" #include "perl.h" #include "XSUB.h" /* http://cpansearch.perl.org/src/SHLOMIF/Digest-JHash-0.10/JHash.xs */ /* overly documented version of fix, unsigned char* p ; */ /* Jenkins Hash http://burtleburtle.net/bob/hash/doobs.html */ typedef unsigned long int U32tf; /* unsigned 4-byte quantities */ void c_out0 ( char* str, U32tf a, U32tf b, U32tf c ) { printf( "%-20s%16u %016x - %16u %016x - %16u %016x \n", str,a,a,b,b,c,c ); } const int DEBUGODV = 1; /* Need to constrain U32 to only 32 bits on 64 bit systems * For efficiency we only use the & 0xffffffff if required */ #if BYTEORDER > 0x4321 || defined(TRUNCATE_U32) #define MIXODV(a,b,c) \ { \ c_out0(" cm064 : ABC : ",a,b,c); \ a &= 0xffffffff; b &= 0xffffffff; c &= 0xffffffff; \ c_out0(" cm &ff : ABC : ",a,b,c); \ a -= b;\ c_out0(" cm a1-b : ABC : ",a,b,c); \ a -= c; \ c_out0(" cm a1-c : ABC : ",a,b,c); \ a ^= (c>>13);\ c_out0(" cm c1-x c>13 : ABC : ",a,b,c); \ a &= 0xffffffff; \ c_out0(" cm a1 : ABC : ",a,b,c); \ \ \ b -= c; b -= a; b ^= (a<<8); b &= 0xffffffff; \ c_out0(" cm b1 : ABC : ",a,b,c); \ \ c -= a; \ c_out0(" cm c1-a : ABC : ",a,b,c); \ c -= b; \ c_out0(" cm c1-b : ABC : ",a,b,c); \ c ^= (b>>13);\ c_out0(" cm c1-x b>13 : ABC : ",a,b,c); \ c &= 0xffffffff; \ c_out0(" cm c1 : ABC : ",a,b,c); \ \ \ \ a -= b; a -= c; a ^= (c>>12); a &= 0xffffffff; \ c_out0(" cm a2 : ABC : ",a,b,c); \ b -= c; b -= a; b ^= (a<<16); b &= 0xffffffff; \ c_out0(" cm b2 : ABC : ",a,b,c); \ c -= a; c -= b; c ^= (b>>5); c &= 0xffffffff; \ c_out0(" cm c2 : ABC : ",a,b,c); \ a -= b; a -= c; a ^= (c>>3); a &= 0xffffffff; \ c_out0(" cm a3 : ABC : ",a,b,c); \ b -= c; b -= a; b ^= (a<<10); b &= 0xffffffff; \ c_out0(" cm b3 : ABC : ",a,b,c); \ c -= a; c -= b; c ^= (b>>15); c &= 0xffffffff; \ c_out0(" cm c3 : ABC : ",a,b,c); \ } #else #define MIXODV(a,b,c) \ { \ c_out0(" cm032 : ABC : ",a,b,c); \ a -= b; a -= c; a ^= (c>>13); \ b -= c; b -= a; b ^= (a<<8); \ c -= a; c -= b; c ^= (b>>13); \ a -= b; a -= c; a ^= (c>>12); \ b -= c; b -= a; b ^= (a<<16); \ c -= a; c -= b; c ^= (b>>5); \ a -= b; a -= c; a ^= (c>>3); \ b -= c; b -= a; b ^= (a<<10); \ c -= a; c -= b; c ^= (b>>15); \ } #endif U32 jhashu( SV* str ) { STRLEN rawlen; unsigned char* p; U32tf a, b, c, len, length; U32tf x, y, z; /* extract the string data and string length from the perl scalar */ p = (char*)SvPV(str, rawlen); length = len = (U32tf)rawlen; /* Test for undef or null string case and return 0 */ if ( length == 0 ) { DEBUGODV && printf( "Recieved a null or undef string!\n" ); return 0; } DEBUGODV && printf( "Received string %6i '%.*s'.\n", (int)len,(int)len, p ); a = b = 0x9e3779b9; /* golden ratio suggested by Jenkins */ c = 0; c_out0(" centry : ABC : ",a,b,c); while (len >= 12) { a += (p[0] + (((U32tf)p[1])<<8) + (((U32tf)p[2])<<16) + (((U32tf)p[3])<<24)); b += (p[4] + (((U32tf)p[5])<<8) + (((U32tf)p[6])<<16) + (((U32tf)p[7])<<24)); c += (p[8] + (((U32tf)p[9])<<8) + (((U32tf)p[10])<<16) + (((U32tf)p[11])<<24)); c_out0(" cloop+ : ABC : ",a,b,c); MIXODV(a, b, c); c_out0(" clout : ABC : ",a,b,c); p += 12; len -= 12; } x = y = z= 0; z += length; switch(len) { case 11: z+=((U32tf)p[10]<<24); case 10: z+=((U32tf)p[9]<<16); case 9: z+=((U32tf)p[8]<<8); case 8: y+=((U32tf)p[7]<<24); case 7: y+=((U32tf)p[6]<<16); case 6: y+=((U32tf)p[5]<<8); case 5: y+=((U32tf)p[4]); case 4: x+=((U32tf)p[3]<<24); case 3: x+=((U32tf)p[2]<<16); case 2: x+=((U32tf)p[1]<<8); case 1: x+=((U32tf)p[0]); } c_out0(" cpost8 : XYZ : ",x,y,z); a+=x; b+=y;c+=z; c_out0(" cpost+ : ABC : ",a,b,c); MIXODV(a, b, c); c_out0(" cpout : ABC : ",a,b,c); DEBUGODV && printf( "Hash value is %d.\n", (int)(c) ); return(c); }