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.
This commit is contained in:
parent
d42187770d
commit
842ee049dd
@ -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 <jtc@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 */
|
||||
|
||||
|
@ -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 unsetenv.3 getenv.3 putenv.3
|
||||
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
|
||||
|
@ -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
|
||||
The traditional
|
||||
.Fn hdestroy
|
||||
and
|
||||
.Fn hdestroy
|
||||
will be called.
|
||||
This is because
|
||||
.Fn hdestroy
|
||||
will call
|
||||
.Fn hdestroy_r
|
||||
functions don't
|
||||
.Xr free 3
|
||||
for each comparison
|
||||
the data associated with the
|
||||
.Fa key
|
||||
(but not
|
||||
.Fa data ) .
|
||||
Typically the comparison
|
||||
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
|
||||
is allocated by using
|
||||
.Xr strdup 3 .
|
||||
or
|
||||
.Fa value
|
||||
will be freed using the
|
||||
.Fa flags
|
||||
argument.
|
||||
If the bit
|
||||
.Dv FREE_KEY
|
||||
is set, then the
|
||||
.Fa key
|
||||
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 hash table at a time.
|
||||
.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
|
||||
|
@ -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_data *head)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user