From d583417dd0afd135d14680ebe244c31077ae1f9c Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Sat, 31 Mar 2018 03:02:34 +0430 Subject: [PATCH] dict: use more characters in the hash function --- dict.c | 27 ++++++++++++++++++++++----- font.c | 6 +++--- post.h | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/dict.c b/dict.c index fd8e816..49d2134 100644 --- a/dict.c +++ b/dict.c @@ -3,7 +3,6 @@ #include #include "post.h" -#define DHASH(d, s) ((unsigned char) (s)[0]) #define CNTMIN (1 << 10) struct dict { @@ -13,6 +12,7 @@ struct dict { int size; int n; int notfound; /* the value returned for missing keys */ + int hashlen; /* the number of characters used for hashing */ int dupkeys; /* duplicate keys if set */ }; @@ -23,11 +23,19 @@ static void dict_extend(struct dict *d, int size) d->size = size; } -struct dict *dict_make(int notfound, int dupkeys) +/* + * initialise a dictionary + * + * notfound: the value returned for missing keys. + * dupkeys: if nonzero, store a copy of keys inserted via dict_put(). + * hashlen: the number of characters used for hashing + */ +struct dict *dict_make(int notfound, int dupkeys, int hashlen) { struct dict *d = malloc(sizeof(*d)); memset(d, 0, sizeof(*d)); d->n = 1; + d->hashlen = hashlen ? hashlen : 32; d->dupkeys = dupkeys; d->notfound = notfound; d->map = iset_make(); @@ -47,6 +55,15 @@ void dict_free(struct dict *d) free(d); } +static int dict_hash(struct dict *d, char *key) +{ + unsigned long hash = (unsigned char) *key++; + int i = d->hashlen; + while (--i > 0 && *key) + hash = (hash << 5) + hash + (unsigned char) *key++; + return hash & 0x3ff; +} + void dict_put(struct dict *d, char *key, int val) { int idx; @@ -61,13 +78,13 @@ void dict_put(struct dict *d, char *key, int val) idx = d->n++; d->key[idx] = key; d->val[idx] = val; - iset_put(d->map, DHASH(d, key), idx); + iset_put(d->map, dict_hash(d, key), idx); } /* return the index of key in d */ int dict_idx(struct dict *d, char *key) { - int h = DHASH(d, key); + int h = dict_hash(d, key); int *b = iset_get(d->map, h); int *r = b + iset_len(d->map, h); while (b && --r >= b) @@ -95,7 +112,7 @@ int dict_get(struct dict *d, char *key) /* match a prefix of key; in the first call, *idx should be -1 */ int dict_prefix(struct dict *d, char *key, int *pos) { - int *r = iset_get(d->map, DHASH(d, key)); + int *r = iset_get(d->map, dict_hash(d, key)); while (r && r[++*pos] >= 0) { int idx = r[*pos]; int plen = strlen(d->key[idx]); diff --git a/font.c b/font.c index 367cd8e..0dcefef 100644 --- a/font.c +++ b/font.c @@ -117,9 +117,9 @@ struct font *font_open(char *path) } memset(fn, 0, sizeof(*fn)); snprintf(fn->desc, sizeof(fn->desc), "%s", path); - fn->gl_dict = dict_make(-1, 1); - fn->ch_dict = dict_make(-1, 1); - fn->ch_map = dict_make(-1, 1); + fn->gl_dict = dict_make(-1, 1, 0); + fn->ch_dict = dict_make(-1, 1, 0); + fn->ch_map = dict_make(-1, 1, 0); while (fscanf(fin, "%s", tok) == 1) { if (!strcmp("char", tok)) { font_readchar(fn, fin, &ch_n, &ch_g); diff --git a/post.h b/post.h index 994bc77..3bde07f 100644 --- a/post.h +++ b/post.h @@ -96,7 +96,7 @@ void iset_put(struct iset *iset, int key, int ent); int iset_len(struct iset *iset, int key); /* mapping strings to longs */ -struct dict *dict_make(int notfound, int dupkeys); +struct dict *dict_make(int notfound, int dupkeys, int hashlen); void dict_free(struct dict *d); void dict_put(struct dict *d, char *key, int val); int dict_get(struct dict *d, char *key);