diff options
author | pfg <pfg@FreeBSD.org> | 2014-07-21 15:22:48 +0000 |
---|---|---|
committer | pfg <pfg@FreeBSD.org> | 2014-07-21 15:22:48 +0000 |
commit | f47a57d4401b5129afbc000403e0aab5e10fc5f6 (patch) | |
tree | 04c219a619b87d71d16ffe6fb7dcf512acecacc9 /lib/libc/stdlib/hcreate.c | |
parent | 428b45aa532260e8c6ddf0217ec31db2234d29a8 (diff) | |
download | FreeBSD-src-f47a57d4401b5129afbc000403e0aab5e10fc5f6.zip FreeBSD-src-f47a57d4401b5129afbc000403e0aab5e10fc5f6.tar.gz |
Add re-entrant versions of the hash functions based on the GNU api.
While testing this I found a conformance issue in hdestroy()
that will be fixed in a subsequent commit.
Obtained from: NetBSD (hcreate.c, CVS Rev. 1.7)
Diffstat (limited to 'lib/libc/stdlib/hcreate.c')
-rw-r--r-- | lib/libc/stdlib/hcreate.c | 97 |
1 files changed, 68 insertions, 29 deletions
diff --git a/lib/libc/stdlib/hcreate.c b/lib/libc/stdlib/hcreate.c index cfcd115..8bb4d3e 100644 --- a/lib/libc/stdlib/hcreate.c +++ b/lib/libc/stdlib/hcreate.c @@ -1,4 +1,4 @@ -/* $NetBSD: hcreate.c,v 1.6 2008/07/21 12:05:43 lukem Exp $ */ +/* $NetBSD: hcreate.c,v 1.7 2011/09/14 23:33:51 christos Exp $ */ /* * Copyright (c) 2001 Christopher G. Demetriou @@ -49,7 +49,7 @@ #include <sys/cdefs.h> #if 0 #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: hcreate.c,v 1.6 2008/07/21 12:05:43 lukem Exp $"); +__RCSID("$NetBSD: hcreate.c,v 1.7 2011/09/14 23:33:51 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #endif __FBSDID("$FreeBSD$"); @@ -84,20 +84,27 @@ SLIST_HEAD(internal_head, internal_entry); /* Default hash function, from db/hash/hash_func.c */ extern u_int32_t (*__default_hash)(const void *, size_t); -static struct internal_head *htable; -static size_t htablesize; +static struct hsearch_data htable; int hcreate(size_t nel) { - size_t idx; - unsigned int p2; /* Make sure this is not called when a table already exists. */ - if (htable != NULL) { + if (htable.table != NULL) { errno = EINVAL; return 0; } + return hcreate_r(nel, &htable); +} + +int +hcreate_r(size_t nel, struct hsearch_data *head) +{ + struct internal_head *table; + size_t idx; + unsigned int p2; + void *p; /* If nel is too small, make it min sized. */ if (nel < MIN_BUCKETS) @@ -115,16 +122,19 @@ hcreate(size_t nel) } /* Allocate the table. */ - htablesize = nel; - htable = malloc(htablesize * sizeof htable[0]); - if (htable == NULL) { + head->size = nel; + head->filled = 0; + p = malloc(nel * sizeof table[0]); + if (p == NULL) { errno = ENOMEM; return 0; } + head->table = p; + table = p; /* Initialize it. */ - for (idx = 0; idx < htablesize; idx++) - SLIST_INIT(&htable[idx]); + for (idx = 0; idx < nel; idx++) + SLIST_INIT(&table[idx]); return 1; } @@ -132,54 +142,83 @@ hcreate(size_t nel) void hdestroy(void) { + hdestroy_r(&htable); +} + +void +hdestroy_r(struct hsearch_data *head) +{ struct internal_entry *ie; size_t idx; + void *p; + struct internal_head *table; - if (htable == NULL) + if (head == NULL) return; - for (idx = 0; idx < htablesize; idx++) { - while (!SLIST_EMPTY(&htable[idx])) { - ie = SLIST_FIRST(&htable[idx]); - SLIST_REMOVE_HEAD(&htable[idx], link); + p = head->table; + head->table = NULL; + table = p; + + for (idx = 0; idx < head->size; idx++) { + while (!SLIST_EMPTY(&table[idx])) { + ie = SLIST_FIRST(&table[idx]); + SLIST_REMOVE_HEAD(&table[idx], link); free(ie->ent.key); free(ie); } } - free(htable); - htable = NULL; + free(table); } ENTRY * hsearch(ENTRY item, ACTION action) { - struct internal_head *head; + ENTRY *ep; + (void)hsearch_r(item, action, &ep, &htable); + return ep; +} + +int +hsearch_r(ENTRY item, ACTION action, ENTRY **itemp, struct hsearch_data *head) +{ + struct internal_head *table, *chain; struct internal_entry *ie; uint32_t hashval; size_t len; + void *p; + + p = head->table; + table = p; len = strlen(item.key); hashval = (*__default_hash)(item.key, len); - head = &htable[hashval & (htablesize - 1)]; - ie = SLIST_FIRST(head); + chain = &table[hashval & (head->size - 1)]; + ie = SLIST_FIRST(chain); while (ie != NULL) { if (strcmp(ie->ent.key, item.key) == 0) break; ie = SLIST_NEXT(ie, link); } - if (ie != NULL) - return &ie->ent; - else if (action == FIND) - return NULL; + if (ie != NULL) { + *itemp = &ie->ent; + return 1; + } else if (action == FIND) { + *itemp = NULL; + errno = ESRCH; + return 1; + } ie = malloc(sizeof *ie); if (ie == NULL) - return NULL; + return 0; ie->ent.key = item.key; ie->ent.data = item.data; - SLIST_INSERT_HEAD(head, ie, link); - return &ie->ent; + SLIST_INSERT_HEAD(chain, ie, link); + *itemp = &ie->ent; + head->filled++; + return 1; } |