[v2 PATCH] msvcrt: Implement __strncnt().

Nikolay Sivov nsivov at codeweavers.com
Tue Oct 30 08:01:09 CDT 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

v2: removed unnecessary function pointer check in tests.

 .../api-ms-win-crt-string-l1-1-0.spec         |  2 +-
 dlls/msvcr100/msvcr100.spec                   |  2 +-
 dlls/msvcr100/tests/msvcr100.c                | 32 ++++++++++++++
 dlls/msvcr110/msvcr110.spec                   |  2 +-
 dlls/msvcr110/tests/msvcr110.c                | 32 ++++++++++++++
 dlls/msvcr120/msvcr120.spec                   |  2 +-
 dlls/msvcr120_app/msvcr120_app.spec           |  2 +-
 dlls/msvcr80/msvcr80.spec                     |  2 +-
 dlls/msvcr90/msvcr90.spec                     |  2 +-
 dlls/msvcr90/tests/msvcr90.c                  | 32 ++++++++++++++
 dlls/msvcrt/msvcrt.spec                       |  2 +-
 dlls/msvcrt/string.c                          | 19 +++++++++
 dlls/msvcrt/tests/string.c                    | 38 +++++++++++++++++
 dlls/ucrtbase/tests/string.c                  | 42 +++++++++++++++++++
 dlls/ucrtbase/ucrtbase.spec                   |  2 +-
 15 files changed, 204 insertions(+), 9 deletions(-)

diff --git a/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec b/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec
index d045996756..bbc247c79c 100644
--- a/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec
+++ b/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec
@@ -3,7 +3,7 @@
 @ cdecl __iscsymf(long) ucrtbase.__iscsymf
 @ stub __iswcsym
 @ stub __iswcsymf
-@ stub __strncnt
+@ cdecl __strncnt(str long) ucrtbase.__strncnt
 @ stub __wcsncnt
 @ cdecl _isalnum_l(long ptr) ucrtbase._isalnum_l
 @ cdecl _isalpha_l(long ptr) ucrtbase._isalpha_l
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 1579415edc..482dcbbf03 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -656,7 +656,7 @@
 @ stub __set_flsgetvalue
 @ extern __setlc_active MSVCRT___setlc_active
 @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr
-@ stub __strncnt
+@ cdecl __strncnt(str long) MSVCRT___strncnt
 @ varargs  __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l
 @ cdecl __sys_errlist()
 @ cdecl __sys_nerr()
diff --git a/dlls/msvcr100/tests/msvcr100.c b/dlls/msvcr100/tests/msvcr100.c
index 594ac28072..8ac8f4ea3b 100644
--- a/dlls/msvcr100/tests/msvcr100.c
+++ b/dlls/msvcr100/tests/msvcr100.c
@@ -235,6 +235,7 @@ static int (__cdecl *p__memicmp)(const char*, const char*, size_t);
 static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t,_locale_t);
 
 static char* (__cdecl *p_setlocale)(int, const char*);
+static size_t (__cdecl *p___strncnt)(const char*, size_t);
 
 /* make sure we use the correct errno */
 #undef errno
@@ -270,6 +271,7 @@ static BOOL init(void)
     SET(p__memicmp, "_memicmp");
     SET(p__memicmp_l, "_memicmp_l");
     SET(p_setlocale, "setlocale");
+    SET(p___strncnt, "__strncnt");
 
     SET(p_Context_Id, "?Id at Context@Concurrency@@SAIXZ");
     SET(p_CurrentScheduler_Detach, "?Detach at CurrentScheduler@Concurrency@@SAXXZ");
@@ -1075,6 +1077,35 @@ static void test_setlocale(void)
     ok(!ret, "got %p\n", ret);
 }
 
+static void test___strncnt(void)
+{
+    static const struct
+    {
+        const char *str;
+        size_t size;
+        size_t ret;
+    }
+    strncnt_tests[] =
+    {
+        { NULL, 0, 0 },
+        { "a", 0, 0 },
+        { "a", 1, 1 },
+        { "a", 10, 1 },
+        { "abc", 1, 1 },
+    };
+    unsigned int i;
+    size_t ret;
+
+    if (0) /* crashes */
+        ret = p___strncnt(NULL, 1);
+
+    for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i)
+    {
+        ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size);
+        ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret);
+    }
+}
+
 START_TEST(msvcr100)
 {
     if (!init())
@@ -1094,4 +1125,5 @@ START_TEST(msvcr100)
     test__memicmp();
     test__memicmp_l();
     test_setlocale();
+    test___strncnt();
 }
diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec
index 029620f72e..4ad61d4022 100644
--- a/dlls/msvcr110/msvcr110.spec
+++ b/dlls/msvcr110/msvcr110.spec
@@ -1004,7 +1004,7 @@
 @ cdecl __set_app_type(long) MSVCRT___set_app_type
 @ extern __setlc_active MSVCRT___setlc_active
 @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr
-@ stub __strncnt
+@ cdecl __strncnt(str long) MSVCRT___strncnt
 @ varargs  __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l
 @ cdecl __sys_errlist()
 @ cdecl __sys_nerr()
diff --git a/dlls/msvcr110/tests/msvcr110.c b/dlls/msvcr110/tests/msvcr110.c
index dcee5c1ecc..09876131f0 100644
--- a/dlls/msvcr110/tests/msvcr110.c
+++ b/dlls/msvcr110/tests/msvcr110.c
@@ -32,6 +32,7 @@
 #include <locale.h>
 
 static char* (CDECL *p_setlocale)(int category, const char* locale);
+static size_t (CDECL *p___strncnt)(const char *str, size_t count);
 
 static unsigned int (CDECL *p_CurrentScheduler_GetNumberOfVirtualProcessors)(void);
 static unsigned int (CDECL *p__CurrentScheduler__GetNumberOfVirtualProcessors)(void);
@@ -50,6 +51,7 @@ static BOOL init(void)
     }
 
     p_setlocale = (void*)GetProcAddress(module, "setlocale");
+    p___strncnt = (void*)GetProcAddress(module, "__strncnt");
     p_CurrentScheduler_GetNumberOfVirtualProcessors = (void*)GetProcAddress(module, "?GetNumberOfVirtualProcessors at CurrentScheduler@Concurrency@@SAIXZ");
     p__CurrentScheduler__GetNumberOfVirtualProcessors = (void*)GetProcAddress(module, "?_GetNumberOfVirtualProcessors at _CurrentScheduler@details at Concurrency@@SAIXZ");
     p_CurrentScheduler_Id = (void*)GetProcAddress(module, "?Id at CurrentScheduler@Concurrency@@SAIXZ");
@@ -112,9 +114,39 @@ static void test_setlocale(void)
     p_setlocale(LC_ALL, "C");
 }
 
+static void test___strncnt(void)
+{
+    static const struct
+    {
+        const char *str;
+        size_t size;
+        size_t ret;
+    }
+    strncnt_tests[] =
+    {
+        { NULL, 0, 0 },
+        { "a", 0, 0 },
+        { "a", 1, 1 },
+        { "a", 10, 1 },
+        { "abc", 1, 1 },
+    };
+    unsigned int i;
+    size_t ret;
+
+    if (0) /* crashes */
+        ret = p___strncnt(NULL, 1);
+
+    for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i)
+    {
+        ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size);
+        ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret);
+    }
+}
+
 START_TEST(msvcr110)
 {
     if (!init()) return;
     test_CurrentScheduler(); /* MUST be first (at least among Concurrency tests) */
     test_setlocale();
+    test___strncnt();
 }
diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec
index 89002ed15b..47834e5d62 100644
--- a/dlls/msvcr120/msvcr120.spec
+++ b/dlls/msvcr120/msvcr120.spec
@@ -994,7 +994,7 @@
 @ cdecl __set_app_type(long) MSVCRT___set_app_type
 @ extern __setlc_active MSVCRT___setlc_active
 @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr
-@ stub __strncnt
+@ cdecl __strncnt(str long) MSVCRT___strncnt
 @ varargs  __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l
 @ cdecl __sys_errlist()
 @ cdecl __sys_nerr()
diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec
index e926bbbf48..e5b26a4746 100644
--- a/dlls/msvcr120_app/msvcr120_app.spec
+++ b/dlls/msvcr120_app/msvcr120_app.spec
@@ -965,7 +965,7 @@
 @ stub __report_gsfailure
 @ extern __setlc_active msvcr120.__setlc_active
 @ cdecl __setusermatherr(ptr) msvcr120.__setusermatherr
-@ stub __strncnt
+@ cdecl __strncnt(str long) msvcr120.__strncnt
 @ varargs __swprintf_l(ptr wstr ptr) msvcr120.__swprintf_l
 @ cdecl __sys_errlist() msvcr120.__sys_errlist
 @ cdecl __sys_nerr() msvcr120.__sys_nerr
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 7aebe34f23..69355cc1f7 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -305,7 +305,7 @@
 @ stub __set_flsgetvalue
 @ extern __setlc_active MSVCRT___setlc_active
 @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr
