xref: /llvm-project/libc/src/stdlib/bsearch.cpp (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
132a50078SSiva Chandra Reddy //===-- Implementation of bsearch -----------------------------------------===//
232a50078SSiva Chandra Reddy //
332a50078SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
432a50078SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
532a50078SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
632a50078SSiva Chandra Reddy //
732a50078SSiva Chandra Reddy //===----------------------------------------------------------------------===//
832a50078SSiva Chandra Reddy 
932a50078SSiva Chandra Reddy #include "src/stdlib/bsearch.h"
1032a50078SSiva Chandra Reddy #include "src/__support/common.h"
11*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
1232a50078SSiva Chandra Reddy 
1332a50078SSiva Chandra Reddy #include <stdint.h>
1432a50078SSiva Chandra Reddy 
15*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
1632a50078SSiva Chandra Reddy 
1732a50078SSiva Chandra Reddy LLVM_LIBC_FUNCTION(void *, bsearch,
1832a50078SSiva Chandra Reddy                    (const void *key, const void *array, size_t array_size,
1932a50078SSiva Chandra Reddy                     size_t elem_size,
2032a50078SSiva Chandra Reddy                     int (*compare)(const void *, const void *))) {
2132a50078SSiva Chandra Reddy   if (key == nullptr || array == nullptr || array_size == 0 || elem_size == 0)
2232a50078SSiva Chandra Reddy     return nullptr;
2332a50078SSiva Chandra Reddy 
2432a50078SSiva Chandra Reddy   while (array_size > 0) {
2532a50078SSiva Chandra Reddy     size_t mid = array_size / 2;
2632a50078SSiva Chandra Reddy     const void *elem =
2732a50078SSiva Chandra Reddy         reinterpret_cast<const uint8_t *>(array) + mid * elem_size;
2832a50078SSiva Chandra Reddy     int compare_result = compare(key, elem);
2932a50078SSiva Chandra Reddy     if (compare_result == 0)
3032a50078SSiva Chandra Reddy       return const_cast<void *>(elem);
3132a50078SSiva Chandra Reddy 
3232a50078SSiva Chandra Reddy     if (compare_result < 0) {
3332a50078SSiva Chandra Reddy       // This means that key is less than the element at |mid|.
3432a50078SSiva Chandra Reddy       // So, in the next iteration, we only compare elements less
3532a50078SSiva Chandra Reddy       // than mid.
3632a50078SSiva Chandra Reddy       array_size = mid;
3732a50078SSiva Chandra Reddy     } else {
3832a50078SSiva Chandra Reddy       // |mid| is strictly less than |array_size|. So, the below
3932a50078SSiva Chandra Reddy       // decrement in |array_size| will not lead to a wrap around.
4032a50078SSiva Chandra Reddy       array_size -= (mid + 1);
4132a50078SSiva Chandra Reddy       array = reinterpret_cast<const uint8_t *>(elem) + elem_size;
4232a50078SSiva Chandra Reddy     }
4332a50078SSiva Chandra Reddy   }
4432a50078SSiva Chandra Reddy 
4532a50078SSiva Chandra Reddy   return nullptr;
4632a50078SSiva Chandra Reddy }
4732a50078SSiva Chandra Reddy 
48*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
49