msvcrt: Add bsearch_s implementation by reusing code and tests from ntdll (try 5)
André Hentschel
nerv at dawncrow.de
Wed Apr 11 13:54:12 CDT 2012
---
dlls/msvcr100/msvcr100.spec | 2 +-
dlls/msvcr80/msvcr80.spec | 2 +-
dlls/msvcr90/msvcr90.spec | 2 +-
dlls/msvcrt/misc.c | 32 ++++++++++++++
dlls/msvcrt/msvcrt.spec | 2 +-
dlls/msvcrt/tests/misc.c | 97 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 133 insertions(+), 4 deletions(-)
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index ade980c..5c424b1 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -1434,7 +1434,7 @@
@ cdecl atoi(str) msvcrt.atoi
@ cdecl atol(str) msvcrt.atol
@ 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 calloc(long long) msvcrt.calloc
@ cdecl ceil(double) msvcrt.ceil
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index d4d7a86..410e294 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -1290,7 +1290,7 @@
@ cdecl atoi(str) msvcrt.atoi
@ cdecl atol(str) msvcrt.atol
@ 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 calloc(long long) msvcrt.calloc
@ cdecl ceil(double) msvcrt.ceil
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index 70bc2b3..98bde4d 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -1285,7 +1285,7 @@
@ cdecl atoi(str) msvcrt.atoi
@ cdecl atol(str) msvcrt.atol
@ 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 calloc(long long) msvcrt.calloc
@ cdecl ceil(double) msvcrt.ceil
diff --git a/dlls/msvcrt/misc.c b/dlls/msvcrt/misc.c
index d40e38f..754b7d1 100644
--- a/dlls/msvcrt/misc.c
+++ b/dlls/msvcrt/misc.c
@@ -124,6 +124,38 @@ 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;
+
+ if (!MSVCRT_CHECK_PMT(key != NULL) || !MSVCRT_CHECK_PMT(base != NULL) ||
+ !MSVCRT_CHECK_PMT(size != 0) || !MSVCRT_CHECK_PMT(compare != NULL))
+ {
+ *MSVCRT__errno() = MSVCRT_EINVAL;
+ return NULL;
+ }
+
+ max = nmemb - 1;
+ 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.@)
*
* Trap to a debugger if the value of the stack pointer has changed.
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 04ef9ad..934c247 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -1226,7 +1226,7 @@
@ cdecl atoi(str) ntdll.atoi
@ cdecl atol(str) ntdll.atol
@ 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 calloc(long long) MSVCRT_calloc
@ cdecl ceil(double) MSVCRT_ceil
diff --git a/dlls/msvcrt/tests/misc.c b/dlls/msvcrt/tests/misc.c
index 7135248..b72e309 100644
--- a/dlls/msvcrt/tests/misc.c
+++ b/dlls/msvcrt/tests/misc.c
@@ -26,10 +26,15 @@ static int (__cdecl *prand_s)(unsigned int *);
static int (__cdecl *pmemcpy_s)(void *, MSVCRT_size_t, void*, MSVCRT_size_t);
static int (__cdecl *pI10_OUTPUT)(long double, int, int, void*);
static int (__cdecl *pstrerror_s)(char *, MSVCRT_size_t, int);
+static void* (__cdecl *pbsearch_s)(const void *, const void *, MSVCRT_size_t, MSVCRT_size_t,
+ int (__cdecl *compare)(void *, const void *, const void *), void *);
static int (__cdecl *p_get_doserrno)(int *);
static int (__cdecl *p_get_errno)(int *);
static int (__cdecl *p_set_doserrno)(int);
static int (__cdecl *p_set_errno)(int);
+static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
+
+static int invalid_parameter_cnt;
static void init(void)
{
@@ -39,10 +44,19 @@ static void init(void)
pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s");
pI10_OUTPUT = (void*)GetProcAddress(hmod, "$I10_OUTPUT");
pstrerror_s = (void *)GetProcAddress(hmod, "strerror_s");
+ pbsearch_s = (void *)GetProcAddress(hmod, "bsearch_s");
p_get_doserrno = (void *)GetProcAddress(hmod, "_get_doserrno");
p_get_errno = (void *)GetProcAddress(hmod, "_get_errno");
p_set_doserrno = (void *)GetProcAddress(hmod, "_set_doserrno");
p_set_errno = (void *)GetProcAddress(hmod, "_set_errno");
+ p_set_invalid_parameter_handler = (void *)GetProcAddress(hmod, "_set_invalid_parameter_handler");
+}
+
+static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
+ const wchar_t *function, const wchar_t *file,
+ unsigned line, uintptr_t arg)
+{
+ invalid_parameter_cnt++;
}
static void test_rand_s(void)
@@ -260,6 +274,88 @@ static void test_strerror_s(void)
ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret);
}
+static int __cdecl intcomparefunc(void* ctx, const void *a, const void *b)
+{
+ const int *p = a, *q = b;
+
+ ok(a != b, "must never get the same pointer\n");
+ ok(ctx == pbsearch_s, "Got the wrong context pointer: %p\n", ctx);
+
+ return *p - *q;
+}
+
+static void test_bsearch_s(void)
+{
+ int arr[7] = { 1, 3, 4, 8, 16, 23, 42 };
+ int *x, l, i, j = 1;
+
+ if (!pbsearch_s)
+ {
+ win_skip("bsearch_s is not available\n");
+ return;
+ }
+
+ if (p_set_invalid_parameter_handler)
+ {
+ ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
+ "Invalid parameter handler was already set\n");
+
+ invalid_parameter_cnt = 0;
+ errno = 0xdeadbeef;
+ x = pbsearch_s(NULL, NULL, 0, 0, NULL, NULL);
+ ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(invalid_parameter_cnt == 1, "Expected invalid_parameter_handler to be called once, got %i\n",
+ invalid_parameter_cnt);
+
+ errno = 0xdeadbeef;
+ x = pbsearch_s(NULL, arr, j, sizeof(arr[0]), intcomparefunc, pbsearch_s);
+ ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(invalid_parameter_cnt == 2, "Expected invalid_parameter_handler to be called 2 times, got %i\n",
+ invalid_parameter_cnt);
+
+ errno = 0xdeadbeef;
+ x = pbsearch_s(&l, NULL, j, sizeof(arr[0]), intcomparefunc, pbsearch_s);
+ ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(invalid_parameter_cnt == 3, "Expected invalid_parameter_handler to be called 3 times, got %i\n",
+ invalid_parameter_cnt);
+
+ errno = 0xdeadbeef;
+ x = pbsearch_s(&l, arr, j, 0, intcomparefunc, pbsearch_s);
+ ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(invalid_parameter_cnt == 4, "Expected invalid_parameter_handler to be called 5 times, got %i\n",
+ invalid_parameter_cnt);
+
+ errno = 0xdeadbeef;
+ x = pbsearch_s(&l, arr, j, sizeof(arr[0]), NULL, pbsearch_s);
+ ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(invalid_parameter_cnt == 5, "Expected invalid_parameter_handler to be called 6 times, got %i\n",
+ invalid_parameter_cnt);
+ }
+
+ /* just try all array sizes */
+ for (j=1;j<sizeof(arr)/sizeof(arr[0]);j++) {
+ for (i=0;i<j;i++) {
+ l = arr[i];
+ x = pbsearch_s(&l, arr, j, sizeof(arr[0]), intcomparefunc, pbsearch_s);
+ ok (x == &arr[i], "bsearch_s did not find %d entry in loopsize %d.\n", i, j);
+ }
+ l = 4242;
+ x = pbsearch_s(&l, arr, j, sizeof(arr[0]), intcomparefunc, pbsearch_s);
+ ok (x == NULL, "bsearch_s did find 4242 entry in loopsize %d.\n", j);
+ }
+
+ if (p_set_invalid_parameter_handler)
+ {
+ ok(invalid_parameter_cnt == 5, "Expected invalid_parameter_handler to be called 7 times, got %i\n",
+ invalid_parameter_cnt);
+ }
+}
+
static void test__get_doserrno(void)
{
int ret, out;
@@ -370,6 +466,7 @@ START_TEST(misc)
test_memcpy_s();
test_I10_OUTPUT();
test_strerror_s();
+ test_bsearch_s();
test__get_doserrno();
test__get_errno();
test__set_doserrno();
--
Best Regards, André Hentschel
More information about the wine-patches
mailing list