Module Name: src Committed By: uebayasi Date: Sun Oct 12 05:20:54 UTC 2014
Modified Files: src/usr.bin/config: defs.h hash.c Log Message: Make hash capable of taking two key strings. To generate a diff of this commit: cvs rdiff -u -r1.56 -r1.57 src/usr.bin/config/defs.h cvs rdiff -u -r1.8 -r1.9 src/usr.bin/config/hash.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/config/defs.h diff -u src/usr.bin/config/defs.h:1.56 src/usr.bin/config/defs.h:1.57 --- src/usr.bin/config/defs.h:1.56 Sat Oct 11 03:17:40 2014 +++ src/usr.bin/config/defs.h Sun Oct 12 05:20:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: defs.h,v 1.56 2014/10/11 03:17:40 uebayasi Exp $ */ +/* $NetBSD: defs.h,v 1.57 2014/10/12 05:20:54 uebayasi Exp $ */ /* * Copyright (c) 1992, 1993 @@ -536,14 +536,20 @@ int expr_eval(struct condexpr *, int (*) /* hash.c */ struct hashtab *ht_new(void); void ht_free(struct hashtab *); +int ht_insrep2(struct hashtab *, const char *, const char *, void *, int); int ht_insrep(struct hashtab *, const char *, void *, int); +#define ht_insert2(ht, nam1, nam2, val) ht_insrep2(ht, nam1, nam2, val, 0) #define ht_insert(ht, nam, val) ht_insrep(ht, nam, val, 0) #define ht_replace(ht, nam, val) ht_insrep(ht, nam, val, 1) +int ht_remove2(struct hashtab *, const char *, const char *); int ht_remove(struct hashtab *, const char *); +void *ht_lookup2(struct hashtab *, const char *, const char *); void *ht_lookup(struct hashtab *, const char *); void initintern(void); const char *intern(const char *); +typedef int (*ht_callback2)(const char *, const char *, void *, void *); typedef int (*ht_callback)(const char *, void *, void *); +int ht_enumerate2(struct hashtab *, ht_callback2, void *); int ht_enumerate(struct hashtab *, ht_callback, void *); /* typed hash, named struct HT, whose type is string -> struct VT */ Index: src/usr.bin/config/hash.c diff -u src/usr.bin/config/hash.c:1.8 src/usr.bin/config/hash.c:1.9 --- src/usr.bin/config/hash.c:1.8 Mon Mar 12 02:58:55 2012 +++ src/usr.bin/config/hash.c Sun Oct 12 05:20:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: hash.c,v 1.8 2012/03/12 02:58:55 dholland Exp $ */ +/* $NetBSD: hash.c,v 1.9 2014/10/12 05:20:54 uebayasi Exp $ */ /* * Copyright (c) 1992, 1993 @@ -58,7 +58,10 @@ struct hashent { // XXXLUKEM: a SIMPLEQ might be more appropriate TAILQ_ENTRY(hashent) h_next; - const char *h_name; /* the string */ + const char *h_names[2]; /* the string */ +#define h_name1 h_names[0] +#define h_name2 h_names[1] +#define h_name h_name1 u_int h_hash; /* its hash value */ void *h_value; /* other values (for name=value) */ }; @@ -81,7 +84,8 @@ static struct hashtab strings; static void ht_expand(struct hashtab *); static void ht_init(struct hashtab *, size_t); -static inline u_int hash(const char *); +static inline u_int hash(u_int, const char *); +static inline u_int hash2(u_int, const char *, const char *); static inline struct hashent *newhashent(const char *, u_int); /* @@ -137,27 +141,51 @@ ht_expand(struct hashtab *ht) * otherwise allocate a new entry. */ static inline struct hashent * -newhashent(const char *name, u_int h) +newhashent2(const char *name1, const char *name2, u_int h) { struct hashent *hp; hp = ecalloc(1, sizeof(*hp)); - hp->h_name = name; + hp->h_name1 = name1; + hp->h_name2 = name2; hp->h_hash = h; return (hp); } +static inline struct hashent * +newhashent(const char *name, u_int h) +{ + return newhashent2(name, NULL, h); +} + +static inline u_int +hv(u_int h, char c) +{ + return (h << 5) + h + c; +} + /* * Hash a string. */ static inline u_int -hash(const char *str) +hash(u_int h, const char *str) { - u_int h; - for (h = 0; *str;) - h = (h << 5) + h + *str++; + while (str && *str) + h = hv(h, *str++); + return (h); +} + +#define HASH2DELIM ' ' + +static inline u_int +hash2(u_int h, const char *str1, const char *str2) +{ + + h = hash(h, str1); + h = hv(h, HASH2DELIM); + h = hash(h, str2); return (h); } @@ -182,7 +210,7 @@ intern(const char *s) char *p; ht = &strings; - h = hash(s); + h = hash2(0, s, NULL); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) { if (hp->h_hash == h && strcmp(hp->h_name, s) == 0) @@ -231,22 +259,23 @@ ht_free(struct hashtab *ht) * Insert and/or replace. */ int -ht_insrep(struct hashtab *ht, const char *nam, void *val, int replace) +ht_insrep2(struct hashtab *ht, const char *nam1, const char *nam2, void *val, int replace) { struct hashent *hp; struct hashenthead *hpp; u_int h; - h = hash(nam); + h = hash2(0, nam1, NULL); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) { - if (hp->h_name == nam) { + if (hp->h_name1 == nam1 && + hp->h_name2 == nam2) { if (replace) hp->h_value = val; return (1); } } - hp = newhashent(nam, h); + hp = newhashent2(nam1, nam2, h); TAILQ_INSERT_TAIL(hpp, hp, h_next); hp->h_value = val; if (++ht->ht_used > ht->ht_lim) @@ -254,21 +283,27 @@ ht_insrep(struct hashtab *ht, const char return (0); } +int +ht_insrep(struct hashtab *ht, const char *nam, void *val, int replace) +{ + return ht_insrep2(ht, nam, NULL, val, replace); +} + /* * Remove. */ int -ht_remove(struct hashtab *ht, const char *name) +ht_remove2(struct hashtab *ht, const char *name1, const char *name2) { struct hashent *hp; struct hashenthead *hpp; u_int h; - h = hash(name); + h = hash2(0, name1, name2); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) { - if (hp->h_name != name) + if (hp->h_name1 != name1 || hp->h_name2 != name2) continue; TAILQ_REMOVE(hpp, hp, h_next); @@ -279,21 +314,33 @@ ht_remove(struct hashtab *ht, const char return (1); } +int +ht_remove(struct hashtab *ht, const char *name) +{ + return ht_remove2(ht, name, NULL); +} + void * -ht_lookup(struct hashtab *ht, const char *nam) +ht_lookup2(struct hashtab *ht, const char *nam1, const char *nam2) { struct hashent *hp; struct hashenthead *hpp; u_int h; - h = hash(nam); + h = hash2(0, nam1, NULL); hpp = &ht->ht_tab[h & ht->ht_mask]; TAILQ_FOREACH(hp, hpp, h_next) - if (hp->h_name == nam) + if (hp->h_name == nam1) return (hp->h_value); return (NULL); } +void * +ht_lookup(struct hashtab *ht, const char *nam) +{ + return ht_lookup2(ht, nam, NULL); +} + /* * first parameter to callback is the entry name from the hash table * second parameter is the value from the hash table @@ -301,6 +348,22 @@ ht_lookup(struct hashtab *ht, const char */ int +ht_enumerate2(struct hashtab *ht, ht_callback2 cbfunc2, void *arg) +{ + struct hashent *hp; + struct hashenthead *hpp; + size_t i; + int rval = 0; + + for (i = 0; i < ht->ht_size; i++) { + hpp = &ht->ht_tab[i]; + TAILQ_FOREACH(hp, hpp, h_next) + rval += (*cbfunc2)(hp->h_name1, hp->h_name2, hp->h_value, arg); + } + return rval; +} + +int ht_enumerate(struct hashtab *ht, ht_callback cbfunc, void *arg) { struct hashent *hp;