msvcrt: Improved tolower_l and toupper_l implementation.

This commit is contained in:
Piotr Caban 2011-06-03 15:28:56 +02:00 committed by Alexandre Julliard
parent 2b9d946aea
commit e398b93900
3 changed files with 46 additions and 7 deletions

View File

@ -345,7 +345,7 @@ int CDECL MSVCRT__toupper_l(int c, MSVCRT__locale_t locale)
locinfo = locale->locinfo; locinfo = locale->locinfo;
if(c < 256) if(c < 256)
return locinfo->pcumap[c]; return locinfo->pcumap[(unsigned char)c];
if(locinfo->pctype[(c>>8)&255] & MSVCRT__LEADBYTE) if(locinfo->pctype[(c>>8)&255] & MSVCRT__LEADBYTE)
{ {
@ -400,7 +400,7 @@ int CDECL MSVCRT__tolower_l(int c, MSVCRT__locale_t locale)
locinfo = locale->locinfo; locinfo = locale->locinfo;
if(c < 256) if(c < 256)
return locinfo->pclmap[c]; return locinfo->pclmap[(unsigned char)c];
if(locinfo->pctype[(c>>8)&255] & MSVCRT__LEADBYTE) if(locinfo->pctype[(c>>8)&255] & MSVCRT__LEADBYTE)
{ {

View File

@ -79,7 +79,7 @@ int CDECL _strlwr_s_l(char *str, MSVCRT_size_t len, MSVCRT__locale_t locale)
while (*str) while (*str)
{ {
*str = MSVCRT__tolower_l(*str, locale); *str = MSVCRT__tolower_l((unsigned char)*str, locale);
str++; str++;
} }
@ -140,7 +140,7 @@ int CDECL _strupr_s_l(char *str, MSVCRT_size_t len, MSVCRT__locale_t locale)
while (*str) while (*str)
{ {
*str = MSVCRT__toupper_l(*str, locale); *str = MSVCRT__toupper_l((unsigned char)*str, locale);
str++; str++;
} }

View File

@ -80,6 +80,7 @@ static int (__cdecl *p_wcslwr_s)(wchar_t*,size_t);
static errno_t (__cdecl *p_mbsupr_s)(unsigned char *str, size_t numberOfElements); static errno_t (__cdecl *p_mbsupr_s)(unsigned char *str, size_t numberOfElements);
static errno_t (__cdecl *p_mbslwr_s)(unsigned char *str, size_t numberOfElements); static errno_t (__cdecl *p_mbslwr_s)(unsigned char *str, size_t numberOfElements);
static int (__cdecl *p_wctob)(wint_t); static int (__cdecl *p_wctob)(wint_t);
static int (__cdecl *p_tolower)(int);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y) #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) #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
@ -1326,6 +1327,7 @@ static void test_mbstowcs(void)
ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut); ok(!memcmp(mOut, mHiragana, sizeof(mHiragana)), "mOut = %s\n", mOut);
if(!pmbstowcs_s || !pwcstombs_s) { if(!pmbstowcs_s || !pwcstombs_s) {
setlocale(LC_ALL, "C");
win_skip("mbstowcs_s or wcstombs_s not available\n"); win_skip("mbstowcs_s or wcstombs_s not available\n");
return; return;
} }
@ -1359,6 +1361,7 @@ static void test_mbstowcs(void)
ok(ret == 5, "wcstombs_s did not return 5\n"); ok(ret == 5, "wcstombs_s did not return 5\n");
if(!pwcsrtombs) { if(!pwcsrtombs) {
setlocale(LC_ALL, "C");
win_skip("wcsrtombs not available\n"); win_skip("wcsrtombs not available\n");
return; return;
} }
@ -1376,6 +1379,8 @@ static void test_mbstowcs(void)
ok(ret == 4, "wcsrtombs did not return 4\n"); ok(ret == 4, "wcsrtombs did not return 4\n");
ok(pwstr == NULL, "pwstr != NULL\n"); ok(pwstr == NULL, "pwstr != NULL\n");
ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut); ok(!memcmp(mOut, mSimple, sizeof(mSimple)), "mOut = %s\n", mOut);
setlocale(LC_ALL, "C");
} }
static void test_gcvt(void) static void test_gcvt(void)
@ -1854,7 +1859,6 @@ static void test__mbslwr_s(void)
ok(!memcmp(buffer, "abcdefgh\0IJKLMNOP", sizeof("abcdefgh\0IJKLMNOP")), ok(!memcmp(buffer, "abcdefgh\0IJKLMNOP", sizeof("abcdefgh\0IJKLMNOP")),
"Expected the output buffer to be \"abcdefgh\\0IJKLMNOP\", got \"%s\"\n", "Expected the output buffer to be \"abcdefgh\\0IJKLMNOP\", got \"%s\"\n",
buffer); buffer);
} }
static void test__ultoa_s(void) static void test__ultoa_s(void)
@ -1969,6 +1973,41 @@ static void test_wctob(void)
ok(ret == (int)(char)0xe0, "ret = %x\n", ret); ok(ret == (int)(char)0xe0, "ret = %x\n", ret);
} }
static void test_tolower(void)
{
int ret;
ret = p_tolower(0x41);
ok(ret == 0x61, "ret = %x\n", ret);
ret = p_tolower(0xF4);
ok(ret == 0xF4, "ret = %x\n", ret);
ret = p_tolower((char)0xF4);
ok(ret==0xF4/*Vista+*/ || ret==(char)0xF4, "ret = %x\n", ret);
/* is it using different locale (CP_ACP) for negative values?? */
/* current implementation matches msvcr90 behaviour */
ret = p_tolower((char)0xD0);
todo_wine ok(ret==0xF0/*Vista+*/ || ret==(char)0xD0, "ret = %x\n", ret);
ret = p_tolower(0xD0);
ok(ret == 0xD0, "ret = %x\n", ret);
if(!setlocale(LC_ALL, "us")) {
win_skip("skipping tolower tests that depends on locale\n");
return;
}
ret = p_tolower((char)0xD0);
ok(ret == 0xF0, "ret = %x\n", ret);
ret = p_tolower(0xD0);
ok(ret == 0xF0, "ret = %x\n", ret);
setlocale(LC_ALL, "C");
}
START_TEST(string) START_TEST(string)
{ {
char mem[100]; char mem[100];
@ -2005,6 +2044,7 @@ START_TEST(string)
p_mbsupr_s = (void*)GetProcAddress(hMsvcrt, "_mbsupr_s"); p_mbsupr_s = (void*)GetProcAddress(hMsvcrt, "_mbsupr_s");
p_mbslwr_s = (void*)GetProcAddress(hMsvcrt, "_mbslwr_s"); p_mbslwr_s = (void*)GetProcAddress(hMsvcrt, "_mbslwr_s");
p_wctob = (void*)GetProcAddress(hMsvcrt, "wctob"); p_wctob = (void*)GetProcAddress(hMsvcrt, "wctob");
p_tolower = (void*)GetProcAddress(hMsvcrt, "tolower");
/* MSVCRT memcpy behaves like memmove for overlapping moves, /* MSVCRT memcpy behaves like memmove for overlapping moves,
MFC42 CString::Insert seems to rely on that behaviour */ MFC42 CString::Insert seems to rely on that behaviour */
@ -2047,7 +2087,6 @@ START_TEST(string)
test__wcslwr_s(); test__wcslwr_s();
test__mbsupr_s(); test__mbsupr_s();
test__mbslwr_s(); test__mbslwr_s();
/* This test is changing locale */
test_wctob(); test_wctob();
test_tolower();
} }