summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormillert <>2004-06-24 04:43:33 +0000
committermillert <>2004-06-24 04:43:33 +0000
commitf22795e90c0343742b46ca0a209a6e4059676f88 (patch)
tree73a9810e9f7758f89202c177e4c823835a49a71c /src
parent242acba8652a28aeb609072dfde10f2074651e07 (diff)
downloadopenbsd-f22795e90c0343742b46ca0a209a6e4059676f88.tar.gz
openbsd-f22795e90c0343742b46ca0a209a6e4059676f88.tar.bz2
openbsd-f22795e90c0343742b46ca0a209a6e4059676f88.zip
Working hcreate(3) et al from NetBSD (cgd) via ray at cyth dot net.
Now passes the regress tests.
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/stdlib/Makefile.inc11
-rw-r--r--src/lib/libc/stdlib/hcreate.3195
-rw-r--r--src/lib/libc/stdlib/hcreate.c200
3 files changed, 401 insertions, 5 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
index 80d3c22112..1d5ba5c9bd 100644
--- a/src/lib/libc/stdlib/Makefile.inc
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -5,10 +5,10 @@
5 5
6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \ 6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
7 calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \ 7 calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
8 getsubopt.c heapsort.c l64a.c llabs.c lsearch.c malloc.c merge.c \ 8 getsubopt.c hcreate.c heapsort.c l64a.c llabs.c lsearch.c malloc.c \
9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \ 9 merge.c multibyte.c putenv.c qsort.c radixsort.c rand.c random.c \
10 setenv.c strtod.c strtol.c strtoll.c strtonum.c strtoul.c strtoull.c \ 10 realpath.c setenv.c strtod.c strtol.c strtoll.c strtonum.c strtoul.c \
11 system.c \ 11 strtoull.c system.c \
12 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \ 12 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
13 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c _Exit.c 13 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c _Exit.c
14 14
@@ -41,7 +41,7 @@ SRCS+= insque.c remque.c
41 41
42MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \ 42MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
43 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \ 43 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
44 getsubopt.3 insque.3 labs.3 ldiv.3 lsearch.3 malloc.3 qabs.3 \ 44 getsubopt.3 hcreate.3 insque.3 labs.3 ldiv.3 lsearch.3 malloc.3 qabs.3 \
45 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \ 45 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
46 strtod.3 strtonum.3 strtol.3 strtoul.3 system.3 tsearch.3 46 strtod.3 strtonum.3 strtol.3 strtoul.3 system.3 tsearch.3
47 47
@@ -49,6 +49,7 @@ MLINKS+=exit.3 _Exit.3
49MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3 49MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
50MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3 50MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
51MLINKS+=getopt_long.3 getopt_long_only.3 51MLINKS+=getopt_long.3 getopt_long_only.3
52MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
52MLINKS+=insque.3 remque.3 53MLINKS+=insque.3 remque.3
53MLINKS+=labs.3 llabs.3 54MLINKS+=labs.3 llabs.3
54MLINKS+=lsearch.3 lfind.3 55MLINKS+=lsearch.3 lfind.3
diff --git a/src/lib/libc/stdlib/hcreate.3 b/src/lib/libc/stdlib/hcreate.3
new file mode 100644
index 0000000000..d1d4e5c185
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,195 @@
1.\" $OpenBSD: hcreate.3,v 1.1 2004/06/24 04:43:33 millert Exp $
2.\" $NetBSD: hcreate.3,v 1.6 2003/04/16 13:34:46 wiz Exp $
3.\"
4.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Klaus Klein.
9.\"
10.\" Redistribution and use in source and binary forms, with or without
11.\" modification, are permitted provided that the following conditions
12.\" are met:
13.\" 1. Redistributions of source code must retain the above copyright
14.\" notice, this list of conditions and the following disclaimer.
15.\" 2. Redistributions in binary form must reproduce the above copyright
16.\" notice, this list of conditions and the following disclaimer in the
17.\" documentation and/or other materials provided with the distribution.
18.\" 3. All advertising materials mentioning features or use of this software
19.\" must display the following acknowledgement:
20.\" This product includes software developed by the NetBSD
21.\" Foundation, Inc. and its contributors.
22.\" 4. Neither the name of The NetBSD Foundation nor the names of its
23.\" contributors may be used to endorse or promote products derived
24.\" from this software without specific prior written permission.
25.\"
26.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36.\" POSSIBILITY OF SUCH DAMAGE.
37.\"
38.Dd February 13, 2001
39.Dt HCREATE 3
40.Os
41.Sh NAME
42.Nm hcreate ,
43.Nm hdestroy ,
44.Nm hsearch
45.Nd manage hash search table
46.Sh SYNOPSIS
47.In search.h
48.Ft int
49.Fn hcreate "size_t nel"
50.Ft void
51.Fn hdestroy "void"
52.Ft ENTRY *
53.Fn hsearch "ENTRY item" "ACTION action"
54.Sh DESCRIPTION
55The
56.Fn hcreate ,
57.Fn hdestroy
58and
59.Fn hsearch
60functions manage hash search tables.
61.Pp
62The
63.Fn hcreate
64function allocates and initializes the table.
65The
66.Fa nel
67argument specifies an estimate of the maximum number of entries to be held
68by the table.
69Unless further memory allocation fails, supplying an insufficient
70.Fa nel
71value will not result in functional harm, although a performance degradation
72may occur.
73Initialization using the
74.Fn hcreate
75function is mandatory prior to any access operations using
76.Fn hsearch .
77.Pp
78The
79.Fn hdestroy
80function destroys a table previously created using
81.Fn hcreate .
82After a call to
83.Fn hdestroy ,
84the data can no longer be accessed.
85.Pp
86The
87.Fn hsearch
88function is used to search to the hash table.
89It returns a pointer into the
90hash table indicating the address of an item.
91The
92.Fa item
93argument is of type
94.Dv ENTRY ,
95a structural type which contains the following members:
96.Bl -tag -compact -offset indent -width voidX*dataXX
97.It Fa char *key
98comparison key.
99.It Fa void *data
100pointer to data associated with
101.Fa key .
102.El
103.Pp
104The key comparison function used by
105.Fn hsearch
106is
107.Xr strcmp 3 .
108.Pp
109The
110.Fa action
111argument is of type
112.Dv ACTION ,
113an enumeration type which defines the following values:
114.Bl -tag -compact -offset indent -width ENTERXX
115.It Dv ENTER
116Insert
117.Fa item
118into the hash table.
119If an existing item with the same key is found, it is not replaced.
120Note that the
121.Fa key
122and
123.Fa data
124elements of
125.Fa item
126are used directly by the new table entry.
127The storage for the
128key must not be modified during the lifetime of the hash table.
129.It Dv FIND
130Search the hash table without inserting
131.Fa item .
132.El
133.Sh RETURN VALUES
134If successful, the
135.Fn hcreate
136function returns a non-zero value.
137Otherwise, a value of 0 is returned and
138.Va errno
139is set to indicate the error.
140.Pp
141The
142.Fn hdestroy
143functions
144returns no value.
145.Pp
146If successful, the
147.Fn hsearch
148function returns a pointer to hash table entry matching
149the provided key.
150If the action is
151.Dv FIND
152and the item was not found, or if the action is
153.Dv ENTER
154and the insertion failed,
155.Dv NULL
156is returned and
157.Va errno
158is set to indicate the error.
159If the action is
160.Dv ENTER
161and an entry already existed in the table matching the given
162key, the existing entry is returned and is not replaced.
163.Sh ERRORS
164The
165.Fn hcreate
166and
167.Fn hsearch
168functions will fail if:
169.Bl -tag -width Er
170.It Bq Er ENOMEM
171Insufficient memory is available.
172.El
173.Sh SEE ALSO
174.Xr bsearch 3 ,
175.Xr lsearch 3 ,
176.Xr malloc 3 ,
177.Xr strcmp 3
178.Sh STANDARDS
179The
180.Fn hcreate ,
181.Fn hdestroy
182and
183.Fn hsearch
184functions conform to
185.St -xpg4.2 .
186.Sh HISTORY
187The
188.Fn hcreate ,
189.Fn hdestroy
190and
191.Fn hsearch
192functions first appeared in
193.At V .
194.Sh BUGS
195The interface permits the use of only one hash table at a time.
diff --git a/src/lib/libc/stdlib/hcreate.c b/src/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000000..14e6fa41f2
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,200 @@
1/* $OpenBSD: hcreate.c,v 1.1 2004/06/24 04:43:33 millert Exp $ */
2/* $NetBSD: hcreate.c,v 1.5 2004/04/23 02:48:12 simonb Exp $ */
3
4/*
5 * Copyright (c) 2001 Christopher G. Demetriou
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the
19 * NetBSD Project. See http://www.NetBSD.org/ for
20 * information about NetBSD.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
36 */
37
38/*
39 * hcreate() / hsearch() / hdestroy()
40 *
41 * SysV/XPG4 hash table functions.
42 *
43 * Implementation done based on NetBSD manual page and Solaris manual page,
44 * plus my own personal experience about how they're supposed to work.
45 *
46 * I tried to look at Knuth (as cited by the Solaris manual page), but
47 * nobody had a copy in the office, so...
48 */
49
50#ifndef lint
51static const char copyright[] =
52"@(#) Copyright (c) 2001 Christopher G. Demetriou. All rights reserved.\n";
53#endif /* not lint */
54
55#ifndef lint
56static const char rcsid[] = "$OpenBSD: hcreate.c,v 1.1 2004/06/24 04:43:33 millert Exp $";
57#endif /* not lint */
58
59#include "namespace.h"
60#include <assert.h>
61#include <errno.h>
62#include <inttypes.h>
63#include <search.h>
64#include <stdlib.h>
65#include <string.h>
66#include <sys/queue.h>
67
68#ifndef _DIAGASSERT
69#define _DIAGASSERT
70#endif
71
72/*
73 * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
74 * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
75 */
76struct internal_entry {
77 SLIST_ENTRY(internal_entry) link;
78 ENTRY ent;
79};
80SLIST_HEAD(internal_head, internal_entry);
81
82#define MIN_BUCKETS_LG2 4
83#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
84
85/*
86 * max * sizeof internal_entry must fit into size_t.
87 * assumes internal_entry is <= 32 (2^5) bytes.
88 */
89#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
90#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
91
92/* Default hash function, from db/hash/hash_func.c */
93extern u_int32_t (*__default_hash)(const void *, size_t);
94
95static struct internal_head *htable;
96static size_t htablesize;
97
98int
99hcreate(size_t nel)
100{
101 size_t idx;
102 unsigned int p2;
103
104 /* Make sure this isn't called when a table already exists. */
105 _DIAGASSERT(htable == NULL);
106 if (htable != NULL) {
107 errno = EINVAL;
108 return 0;
109 }
110
111 /* If nel is too small, make it min sized. */
112 if (nel < MIN_BUCKETS)
113 nel = MIN_BUCKETS;
114
115 /* If it's too large, cap it. */
116 if (nel > MAX_BUCKETS)
117 nel = MAX_BUCKETS;
118
119 /* If it's is not a power of two in size, round up. */
120 if ((nel & (nel - 1)) != 0) {
121 for (p2 = 0; nel != 0; p2++)
122 nel >>= 1;
123 _DIAGASSERT(p2 <= MAX_BUCKETS_LG2);
124 nel = 1 << p2;
125 }
126
127 /* Allocate the table. */
128 htablesize = nel;
129 htable = malloc(htablesize * sizeof htable[0]);
130 if (htable == NULL) {
131 errno = ENOMEM;
132 return 0;
133 }
134
135 /* Initialize it. */
136 for (idx = 0; idx < htablesize; idx++)
137 SLIST_INIT(&htable[idx]);
138
139 return 1;
140}
141
142void
143hdestroy(void)
144{
145 struct internal_entry *ie;
146 size_t idx;
147
148 _DIAGASSERT(htable != NULL);
149 if (htable == NULL)
150 return;
151
152 for (idx = 0; idx < htablesize; idx++) {
153 while (!SLIST_EMPTY(&htable[idx])) {
154 ie = SLIST_FIRST(&htable[idx]);
155 SLIST_REMOVE_HEAD(&htable[idx], link);
156 free(ie->ent.key);
157 free(ie);
158 }
159 }
160 free(htable);
161 htable = NULL;
162}
163
164ENTRY *
165hsearch(ENTRY item, ACTION action)
166{
167 struct internal_head *head;
168 struct internal_entry *ie;
169 uint32_t hashval;
170 size_t len;
171
172 _DIAGASSERT(htable != NULL);
173 _DIAGASSERT(item.key != NULL);
174 _DIAGASSERT(action == ENTER || action == FIND);
175
176 len = strlen(item.key);
177 hashval = (*__default_hash)(item.key, len);
178
179 head = &htable[hashval & (htablesize - 1)];
180 ie = SLIST_FIRST(head);
181 while (ie != NULL) {
182 if (strcmp(ie->ent.key, item.key) == 0)
183 break;
184 ie = SLIST_NEXT(ie, link);
185 }
186
187 if (ie != NULL)
188 return &ie->ent;
189 else if (action == FIND)
190 return NULL;
191
192 ie = malloc(sizeof *ie);
193 if (ie == NULL)
194 return NULL;
195 ie->ent.key = item.key;
196 ie->ent.data = item.data;
197
198 SLIST_INSERT_HEAD(head, ie, link);
199 return &ie->ent;
200}