Module: wine Branch: master Commit: c5268a20abd734b8591138fedaa4c9f1cc4b007e URL: http://source.winehq.org/git/wine.git/?a=commit;h=c5268a20abd734b8591138feda...
Author: Mikolaj Zalewski mikolajz@google.com Date: Wed Aug 22 10:47:01 2007 -0700
msvcrt: Test and fix _mbccpy, _mbsncpy and _mbsnbcpy.
---
dlls/msvcrt/mbcs.c | 56 +++++++++++++++++++++++++++---------------- dlls/msvcrt/tests/string.c | 57 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 23 deletions(-)
diff --git a/dlls/msvcrt/mbcs.c b/dlls/msvcrt/mbcs.c index 38c249b..e2148e8 100644 --- a/dlls/msvcrt/mbcs.c +++ b/dlls/msvcrt/mbcs.c @@ -31,6 +31,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
unsigned char MSVCRT_mbctype[257]; +static int g_mbcp_is_multibyte = 0; + int MSVCRT___mb_cur_max = 1; extern int MSVCRT___lc_collate_cp;
@@ -207,6 +209,8 @@ int CDECL _setmbcp(int cp) { /* trail bytes not available through kernel32 but stored in a structure in msvcrt */ struct cp_extra_info_t *cpextra = g_cpextrainfo; + + g_mbcp_is_multibyte = 1; while (TRUE) { if (cpextra->cp == 0 || cpextra->cp == newcp) @@ -226,6 +230,8 @@ int CDECL _setmbcp(int cp) cpextra++; } } + else + g_mbcp_is_multibyte = 0;
/* we can't use GetStringTypeA directly because we don't have a locale - only a code page */ @@ -385,26 +391,39 @@ MSVCRT_size_t CDECL _mbslen(const unsigned char* str) void CDECL _mbccpy(unsigned char* dest, const unsigned char* src) { *dest = *src; - if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*src)) + if(_ismbblead(*src)) *++dest = *++src; /* MB char */ }
/********************************************************************* * _mbsncpy(MSVCRT.@) + * REMARKS + * The parameter n is the number or characters to copy, not the size of + * the buffer. Use _mbsnbcpy for a function analogical to strncpy */ unsigned char* CDECL _mbsncpy(unsigned char* dst, const unsigned char* src, MSVCRT_size_t n) { unsigned char* ret = dst; if(!n) return dst; - if(MSVCRT___mb_cur_max > 1) + if (g_mbcp_is_multibyte) { while (*src && n) { n--; - *dst++ = *src; - if (MSVCRT_isleadbyte(*src++)) - *dst++ = *src++; + if (_ismbblead(*src)) + { + if (!*(src+1)) + { + *dst++ = 0; + *dst++ = 0; + break; + } + + *dst++ = *src++; + } + + *dst++ = *src++; } } else @@ -421,32 +440,27 @@ unsigned char* CDECL _mbsncpy(unsigned char* dst, const unsigned char* src, MSVC
/********************************************************************* * _mbsnbcpy(MSVCRT.@) + * REMARKS + * Like strncpy this function doesn't enforce the string to be + * NUL-terminated */ unsigned char* CDECL _mbsnbcpy(unsigned char* dst, const unsigned char* src, MSVCRT_size_t n) { unsigned char* ret = dst; if(!n) return dst; - if(MSVCRT___mb_cur_max > 1) + if(g_mbcp_is_multibyte) { - while (*src && (n > 1)) - { - n--; - *dst++ = *src; - if (MSVCRT_isleadbyte(*src++)) - { - *dst++ = *src++; - n--; - } - } - if (*src && n && !MSVCRT_isleadbyte(*src)) + int is_lead = 0; + while (*src && n) { - /* If the last character is a multi-byte character then - * we cannot copy it since we have only one byte left - */ - *dst++ = *src; + is_lead = (!is_lead && _ismbblead(*src)); n--; + *dst++ = *src++; } + + if (is_lead) /* if string ends with a lead, remove it */ + *(dst - 1) = 0; } else { diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index 4f82652..d400823 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -23,9 +23,26 @@ #include <string.h> #include <mbstring.h> #include <stdlib.h> +#include <stdio.h> #include <mbctype.h> +#include <locale.h> + +static char *buf_to_string(const unsigned char *bin, int len, int nr) +{ + static char buf[2][1024]; + char *w = buf[nr]; + int i; + + for (i = 0; i < len; i++) + { + sprintf(w, "%02x ", (unsigned char)bin[i]); + w += strlen(w); + } + return buf[nr]; +}
#define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); } +#define expect_bin(buf, value, len) { ok(memcmp((buf), value, len) == 0, "Binary buffer mismatch - expected %s, got %s\n", buf_to_string((unsigned char *)value, len, 1), buf_to_string((buf), len, 0)); }
static void* (*pmemcpy)(void *, const void *, size_t n); static int* (*pmemcmp)(void *, const void *, size_t n); @@ -33,6 +50,8 @@ static int* (*pmemcmp)(void *, const void *, size_t n); #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)
+HMODULE hMsvcrt; + static void test_swab( void ) { char original[] = "BADCFEHGJILKNMPORQTSVUXWZY@#"; char expected1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#"; @@ -167,7 +186,8 @@ static void test_mbcp(void) int curr_mbcp = _getmbcp(); unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */ unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */ - unsigned char *mbsonlylead = (unsigned char *)"\xb0"; + unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2"; + unsigned char buf[16];
/* some two single-byte code pages*/ test_codepage(1252); @@ -201,6 +221,40 @@ static void test_mbcp(void) expect_eq(_mbslen(mbsonlylead), 0, int, "%d"); /* lead + NUL not counted as character */ expect_eq(_mbslen(mbstring), 4, int, "%d"); /* lead + invalid trail counted */
+ /* _mbccpy/_mbsncpy */ + memset(buf, 0xff, sizeof(buf)); + _mbccpy(buf, mbstring); + expect_bin(buf, "\xb0\xb1\xff", 3); + + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 1); + expect_bin(buf, "\xb0\xb1\xff", 3); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 2); + expect_bin(buf, "\xb0\xb1\xb2 \xff", 5); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 3); + expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 4); + expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 5); + expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbsonlylead, 6); + expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8); + + memset(buf, 0xff, sizeof(buf)); + _mbsnbcpy(buf, mbstring2, 2); + expect_bin(buf, "\xb0\xb1\xff", 3); + _mbsnbcpy(buf, mbstring2, 3); + expect_bin(buf, "\xb0\xb1\0\xff", 4); + _mbsnbcpy(buf, mbstring2, 4); + expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5); + memset(buf, 0xff, sizeof(buf)); + _mbsnbcpy(buf, mbsonlylead, 5); + expect_bin(buf, "\0\0\0\0\0\xff", 6);
/* functions that depend on locale codepage, not mbcp. * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet @@ -263,7 +317,6 @@ START_TEST(string) void *mem; static const char xilstring[]="c:/xilinx"; int nLen; - HMODULE hMsvcrt;
hMsvcrt = GetModuleHandleA("msvcrt.dll"); if (!hMsvcrt)