diff --git a/m-core.h b/m-core.h index 4bda8d62..060a0a77 100644 --- a/m-core.h +++ b/m-core.h @@ -534,6 +534,40 @@ #define M_POWEROF2_P(n) (!((n)&((n)-1))) +/************************************************************/ +/********************* HASH selection ***********************/ +/************************************************************/ + +#if defined(M_USE_DJB_HASH) +#define M_HASH_INIT 5381UL +#define M_HASH_CALC(h1,h2) (((h1) * 33UL) + (h2)) +#elif defined(M_USE_JSHASH) +#define M_HASH_INIT 1315423911UL +#define M_HASH_CALC(h1,h2) ((h1) ^ (((h1) << 5) + (h2) + (h1) >> 2)) +#elif defined(M_USE_BKDRHASH) +#define M_HASH_INIT 0UL +#define M_HASH_CALC(h1,h2) (((h1) * 131) + (h2)) +#elif defined(M_USE_SDBMHASH) +#define M_HASH_INIT 0UL +#define M_HASH_CALC(h1,h2) ((h2) + (h1) << 6 + ((h1) << 16) - (h1)) +#elif defined(M_USE_DEKHASH) +#define M_HASH_INIT 0UL /* should be len but not possible with interface */ +#define M_HASH_CALC(h1,h2) (((h1)<<5) ^ (hash >> 27) ^(h2)) +#elif defined(M_USE_BPHASH) +#define M_HASH_INIT 0UL +#define M_HASH_CALC(h1,h2) ((h1) << 7 ^ (h2)) +#elif defined(M_USE_FNVHASH) +#define M_HASH_INIT 0UL +#define M_HASH_CALC(h1,h2) (((h1) * 0x811C9DC5UL) ^ (h2)) +#else +#define M_HASH_INIT 0UL +#define M_HASH_CALC(h1,h2) (((h1) * 31421) + (h2) + 6927) +#endif + +#define M_HASH_DECL(hash) size_t hash = M_HASH_INIT +#define M_HASH_UP(hash,h) hash = M_HASH_CALC(hash, (h)) + + /************************************************************/ /******************** METHODS handling **********************/ /************************************************************/ @@ -647,15 +681,14 @@ #define M_NO_EXT_ALGO(n,co,to) /* Default hash: perform a hash of the memory pattern of the object */ -// TODO: Better hash function? static inline size_t m_core_hash(const void *ptr, size_t s) { const unsigned char *p = (const unsigned char *) ptr; - size_t hash = 0; + M_HASH_DECL(hash); for(size_t i = 0 ; i < s; i++) { unsigned int c = p[i]; - hash = hash * 31421 + c + 6297; + M_HASH_UP(hash, c); } return hash; } diff --git a/m-string.h b/m-string.h index a3455094..76ab58b3 100644 --- a/m-string.h +++ b/m-string.h @@ -534,11 +534,11 @@ string_hash(const string_t v) { STRING_CONTRACT (v); const char *p = string_get_cstr(v); - size_t hash = 0; + M_HASH_DECL(hash); char c; do { c = *p++; - hash = hash * 31421 + (unsigned int) c + 6297; + M_HASH_UP(hash, M_ASSIGN_CAST(unsigned int,c)); } while (c != 0); return hash; } diff --git a/tests/test-mdict.c b/tests/test-mdict.c index d2f0367d..3e88f9a6 100644 --- a/tests/test-mdict.c +++ b/tests/test-mdict.c @@ -75,7 +75,8 @@ static void check_io(void) assert (string_cmp_str (str, "{\"LICENCE\":\"BSD3\"}") == 0); dict_str_set_at (dict, STRING_CTE("AUTHOR"), STRING_CTE("PP")); dict_str_get_str(str, dict, false); - assert (string_cmp_str (str, "{\"AUTHOR\":\"PP\",\"LICENCE\":\"BSD3\"}") == 0); + //NOTE: order is dependent on the hash system. + assert (string_cmp_str (str, "{\"LICENCE\":\"BSD3\",\"AUTHOR\":\"PP\"}") == 0); FILE *f = fopen ("a.dat", "wt"); if (!f) abort(); dict_str_out_str(f, dict);