/**************************************************************************** * libc/stdlib/lib_bsearch.c * * Copyright (c) 1990, 1993 * The Regents of the University of California. 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 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. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: bsearch * * Description: * The bsearch() function will search an array of nel objects, the initial * element of which is pointed to by 'base', for an element that matches * the object pointed to by 'key'. The size of each element in the array * is specified by 'width'. If the nel argument has the value zero, the * comparison function pointed to by 'compar' will not be called and no * match will be found. * * The comparison function pointed to by 'compar' will be called with two * arguments that point to the 'key' object and to an array element, in * that order. * * The application will ensure that the comparison function pointed to by * 'compar 'does not alter the contents of the array. The implementation * may reorder elements of the array between calls to the comparison * function, but will not alter the contents of any individual element. * * The implementation will ensure that the first argument is always a * pointer to the 'key'. * * When the same objects (consisting of width bytes, irrespective of their * current positions in the array) are passed more than once to the * comparison function, the results will be consistent with one another. * That is, the same object will always compare the same way with the key. * * The application will ensure that the function returns an integer less * than, equal to, or greater than 0 if the key object is considered, * respectively, to be less than, to match, or to be greater than the * array element. The application will ensure that the array consists of * all the elements that compare less than, all the elements that compare * equal to, and all the elements that compare greater than the key * object, in that order. * * (Based on description from OpenGroup.org). * * Returned Value: * The bsearch() function will return a pointer to a matching member of * the array, or a null pointer if no match is found. If two or more * members compare equal, which member is returned is unspecified. * * Notes from the NetBSD version: * The code below is a bit sneaky. After a comparison fails, we divide * the work in half by moving either left or right. If 'lim' is odd, * moving left simply involves halving 'lim': e.g., when 'lim' is 5 we * look at item 2, so we change 'lim' to 2 so that we will look at items * 0 & 1. If 'lim' is even, the same applies. If 'lim' is odd, moving * right again involes halving 'lim', this time moving the base up one * item past 'middle': e.g., when 'lim' is 5 we change base to item 3 and * make 'lim' 2 so that we will look at items 3 and 4. If 'lim' is * even, however, we have to shrink it by one before halving: e.g., * when 'lim' is 4, we still looked at item 2, so we have to make 'lim' * 3, then halve, obtaining 1, so that we will only look at item 3. * ****************************************************************************/ FAR void *bsearch(FAR const void *key, FAR const void *base, size_t nel, size_t width, CODE int (*compar)(FAR const void *, FAR const void *)) { FAR const void *middle; /* Current entry being tested */ FAR const char *lower; /* The lower limit of the search region */ size_t lim; /* The number of elements in the region */ int cmp; /* Boolean comparison result */ DEBUGASSERT(key != NULL); DEBUGASSERT(base != NULL || nel == 0); DEBUGASSERT(compar != NULL); for (lim = nel, lower = (const char *)base; lim != 0; lim >>= 1) { middle = lower + (lim >> 1) * width; cmp = (*compar)(key, middle); if (cmp == 0) { return (FAR void *)middle; } if (cmp > 0) { /* key > middle: move right (else move left) */ lower = (FAR const char *)middle + width; lim--; } } return NULL; }