]> granicus.if.org Git - json-c/commitdiff
add perllike hash function for strings
authorRainer Gerhards <rgerhards@adiscon.com>
Wed, 23 Sep 2015 09:12:13 +0000 (11:12 +0200)
committerRainer Gerhards <rgerhards@adiscon.com>
Wed, 23 Sep 2015 10:23:09 +0000 (12:23 +0200)
This also adds a new API json_global_set_string_hash() which permits
to select the hash function. The default one is the only one that was
previously present. So there are no changes to existing apps, and the
new hash function needs to be explicitely be opted in. Especially for
smaller strings, the perllike functions seems to be around twice as
fast as the other one, with similarly good results in value distribution.

linkhash.c
linkhash.h

index f89859ee16c08b3f275645e70d67f5f11f21fd84..5a9a239881987ef57878510958682d88d3624954 100644 (file)
 #include "random_seed.h"
 #include "linkhash.h"
 
+/* hash functions */
+static unsigned long lh_char_hash(const void *k);
+static unsigned long lh_perllike_str_hash(const void *k);
+static lh_hash_fn *char_hash_fn = lh_char_hash;
+
+int
+json_global_set_string_hash(const int h)
+{
+       switch(h) {
+       case JSON_C_STR_HASH_DFLT:
+               char_hash_fn = lh_char_hash;
+               break;
+       case JSON_C_STR_HASH_PERLLIKE:
+               char_hash_fn = lh_perllike_str_hash;
+               break;
+       default:
+               return -1;
+       }
+       return 0;
+}
+
 void lh_abort(const char *msg, ...)
 {
        va_list ap;
@@ -33,7 +54,7 @@ void lh_abort(const char *msg, ...)
        exit(1);
 }
 
-unsigned long lh_ptr_hash(const void *k)
+static unsigned long lh_ptr_hash(const void *k)
 {
        /* CAW: refactored to be 64bit nice */
        return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
@@ -397,7 +418,21 @@ static uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
   return c;
 }
 
-unsigned long lh_char_hash(const void *k)
+/* a simple hash function similiar to what perl does for strings.
+ * for good results, the string should not be excessivly large.
+ */
+static unsigned long lh_perllike_str_hash(const void *k) 
+{
+    const char *rkey = (char*) k;
+    unsigned hashval = 1;
+
+    while (*rkey)
+        hashval = hashval * 33 + *rkey++;
+
+    return hashval;
+}
+
+static unsigned long lh_char_hash(const void *k)
 {
        static volatile int random_seed = -1;
 
@@ -448,7 +483,7 @@ struct lh_table* lh_table_new(int size, const char *name,
 struct lh_table* lh_kchar_table_new(int size, const char *name,
                                    lh_entry_free_fn *free_fn)
 {
-       return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
+       return lh_table_new(size, name, free_fn, char_hash_fn, lh_char_equal);
 }
 
 struct lh_table* lh_kptr_table_new(int size, const char *name,
index f967bf9ad517cfcd6f9f29f2d3b1b8feb2807dcb..ba7e62782fab8152df248dd194ae730af7142d2c 100644 (file)
@@ -41,6 +41,23 @@ extern "C" {
  */
 #define LH_FREED (void*)-2
 
+/**
+ * default string hash function
+ */
+#define JSON_C_STR_HASH_DFLT 0
+
+/**
+ * perl-like string hash function
+ */
+#define JSON_C_STR_HASH_PERLLIKE 1
+
+/**
+ * This function sets the hash function to be used for strings.
+ * Must be one of the JSON_C_STR_HASH_* values.
+ * @returns 0 - ok, -1 if parameter was invalid
+ */
+int json_global_set_string_hash(const int h);
+
 struct lh_entry;
 
 /**
@@ -144,16 +161,6 @@ struct lh_table {
 };
 
 
-/**
- * Pre-defined hash and equality functions
- */
-extern unsigned long lh_ptr_hash(const void *k);
-extern int lh_ptr_equal(const void *k1, const void *k2);
-
-extern unsigned long lh_char_hash(const void *k);
-extern int lh_char_equal(const void *k1, const void *k2);
-
-
 /**
  * Convenience list iterator.
  */