diff options
| author | Ruslan Ermilov <ru@FreeBSD.org> | 2001-05-15 07:08:20 +0000 | 
|---|---|---|
| committer | Ruslan Ermilov <ru@FreeBSD.org> | 2001-05-15 07:08:20 +0000 | 
| commit | ec7d12549cfb2d34e42c9f12cf35187f67f41b02 (patch) | |
| tree | cbb42d0fdd48505c91f96b56a0e610ac7207f276 /lib/libc | |
| parent | 9829d36a8683ded23a8c7cbc12dac15ceb045e0a (diff) | |
Notes
Diffstat (limited to 'lib/libc')
| -rw-r--r-- | lib/libc/db/hash/Makefile.inc | 2 | ||||
| -rw-r--r-- | lib/libc/db/hash/hsearch.c | 109 | ||||
| -rw-r--r-- | lib/libc/stdlib/Makefile.inc | 7 | ||||
| -rw-r--r-- | lib/libc/stdlib/hcreate.3 | 206 | ||||
| -rw-r--r-- | lib/libc/stdlib/hcreate.c | 184 | 
5 files changed, 395 insertions, 113 deletions
diff --git a/lib/libc/db/hash/Makefile.inc b/lib/libc/db/hash/Makefile.inc index 38b523d2c696..0bc0e42a4a03 100644 --- a/lib/libc/db/hash/Makefile.inc +++ b/lib/libc/db/hash/Makefile.inc @@ -4,4 +4,4 @@  .PATH: ${.CURDIR}/../libc/db/hash  SRCS+=	hash.c hash_bigkey.c hash_buf.c hash_func.c hash_log2.c \ -	hash_page.c hsearch.c ndbm.c +	hash_page.c ndbm.c diff --git a/lib/libc/db/hash/hsearch.c b/lib/libc/db/hash/hsearch.c deleted file mode 100644 index 7af9d12b05b4..000000000000 --- a/lib/libc/db/hash/hsearch.c +++ /dev/null @@ -1,109 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - *	The Regents of the University of California.  All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - *    may be used to endorse or promote products derived from this software - *    without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hsearch.c	8.4 (Berkeley) 7/21/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <fcntl.h> -#include <string.h> - -#include <db.h> -#include <search.h> - -static DB *dbp = NULL; -static ENTRY retval; - -extern int -hcreate(nel) -	size_t nel; -{ -	HASHINFO info; - -	info.nelem = nel; -	info.bsize = 256; -	info.ffactor = 8; -	info.cachesize = 0; -	info.hash = NULL; -	info.lorder = 0; -	dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0); -	return (dbp != NULL); -} - -extern ENTRY * -hsearch(item, action) -	ENTRY item; -	ACTION action; -{ -	DBT key, val; -	int status; - -	if (!dbp) -		return (NULL); -	key.data = (u_char *)item.key; -	key.size = strlen(item.key) + 1; - -	if (action == ENTER) { -		val.data = (u_char *)item.data; -		val.size = strlen(item.data) + 1; -		status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE); -		if (status) -			return (NULL); -	} else { -		/* FIND */ -		status = (dbp->get)(dbp, &key, &val, 0); -		if (status) -			return (NULL); -		else -			item.data = (char *)val.data; -	} -	retval.key = item.key; -	retval.data = item.data; -	return (&retval); -} - -extern void -hdestroy() -{ -	if (dbp) { -		(void)(dbp->close)(dbp); -		dbp = NULL; -	} -} diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index c2f42df4477a..9a96360c69e7 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -5,8 +5,8 @@  .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/stdlib ${.CURDIR}/../libc/stdlib  MISRCS+=abort.c abs.c atexit.c atof.c atoi.c atol.c bsearch.c calloc.c div.c \ -	exit.c getenv.c getopt.c getsubopt.c heapsort.c labs.c ldiv.c \ -	malloc.c merge.c putenv.c qsort.c radixsort.c rand.c random.c \ +	exit.c getenv.c getopt.c getsubopt.c hcreate.c heapsort.c labs.c \ +	ldiv.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c random.c \  	reallocf.c realpath.c setenv.c strhash.c strtol.c strtoll.c strtoq.c \  	strtoul.c strtoull.c strtouq.c system.c tdelete.c tfind.c tsearch.c \  	twalk.c @@ -25,11 +25,12 @@ SRCS+=	strtod.c  .if ${LIB} == "c"  MAN+=	abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ -	div.3 exit.3 getenv.3 getopt.3 getsubopt.3 labs.3 \ +	div.3 exit.3 getenv.3 getopt.3 getsubopt.3 hcreate.3 labs.3 \  	ldiv.3 malloc.3 memory.3 qsort.3 radixsort.3 rand.3 random.3 \  	realpath.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3  MLINKS+=getenv.3 putenv.3 getenv.3 setenv.3 getenv.3 unsetenv.3 +MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3  MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3  MLINKS+=rand.3 rand_r.3 rand.3 srand.3 rand.3 sranddev.3  MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 \ diff --git a/lib/libc/stdlib/hcreate.3 b/lib/libc/stdlib/hcreate.3 new file mode 100644 index 000000000000..1500b2a5722f --- /dev/null +++ b/lib/libc/stdlib/hcreate.3 @@ -0,0 +1,206 @@ +.\" $FreeBSD$ +.\" +.Dd May 8, 2001 +.Os +.Dt HCREATE 3 +.Sh NAME +.Nm hcreate , hdestroy , hsearch +.Nd manage hash search table +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In search.h +.Ft int +.Fn hcreate "size_t nel" +.Ft void +.Fn hdestroy void +.Ft ENTRY * +.Fn hsearch "ENTRY item" "ACTION action" +.Sh DESCRIPTION +The +.Fn hcreate , +.Fn hdestroy , +and +.Fn hsearch +functions manage hash search tables. +.Pp +The +.Fn hcreate +function allocates sufficient space for the table, and the application should +ensure it is called before +.Fn hsearch +is used. +The +.Fa nel +argument is an estimate of the maximum +number of entries that the table should contain. +This number may be adjusted upward by the +algorithm in order to obtain certain mathematically favorable circumstances. +.Pp +The +.Fn hdestroy +function disposes of the search table, and may be followed by another call to +.Fn hcreate . +After the call to +.Fn hdestroy , +the data can no longer be considered accessible. +.Pp +The +.Fn hsearch +function is a hash-table search routine. +It returns a pointer into a hash table +indicating the location at which an entry can be found. +The +.Fa item +argument is a structure of type +.Vt ENTRY +(defined in the +.Aq Pa search.h +header) containing two pointers: +.Fa item.key +points to the comparison key (a +.Vt "char *" ) , +and +.Fa item.data +(a +.Vt "void *" ) +points to any other data to be associated with +that key. +The comparison function used by +.Fn hsearch +is +.Xr strcmp 3 . +The +.Fa action +argument is a +member of an enumeration type +.Vt ACTION +indicating the disposition of the entry if it cannot be +found in the table. +.Dv ENTER +indicates that the +.Fa item +should be inserted in the table at an +appropriate point. +.Dv FIND +indicates that no entry should be made. +Unsuccessful resolution is +indicated by the return of a +.Dv NULL +pointer. +.Sh RETURN VALUES +The +.Fn hcreate +function returns 0 if it cannot allocate sufficient space for the table; +otherwise, it returns non-zero. +.Pp +The +.Fn hdestroy +function does not return a value. +.Pp +The +.Fn hsearch +function returns a +.Dv NULL +pointer if either the +.Fa action +is +.Dv FIND +and the +.Fa item +could not be found or the +.Fa action +is +.Dv ENTER +and the table is full. +.Sh ERRORS +The +.Fn hcreate +and +.Fn hsearch +functions may fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +Insufficient storage space is available. +.El +.Sh EXAMPLES +The following example reads in strings followed by two numbers +and stores them in a hash table, discarding duplicates. +It then reads in strings and finds the matching entry in the hash +table and prints it out. +.Bd -literal +#include <stdio.h> +#include <search.h> +#include <string.h> + +struct info {			/* This is the info stored in the table */ +	int age, room;		/* other than the key. */ +}; + +#define NUM_EMPL	5000	/* # of elements in search table. */ + +int +main(void) +{ +	char string_space[NUM_EMPL*20]; /* Space to store strings. */ +	struct info info_space[NUM_EMPL]; /* Space to store employee info. */ +	char *str_ptr = string_space; /* Next space in string_space. */ +	struct info *info_ptr = info_space; /* Next space in info_space. */ +	ENTRY item; +	ENTRY *found_item; /* Name to look for in table. */ +	char name_to_find[30]; +	int i = 0; + +	/* Create table; no error checking is performed. */ +	(void) hcreate(NUM_EMPL); + +	while (scanf("%s%d%d", str_ptr, &info_ptr->age, +	    &info_ptr->room) != EOF && i++ < NUM_EMPL) { +		/* Put information in structure, and structure in item. */ +		item.key = str_ptr; +		item.data = info_ptr; +		str_ptr += strlen(str_ptr) + 1; +		info_ptr++; +		/* Put item into table. */ +		(void) hsearch(item, ENTER); +	} + +	/* Access table. */ +	item.key = name_to_find; +	while (scanf("%s", item.key) != EOF) { +		if ((found_item = hsearch(item, FIND)) != NULL) { +			/* If item is in the table. */ +			(void)printf("found %s, age = %d, room = %d\n", +			    found_item->key, +			    ((struct info *)found_item->data)->age, +			    ((struct info *)found_item->data)->room); +		} else +			(void)printf("no such employee %s\n", name_to_find); +	} +	return 0; +} +.Ed +.Sh SEE ALSO +.Xr bsearch 3 , +.Xr lsearch 3 , +.Xr malloc 3 , +.Xr strcmp 3 , +.Xr tsearch 3 +.Sh STANDARDS +The +.Fn hcreate , +.Fn hdestroy , +and +.Fn hsearch +functions conform to +.St -xpg4.2 . +.Sh HISTORY +The +.Fn hcreate , +.Fn hdestroy , +and +.Fn hsearch +functions first appeared in +.At V . +.Sh BUGS +The interface permits the use of only one hash table at a time. diff --git a/lib/libc/stdlib/hcreate.c b/lib/libc/stdlib/hcreate.c new file mode 100644 index 000000000000..ecc24310ae4b --- /dev/null +++ b/lib/libc/stdlib/hcreate.c @@ -0,0 +1,184 @@ +/* $NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $ */ +/* $FreeBSD$ */ + +/* + * Copyright (c) 2001 Christopher G. Demetriou + * All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *          This product includes software developed for the + *          NetBSD Project.  See http://www.netbsd.org/ for + *          information about NetBSD. + * 4. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + *  + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *  + * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> + */ + +/* + * hcreate() / hsearch() / hdestroy() + * + * SysV/XPG4 hash table functions. + * + * Implementation done based on NetBSD manual page and Solaris manual page, + * plus my own personal experience about how they're supposed to work. + * + * I tried to look at Knuth (as cited by the Solaris manual page), but + * nobody had a copy in the office, so... + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <errno.h> +#include <search.h> +#include <stdlib.h> +#include <string.h> +#include "namespace.h" + +/* + * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit + * ptr machine) without adjusting MAX_BUCKETS_LG2 below. + */ +struct internal_entry { +	SLIST_ENTRY(internal_entry) link; +	ENTRY ent; +}; +SLIST_HEAD(internal_head, internal_entry); + +#define	MIN_BUCKETS_LG2	4 +#define	MIN_BUCKETS	(1 << MIN_BUCKETS_LG2) + +/* + * max * sizeof internal_entry must fit into size_t. + * assumes internal_entry is <= 32 (2^5) bytes. + */ +#define	MAX_BUCKETS_LG2	(sizeof (size_t) * 8 - 1 - 5) +#define	MAX_BUCKETS	((size_t)1 << MAX_BUCKETS_LG2) + +/* 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; + +int +hcreate(size_t nel) +{ +	size_t idx; +	unsigned int p2; + +	/* Make sure this this isn't called when a table already exists. */ +	if (htable != NULL) { +		errno = EINVAL; +		return 0; +	} + +	/* If nel is too small, make it min sized. */ +	if (nel < MIN_BUCKETS) +		nel = MIN_BUCKETS; + +	/* If it's too large, cap it. */ +	if (nel > MAX_BUCKETS) +		nel = MAX_BUCKETS; + +	/* If it's is not a power of two in size, round up. */ +	if ((nel & (nel - 1)) != 0) { +		for (p2 = 0; nel != 0; p2++) +			nel >>= 1; +		nel = 1 << p2; +	} +	 +	/* Allocate the table. */ +	htablesize = nel; +	htable = malloc(htablesize * sizeof htable[0]); +	if (htable == NULL) { +		errno = ENOMEM; +		return 0; +	} + +	/* Initialize it. */ +	for (idx = 0; idx < htablesize; idx++) +		SLIST_INIT(&htable[idx]); + +	return 1; +} + +void +hdestroy(void) +{ +	struct internal_entry *ie; +	size_t idx; + +	if (htable == NULL) +		return; + +	for (idx = 0; idx < htablesize; idx++) { +		while (!SLIST_EMPTY(&htable[idx])) { +			ie = SLIST_FIRST(&htable[idx]); +			SLIST_REMOVE_HEAD(&htable[idx], link); +			free(ie->ent.key); +			free(ie); +		} +	} +	free(htable); +	htable = NULL; +} + +ENTRY * +hsearch(ENTRY item, ACTION action) +{ +	struct internal_head *head; +	struct internal_entry *ie; +	uint32_t hashval; +	size_t len; + +	len = strlen(item.key); +	hashval = (*__default_hash)(item.key, len); + +	head = &htable[hashval & (htablesize - 1)]; +	ie = SLIST_FIRST(head); +	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; + +	ie = malloc(sizeof *ie); +	if (ie == NULL) +		return NULL; +	ie->ent.key = item.key; +	ie->ent.data = item.data; + +	SLIST_INSERT_HEAD(head, ie, link); +	return &ie->ent; +}  | 
