diff options
Diffstat (limited to 'str_array.c')
-rw-r--r-- | str_array.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/str_array.c b/str_array.c index f6e4deeb..08704312 100644 --- a/str_array.c +++ b/str_array.c @@ -95,6 +95,7 @@ static void grow_table(NODE *symbol); static unsigned long gst_hash_string(const char *str, size_t len, unsigned long hsize, size_t *code); static unsigned long scramble(unsigned long x); +static unsigned long fnv1a_hash_string(const char *str, size_t len, unsigned long hsize, size_t *code); static unsigned long awk_hash(const char *s, size_t len, unsigned long hsize, size_t *code); unsigned long (*hash)(const char *s, size_t len, unsigned long hsize, size_t *code) = awk_hash; @@ -112,8 +113,13 @@ str_array_init(NODE *symbol ATTRIBUTE_UNUSED, NODE *subs ATTRIBUTE_UNUSED) /* check relevant environment variables */ if ((newval = getenv_long("STR_CHAIN_MAX")) > 0) STR_CHAIN_MAX = newval; - if ((val = getenv("AWK_HASH")) != NULL && strcmp(val, "gst") == 0) - hash = gst_hash_string; + + if ((val = getenv("AWK_HASH")) != NULL) { + if (strcmp(val, "gst") == 0) + hash = gst_hash_string; + else if (strcmp(val, "fnv1a") == 0) + hash = fnv1a_hash_string; + } } else null_array(symbol); @@ -773,6 +779,34 @@ scramble(unsigned long x) return x; } +/* fnv1a_hash_string --- fnv1a hash function */ + +/* + * FNV-1a hash function + * http://www.isthe.com/chongo/tech/comp/fnv/index.html + */ + +static unsigned long +fnv1a_hash_string(const char *str, size_t len, unsigned long hsize, size_t *code) +{ + /* FNV-1a */ + register unsigned ret = 2166136261U; + + while (len > 0) { + ret ^= (unsigned char) (*str++); + ret *= 16777619U; + len-- ; + } + + if (code != NULL) + *code = ret; + + if (ret >= hsize) + ret %= hsize; + + return ret; +} + /* env_remove --- for ENVIRON, remove value from real environment */ static NODE ** |