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