bsearch.c revision 74840
174840Sken/*
274840Sken * Copyright (c) 1990, 1993
374840Sken *	The Regents of the University of California.  All rights reserved.
474840Sken *
574840Sken * Redistribution and use in source and binary forms, with or without
674840Sken * modification, are permitted provided that the following conditions
774840Sken * are met:
874840Sken * 1. Redistributions of source code must retain the above copyright
974840Sken *    notice, this list of conditions and the following disclaimer.
1074840Sken * 2. Redistributions in binary form must reproduce the above copyright
1174840Sken *    notice, this list of conditions and the following disclaimer in the
1274840Sken *    documentation and/or other materials provided with the distribution.
1374840Sken * 3. All advertising materials mentioning features or use of this software
1474840Sken *    must display the following acknowledgement:
1574840Sken *	This product includes software developed by the University of
1674840Sken *	California, Berkeley and its contributors.
1774840Sken * 4. Neither the name of the University nor the names of its contributors
1874840Sken *    may be used to endorse or promote products derived from this software
1974840Sken *    without specific prior written permission.
2074840Sken *
2174840Sken * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2274840Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2374840Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2474840Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2574840Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2674840Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2774840Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2874840Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2974840Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3074840Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3174840Sken * SUCH DAMAGE.
3274840Sken *
3374840Sken * $FreeBSD: head/sys/libkern/bsearch.c 74840 2001-03-27 05:45:52Z ken $
3474840Sken */
3574840Sken
3674840Sken#if defined(LIBC_SCCS) && !defined(lint)
3774840Skenstatic char sccsid[] = "@(#)bsearch.c	8.1 (Berkeley) 6/4/93";
3874840Sken#endif /* LIBC_SCCS and not lint */
3974840Sken
4074840Sken#include <stddef.h>
4174840Sken#include <stdlib.h>
4274840Sken
4374840Sken/*
4474840Sken * Perform a binary search.
4574840Sken *
4674840Sken * The code below is a bit sneaky.  After a comparison fails, we
4774840Sken * divide the work in half by moving either left or right. If lim
4874840Sken * is odd, moving left simply involves halving lim: e.g., when lim
4974840Sken * is 5 we look at item 2, so we change lim to 2 so that we will
5074840Sken * look at items 0 & 1.  If lim is even, the same applies.  If lim
5174840Sken * is odd, moving right again involes halving lim, this time moving
5274840Sken * the base up one item past p: e.g., when lim is 5 we change base
5374840Sken * to item 3 and make lim 2 so that we will look at items 3 and 4.
5474840Sken * If lim is even, however, we have to shrink it by one before
5574840Sken * halving: e.g., when lim is 4, we still looked at item 2, so we
5674840Sken * have to make lim 3, then halve, obtaining 1, so that we will only
5774840Sken * look at item 3.
5874840Sken */
5974840Skenvoid *
6074840Skenbsearch(key, base0, nmemb, size, compar)
6174840Sken	register const void *key;
6274840Sken	const void *base0;
6374840Sken	size_t nmemb;
6474840Sken	register size_t size;
6574840Sken	register int (*compar) __P((const void *, const void *));
6674840Sken{
6774840Sken	register const char *base = base0;
6874840Sken	register size_t lim;
6974840Sken	register int cmp;
7074840Sken	register const void *p;
7174840Sken
7274840Sken	for (lim = nmemb; lim != 0; lim >>= 1) {
7374840Sken		p = base + (lim >> 1) * size;
7474840Sken		cmp = (*compar)(key, p);
7574840Sken		if (cmp == 0)
7674840Sken			return ((void *)p);
7774840Sken		if (cmp > 0) {	/* key > p: move right */
7874840Sken			base = (const char *)p + size;
7974840Sken			lim--;
8074840Sken		}		/* else move left */
8174840Sken	}
8274840Sken	return (NULL);
8374840Sken}
84