-@ stub __strncnt
+@ cdecl __strncnt(str long) MSVCRT___strncnt
 @ varargs  __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l
 @ cdecl __sys_errlist()
 @ cdecl __sys_nerr()
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index eb70ff9153..33ec4b2df7 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -289,7 +289,7 @@
 @ stub __set_flsgetvalue
 @ extern __setlc_active MSVCRT___setlc_active
 @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr
-@ stub __strncnt
+@ cdecl __strncnt(str long) MSVCRT___strncnt
 @ varargs  __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l
 @ cdecl __sys_errlist()
 @ cdecl __sys_nerr()
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index 777d4fee97..0ba1f1a7b1 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -134,6 +134,7 @@ static int (__cdecl *p__fpieee_flt)(ULONG, EXCEPTION_POINTERS*, int (__cdecl *ha
 static int (__cdecl *p__memicmp)(const char*, const char*, size_t);
 static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t, _locale_t);
 static int (__cdecl *p__vsnwprintf)(wchar_t *buffer,size_t count, const wchar_t *format, __ms_va_list valist);
+static size_t (__cdecl *p___strncnt)(const char *str, size_t count);
 
 /* make sure we use the correct errno */
 #undef errno
@@ -403,6 +404,7 @@ static BOOL init(void)
     SET(p__memicmp, "_memicmp");
     SET(p__memicmp_l, "_memicmp_l");
     SET(p__vsnwprintf, "_vsnwprintf");
+    SET(p___strncnt, "__strncnt");
 
     if (sizeof(void *) == 8)
     {
@@ -1894,6 +1896,35 @@ static void test__vsnwprintf(void)
     ok(p_set_invalid_parameter_handler(old_handler) == test_invalid_parameter_handler, "Cannot reset invalid parameter handler\n");
 }
 
+static void test___strncnt(void)
+{
+    static const struct
+    {
+        const char *str;
+        size_t size;
+        size_t ret;
+    }
+    strncnt_tests[] =
+    {
+        { NULL, 0, 0 },
+        { "a", 0, 0 },
+        { "a", 1, 1 },
+        { "a", 10, 1 },
+        { "abc", 1, 1 },
+    };
+    unsigned int i;
+    size_t ret;
+
+    if (0)
+        ret = p___strncnt(NULL, 1);
+
+    for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i)
+    {
+        ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size);
+        ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret);
+    }
+}
+
 START_TEST(msvcr90)
 {
     if(!init())
@@ -1931,4 +1962,5 @@ START_TEST(msvcr90)
 #ifdef __i386__
     test__fpieee_flt();
 #endif
+    test___strncnt();
 }
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index d963f7cbd9..7faecb261e 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -281,7 +281,7 @@
 @ cdecl __set_app_type(long) MSVCRT___set_app_type
 @ extern __setlc_active MSVCRT___setlc_active
 @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr
-# stub __strncnt(str long)
+@ cdecl __strncnt(str long) MSVCRT___strncnt
 @ cdecl __threadhandle() kernel32.GetCurrentThread
 @ cdecl __threadid() kernel32.GetCurrentThreadId
 @ cdecl __toascii(long) MSVCRT___toascii
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index cbbb65b249..fc827d8093 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -2060,3 +2060,22 @@ char* __cdecl MSVCRT_strpbrk(const char *str, const char *accept)
 {
     return strpbrk(str, accept);
 }
+
+/*********************************************************************
+ *                  __strncnt   (MSVCRT.@)
+ */
+MSVCRT_size_t __cdecl MSVCRT___strncnt(const char *str, MSVCRT_size_t size)
+{
+    MSVCRT_size_t ret = 0;
+
+#if _MSVCR_VER >= 140
+    while (*str++ && size--)
+#else
+    while (size-- && *str++)
+#endif
+    {
+        ret++;
+    }
+
+    return ret;
+}
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 670c7cf91f..d0988bf86c 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -100,6 +100,7 @@ static size_t (__cdecl *p__mbsnlen)(const unsigned char*, size_t);
 static int (__cdecl *p__mbccpy_s)(unsigned char*, size_t, int*, const unsigned char*);
 static int (__cdecl *p__memicmp)(const char*, const char*, size_t);
 static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t, _locale_t);
