am b902641d: Implement twalk(3), add unit tests.
				
					
				
			* commit 'b902641d7303d2ea24c10f6d6e7ff49e7ee75611': Implement twalk(3), add unit tests.
This commit is contained in:
		@@ -287,20 +287,18 @@ libc_upstream_netbsd_src_files := \
 | 
				
			|||||||
    upstream-netbsd/lib/libc/stdlib/div.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/div.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/drand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/drand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/erand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/erand48.c \
 | 
				
			||||||
 | 
					    upstream-netbsd/lib/libc/stdlib/insque.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/jrand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/jrand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/ldiv.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/ldiv.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/lldiv.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/lldiv.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/lrand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/lrand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/lsearch.c \
 | 
					 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/mrand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/mrand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/nrand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/nrand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/_rand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/_rand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/rand_r.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/rand_r.c \
 | 
				
			||||||
 | 
					    upstream-netbsd/lib/libc/stdlib/remque.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/seed48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/seed48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/srand48.c \
 | 
					    upstream-netbsd/lib/libc/stdlib/srand48.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/tdelete.c \
 | 
					 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/tfind.c \
 | 
					 | 
				
			||||||
    upstream-netbsd/lib/libc/stdlib/tsearch.c \
 | 
					 | 
				
			||||||
    upstream-netbsd/lib/libc/string/memccpy.c \
 | 
					    upstream-netbsd/lib/libc/string/memccpy.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/string/strcasestr.c \
 | 
					    upstream-netbsd/lib/libc/string/strcasestr.c \
 | 
				
			||||||
    upstream-netbsd/lib/libc/string/strcoll.c \
 | 
					    upstream-netbsd/lib/libc/string/strcoll.c \
 | 
				
			||||||
@@ -469,6 +467,7 @@ libc_upstream_openbsd_src_files := \
 | 
				
			|||||||
    upstream-openbsd/lib/libc/stdlib/atoll.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/atoll.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/stdlib/exit.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/exit.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/stdlib/getenv.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/getenv.c \
 | 
				
			||||||
 | 
					    upstream-openbsd/lib/libc/stdlib/lsearch.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/stdlib/setenv.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/setenv.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/stdlib/strtoimax.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/strtoimax.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/stdlib/strtol.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/strtol.c \
 | 
				
			||||||
@@ -477,6 +476,8 @@ libc_upstream_openbsd_src_files := \
 | 
				
			|||||||
    upstream-openbsd/lib/libc/stdlib/strtoull.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/strtoull.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/stdlib/strtoumax.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/strtoumax.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/stdlib/system.c \
 | 
					    upstream-openbsd/lib/libc/stdlib/system.c \
 | 
				
			||||||
 | 
					    upstream-openbsd/lib/libc/stdlib/tfind.c \
 | 
				
			||||||
 | 
					    upstream-openbsd/lib/libc/stdlib/tsearch.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/string/strcasecmp.c \
 | 
					    upstream-openbsd/lib/libc/string/strcasecmp.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/string/strcspn.c \
 | 
					    upstream-openbsd/lib/libc/string/strcspn.c \
 | 
				
			||||||
    upstream-openbsd/lib/libc/string/strdup.c \
 | 
					    upstream-openbsd/lib/libc/string/strdup.c \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								libc/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								libc/NOTICE
									
									
									
									
									
								
							@@ -55,6 +55,34 @@
 | 
				
			|||||||
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
					   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
					   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Copyright (c) 1993 John Brezak
 | 
				
			||||||
 | 
					 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. The name of the author may 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-------------------------------------------------------------------
 | 
					-------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
====================================================
 | 
					====================================================
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@
 | 
				
			|||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Destroy a tree and free all allocated resources.
 | 
					// Destroy a tree and free all allocated resources.
 | 
				
			||||||
// This is a GNU extension, not available from NetBSD.
 | 
					// This is a GNU extension, not available from BSD.
 | 
				
			||||||
