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

André Hentschel nerv at dawncrow.de
Sun Jan 29 13:26:31 CST 2012


---
 dlls/msvcrt/misc.c       |   30 ++++++++++++++++++
 dlls/msvcrt/msvcrt.spec  |    2 +-
 dlls/msvcrt/tests/misc.c |   76 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+), 1 deletions(-)

diff --git a/dlls/msvcrt/misc.c b/dlls/msvcrt/misc.c
index d40e38f..4880aa0 100644
--- a/dlls/msvcrt/misc.c
+++ b/dlls/msvcrt/misc.c
@@ -124,6 +124,36 @@ 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 (!size || !compare)
+    {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        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.@)
  *
  * 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 1260dfa..b103f57 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..ef2bf4b 100644
--- a/dlls/msvcrt/tests/misc.c
+++ b/dlls/msvcrt/tests/misc.c
@@ -26,6 +26,8 @@ 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);
@@ -39,6 +41,7 @@ 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");
@@ -260,6 +263,78 @@ 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");
+
+    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;
+    }
+
+    errno = EBADF;
+    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);
+
+if(0)
+{
+    /* crashes on native */
+    errno = EBADF;
+    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);
+
+    errno = EBADF;
+    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);
+}
+
+    errno = EBADF;
+    x = pbsearch_s(&l, arr, 0, sizeof(arr[0]), intcomparefunc, pbsearch_s);
+    ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
+    ok(errno == EBADF, "Expected errno to be EBADF, got %d\n", errno);
+
+    errno = EBADF;
+    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);
+
+    errno = EBADF;
+    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);
+
+    errno = EBADF;
+    x = pbsearch_s(&l, arr, j, sizeof(arr[0]), intcomparefunc, NULL);
+    ok(x == NULL, "Expected bsearch_s to return NULL, got %p\n", x);
+    ok(errno == EBADF, "Expected errno to be EBADF, got %d\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];
+            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);
+    }
+}
+
 static void test__get_doserrno(void)
 {
     int ret, out;
@@ -370,6 +445,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
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: Nachrichtenteil als Anhang
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20120129/a8bce74b/attachment-0001.ksh>


More information about the wine-patches mailing list