Commit f320f6cf authored by André Hentschel's avatar André Hentschel Committed by Alexandre Julliard

msvcrt: Add bsearch_s implementation by reusing code and tests from ntdll.

parent f857ad52
...@@ -1434,7 +1434,7 @@ ...@@ -1434,7 +1434,7 @@
@ cdecl atoi(str) msvcrt.atoi @ cdecl atoi(str) msvcrt.atoi
@ cdecl atol(str) msvcrt.atol @ cdecl atol(str) msvcrt.atol
@ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch @ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch
@ stub bsearch_s @ cdecl bsearch_s(ptr ptr long long ptr ptr) msvcrt.bsearch_s
@ cdecl btowc(long) msvcrt.btowc @ cdecl btowc(long) msvcrt.btowc
@ cdecl calloc(long long) msvcrt.calloc @ cdecl calloc(long long) msvcrt.calloc
@ cdecl ceil(double) msvcrt.ceil @ cdecl ceil(double) msvcrt.ceil
......
...@@ -1290,7 +1290,7 @@ ...@@ -1290,7 +1290,7 @@
@ cdecl atoi(str) msvcrt.atoi @ cdecl atoi(str) msvcrt.atoi
@ cdecl atol(str) msvcrt.atol @ cdecl atol(str) msvcrt.atol
@ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch @ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch
@ stub bsearch_s @ cdecl bsearch_s(ptr ptr long long ptr ptr) msvcrt.bsearch_s
@ cdecl btowc(long) msvcrt.btowc @ cdecl btowc(long) msvcrt.btowc
@ cdecl calloc(long long) msvcrt.calloc @ cdecl calloc(long long) msvcrt.calloc
@ cdecl ceil(double) msvcrt.ceil @ cdecl ceil(double) msvcrt.ceil
......
...@@ -1285,7 +1285,7 @@ ...@@ -1285,7 +1285,7 @@
@ cdecl atoi(str) msvcrt.atoi @ cdecl atoi(str) msvcrt.atoi
@ cdecl atol(str) msvcrt.atol @ cdecl atol(str) msvcrt.atol
@ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch @ cdecl bsearch(ptr ptr long long ptr) msvcrt.bsearch
@ stub bsearch_s @ cdecl bsearch_s(ptr ptr long long ptr ptr) msvcrt.bsearch_s
@ cdecl btowc(long) msvcrt.btowc @ cdecl btowc(long) msvcrt.btowc
@ cdecl calloc(long long) msvcrt.calloc @ cdecl calloc(long long) msvcrt.calloc
@ cdecl ceil(double) msvcrt.ceil @ cdecl ceil(double) msvcrt.ceil
......
...@@ -72,6 +72,8 @@ static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int); ...@@ -72,6 +72,8 @@ static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int); static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count); static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *); static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
static void* (__cdecl *p_bsearch_s)(const void *, const void *, size_t, size_t,
int (__cdecl *compare)(void *, const void *, const void *), void *);
static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int); static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *); static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *);
static unsigned int (__cdecl *p_set_abort_behavior)(unsigned int, unsigned int); static unsigned int (__cdecl *p_set_abort_behavior)(unsigned int, unsigned int);
...@@ -134,6 +136,7 @@ static void* (WINAPI *pEncodePointer)(void *); ...@@ -134,6 +136,7 @@ static void* (WINAPI *pEncodePointer)(void *);
static int cb_called[4]; static int cb_called[4];
static int g_qsort_s_context_counter; static int g_qsort_s_context_counter;
static int g_bsearch_s_context_counter;
static inline int almost_equal_f(float f1, float f2) static inline int almost_equal_f(float f1, float f2)
{ {
...@@ -250,6 +253,7 @@ static BOOL init(void) ...@@ -250,6 +253,7 @@ static BOOL init(void)
SET(p_itoa_s, "_itoa_s"); SET(p_itoa_s, "_itoa_s");
SET(p_wcsncat_s,"wcsncat_s" ); SET(p_wcsncat_s,"wcsncat_s" );
SET(p_qsort_s, "qsort_s"); SET(p_qsort_s, "qsort_s");
SET(p_bsearch_s, "bsearch_s");
SET(p_controlfp_s, "_controlfp_s"); SET(p_controlfp_s, "_controlfp_s");
SET(p_atoflt, "_atoflt"); SET(p_atoflt, "_atoflt");
SET(p_set_abort_behavior, "_set_abort_behavior"); SET(p_set_abort_behavior, "_set_abort_behavior");
...@@ -750,6 +754,49 @@ static void test_qsort_s(void) ...@@ -750,6 +754,49 @@ static void test_qsort_s(void)
ok(!strcmp(strarr[6],"World"), "badly sorted, strarr[6] is %s\n", strarr[6]); ok(!strcmp(strarr[6],"World"), "badly sorted, strarr[6] is %s\n", strarr[6]);
} }
static void test_bsearch_s(void)
{
int arr[7] = { 1, 3, 4, 8, 16, 23, 42 };
int *x, l, i, j = 1;
errno = 0xdeadbeef;
SET_EXPECT(invalid_parameter_handler);
x = p_bsearch_s(NULL, NULL, 0, 0, NULL, NULL);
ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
CHECK_CALLED(invalid_parameter_handler);
g_bsearch_s_context_counter = 0;
SET_EXPECT(invalid_parameter_handler);
x = p_bsearch_s(&l, arr, j, 0, intcomparefunc, &g_bsearch_s_context_counter);
ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
ok(g_bsearch_s_context_counter == 0, "callback shouldn't have been called\n");
CHECK_CALLED(invalid_parameter_handler);
g_bsearch_s_context_counter = 0;
SET_EXPECT(invalid_parameter_handler);
x = p_bsearch_s(&l, arr, j, sizeof(arr[0]), NULL, &g_bsearch_s_context_counter);
ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
ok(g_bsearch_s_context_counter == 0, "callback shouldn't have been called\n");
CHECK_CALLED(invalid_parameter_handler);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
/* just try all array sizes */
for (j=1;j<sizeof(arr)/sizeof(arr[0]);j++) {
for (i=0;i<j;i++) {
l = arr[i];
g_bsearch_s_context_counter = 0;
x = p_bsearch_s(&l, arr, j, sizeof(arr[0]), intcomparefunc, &g_bsearch_s_context_counter);
ok (x == &arr[i], "bsearch_s did not find %d entry in loopsize %d.\n", i, j);
ok(g_bsearch_s_context_counter > 0, "callback wasn't called\n");
}
l = 4242;
g_bsearch_s_context_counter = 0;
x = p_bsearch_s(&l, arr, j, sizeof(arr[0]), intcomparefunc, &g_bsearch_s_context_counter);
ok (x == NULL, "bsearch_s did find 4242 entry in loopsize %d.\n", j);
ok(g_bsearch_s_context_counter > 0, "callback wasn't called\n");
}
}
static void test_controlfp_s(void) static void test_controlfp_s(void)
{ {
unsigned int cur; unsigned int cur;
...@@ -1162,6 +1209,7 @@ START_TEST(msvcr90) ...@@ -1162,6 +1209,7 @@ START_TEST(msvcr90)
test__itoa_s(); test__itoa_s();
test_wcsncat_s(); test_wcsncat_s();
test_qsort_s(); test_qsort_s();
test_bsearch_s();
test_controlfp_s(); test_controlfp_s();
test__atoflt(); test__atoflt();
test__set_abort_behavior(); test__set_abort_behavior();
......
...@@ -124,6 +124,33 @@ void* CDECL _lsearch(const void* match, void* start, ...@@ -124,6 +124,33 @@ void* CDECL _lsearch(const void* match, void* start,
} }
/********************************************************************* /*********************************************************************
* bsearch_s (msvcrt.@)
*/
void* CDECL MSVCRT_bsearch_s(const void *key, const void *base,
MSVCRT_size_t nmemb, MSVCRT_size_t size,
int (__cdecl *compare)(void *, const void *, const void *), void *ctx)
{
ssize_t min = 0;
ssize_t max = nmemb - 1;
if (!MSVCRT_CHECK_PMT(size != 0) || !MSVCRT_CHECK_PMT(compare != NULL))
return NULL;
while (min <= max)
{
ssize_t cursor = (min + max) / 2;
int ret = compare(ctx, key,(const char *)base+(cursor*size));
if (!ret)
return (char*)base+(cursor*size);
if (ret < 0)
max = cursor - 1;
else
min = cursor + 1;
}
return NULL;
}
/*********************************************************************
* _chkesp (MSVCRT.@) * _chkesp (MSVCRT.@)
* *
* Trap to a debugger if the value of the stack pointer has changed. * Trap to a debugger if the value of the stack pointer has changed.
......
...@@ -1226,7 +1226,7 @@ ...@@ -1226,7 +1226,7 @@
@ cdecl atoi(str) ntdll.atoi @ cdecl atoi(str) ntdll.atoi
@ cdecl atol(str) ntdll.atol @ cdecl atol(str) ntdll.atol
@ cdecl bsearch(ptr ptr long long ptr) ntdll.bsearch @ cdecl bsearch(ptr ptr long long ptr) ntdll.bsearch
# stub bsearch_s(ptr ptr long long ptr ptr) @ cdecl bsearch_s(ptr ptr long long ptr ptr) MSVCRT_bsearch_s
@ cdecl btowc(long) MSVCRT_btowc @ cdecl btowc(long) MSVCRT_btowc
@ cdecl calloc(long long) MSVCRT_calloc @ cdecl calloc(long long) MSVCRT_calloc
@ cdecl ceil(double) MSVCRT_ceil @ cdecl ceil(double) MSVCRT_ceil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment