msvcrt: Add bsearch_s implementation by reusing code and tests from ntdll (try 3)

André Hentschel nerv at dawncrow.de
Thu Apr 5 14:08:52 CDT 2012


---
 dlls/msvcr100/msvcr100.spec |    2 +-
 dlls/msvcr80/msvcr80.spec   |    2 +-
 dlls/msvcr90/msvcr90.spec   |    2 +-
 dlls/msvcrt/misc.c          |   33 +++++++++++++++++++++++++++++++++
 dlls/msvcrt/msvcrt.spec     |    2 +-
 dlls/msvcrt/tests/misc.c    |   38 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 75 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..94c2906 100644
--- a/dlls/msvcrt/misc.c
+++ b/dlls/msvcrt/misc.c
@@ -124,6 +124,39 @@ 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(nmemb != 0) || !MSVCRT_CHECK_PMT(size != 0) ||
+        !MSVCRT_CHECK_PMT(compare != NULL) || !MSVCRT_CHECK_PMT(ctx != 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..ec480f4 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,40 @@ 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;
+    }
+
+    /* 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 +407,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