Module: wine Branch: master Commit: 00bce25143b09a17c628dfded47ce2506b90aba5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=00bce25143b09a17c628dfded4...
Author: Piotr Caban piotr@codeweavers.com Date: Thu Jun 12 17:52:40 2014 +0200
msvcrt: Add _strxfrm_l implementation.
---
dlls/msvcr100/msvcr100.spec | 2 +- dlls/msvcr110/msvcr110.spec | 2 +- dlls/msvcr80/msvcr80.spec | 2 +- dlls/msvcr90/msvcr90.spec | 2 +- dlls/msvcrt/msvcrt.spec | 2 +- dlls/msvcrt/string.c | 49 +++++++++++++++++++++++++++++-- dlls/msvcrt/tests/string.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 120 insertions(+), 7 deletions(-)
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index ed40b65..ab71711 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -1367,7 +1367,7 @@ @ cdecl _strupr_l(str ptr) MSVCRT__strupr_l @ cdecl _strupr_s(str long) MSVCRT__strupr_s @ cdecl _strupr_s_l(str long ptr) MSVCRT__strupr_s_l -@ stub _strxfrm_l +@ cdecl _strxfrm_l(ptr str long ptr) MSVCRT__strxfrm_l @ cdecl _swab(str str long) MSVCRT__swab @ varargs _swprintf(ptr wstr) MSVCRT_swprintf @ stub _swprintf_c diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 8af410c..c231de9 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -1725,7 +1725,7 @@ @ cdecl _strupr_l(str ptr) MSVCRT__strupr_l @ cdecl _strupr_s(str long) MSVCRT__strupr_s @ cdecl _strupr_s_l(str long ptr) MSVCRT__strupr_s_l -@ stub _strxfrm_l +@ cdecl _strxfrm_l(ptr str long ptr) MSVCRT__strxfrm_l @ cdecl _swab(str str long) MSVCRT__swab @ varargs _swprintf(ptr wstr) MSVCRT_swprintf @ stub _swprintf_c diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index 1898d11..d4985bc 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -1047,7 +1047,7 @@ @ cdecl _strupr_l(str ptr) MSVCRT__strupr_l @ cdecl _strupr_s(str long) MSVCRT__strupr_s @ cdecl _strupr_s_l(str long ptr) MSVCRT__strupr_s_l -@ stub _strxfrm_l +@ cdecl _strxfrm_l(ptr str long ptr) MSVCRT__strxfrm_l @ cdecl _swab(str str long) MSVCRT__swab @ varargs _swprintf(ptr wstr) MSVCRT_swprintf @ stub _swprintf_c diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index b4ea4b8..c5ec79a 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -1022,7 +1022,7 @@ @ cdecl _strupr_l(str ptr) MSVCRT__strupr_l @ cdecl _strupr_s(str long) MSVCRT__strupr_s @ cdecl _strupr_s_l(str long ptr) MSVCRT__strupr_s_l -@ stub _strxfrm_l +@ cdecl _strxfrm_l(ptr str long ptr) MSVCRT__strxfrm_l @ cdecl _swab(str str long) MSVCRT__swab @ varargs _swprintf(ptr wstr) MSVCRT_swprintf @ stub _swprintf_c diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 69020f6..82d352d 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -988,7 +988,7 @@ @ cdecl _strupr_l(str ptr) MSVCRT__strupr_l @ cdecl _strupr_s(str long) MSVCRT__strupr_s @ cdecl _strupr_s_l(str long ptr) MSVCRT__strupr_s_l -# stub _strxfrm_l(ptr str long ptr) +@ cdecl _strxfrm_l(ptr str long ptr) MSVCRT__strxfrm_l @ cdecl _swab(str str long) MSVCRT__swab @ varargs _swprintf(ptr wstr) MSVCRT_swprintf # stub _swprintf_c(ptr long str) diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index e1a14ac..60e00c9 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -701,12 +701,57 @@ char* __cdecl MSVCRT_strncat(char *dst, const char *src, MSVCRT_size_t len) }
/********************************************************************* + * _strxfrm_l (MSVCRT.@) + */ +MSVCRT_size_t CDECL MSVCRT__strxfrm_l( char *dest, const char *src, + MSVCRT_size_t len, MSVCRT__locale_t locale ) +{ + MSVCRT_pthreadlocinfo locinfo; + int ret; + + if(!MSVCRT_CHECK_PMT(src)) return INT_MAX; + if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX; + + if(len > INT_MAX) { + FIXME("len > INT_MAX not supported\n"); + len = INT_MAX; + } + + if(!locale) + locinfo = get_locinfo(); + else + locinfo = locale->locinfo; + + if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) { + MSVCRT_strncpy(dest, src, len); + return strlen(src); + } + + ret = LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], + LCMAP_SORTKEY, src, -1, NULL, 0); + if(!ret) { + if(len) dest[0] = 0; + *MSVCRT__errno() = MSVCRT_EILSEQ; + return INT_MAX; + } + if(!len) return ret-1; + + if(ret > len) { + dest[0] = 0; + *MSVCRT__errno() = MSVCRT_ERANGE; + return ret-1; + } + + return LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], + LCMAP_SORTKEY, src, -1, dest, len) - 1; +} + +/********************************************************************* * strxfrm (MSVCRT.@) */ MSVCRT_size_t CDECL MSVCRT_strxfrm( char *dest, const char *src, MSVCRT_size_t len ) { - /* FIXME: handle Windows locale */ - return strxfrm( dest, src, len ); + return MSVCRT__strxfrm_l(dest, src, len, NULL); }
/******************************************************************** diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index 822c952..6604819 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -2649,6 +2649,73 @@ static void test_strncpy(void) ok(!strncmp(dst, "0123456789", TEST_STRNCPY_LEN), "dst != 0123456789\n"); }
+static void test_strxfrm(void) +{ + char dest[256]; + size_t ret; + + /* crashes on old version of msvcrt */ + if(p__atodbl_l) { + errno = 0xdeadbeef; + ret = strxfrm(NULL, "src", 1); + ok(ret == INT_MAX, "ret = %d\n", (int)ret); + ok(errno == EINVAL, "errno = %d\n", errno); + + errno = 0xdeadbeef; + ret = strxfrm(dest, NULL, 100); + ok(ret == INT_MAX, "ret = %d\n", (int)ret); + ok(errno == EINVAL, "errno = %d\n", errno); + } + + ret = strxfrm(NULL, "src", 0); + ok(ret == 3, "ret = %d\n", (int)ret); + dest[0] = 'a'; + ret = strxfrm(dest, "src", 0); + ok(ret == 3, "ret = %d\n", (int)ret); + ok(dest[0] == 'a', "dest[0] = %d\n", dest[0]); + + dest[3] = 'a'; + ret = strxfrm(dest, "src", 5); + ok(ret == 3, "ret = %d\n", (int)ret); + ok(!strcmp(dest, "src"), "dest = %s\n", dest); + + errno = 0xdeadbeef; + dest[1] = 'a'; + ret = strxfrm(dest, "src", 1); + ok(ret == 3, "ret = %d\n", (int)ret); + ok(dest[0] == 's', "dest[0] = %d\n", dest[0]); + ok(dest[1] == 'a', "dest[1] = %d\n", dest[1]); + ok(errno == 0xdeadbeef, "errno = %d\n", errno); + + ret = strxfrm(dest, "", 5); + ok(ret == 0, "ret = %d\n", (int)ret); + ok(!dest[0], "dest[0] = %d\n", dest[0]); + + if(!setlocale(LC_ALL, "polish")) { + win_skip("stxfrm tests\n"); + return; + } + + ret = strxfrm(NULL, "src", 0); + ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret); + dest[0] = 'a'; + ret = strxfrm(dest, "src", 0); + ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret); + ok(dest[0] == 'a', "dest[0] = %d\n", dest[0]); + + ret = strxfrm(dest, "src", ret+1); + ok(ret < sizeof(dest)-1, "ret = %d\n", (int)ret); + ok(dest[0], "dest[0] = 0\n"); + + errno = 0xdeadbeef; + dest[0] = 'a'; + ret = strxfrm(dest, "src", 5); + ok(ret>5 && ret<sizeof(dest)-1, "ret = %d\n", (int)ret); + ok(!dest[0] || broken(!p__atodbl_l && dest[0]=='a'), "dest[0] = %d\n", dest[0]); + + setlocale(LC_ALL, "C"); +} + START_TEST(string) { char mem[100]; @@ -2748,4 +2815,5 @@ START_TEST(string) test__wcstoi64(); test_atoi(); test_strncpy(); + test_strxfrm(); }