opr: Add opr_jhash_opaque
authorSimon Wilkinson <sxw@your-file-system.com>
Tue, 17 Jul 2012 16:20:13 +0000 (17:20 +0100)
committerJeffrey Altman <jaltman@your-file-system.com>
Tue, 14 Aug 2012 20:48:44 +0000 (13:48 -0700)
Add a function which can be used to obtain a hash of an arbitrary
opaque string of arbitrary length

Change-Id: I9e6aa29fa06a54976b81eda399c8838b73007962
Reviewed-on: http://gerrit.openafs.org/7978
Reviewed-by: Derrick Brashear <shadow@dementix.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/opr/jhash.h
tests/opr/.gitignore
tests/opr/jhash-t.c

index 27306c9..6e9bc79 100644 (file)
@@ -103,4 +103,46 @@ opr_jhash_int(afs_uint32 a, afs_uint32 initval) {
    return c;
 }
 
+static_inline afs_uint32
+opr_jhash_opaque(const void *val, size_t length, afs_uint32 initval)
+{
+    const unsigned char *str = (const unsigned char *) val;
+    afs_uint32 a,b,c;
+    afs_uint32 k[3];
+
+    /* Set up the internal state */
+    a = b = c = 0xdeadbeef + (((afs_uint32)length)<<2) + initval;
+
+    while (length > 12) {
+       memcpy(&k, str, 12);
+       a += k[0];
+       b += k[1];
+       c += k[2];
+       opr_jhash_mix(a, b, c);
+       length -= 12;
+       str += 12;
+    }
+
+    /* All the case statements fall through */
+    switch(length) {
+      case 12 : c += (afs_uint32) str[11]<<24;
+      case 11 : c += (afs_uint32) str[10]<<16;
+      case 10 : c += (afs_uint32) str[9]<<8;
+      case 9  : c += (afs_uint32) str[8];
+      case 8  : b += (afs_uint32) str[7]<<24;
+      case 7  : b += (afs_uint32) str[6]<<16;
+      case 6  : b += (afs_uint32) str[5]<<8;
+      case 5  : b += (afs_uint32) str[4];
+      case 4  : a += (afs_uint32) str[3]<<24;
+      case 3  : a += (afs_uint32) str[2]<<16;
+      case 2  : a += (afs_uint32) str[1]<<8;
+      case 1  : a += (afs_uint32) str[0];
+       opr_jhash_final(a, b, c);
+      case 0:     /* case 0: nothing left to add */
+       break;
+    }
+
+    return c;
+}
+
 #endif
index 578ee06..0f8cdbb 100644 (file)
@@ -6,3 +6,4 @@
 /rbtree-t
 /queues-t
 /time-t
+/uuid-t
index 80bdf70..a802fe5 100644 (file)
@@ -39,7 +39,7 @@
 int
 main(int argc, char **argv)
 {
-   plan(8);
+   plan(11);
    uint32_t test[] = {3526055646, 2064483663, 3234460805, 3963629775};
 
    is_int(256, opr_jhash_size(8), "opr_jhash_size returns expected value");
@@ -57,5 +57,14 @@ main(int argc, char **argv)
    is_int(1100796964, opr_jhash_int(test[0], 0),
           "single value works through jhash_int");
 
-   return 0;
+   is_int(0xdeadbeef, opr_jhash_opaque("", 0, 0),
+         "Hashing an empty string works");
+
+   is_int(2748273291,
+         opr_jhash_opaque("Four score and seven years ago", 30, 0),
+         "Hashing a string with a 0 initval works");
+   is_int(1389900913,
+         opr_jhash_opaque("Four score and seven years ago", 30, 1),
+         "Hashing a string with a 1 initval works");
+  return 0;
 }