Module Name: src Committed By: christos Date: Sun Jul 20 13:34:17 UTC 2014
Modified Files: src/include: search.h src/lib/libc/stdlib: Makefile.inc hcreate.3 hcreate.c Log Message: Our hdestroy implementation was non-conformant because it freed the key of each entry. Add a new function hdestroy1 that allows the user to control what gets freed. Pointed out by Pedro Giffuni at FreeBSD. To generate a diff of this commit: cvs rdiff -u -r1.20 -r1.21 src/include/search.h cvs rdiff -u -r1.81 -r1.82 src/lib/libc/stdlib/Makefile.inc cvs rdiff -u -r1.10 -r1.11 src/lib/libc/stdlib/hcreate.3 cvs rdiff -u -r1.8 -r1.9 src/lib/libc/stdlib/hcreate.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/include/search.h diff -u src/include/search.h:1.20 src/include/search.h:1.21 --- src/include/search.h:1.20 Sat Apr 27 17:35:25 2013 +++ src/include/search.h Sun Jul 20 09:34:17 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: search.h,v 1.20 2013/04/27 21:35:25 joerg Exp $ */ +/* $NetBSD: search.h,v 1.21 2014/07/20 13:34:17 christos Exp $ */ /* * Written by J.T. Conklin <j...@netbsd.org> @@ -62,8 +62,12 @@ void hdestroy(void); ENTRY *hsearch(ENTRY, ACTION); #ifdef _NETBSD_SOURCE +#define FREE_KEY 1 +#define FREE_DATA 2 +void hdestroy1(int); int hcreate_r(size_t, struct hsearch_data *); void hdestroy_r(struct hsearch_data *); +void hdestroy1_r(struct hsearch_data *, int); int hsearch_r(ENTRY, ACTION, ENTRY **, struct hsearch_data *); #endif /* _NETBSD_SOURCE */ Index: src/lib/libc/stdlib/Makefile.inc diff -u src/lib/libc/stdlib/Makefile.inc:1.81 src/lib/libc/stdlib/Makefile.inc:1.82 --- src/lib/libc/stdlib/Makefile.inc:1.81 Tue Jan 7 21:15:42 2014 +++ src/lib/libc/stdlib/Makefile.inc Sun Jul 20 09:34:17 2014 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.81 2014/01/08 02:15:42 christos Exp $ +# $NetBSD: Makefile.inc,v 1.82 2014/07/20 13:34:17 christos Exp $ # from: @(#)Makefile.inc 8.3 (Berkeley) 2/4/95 # stdlib sources @@ -66,6 +66,7 @@ MLINKS+=getenv.3 setenv.3 getenv.3 unset MLINKS+=getenv.3 getenv_r.3 MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3 MLINKS+=hcreate.3 hcreate_r.3 hcreate.3 hdestroy_r.3 hcreate.3 hsearch_r.3 +MLINKS+=hcreate.3 hdestroy1.3 hcreate.3 hdestroy1_r.3 MLINKS+=insque.3 remque.3 MLINKS+=lsearch.3 lfind.3 MLINKS+=malloc.3 calloc.3 malloc.3 realloc.3 malloc.3 free.3 Index: src/lib/libc/stdlib/hcreate.3 diff -u src/lib/libc/stdlib/hcreate.3:1.10 src/lib/libc/stdlib/hcreate.3:1.11 --- src/lib/libc/stdlib/hcreate.3:1.10 Thu Sep 15 05:14:54 2011 +++ src/lib/libc/stdlib/hcreate.3 Sun Jul 20 09:34:17 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: hcreate.3,v 1.10 2011/09/15 09:14:54 wiz Exp $ +.\" $NetBSD: hcreate.3,v 1.11 2014/07/20 13:34:17 christos Exp $ .\" .\" Copyright (c) 1999 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,14 +27,16 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd September 14, 2011 +.Dd July 20, 2014 .Dt HCREATE 3 .Os .Sh NAME .Nm hcreate , .Nm hcreate_r , .Nm hdestroy , +.Nm hdestroy1 , .Nm hdestroy_r , +.Nm hdestroy1_r , .Nm hsearch , .Nm hsearch_r .Nd manage hash search table @@ -49,7 +51,11 @@ .Ft void .Fn hdestroy "void" .Ft void +.Fn hdestroy1 "int flags" +.Ft void .Fn hdestroy_r "struct hsearch_data *table" +.Ft void +.Fn hdestroy1_r "struct hsearch_data *table" "int flags" .Ft ENTRY * .Fn hsearch "ENTRY item" "ACTION action" .Ft int @@ -60,6 +66,8 @@ The .Fn hcreate_r , .Fn hdestroy , .Fn hdestroy_r +.Fn hdestroy1 , +.Fn hdestroy1_r .Fn hsearch , and .Fn hsearch_r @@ -141,33 +149,49 @@ Search the hash table without inserting .Fa item . .El .Pp -Note that the comparison -.Fa key -must be allocated using -.Xr malloc 3 -or -.Xr calloc 3 -if action is -.Dv ENTER -and -.Fn hdestroy -will be called. -This is because +The traditional .Fn hdestroy -will call +and +.Fn hdestroy_r +functions don't .Xr free 3 -for each comparison +the data associated with the +.Fa key +and +.Fa value +of each entry, because they did not allocate them. +Since there is no +.Dq iterator +function provided, the +.Fn hdestroy1 +and +.Fn hdestroy1_r +allow controlling if the .Fa key -(but not -.Fa data ) . -Typically the comparison +or +.Fa value +will be freed using the +.Fa flags +argument. +If the bit +.Dv FREE_KEY +is set, then the .Fa key -is allocated by using -.Xr strdup 3 . +of each entry will be +passed to +.Xr free 3 . +If the bit +.Dv FREE_VALUE +is set, then the +.Fa value +of each entry will be +passed to +.Xr free 3 . .Pp The .Fn hcreate_r , .Fn hdestroy_r , +.Fn hdestroy1_r , and .Fn hsearch_r functions are re-entrant versions of the above functions that can @@ -266,6 +290,7 @@ given is not found. .Xr bsearch 3 , .Xr lsearch 3 , .Xr malloc 3 , +.Xr free 3 , .Xr strcmp 3 .Sh STANDARDS The @@ -291,6 +316,13 @@ and functions are .Tn GNU extensions. +The +.Fn hdestroy1 +and +.Fn hdestroy1_r +are +.Nx +extensions. .Sh CAVEATS At least the following limitations can be mentioned: .Bl -bullet @@ -301,20 +333,5 @@ interface permits the use of only one ha .It Individual hash table entries can be added, but not deleted. .It -The standard is indecipherable about the -internal memory usage of the functions, -mentioning only that -.Do -.Fn hcreate -and -.Fn hsearch -functions may use -.Fn malloc -to allocate space -.Dc . -This limits the portability of the functions, -given that other implementations may not -.Xr free 3 -the buffer pointed by -.Fa key . +There is no iterator to scan for all entries in the table. .El Index: src/lib/libc/stdlib/hcreate.c diff -u src/lib/libc/stdlib/hcreate.c:1.8 src/lib/libc/stdlib/hcreate.c:1.9 --- src/lib/libc/stdlib/hcreate.c:1.8 Sat Sep 17 12:54:39 2011 +++ src/lib/libc/stdlib/hcreate.c Sun Jul 20 09:34:17 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: hcreate.c,v 1.8 2011/09/17 16:54:39 christos Exp $ */ +/* $NetBSD: hcreate.c,v 1.9 2014/07/20 13:34:17 christos Exp $ */ /* * Copyright (c) 2001 Christopher G. Demetriou @@ -43,7 +43,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: hcreate.c,v 1.8 2011/09/17 16:54:39 christos Exp $"); +__RCSID("$NetBSD: hcreate.c,v 1.9 2014/07/20 13:34:17 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #if !defined(lint) @@ -141,14 +141,20 @@ hcreate_r(size_t nel, struct hsearch_dat } void -hdestroy(void) +hdestroy1(int flags) { _DIAGASSERT(htable.table != NULL); - hdestroy_r(&htable); + hdestroy1_r(&htable, flags); } void -hdestroy_r(struct hsearch_data *head) +hdestroy(void) +{ + hdestroy1(0); +} + +void +hdestroy1_r(struct hsearch_data *head, int flags) { struct internal_entry *ie; size_t idx; @@ -166,13 +172,22 @@ hdestroy_r(struct hsearch_data *head) while (!SLIST_EMPTY(&table[idx])) { ie = SLIST_FIRST(&table[idx]); SLIST_REMOVE_HEAD(&table[idx], link); - free(ie->ent.key); + if (flags & FREE_KEY) + free(ie->ent.key); + if (flags & FREE_DATA) + free(ie->ent.data); free(ie); } } free(table); } +void +hdestroy_r(struct hsearch_data *head) +{ + hdestroy1_r(head, 0); +} + ENTRY * hsearch(ENTRY item, ACTION action) {