+static size_t (__cdecl *p___strncnt)(const char*, size_t);
 
 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
@@ -3568,6 +3569,41 @@ static void test__tcsnicoll(void)
     }
 }
 
+static void test___strncnt(void)
+{
+    static const struct
+    {
+        const char *str;
+        size_t size;
+        size_t ret;
+    }
+    strncnt_tests[] =
+    {
+        { NULL, 0, 0 },
+        { "a", 0, 0 },
+        { "a", 1, 1 },
+        { "a", 10, 1 },
+        { "abc", 1, 1 },
+    };
+    unsigned int i;
+    size_t ret;
+
+    if (!p___strncnt)
+    {
+        win_skip("__strncnt() is not available.\n");
+        return;
+    }
+
+    if (0) /* crashes */
+        ret = p___strncnt(NULL, 1);
+
+    for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i)
+    {
+        ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size);
+        ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret);
+    }
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -3626,6 +3662,7 @@ START_TEST(string)
     p__mbccpy_s = (void*)GetProcAddress(hMsvcrt, "_mbccpy_s");
     p__memicmp = (void*)GetProcAddress(hMsvcrt, "_memicmp");
     p__memicmp_l = (void*)GetProcAddress(hMsvcrt, "_memicmp_l");
+    p___strncnt = (void*)GetProcAddress(hMsvcrt, "__strncnt");
 
     /* MSVCRT memcpy behaves like memmove for overlapping moves,
        MFC42 CString::Insert seems to rely on that behaviour */
@@ -3693,4 +3730,5 @@ START_TEST(string)
     test__strupr();
     test__tcsncoll();
     test__tcsnicoll();
+    test___strncnt();
 }
diff --git a/dlls/ucrtbase/tests/string.c b/dlls/ucrtbase/tests/string.c
index ab86f46810..34f5a78b07 100644
--- a/dlls/ucrtbase/tests/string.c
+++ b/dlls/ucrtbase/tests/string.c
@@ -89,6 +89,7 @@ static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
 static double (__cdecl *p_strtod)(const char*, char** end);
 static int (__cdecl *p__memicmp)(const char*, const char*, size_t);
 static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t,_locale_t);
+static size_t (__cdecl *p___strncnt)(const char*, size_t);
 
 static BOOL init(void)
 {
@@ -105,6 +106,7 @@ static BOOL init(void)
     p_strtod = (void*)GetProcAddress(module, "strtod");
     p__memicmp = (void*)GetProcAddress(module, "_memicmp");
     p__memicmp_l = (void*)GetProcAddress(module, "_memicmp_l");
+    p___strncnt = (void*)GetProcAddress(module, "__strncnt");
     return TRUE;
 }
 
@@ -244,10 +246,50 @@ static void test__memicmp_l(void)
     ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
             "Cannot reset invalid parameter handler\n");
 }
+
+
+static void test___strncnt(void)
+{
+    static const struct
+    {
+        const char *str;
+        size_t size;
+        size_t ret;
+    }
+    strncnt_tests[] =
+    {
+        { "a", 0, 0 },
+        { "a", 1, 1 },
+        { "a", 10, 1 },
+        { "abc", 1, 1 },
+    };
+    unsigned int i;
+    size_t ret;
+
+    for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i)
+    {
+        ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size);
+        ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret);
+    }
+
+    ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
+            "Invalid parameter handler was already set\n");
+
+    if (0) /* crashes */
+    {
+        ret = p___strncnt(NULL, 0);
+        ret = p___strncnt(NULL, 1);
+    }
+
+    ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
+            "Cannot reset invalid parameter handler\n");
+}
+
 START_TEST(string)
 {
     if (!init()) return;
     test_strtod();
     test__memicmp();
     test__memicmp_l();
+    test___strncnt();
 }
diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec
index 404da75f9a..142ac86913 100644
--- a/dlls/ucrtbase/ucrtbase.spec
+++ b/dlls/ucrtbase/ucrtbase.spec
@@ -164,7 +164,7 @@
 @ cdecl __stdio_common_vswprintf_p(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswprintf_p
 @ cdecl __stdio_common_vswprintf_s(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswprintf_s
 @ cdecl __stdio_common_vswscanf(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswscanf
-@ stub __strncnt
+@ cdecl __strncnt(str long) MSVCRT___strncnt
 @ cdecl __sys_errlist()
 @ cdecl __sys_nerr()
 @ cdecl __threadhandle() kernel32.GetCurrentThread
-- 
2.19.1




More information about the wine-devel mailing list