summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib/hcreate.c
diff options
context:
space:
mode:
authorpfg <pfg@FreeBSD.org>2014-07-21 15:22:48 +0000
committerpfg <pfg@FreeBSD.org>2014-07-21 15:22:48 +0000
commitf47a57d4401b5129afbc000403e0aab5e10fc5f6 (patch)
tree04c219a619b87d71d16ffe6fb7dcf512acecacc9 /lib/libc/stdlib/hcreate.c
parent428b45aa532260e8c6ddf0217ec31db2234d29a8 (diff)
downloadFreeBSD-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.c97
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;
}
OpenPOWER on IntegriCloud