X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fsearch%2Fhsearch.c;h=b3ac8796e70fd00d6251949b308db7761b156e97;hb=6d8a515796270eb6cec8a278cb353a078a10f09a;hp=be856b2aa8e522ff62f12597d90f5a21125d092f;hpb=febbd12d00883a716a9edca25011f8aa306b859b;p=musl diff --git a/src/search/hsearch.c b/src/search/hsearch.c index be856b2a..b3ac8796 100644 --- a/src/search/hsearch.c +++ b/src/search/hsearch.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -14,14 +15,17 @@ with the posix api items cannot be iterated and length cannot be queried #define MINSIZE 8 #define MAXSIZE ((size_t)-1/2 + 1) -struct entry { - ENTRY item; - size_t hash; +struct __tab { + ENTRY *entries; + size_t mask; + size_t used; }; -static size_t mask; -static size_t used; -static struct entry *tab; +static struct hsearch_data htab; + +static int __hcreate_r(size_t, struct hsearch_data *); +static void __hdestroy_r(struct hsearch_data *); +static int __hsearch_r(ENTRY, ACTION, ENTRY **, struct hsearch_data *); static size_t keyhash(char *k) { @@ -33,30 +37,30 @@ static size_t keyhash(char *k) return h; } -static int resize(size_t nel) +static int resize(size_t nel, struct hsearch_data *htab) { size_t newsize; size_t i, j; - struct entry *e, *newe; - struct entry *oldtab = tab; - struct entry *oldend = tab + mask + 1; + ENTRY *e, *newe; + ENTRY *oldtab = htab->__tab->entries; + ENTRY *oldend = htab->__tab->entries + htab->__tab->mask + 1; if (nel > MAXSIZE) nel = MAXSIZE; for (newsize = MINSIZE; newsize < nel; newsize *= 2); - tab = calloc(newsize, sizeof *tab); - if (!tab) { - tab = oldtab; + htab->__tab->entries = calloc(newsize, sizeof *htab->__tab->entries); + if (!htab->__tab->entries) { + htab->__tab->entries = oldtab; return 0; } - mask = newsize - 1; + htab->__tab->mask = newsize - 1; if (!oldtab) return 1; for (e = oldtab; e < oldend; e++) - if (e->item.key) { - for (i=e->hash,j=1; ; i+=j++) { - newe = tab + (i & mask); - if (!newe->item.key) + if (e->key) { + for (i=keyhash(e->key),j=1; ; i+=j++) { + newe = htab->__tab->entries + (i & htab->__tab->mask); + if (!newe->key) break; } *newe = *e; @@ -67,52 +71,83 @@ static int resize(size_t nel) int hcreate(size_t nel) { - mask = 0; - used = 0; - tab = 0; - return resize(nel); + return __hcreate_r(nel, &htab); } void hdestroy(void) { - free(tab); - tab = 0; - mask = 0; - used = 0; + __hdestroy_r(&htab); } -static struct entry *lookup(char *key, size_t hash) +static ENTRY *lookup(char *key, size_t hash, struct hsearch_data *htab) { size_t i, j; - struct entry *e; + ENTRY *e; for (i=hash,j=1; ; i+=j++) { - e = tab + (i & mask); - if (!e->item.key || - (e->hash==hash && strcmp(e->item.key, key)==0)) + e = htab->__tab->entries + (i & htab->__tab->mask); + if (!e->key || strcmp(e->key, key) == 0) break; } return e; } ENTRY *hsearch(ENTRY item, ACTION action) +{ + ENTRY *e; + + __hsearch_r(item, action, &e, &htab); + return e; +} + +static int __hcreate_r(size_t nel, struct hsearch_data *htab) +{ + int r; + + htab->__tab = calloc(1, sizeof *htab->__tab); + if (!htab->__tab) + return 0; + r = resize(nel, htab); + if (r == 0) { + free(htab->__tab); + htab->__tab = 0; + } + return r; +} +weak_alias(__hcreate_r, hcreate_r); + +static void __hdestroy_r(struct hsearch_data *htab) +{ + if (htab->__tab) free(htab->__tab->entries); + free(htab->__tab); + htab->__tab = 0; +} +weak_alias(__hdestroy_r, hdestroy_r); + +static int __hsearch_r(ENTRY item, ACTION action, ENTRY **retval, struct hsearch_data *htab) { size_t hash = keyhash(item.key); - struct entry *e = lookup(item.key, hash); + ENTRY *e = lookup(item.key, hash, htab); - if (e->item.key) - return &e->item; - if (action == FIND) + if (e->key) { + *retval = e; + return 1; + } + if (action == FIND) { + *retval = 0; return 0; - e->item = item; - e->hash = hash; - if (++used > mask - mask/4) { - if (!resize(2*used)) { - used--; - e->item.key = 0; + } + *e = item; + if (++htab->__tab->used > htab->__tab->mask - htab->__tab->mask/4) { + if (!resize(2*htab->__tab->used, htab)) { + htab->__tab->used--; + e->key = 0; + *retval = 0; return 0; } - e = lookup(item.key, hash); + e = lookup(item.key, hash, htab); } - return &e->item; + *retval = e; + return 1; } +weak_alias(__hsearch_r, hsearch_r);