diff --git a/moo/lib/utl.c b/moo/lib/utl.c index f518202..f4517b0 100644 --- a/moo/lib/utl.c +++ b/moo/lib/utl.c @@ -216,18 +216,45 @@ moo_uint128_t moo_hton128 (moo_uint128_t x) * utobcstr -> ucstr to bcstr */ + +#if MOO_SIZEOF_OOW_T == 4 +# define FNV_MAGIC_INIT (0x811c9dc5) +# define FNV_MAGIC_PRIME (0x01000193) +#elif MOO_SIZEOF_OOW_T == 8 +# define FNV_MAGIC_INIT (0xCBF29CE484222325) +# define FNV_MAGIC_PRIME (0x100000001B3) +#elif MOO_SIZEOF_OOW_T == 16 +# define FNV_MAGIC_INIT (0x6C62272E07BB014262B821756295C58D) +# define FNV_MAGIC_PRIME (0x1000000000000000000013B) +#endif + moo_oow_t moo_hash_bytes (const moo_oob_t* ptr, moo_oow_t len) { - moo_oow_t h = 0; + moo_oow_t h; const moo_uint8_t* bp, * be; bp = ptr; be = bp + len; /* this hash doesn't produce good distribution */ - /*while (bp < be) h = h * 31 + *bp++; */ + /* + h = 0 + while (bp < be) h = h * 31 + *bp++; + */ - /* SDBM hash is know to produce good overall distribution for many different data sets */ +#if defined(FNV_MAGIC_INIT) + /* FNV-1 hash */ + h = FNV_MAGIC_INIT; + while (bp < be) + { + h ^= (moo_oow_t)(*bp++); + h *= FNV_MAGIC_PRIME; + } +#else + /* SDBM hash is known to produce good overall distribution + * for many different data sets */ + h = 0; while (bp < be) h = (h << 6) + (h << 16) - h + *bp++; +#endif /* constrain the hash value to be representable in a small integer * for convenience sake */