diff --git a/bake.cmd b/bake.cmd index fa0fdfd..58e8bb4 100644 --- a/bake.cmd +++ b/bake.cmd @@ -51,4 +51,4 @@ del build\*.obj :skip_crt_compilation echo Compiling test.. -clang test\test.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS% +clang test\test4.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS% diff --git a/code/stdlib.c b/code/stdlib.c new file mode 100644 index 0000000..39ff5b9 --- /dev/null +++ b/code/stdlib.c @@ -0,0 +1,18 @@ +#include + +const void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { + size_t left = 0; + size_t right = nmemb; + + const char* buffer = base; + while (left < right) { + size_t middle = (left + right) / 2; + + int cmp = compar(&buffer[middle * size], key); + if (cmp == 0) return &buffer[left * size]; + if (cmp < 0) left = middle + 1; + else right = middle; + } + + return NULL; +} diff --git a/inc/stdlib.h b/inc/stdlib.h index 749742b..ae9c2fa 100644 --- a/inc/stdlib.h +++ b/inc/stdlib.h @@ -71,7 +71,7 @@ _Noreturn void _Exit(int status); char *getenv(const char *name); // _Noreturn void quick_exit(int status); // int system(const char *string); -// void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); +const void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); // void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); // int abs(int j); // long int labs(long int j); diff --git a/test/test4.c b/test/test4.c new file mode 100644 index 0000000..32187e9 --- /dev/null +++ b/test/test4.c @@ -0,0 +1,34 @@ +// https://en.cppreference.com/w/c/algorithm/bsearch +#include +#include + +struct data { + int nr; + char const *value; +} dat[] = { + {1, "Foo"}, {2, "Bar"}, {3, "Hello"}, {4, "World"} +}; + +int data_cmp(void const *lhs, void const *rhs) +{ + struct data const *const l = lhs; + struct data const *const r = rhs; + + if (l->nr < r->nr) return -1; + else if (l->nr > r->nr) return 1; + else return 0; + + // return (l->nr > r->nr) - (l->nr < r->nr); // possible shortcut + // return l->nr - r->nr; // erroneous shortcut (fails if INT_MIN is present) +} + +int main(void) +{ + struct data key = { .nr = 3 }; + struct data const *res = bsearch(&key, dat, sizeof dat / sizeof dat[0], sizeof dat[0], data_cmp); + if (res) { + printf("No %d: %s\n", res->nr, res->value); + } else { + printf("No %d not found\n", key.nr); + } +}