void tdestroy(void* root, void (*destroy_func)(void*)) {
 | 
					void tdestroy(void* root, void (*destroy_func)(void*)) {
 | 
				
			||||||
  node_t* root_node = (node_t*) root;
 | 
					  node_t* root_node = (node_t*) root;
 | 
				
			||||||
  if (root_node == NULL) {
 | 
					  if (root_node == NULL) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,9 @@ typedef struct node {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
__BEGIN_DECLS
 | 
					__BEGIN_DECLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void insque(void*, void*);
 | 
				
			||||||
 | 
					void remque(void*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void* lfind(const void*, const void*, size_t*, size_t, int (*)(const void*, const void*));
 | 
					void* lfind(const void*, const void*, size_t*, size_t, int (*)(const void*, const void*));
 | 
				
			||||||
void* lsearch(const void*, void*, size_t*, size_t, int (*)(const void*, const void*));
 | 
					void* lsearch(const void*, void*, size_t*, size_t, int (*)(const void*, const void*));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										58
									
								
								libc/upstream-netbsd/lib/libc/stdlib/insque.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								libc/upstream-netbsd/lib/libc/stdlib/insque.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  Copyright (c) 1993 John Brezak
 | 
				
			||||||
 | 
					 *  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. The name of the author may 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/cdefs.h>
 | 
				
			||||||
 | 
					#if defined(LIBC_SCCS) && !defined(lint)
 | 
				
			||||||
 | 
					__RCSID("$NetBSD: insque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
 | 
				
			||||||
 | 
					#endif /* LIBC_SCCS and not lint */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <search.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct qelem {
 | 
				
			||||||
 | 
					        struct qelem *q_forw;
 | 
				
			||||||
 | 
					        struct qelem *q_back;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					insque(void *entry, void *pred)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct qelem *e = (struct qelem *) entry;
 | 
				
			||||||
 | 
						struct qelem *p = (struct qelem *) pred;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_DIAGASSERT(e != 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						e->q_back = p;
 | 
				
			||||||
 | 
						if (p) {
 | 
				
			||||||
 | 
							e->q_forw = p->q_forw;
 | 
				
			||||||
 | 
							if (p->q_forw)
 | 
				
			||||||
 | 
								p->q_forw->q_back = e;
 | 
				
			||||||
 | 
							p->q_forw = e;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							e->q_forw = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										53
									
								
								libc/upstream-netbsd/lib/libc/stdlib/remque.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								libc/upstream-netbsd/lib/libc/stdlib/remque.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  Copyright (c) 1993 John Brezak
 | 
				
			||||||
 | 
					 *  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. The name of the author may 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/cdefs.h>
 | 
				
			||||||
 | 
					#if defined(LIBC_SCCS) && !defined(lint)
 | 
				
			||||||
 | 
					__RCSID("$NetBSD: remque.c,v 1.3 2012/06/25 22:32:45 abs Exp $");
 | 
				
			||||||
 | 
					#endif /* LIBC_SCCS and not lint */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <search.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct qelem {
 | 
				
			||||||
 | 
					        struct qelem *q_forw;
 | 
				
			||||||
 | 
					        struct qelem *q_back;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					remque(void *element)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct qelem *e = (struct qelem *) element;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_DIAGASSERT(e != 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (e->q_forw)
 | 
				
			||||||
 | 
							e->q_forw->q_back = e->q_back;
 | 
				
			||||||
 | 
						if (e->q_back)
 | 
				
			||||||
 | 
							e->q_back->q_forw = e->q_forw;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,67 +0,0 @@
 | 
				
			|||||||
/*	$NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $	*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
 | 
					 | 
				
			||||||
 * the AT&T man page says.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The node_t structure is for internal use only, lint doesn't grok it.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Written by reading the System V Interface Definition, not the code.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Totally public domain.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/cdefs.h>
 | 
					 | 
				
			||||||
#if defined(LIBC_SCCS) && !defined(lint)
 | 
					 | 
				
			||||||
__RCSID("$NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $");
 | 
					 | 
				
			||||||
#endif /* LIBC_SCCS and not lint */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#define _SEARCH_PRIVATE
 | 
					 | 
				
			||||||
#include <search.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* find a node with key "vkey" in tree "vrootp" */
 | 
					 | 
				
			||||||
void *
 | 
					 | 
				
			||||||
tdelete(const void *vkey, void **vrootp,
 | 
					 | 
				
			||||||
    int (*compar)(const void *, const void *))
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	node_t **rootp = (node_t **)vrootp;
 | 
					 | 
				
			||||||
	node_t *p, *q, *r;
 | 
					 | 
				
			||||||
	int  cmp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_DIAGASSERT(vkey != NULL);
 | 
					 | 
				
			||||||
	_DIAGASSERT(compar != NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rootp == NULL || (p = *rootp) == NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
 | 
					 | 
				
			||||||
		p = *rootp;
 | 
					 | 
				
			||||||
		rootp = (cmp < 0) ?
 | 
					 | 
				
			||||||
		    &(*rootp)->llink :		/* follow llink branch */
 | 
					 | 
				
			||||||
		    &(*rootp)->rlink;		/* follow rlink branch */
 | 
					 | 
				
			||||||
		if (*rootp == NULL)
 | 
					 | 
				
			||||||
			return NULL;		/* key not found */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r = (*rootp)->rlink;			/* D1: */
 | 
					 | 
				
			||||||
	if ((q = (*rootp)->llink) == NULL)	/* Left NULL? */
 | 
					 | 
				
			||||||
		q = r;
 | 
					 | 
				
			||||||
	else if (r != NULL) {			/* Right link is NULL? */
 | 
					 | 
				
			||||||
		if (r->llink == NULL) {		/* D2: Find successor */
 | 
					 | 
				
			||||||
			r->llink = q;
 | 
					 | 
				
			||||||
			q = r;
 | 
					 | 
				
			||||||
		} else {			/* D3: Find NULL link */
 | 
					 | 
				
			||||||
			for (q = r->llink; q->llink != NULL; q = r->llink)
 | 
					 | 
				
			||||||
				r = q;
 | 
					 | 
				
			||||||
			r->llink = q->rlink;
 | 
					 | 
				
			||||||
			q->llink = (*rootp)->llink;
 | 
					 | 
				
			||||||
			q->rlink = (*rootp)->rlink;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (p != *rootp)
 | 
					 | 
				
			||||||
		free(*rootp);			/* D4: Free node */
 | 
					 | 
				
			||||||
	*rootp = q;				/* link parent to new node */
 | 
					 | 
				
			||||||
	return p;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,47 +0,0 @@
 | 
				
			|||||||
/*	$NetBSD: tfind.c,v 1.7 2012/06/25 22:32:45 abs Exp $	*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
 | 
					 | 
				
			||||||
 * the AT&T man page says.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The node_t structure is for internal use only, lint doesn't grok it.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Written by reading the System V Interface Definition, not the code.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Totally public domain.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/cdefs.h>
 | 
					 | 
				
			||||||
#if defined(LIBC_SCCS) && !defined(lint)
 | 
					 | 
				
			||||||
__RCSID("$NetBSD: tfind.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
 | 
					 | 
				
			||||||
#endif /* LIBC_SCCS and not lint */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#define _SEARCH_PRIVATE
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <search.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* find a node by key "vkey" in tree "vrootp", or return 0 */
 | 
					 | 
				
			||||||
void *
 | 
					 | 
				
			||||||
tfind(const void *vkey, void * const *vrootp,
 | 
					 | 
				
			||||||
    int (*compar)(const void *, const void *))
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	node_t * const *rootp = (node_t * const*)vrootp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_DIAGASSERT(vkey != NULL);
 | 
					 | 
				
			||||||
	_DIAGASSERT(compar != NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rootp == NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (*rootp != NULL) {		/* T1: */
 | 
					 | 
				
			||||||
		int r;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
 | 
					 | 
				
			||||||
			return *rootp;		/* key found */
 | 
					 | 
				
			||||||
		rootp = (r < 0) ?
 | 
					 | 
				
			||||||
		    &(*rootp)->llink :		/* T3: follow left branch */
 | 
					 | 
				
			||||||
		    &(*rootp)->rlink;		/* T4: follow right branch */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,56 +0,0 @@
 | 
				
			|||||||
/*	$NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $	*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
 | 
					 | 
				
			||||||
 * the AT&T man page says.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The node_t structure is for internal use only, lint doesn't grok it.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Written by reading the System V Interface Definition, not the code.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Totally public domain.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/cdefs.h>
 | 
					 | 
				
			||||||
#if defined(LIBC_SCCS) && !defined(lint)
 | 
					 | 
				
			||||||
__RCSID("$NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
 | 
					 | 
				
			||||||
#endif /* LIBC_SCCS and not lint */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#define _SEARCH_PRIVATE
 | 
					 | 
				
			||||||
#include <search.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* find or insert datum into search tree */
 | 
					 | 
				
			||||||
void *
 | 
					 | 
				
			||||||
tsearch(const void *vkey, void **vrootp,
 | 
					 | 
				
			||||||
    int (*compar)(const void *, const void *))
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	node_t *q;
 | 
					 | 
				
			||||||
	node_t **rootp = (node_t **)vrootp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_DIAGASSERT(vkey != NULL);
 | 
					 | 
				
			||||||
	_DIAGASSERT(compar != NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (rootp == NULL)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (*rootp != NULL) {	/* Knuth's T1: */
 | 
					 | 
				
			||||||
		int r;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
 | 
					 | 
				
			||||||
			return *rootp;		/* we found it! */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		rootp = (r < 0) ?
 | 
					 | 
				
			||||||
		    &(*rootp)->llink :		/* T3: follow left branch */
 | 
					 | 
				
			||||||
		    &(*rootp)->rlink;		/* T4: follow right branch */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	q = malloc(sizeof(node_t));		/* T5: key not found */
 | 
					 | 
				
			||||||
	if (q != 0) {				/* make new node */
 | 
					 | 
				
			||||||
		*rootp = q;			/* link new node to old */
 | 
					 | 
				
			||||||
		q->key = __UNCONST(vkey);	/* initialize new node */
 | 
					 | 
				
			||||||
		q->llink = q->rlink = NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return q;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					/*	$OpenBSD: lsearch.c,v 1.5 2014/07/18 04:16:09 matthew Exp $	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright (c) 1989, 1993
 | 
					 * Copyright (c) 1989, 1993
 | 
				
			||||||
 *	The Regents of the University of California.  All rights reserved.
 | 
					 *	The Regents of the University of California.  All rights reserved.
 | 
				
			||||||
@@ -30,24 +32,12 @@
 | 
				
			|||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sys/cdefs.h>
 | 
					 | 
				
			||||||
#if defined(LIBC_SCCS) && !defined(lint)
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
static char sccsid[] = "@(#)lsearch.c	8.1 (Berkeley) 6/4/93";
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
__RCSID("$NetBSD: lsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#endif /* LIBC_SCCS and not lint */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <assert.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <search.h>
 | 
					#include <search.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*cmp_fn_t)(const void *, const void *);
 | 
					typedef int (*cmp_fn_t)(const void *, const void *);
 | 
				
			||||||
static void *linear_base(const void *, void *, size_t *, size_t,
 | 
					static void *linear_base(const void *, const void *, size_t *, size_t,
 | 
				
			||||||
    cmp_fn_t, int);
 | 
					    cmp_fn_t, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *
 | 
					void *
 | 
				
			||||||
@@ -55,10 +45,6 @@ lsearch(const void *key, void *base, size_t *nelp, size_t width,
 | 
				
			|||||||
    	cmp_fn_t compar)
 | 
					    	cmp_fn_t compar)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_DIAGASSERT(key != NULL);
 | 
					 | 
				
			||||||
	_DIAGASSERT(base != NULL);
 | 
					 | 
				
			||||||
	_DIAGASSERT(compar != NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return(linear_base(key, base, nelp, width, compar, 1));
 | 
						return(linear_base(key, base, nelp, width, compar, 1));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,28 +52,19 @@ void *
 | 
				
			|||||||
lfind(const void *key, const void *base, size_t *nelp, size_t width,
 | 
					lfind(const void *key, const void *base, size_t *nelp, size_t width,
 | 
				
			||||||
	cmp_fn_t compar)
 | 
						cmp_fn_t compar)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						return(linear_base(key, base, nelp, width, compar, 0));
 | 
				
			||||||
	_DIAGASSERT(key != NULL);
 | 
					 | 
				
			||||||
	_DIAGASSERT(base != NULL);
 | 
					 | 
				
			||||||
	_DIAGASSERT(compar != NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return(linear_base(key, __UNCONST(base), nelp, width, compar, 0));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *
 | 
					static void *
 | 
				
			||||||
linear_base(const void *key, void *base, size_t *nelp, size_t width,
 | 
					linear_base(const void *key, const void *base, size_t *nelp, size_t width,
 | 
				
			||||||
	cmp_fn_t compar, int add_flag)
 | 
						cmp_fn_t compar, int add_flag)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *element, *end;
 | 
						const char *element, *end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_DIAGASSERT(key != NULL);
 | 
						end = (const char *)base + *nelp * width;
 | 
				
			||||||
	_DIAGASSERT(base != NULL);
 | 
						for (element = base; element < end; element += width)
 | 
				
			||||||
	_DIAGASSERT(compar != NULL);
 | 
							if (!compar(key, element))		/* key found */
 | 
				
			||||||
 | 
								return((void *)element);
 | 
				
			||||||
	end = (char *)base + *nelp * width;
 | 
					 | 
				
			||||||
	for (element = (char *)base; element < end; element += width)
 | 
					 | 
				
			||||||
		if (!compar(element, key))		/* key found */
 | 
					 | 
				
			||||||
			return element;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!add_flag)					/* key not found */
 | 
						if (!add_flag)					/* key not found */
 | 
				
			||||||
		return(NULL);
 | 
							return(NULL);
 | 
				
			||||||
@@ -102,6 +79,6 @@ linear_base(const void *key, void *base, size_t *nelp, size_t width,
 | 
				
			|||||||
	 * manual.
 | 
						 * manual.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	++*nelp;
 | 
						++*nelp;
 | 
				
			||||||
	memcpy(end, key, width);
 | 
						memcpy((void *)end, key, width);
 | 
				
			||||||
	return end;
 | 
						return((void *)end);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								libc/upstream-openbsd/lib/libc/stdlib/tfind.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								libc/upstream-openbsd/lib/libc/stdlib/tfind.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					/*	$OpenBSD: tfind.c,v 1.6 2014/03/16 18:38:30 guenther Exp $	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
 | 
				
			||||||
 | 
					 * the AT&T man page says.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The node_t structure is for internal use only
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by reading the System V Interface Definition, not the code.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Totally public domain.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/*LINTLIBRARY*/
 | 
				
			||||||
 | 
					#include <search.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct node_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char	  *key;
 | 
				
			||||||
 | 
					    struct node_t *llink, *rlink;
 | 
				
			||||||
 | 
					} node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* find a node, or return 0 */
 | 
				
			||||||
 | 
					void *
 | 
				
			||||||
 | 
					tfind(const void *vkey, void * const *vrootp,
 | 
				
			||||||
 | 
					    int (*compar)(const void *, const void *))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    char *key = (char *)vkey;
 | 
				
			||||||
 | 
					    node **rootp = (node **)vrootp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rootp == (struct node_t **)0)
 | 
				
			||||||
 | 
						return ((struct node_t *)0);
 | 
				
			||||||
 | 
					    while (*rootp != (struct node_t *)0) {	/* T1: */
 | 
				
			||||||
 | 
						int r;
 | 
				
			||||||
 | 
						if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
 | 
				
			||||||
 | 
						    return (*rootp);		/* key found */
 | 
				
			||||||
 | 
						rootp = (r < 0) ?
 | 
				
			||||||
 | 
						    &(*rootp)->llink :		/* T3: follow left branch */
 | 
				
			||||||
 | 
						    &(*rootp)->rlink;		/* T4: follow right branch */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (node *)0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										119
									
								
								libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								libc/upstream-openbsd/lib/libc/stdlib/tsearch.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					/*	$OpenBSD: tsearch.c,v 1.8 2014/03/16 18:38:30 guenther Exp $	*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
 | 
				
			||||||
 | 
					 * the AT&T man page says.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The node_t structure is for internal use only
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by reading the System V Interface Definition, not the code.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Totally public domain.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/*LINTLIBRARY*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <search.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct node_t {
 | 
				
			||||||
 | 
					    char	  *key;
 | 
				
			||||||
 | 
					    struct node_t *left, *right;
 | 
				
			||||||
 | 
					} node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* find or insert datum into search tree */
 | 
				
			||||||
 | 
					void *
 | 
				
			||||||
 | 
					tsearch(const void *vkey, void **vrootp,
 | 
				
			||||||
 | 
					    int (*compar)(const void *, const void *))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    node *q;
 | 
				
			||||||
 | 
					    char *key = (char *)vkey;
 | 
				
			||||||
 | 
					    node **rootp = (node **)vrootp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rootp == (struct node_t **)0)
 | 
				
			||||||
 | 
						return ((void *)0);
 | 
				
			||||||
 | 
					    while (*rootp != (struct node_t *)0) {	/* Knuth's T1: */
 | 
				
			||||||
 | 
						int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
 | 
				
			||||||
 | 
						    return ((void *)*rootp);		/* we found it! */
 | 
				
			||||||
 | 
						rootp = (r < 0) ?
 | 
				
			||||||
 | 
						    &(*rootp)->left :		/* T3: follow left branch */
 | 
				
			||||||
 | 
						    &(*rootp)->right;		/* T4: follow right branch */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    q = (node *) malloc(sizeof(node));	/* T5: key not found */
 | 
				
			||||||
 | 
					    if (q != (struct node_t *)0) {	/* make new node */
 | 
				
			||||||
 | 
						*rootp = q;			/* link new node to old */
 | 
				
			||||||
 | 
						q->key = key;			/* initialize new node */
 | 
				
			||||||
 | 
						q->left = q->right = (struct node_t *)0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ((void *)q);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* delete node with given key */
 | 
				
			||||||
 | 
					void *
 | 
				
			||||||
 | 
					tdelete(const void *vkey, void **vrootp,
 | 
				
			||||||
 | 
					    int (*compar)(const void *, const void *))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    node **rootp = (node **)vrootp;
 | 
				
			||||||
 | 
					    char *key = (char *)vkey;
 | 
				
			||||||
 | 
					    node *p = (node *)1;
 | 
				
			||||||
 | 
					    node *q;
 | 
				
			||||||
 | 
					    node *r;
 | 
				
			||||||
 | 
					    int cmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rootp == (struct node_t **)0 || *rootp == (struct node_t *)0)
 | 
				
			||||||
 | 
						return ((struct node_t *)0);
 | 
				
			||||||
 | 
					    while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
 | 
				
			||||||
 | 
						p = *rootp;
 | 
				
			||||||
 | 
						rootp = (cmp < 0) ?
 | 
				
			||||||
 | 
						    &(*rootp)->left :		/* follow left branch */
 | 
				
			||||||
 | 
						    &(*rootp)->right;		/* follow right branch */
 | 
				
			||||||
 | 
						if (*rootp == (struct node_t *)0)
 | 
				
			||||||
 | 
						    return ((void *)0);		/* key not found */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    r = (*rootp)->right;			/* D1: */
 | 
				
			||||||
 | 
					    if ((q = (*rootp)->left) == (struct node_t *)0)	/* Left (struct node_t *)0? */
 | 
				
			||||||
 | 
						q = r;
 | 
				
			||||||
 | 
					    else if (r != (struct node_t *)0) {		/* Right link is null? */
 | 
				
			||||||
 | 
						if (r->left == (struct node_t *)0) {	/* D2: Find successor */
 | 
				
			||||||
 | 
						    r->left = q;
 | 
				
			||||||
 | 
						    q = r;
 | 
				
			||||||
 | 
						} else {			/* D3: Find (struct node_t *)0 link */
 | 
				
			||||||
 | 
						    for (q = r->left; q->left != (struct node_t *)0; q = r->left)
 | 
				
			||||||
 | 
							r = q;
 | 
				
			||||||
 | 
						    r->left = q->right;
 | 
				
			||||||
 | 
						    q->left = (*rootp)->left;
 | 
				
			||||||
 | 
						    q->right = (*rootp)->right;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    free((struct node_t *) *rootp);	/* D4: Free node */
 | 
				
			||||||
 | 
					    *rootp = q;				/* link parent to new node */
 | 
				
			||||||
 | 
					    return(p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Walk the nodes of a tree */
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
 | 
				
			||||||
 | 
						(*action)(root, leaf, level);
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						(*action)(root, preorder, level);
 | 
				
			||||||
 | 
						if (root->left != (struct node_t *)0)
 | 
				
			||||||
 | 
						    trecurse(root->left, action, level + 1);
 | 
				
			||||||
 | 
						(*action)(root, postorder, level);
 | 
				
			||||||
 | 
						if (root->right != (struct node_t *)0)
 | 
				
			||||||
 | 
						    trecurse(root->right, action, level + 1);
 | 
				
			||||||
 | 
						(*action)(root, endorder, level);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Walk the nodes of a tree */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					twalk(const void *vroot, void (*action)(const void *, VISIT, int))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    node *root = (node *)vroot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
 | 
				
			||||||
 | 
						trecurse(root, action, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -85,6 +85,7 @@ libBionicStandardTests_src_files := \
 | 
				
			|||||||
    pthread_test.cpp \
 | 
					    pthread_test.cpp \
 | 
				
			||||||
    regex_test.cpp \
 | 
					    regex_test.cpp \
 | 
				
			||||||
    sched_test.cpp \
 | 
					    sched_test.cpp \
 | 
				
			||||||
 | 
					    search_test.cpp \
 | 
				
			||||||
    signal_test.cpp \
 | 
					    signal_test.cpp \
 | 
				
			||||||
    stack_protector_test.cpp \
 | 
					    stack_protector_test.cpp \
 | 
				
			||||||
    stack_unwinding_test.cpp \
 | 
					    stack_unwinding_test.cpp \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										210
									
								
								tests/search_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								tests/search_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 The Android Open Source Project
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <gtest/gtest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <search.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int int_cmp(const void* lhs, const void* rhs) {
 | 
				
			||||||
 | 
					  return *reinterpret_cast<const int*>(rhs) - *reinterpret_cast<const int*>(lhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(search, lfind_lsearch) {
 | 
				
			||||||
 | 
					  int xs[10];
 | 
				
			||||||
 | 
					  memset(xs, 0, sizeof(xs));
 | 
				
			||||||
 | 
					  size_t x_size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int needle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // lfind(3) can't find '2' in the empty table.
 | 
				
			||||||
 | 
					  needle = 2;
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(0U, x_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // lsearch(3) will add it.
 | 
				
			||||||
 | 
					  ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(2, xs[0]);
 | 
				
			||||||
 | 
					  ASSERT_EQ(1U, x_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // And then lfind(3) can find it.
 | 
				
			||||||
 | 
					  ASSERT_EQ(&xs[0], lfind(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(1U, x_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Inserting a duplicate does nothing (but returns the existing element).
 | 
				
			||||||
 | 
					  ASSERT_EQ(&xs[0], lsearch(&needle, xs, &x_size, sizeof(xs[0]), int_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(1U, x_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct node {
 | 
				
			||||||
 | 
					  node(const char* s) : s(strdup(s)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  char* s;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int node_cmp(const void* lhs, const void* rhs) {
 | 
				
			||||||
 | 
					  return strcmp(reinterpret_cast<const node*>(lhs)->s, reinterpret_cast<const node*>(rhs)->s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static std::vector<std::string> g_nodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void node_walk(const void* p, VISIT order, int) {
 | 
				
			||||||
 | 
					  const node* n = *reinterpret_cast<const node* const*>(p);
 | 
				
			||||||
 | 
					  if (order == postorder || order == leaf)  {
 | 
				
			||||||
 | 
					    g_nodes.push_back(n->s);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static size_t g_free_calls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void node_free(void* p) {
 | 
				
			||||||
 | 
					  node* n = reinterpret_cast<node*>(p);
 | 
				
			||||||
 | 
					  free(n->s);
 | 
				
			||||||
 | 
					  ++g_free_calls;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(search, tfind_tsearch_twalk_tdestroy) {
 | 
				
			||||||
 | 
					  void* root = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  node n1("z");
 | 
				
			||||||
 | 
					  node n2("a");
 | 
				
			||||||
 | 
					  node n3("m");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // tfind(3) can't find anything in the empty tree.
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, tfind(&n1, &root, node_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // tsearch(3) inserts and returns a pointer to a new node.
 | 
				
			||||||
 | 
					  void* i1 = tsearch(&n1, &root, node_cmp);
 | 
				
			||||||
 | 
					  ASSERT_NE(nullptr, i1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // ...which tfind(3) will then return.
 | 
				
			||||||
 | 
					  ASSERT_EQ(i1, tfind(&n1, &root, node_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, tfind(&n2, &root, node_cmp));
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, tfind(&n3, &root, node_cmp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Add the other nodes.
 | 
				
			||||||
 | 
					  ASSERT_NE(nullptr, tsearch(&n2, &root, node_cmp));
 | 
				
			||||||
 | 
					  ASSERT_NE(nullptr, tsearch(&n3, &root, node_cmp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Use twalk(3) to iterate over the nodes.
 | 
				
			||||||
 | 
					  g_nodes.clear();
 | 
				
			||||||
 | 
					  twalk(root, node_walk);
 | 
				
			||||||
 | 
					  ASSERT_EQ(3U, g_nodes.size());
 | 
				
			||||||
 | 
					  ASSERT_EQ("a", g_nodes[0]);
 | 
				
			||||||
 | 
					  ASSERT_EQ("m", g_nodes[1]);
 | 
				
			||||||
 | 
					  ASSERT_EQ("z", g_nodes[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // tdestroy(3) removes nodes under a node, calling our callback to destroy each one.
 | 
				
			||||||
 | 
					  g_free_calls = 0;
 | 
				
			||||||
 | 
					  tdestroy(root, node_free);
 | 
				
			||||||
 | 
					  ASSERT_EQ(3U, g_free_calls);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct pod_node {
 | 
				
			||||||
 | 
					  pod_node(int i) : i(i) {}
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pod_node_cmp(const void* lhs, const void* rhs) {
 | 
				
			||||||
 | 
					  return reinterpret_cast<const pod_node*>(rhs)->i - reinterpret_cast<const pod_node*>(lhs)->i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(search, tdelete) {
 | 
				
			||||||
 | 
					  void* root = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pod_node n1(123);
 | 
				
			||||||
 | 
					  ASSERT_NE(nullptr, tsearch(&n1, &root, pod_node_cmp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // tdelete(3) leaks n1.
 | 
				
			||||||
 | 
					  pod_node not_there(456);
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, tdelete(¬_there, &root, pod_node_cmp));
 | 
				
			||||||
 | 
					  ASSERT_NE(nullptr, tdelete(&n1, &root, pod_node_cmp));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct q_node {
 | 
				
			||||||
 | 
					  q_node(int i) : i(i) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  q_node* next;
 | 
				
			||||||
 | 
					  q_node* prev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(search, insque_remque) {
 | 
				
			||||||
 | 
					  q_node zero(0);
 | 
				
			||||||
 | 
					  q_node one(1);
 | 
				
			||||||
 | 
					  q_node two(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Linear (not circular).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  insque(&zero, NULL);
 | 
				
			||||||
 | 
					  insque(&one, &zero);
 | 
				
			||||||
 | 
					  insque(&two, &one);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int expected = 0;
 | 
				
			||||||
 | 
					  for (q_node* q = &zero; q != NULL; q = q->next) {
 | 
				
			||||||
 | 
					    ASSERT_EQ(expected, q->i);
 | 
				
			||||||
 | 
					    ++expected;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ASSERT_EQ(3, expected);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (q_node* q = &two; q != NULL; q = q->prev) {
 | 
				
			||||||
 | 
					    --expected;
 | 
				
			||||||
 | 
					    ASSERT_EQ(expected, q->i);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, expected);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  q_node* head = &zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  remque(&one);
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(2, head->next->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, head->next->next);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  remque(&two);
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(nullptr, head->next);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  remque(&zero);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Circular.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  zero.next = &zero;
 | 
				
			||||||
 | 
					  zero.prev = &zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  insque(&one, &zero);
 | 
				
			||||||
 | 
					  insque(&two, &one);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(1, head->next->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(2, head->next->next->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->next->next->next->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(1, head->next->next->next->next->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(2, head->next->next->next->next->next->i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  remque(&one);
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(2, head->next->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->next->next->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(2, head->next->next->next->i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  remque(&two);
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->i);
 | 
				
			||||||
 | 
					  ASSERT_EQ(0, head->next->i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  remque(&zero);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user