diff --git a/CODEOWNERS b/CODEOWNERS index 55e9ef62e39..ee1f3f1e7f4 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -237,6 +237,7 @@ /lib/gui/ @vanwinkeljan /lib/os/ @andrewboie @andyross /lib/posix/ @pfalcon +/lib/libc/minimal/source/stdlib/bsearch.c @balajikulkarni /kernel/device.c @andrewboie @andyross @nashif /kernel/idle.c @andrewboie @andyross @nashif /samples/basic/servo_motor/*microbit* @jhe diff --git a/lib/libc/minimal/CMakeLists.txt b/lib/libc/minimal/CMakeLists.txt index c6698c7ac0e..a0fdde04d02 100644 --- a/lib/libc/minimal/CMakeLists.txt +++ b/lib/libc/minimal/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources( source/stdlib/strtol.c source/stdlib/strtoul.c source/stdlib/malloc.c + source/stdlib/bsearch.c source/string/strncasecmp.c source/string/strstr.c source/string/string.c diff --git a/lib/libc/minimal/include/stdlib.h b/lib/libc/minimal/include/stdlib.h index 136a786d734..25f3cbe71ac 100644 --- a/lib/libc/minimal/include/stdlib.h +++ b/lib/libc/minimal/include/stdlib.h @@ -24,6 +24,10 @@ void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void *reallocarray(void *ptr, size_t nmemb, size_t size); +void *bsearch(const void *key, const void *array, + size_t count, size_t size, + int (*cmp)(const void *key, const void *element)); + int rand(void); #define abs(x) ((x) < 0 ? -(x) : (x)) diff --git a/lib/libc/minimal/source/stdlib/bsearch.c b/lib/libc/minimal/source/stdlib/bsearch.c new file mode 100644 index 00000000000..2cee17c9252 --- /dev/null +++ b/lib/libc/minimal/source/stdlib/bsearch.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 Balaji Kulkarni + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/** + * @brief Generic implementation of Binary Search + * + * @param key pointer to first element to search + * @param array pointer to item being searched for + * @param count number of elements + * @param size size of each element + * @param cmp pointer to comparison function + * + * @return pointer to key if present in the array, or NULL otherwise + */ + +void *bsearch(const void *key, const void *array, size_t count, size_t size, + int (*cmp)(const void *key, const void *element)) +{ + size_t low = 0; + size_t high = count; + size_t index; + int result; + const char *pivot; + + while (low < high) { + index = low + (high - low) / 2; + pivot = (const char *)array + index * size; + result = cmp(key, pivot); + + if (result == 0) { + return (void *)pivot; + } else if (result > 0) { + low = index + 1; + } else { + high = index; + + } + } + return NULL; +} diff --git a/tests/lib/c_lib/src/main.c b/tests/lib/c_lib/src/main.c index c679b837eb4..988e3fa1e5f 100644 --- a/tests/lib/c_lib/src/main.c +++ b/tests/lib/c_lib/src/main.c @@ -24,6 +24,7 @@ #include #include #include +#include /* Recent GCC's are issuing a warning for the truncated strncpy() * below (the static source string is longer than the locally-defined @@ -254,6 +255,32 @@ void test_memcmp(void) zassert_true((ret != 0), "memcmp 5"); } +/** + * + * @brief Test binary search function + * + */ + +int cmp_func(const void *a, const void *b) +{ + return (*(int *)a - *(int *)b); +} + +void test_bsearch(void) +{ + void *result = NULL; + int arr[5] = { 2, 5, 20, 50, 60 }; + size_t size = ARRAY_SIZE(arr); + int key = 30; + + result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); + zassert_is_null(result, "bsearch -key not found"); + + key = 60; + result = (int *)bsearch(&key, arr, size, sizeof(int), cmp_func); + zassert_not_null(result, "bsearch -key found"); +} + void test_main(void) { ztest_test_suite(test_c_lib, @@ -267,7 +294,8 @@ void test_main(void) ztest_unit_test(test_strncpy), ztest_unit_test(test_memset), ztest_unit_test(test_strlen), - ztest_unit_test(test_strcmp) + ztest_unit_test(test_strcmp), + ztest_unit_test(test_bsearch) ); ztest_run_test_suite(test_c_lib); }