Move CompareString implementation to libwine_unicode, add a bunch of
CompareString tests.
This commit is contained in:
parent
1bcbd54697
commit
33f9dcb1f9
|
@ -1971,6 +1971,12 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (srclen)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return dst_ptr - dst;
|
return dst_ptr - dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1994,7 +2000,7 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen,
|
||||||
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
||||||
LPSTR dst, INT dstlen)
|
LPSTR dst, INT dstlen)
|
||||||
{
|
{
|
||||||
WCHAR bufW[128];
|
WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
|
||||||
LPWSTR srcW, dstW;
|
LPWSTR srcW, dstW;
|
||||||
INT ret = 0, srclenW, dstlenW;
|
INT ret = 0, srclenW, dstlenW;
|
||||||
UINT locale_cp;
|
UINT locale_cp;
|
||||||
|
@ -2007,7 +2013,7 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
||||||
|
|
||||||
locale_cp = get_lcid_codepage(lcid);
|
locale_cp = get_lcid_codepage(lcid);
|
||||||
|
|
||||||
srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 128);
|
srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260);
|
||||||
if (srclenW)
|
if (srclenW)
|
||||||
srcW = bufW;
|
srcW = bufW;
|
||||||
else
|
else
|
||||||
|
@ -2040,6 +2046,9 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
||||||
}
|
}
|
||||||
|
|
||||||
dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0);
|
dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0);
|
||||||
|
if (!dstlenW)
|
||||||
|
goto map_string_exit;
|
||||||
|
|
||||||
dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
|
dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
|
||||||
if (!dstW)
|
if (!dstW)
|
||||||
{
|
{
|
||||||
|
@ -2172,7 +2181,7 @@ INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen,
|
||||||
INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
||||||
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
|
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
|
||||||
{
|
{
|
||||||
INT ret, len;
|
INT ret;
|
||||||
|
|
||||||
if (!str1 || !str2)
|
if (!str1 || !str2)
|
||||||
{
|
{
|
||||||
|
@ -2180,19 +2189,24 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len1 < 0) len1 = lstrlenW(str1);
|
if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
|
||||||
if (len2 < 0) len2 = lstrlenW(str2);
|
SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|0x10000000) )
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_FLAGS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
len = (len1 < len2) ? len1 : len2;
|
if (style & 0x10000000)
|
||||||
ret = (style & NORM_IGNORECASE) ? strncmpiW(str1, str2, len) :
|
FIXME("Ignoring unknown style 0x10000000\n");
|
||||||
strncmpW(str1, str2, len);
|
|
||||||
|
if (len1 < 0) len1 = strlenW(str1);
|
||||||
|
if (len2 < 0) len2 = strlenW(str2);
|
||||||
|
|
||||||
|
ret = wine_compare_string(style, str1, len1, str2, len2);
|
||||||
|
|
||||||
if (ret) /* need to translate result */
|
if (ret) /* need to translate result */
|
||||||
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
||||||
|
return CSTR_EQUAL;
|
||||||
if (len1 == len2) return CSTR_EQUAL;
|
|
||||||
/* the longer one is lexically greater */
|
|
||||||
return (len1 < len2) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -2216,7 +2230,8 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
||||||
INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
||||||
LPCSTR str1, INT len1, LPCSTR str2, INT len2)
|
LPCSTR str1, INT len1, LPCSTR str2, INT len2)
|
||||||
{
|
{
|
||||||
WCHAR buf1W[128], buf2W[128];
|
WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
|
||||||
|
WCHAR *buf2W = buf1W + 130;
|
||||||
LPWSTR str1W, str2W;
|
LPWSTR str1W, str2W;
|
||||||
INT len1W, len2W, ret;
|
INT len1W, len2W, ret;
|
||||||
UINT locale_cp;
|
UINT locale_cp;
|
||||||
|
@ -2226,13 +2241,12 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len1 < 0) len1 = strlen(str1);
|
if (len1 < 0) len1 = strlen(str1);
|
||||||
if (len2 < 0) len2 = strlen(str2);
|
if (len2 < 0) len2 = strlen(str2);
|
||||||
|
|
||||||
locale_cp = get_lcid_codepage(lcid);
|
locale_cp = get_lcid_codepage(lcid);
|
||||||
|
|
||||||
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 128);
|
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
|
||||||
if (len1W)
|
if (len1W)
|
||||||
str1W = buf1W;
|
str1W = buf1W;
|
||||||
else
|
else
|
||||||
|
@ -2246,7 +2260,7 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
||||||
}
|
}
|
||||||
MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
|
MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
|
||||||
}
|
}
|
||||||
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 128);
|
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130);
|
||||||
if (len2W)
|
if (len2W)
|
||||||
str2W = buf2W;
|
str2W = buf2W;
|
||||||
else
|
else
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
* even when the user has overridden their default i8n settings (e.g. in
|
* even when the user has overridden their default i8n settings (e.g. in
|
||||||
* the control panel i8n page), we will still get the expected results.
|
* the control panel i8n page), we will still get the expected results.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
@ -774,8 +777,151 @@ static void test_CompareStringA()
|
||||||
ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
|
ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
|
||||||
ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
|
ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
|
||||||
|
|
||||||
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "SaLuT", -1);
|
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
|
||||||
ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
|
ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
|
||||||
|
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||||
|
"unexpected error code %ld\n", GetLastError());
|
||||||
|
ok(!ret, "CompareStringA must fail with invalid flag\n");
|
||||||
|
|
||||||
|
ret = lstrcmpA("", "");
|
||||||
|
ok (!ret, "lstrcmpA(\"\", \"\") should return 0, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
|
||||||
|
ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
|
||||||
|
ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
|
||||||
|
ok( ret == 3, "r vs \\ ... expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
|
||||||
|
ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
|
||||||
|
ok( ret == 3, "AAA vs aaa expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
|
||||||
|
ok( ret == 1, "AAA vs aab expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
|
||||||
|
ok( ret == 1, "AAA vs Aab expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
|
||||||
|
ok( ret == 1, ".AAA vs Aab expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
|
||||||
|
ok( ret == 1, ".AAA vs A.ab expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
|
||||||
|
ok( ret == 1, "aa vs AB expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
|
||||||
|
ok( ret == 1, "aa vs Aab expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
|
||||||
|
ok( ret == 3, "aB vs Aab expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
|
||||||
|
ok( ret == 1, "Ba vs bab expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
|
||||||
|
ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
|
||||||
|
ok( ret == 3, "a vs { expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
|
||||||
|
ok( ret == 3, "A vs { expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
|
||||||
|
ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
|
||||||
|
ok(ret == 1, "3.5 vs 4.0 expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
|
||||||
|
ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d", ret);
|
||||||
|
|
||||||
|
/* hyphen and apostrophe are treated differently depending on
|
||||||
|
* whether SORT_STRINGSORT specified or not
|
||||||
|
*/
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
|
||||||
|
ok(ret == 3, "-o vs /m expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
|
||||||
|
ok(ret == 1, "/m vs -o expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
|
||||||
|
ok(ret == 1, "-o vs /m expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
|
||||||
|
ok(ret == 3, "/m vs -o expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
|
||||||
|
ok(ret == 3, "'o vs /m expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
|
||||||
|
ok(ret == 1, "/m vs 'o expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
|
||||||
|
ok(ret == 1, "'o vs /m expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
|
||||||
|
ok(ret == 3, "/m vs 'o expected 3, got %d", ret);
|
||||||
|
|
||||||
|
#if 0 /* this requires collation table patch to make it MS compatible */
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
|
||||||
|
ok(ret == 1, "'o vs -o expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
|
||||||
|
ok(ret == 1, "'o vs -o expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
|
||||||
|
ok(ret == 1, "' vs - expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
|
||||||
|
ok(ret == 1, "' vs - expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
|
||||||
|
ok(ret == 3, "`o vs /m expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
|
||||||
|
ok(ret == 1, "/m vs `o expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
|
||||||
|
ok(ret == 3, "`o vs /m expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
|
||||||
|
ok(ret == 1, "/m vs `o expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
|
||||||
|
ok(ret == 1, "`o vs -m expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
|
||||||
|
ok(ret == 3, "-m vs `o expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
|
||||||
|
ok(ret == 3, "`o vs -m expected 3, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
|
||||||
|
ok(ret == 1, "-m vs `o expected 1, got %d", ret);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
|
||||||
|
ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
|
||||||
|
ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
|
||||||
|
ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d", ret);
|
||||||
|
|
||||||
|
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
|
||||||
|
ok(ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_LCMapStringA(void)
|
void test_LCMapStringA(void)
|
||||||
|
@ -834,6 +980,13 @@ void test_LCMapStringA(void)
|
||||||
ret, GetLastError(), lstrlenA(lower_case) + 1);
|
ret, GetLastError(), lstrlenA(lower_case) + 1);
|
||||||
ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
|
ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
|
||||||
|
|
||||||
|
/* test buffer overflow */
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||||
|
lower_case, -1, buf, 4);
|
||||||
|
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||||
|
"should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
|
||||||
|
|
||||||
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
||||||
lstrcpyA(buf, lower_case);
|
lstrcpyA(buf, lower_case);
|
||||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||||
|
@ -924,6 +1077,13 @@ void test_LCMapStringA(void)
|
||||||
ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
|
ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
|
||||||
lstrlenA(symbols_stripped) + 1, ret);
|
lstrlenA(symbols_stripped) + 1, ret);
|
||||||
ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
|
ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
|
||||||
|
|
||||||
|
/* test srclen = 0 */
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
|
||||||
|
ok(!ret, "LCMapStringA should fail with srclen = 0");
|
||||||
|
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||||
|
"unexpected error code %ld\n", GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_LCMapStringW(void)
|
void test_LCMapStringW(void)
|
||||||
|
@ -988,6 +1148,13 @@ void test_LCMapStringW(void)
|
||||||
ret, GetLastError(), lstrlenW(lower_case) + 1);
|
ret, GetLastError(), lstrlenW(lower_case) + 1);
|
||||||
ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
|
ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
|
||||||
|
|
||||||
|
/* test buffer overflow */
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||||
|
lower_case, -1, buf, 4);
|
||||||
|
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||||
|
"should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
|
||||||
|
|
||||||
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
||||||
lstrcpyW(buf, lower_case);
|
lstrcpyW(buf, lower_case);
|
||||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||||
|
@ -1069,9 +1236,143 @@ void test_LCMapStringW(void)
|
||||||
ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
|
ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
|
||||||
lstrlenW(symbols_stripped) + 1, ret);
|
lstrlenW(symbols_stripped) + 1, ret);
|
||||||
ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
|
ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
|
||||||
|
|
||||||
|
/* test srclen = 0 */
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
|
||||||
|
ok(!ret, "LCMapStringW should fail with srclen = 0");
|
||||||
|
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||||
|
"unexpected error code %ld\n", GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_FoldStringA(void)
|
#if 0 /* this requires collation table patch to make it MS compatible */
|
||||||
|
const char *strings_sorted[] =
|
||||||
|
{
|
||||||
|
"'",
|
||||||
|
"-",
|
||||||
|
"!",
|
||||||
|
"\"",
|
||||||
|
".",
|
||||||
|
":",
|
||||||
|
"\\",
|
||||||
|
"_",
|
||||||
|
"`",
|
||||||
|
"{",
|
||||||
|
"}",
|
||||||
|
"+",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
|
"a",
|
||||||
|
"A",
|
||||||
|
"b",
|
||||||
|
"B",
|
||||||
|
"c",
|
||||||
|
"C"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *strings[] =
|
||||||
|
{
|
||||||
|
"C",
|
||||||
|
"\"",
|
||||||
|
"9",
|
||||||
|
"'",
|
||||||
|
"}",
|
||||||
|
"-",
|
||||||
|
"7",
|
||||||
|
"+",
|
||||||
|
"`",
|
||||||
|
"1",
|
||||||
|
"a",
|
||||||
|
"5",
|
||||||
|
"\\",
|
||||||
|
"8",
|
||||||
|
"B",
|
||||||
|
"3",
|
||||||
|
"_",
|
||||||
|
"6",
|
||||||
|
"{",
|
||||||
|
"2",
|
||||||
|
"c",
|
||||||
|
"4",
|
||||||
|
"!",
|
||||||
|
"0",
|
||||||
|
"A",
|
||||||
|
":",
|
||||||
|
"b",
|
||||||
|
"."
|
||||||
|
};
|
||||||
|
|
||||||
|
static int compare_string1(const void *e1, const void *e2)
|
||||||
|
{
|
||||||
|
const char *s1 = *(const char **)e1;
|
||||||
|
const char *s2 = *(const char **)e2;
|
||||||
|
|
||||||
|
return lstrcmpA(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_string2(const void *e1, const void *e2)
|
||||||
|
{
|
||||||
|
const char *s1 = *(const char **)e1;
|
||||||
|
const char *s2 = *(const char **)e2;
|
||||||
|
|
||||||
|
return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_string3(const void *e1, const void *e2)
|
||||||
|
{
|
||||||
|
const char *s1 = *(const char **)e1;
|
||||||
|
const char *s2 = *(const char **)e2;
|
||||||
|
char key1[256], key2[256];
|
||||||
|
|
||||||
|
LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
|
||||||
|
LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
|
||||||
|
return strcmp(key1, key2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sorting(void)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
char **str_buf = (char **)buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(sizeof(buf) >= sizeof(strings));
|
||||||
|
|
||||||
|
/* 1. sort using lstrcmpA */
|
||||||
|
memcpy(buf, strings, sizeof(strings));
|
||||||
|
qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
|
||||||
|
for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
|
||||||
|
{
|
||||||
|
ok(!strcmp(strings_sorted[i], str_buf[i]),
|
||||||
|
"qsort using lstrcmpA failed for element %d\n", i);
|
||||||
|
}
|
||||||
|
/* 2. sort using CompareStringA */
|
||||||
|
memcpy(buf, strings, sizeof(strings));
|
||||||
|
qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
|
||||||
|
for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
|
||||||
|
{
|
||||||
|
ok(!strcmp(strings_sorted[i], str_buf[i]),
|
||||||
|
"qsort using CompareStringA failed for element %d\n", i);
|
||||||
|
}
|
||||||
|
/* 3. sort using sort keys */
|
||||||
|
memcpy(buf, strings, sizeof(strings));
|
||||||
|
qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
|
||||||
|
for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
|
||||||
|
{
|
||||||
|
ok(!strcmp(strings_sorted[i], str_buf[i]),
|
||||||
|
"qsort using sort keys failed for element %d\n", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void test_FoldStringA(void)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
char src[256], dst[256];
|
char src[256], dst[256];
|
||||||
|
@ -1118,6 +1419,13 @@ void test_FoldStringA(void)
|
||||||
if (!pFoldStringA)
|
if (!pFoldStringA)
|
||||||
return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
|
return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
|
||||||
|
|
||||||
|
/* these tests are locale specific */
|
||||||
|
if (GetACP() != 1252)
|
||||||
|
{
|
||||||
|
trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* MAP_FOLDDIGITS */
|
/* MAP_FOLDDIGITS */
|
||||||
SetLastError(0);
|
SetLastError(0);
|
||||||
ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
|
ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
|
||||||
|
@ -1212,7 +1520,7 @@ void test_FoldStringA(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_FoldStringW(void)
|
static void test_FoldStringW(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
|
@ -1596,8 +1904,8 @@ static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
|
||||||
"Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
|
"Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
|
||||||
|
|
||||||
/* If lParam is one, we are calling with flags defaulted from 0 */
|
/* If lParam is one, we are calling with flags defaulted from 0 */
|
||||||
ok(!lParam || dwFlags == LGRPID_INSTALLED,
|
ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
|
||||||
"Expected dwFlags == LGRPID_INSTALLED, got %ld\n", dwFlags);
|
"Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1710,4 +2018,7 @@ START_TEST(locale)
|
||||||
test_EnumSystemLanguageGroupsA();
|
test_EnumSystemLanguageGroupsA();
|
||||||
test_EnumLanguageGroupLocalesA();
|
test_EnumLanguageGroupLocalesA();
|
||||||
test_SetLocaleInfoA();
|
test_SetLocaleInfoA();
|
||||||
|
#if 0 /* this requires collation table patch to make it MS compatible */
|
||||||
|
test_sorting();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
|
||||||
char str1[3], str2[3];
|
char str1[3], str2[3];
|
||||||
|
|
||||||
str1[0] = LOBYTE(ch1);
|
str1[0] = LOBYTE(ch1);
|
||||||
if (IsDBCSLeadByte(ch1))
|
if (IsDBCSLeadByte(str1[0]))
|
||||||
{
|
{
|
||||||
str1[1] = HIBYTE(ch1);
|
str1[1] = HIBYTE(ch1);
|
||||||
str1[2] = '\0';
|
str1[2] = '\0';
|
||||||
|
@ -73,7 +73,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
|
||||||
str1[1] = '\0';
|
str1[1] = '\0';
|
||||||
|
|
||||||
str2[0] = LOBYTE(ch2);
|
str2[0] = LOBYTE(ch2);
|
||||||
if (IsDBCSLeadByte(ch2))
|
if (IsDBCSLeadByte(str2[0]))
|
||||||
{
|
{
|
||||||
str2[1] = HIBYTE(ch2);
|
str2[1] = HIBYTE(ch2);
|
||||||
str2[2] = '\0';
|
str2[2] = '\0';
|
||||||
|
|
|
@ -156,33 +156,37 @@ static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = {
|
||||||
static void test_StrChrA(void)
|
static void test_StrChrA(void)
|
||||||
{
|
{
|
||||||
char string[129];
|
char string[129];
|
||||||
int count;
|
WORD count;
|
||||||
|
|
||||||
ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!");
|
/* this test crashes on win2k SP4 */
|
||||||
|
/*ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!");*/
|
||||||
|
|
||||||
for (count = 32; count < 128; count++)
|
for (count = 32; count < 128; count++)
|
||||||
string[count] = count;
|
string[count] = (char)count;
|
||||||
string[128] = '\0';
|
string[128] = '\0';
|
||||||
|
|
||||||
for (count = 32; count < 128; count++)
|
for (count = 32; count < 128; count++)
|
||||||
{
|
{
|
||||||
LPSTR result = StrChrA(string+32, count);
|
LPSTR result = StrChrA(string+32, count);
|
||||||
ok(result - string == count, "found char %d in wrong place", count);
|
ok(result - string == count,
|
||||||
|
"found char '%c' in wrong place: got %d, expected %d\n",
|
||||||
|
count, result - string, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (count = 32; count < 128; count++)
|
for (count = 32; count < 128; count++)
|
||||||
{
|
{
|
||||||
LPSTR result = StrChrA(string+count+1, count);
|
LPSTR result = StrChrA(string+count+1, count);
|
||||||
ok(!result, "found char not in the string");
|
ok(!result, "found char '%c' not in the string\n", count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_StrChrW(void)
|
static void test_StrChrW(void)
|
||||||
{
|
{
|
||||||
WCHAR string[16385];
|
WCHAR string[16385];
|
||||||
int count;
|
WORD count;
|
||||||
|
|
||||||
ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!");
|
/* this test crashes on win2k SP4 */
|
||||||
|
/*ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!");*/
|
||||||
|
|
||||||
for (count = 32; count < 16384; count++)
|
for (count = 32; count < 16384; count++)
|
||||||
string[count] = count;
|
string[count] = count;
|
||||||
|
@ -204,12 +208,13 @@ static void test_StrChrW(void)
|
||||||
static void test_StrChrIA(void)
|
static void test_StrChrIA(void)
|
||||||
{
|
{
|
||||||
char string[129];
|
char string[129];
|
||||||
int count;
|
WORD count;
|
||||||
|
|
||||||
ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");
|
/* this test crashes on win2k SP4 */
|
||||||
|
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");*/
|
||||||
|
|
||||||
for (count = 32; count < 128; count++)
|
for (count = 32; count < 128; count++)
|
||||||
string[count] = count;
|
string[count] = (char)count;
|
||||||
string[128] = '\0';
|
string[128] = '\0';
|
||||||
|
|
||||||
for (count = 'A'; count <= 'X'; count++)
|
for (count = 'A'; count <= 'X'; count++)
|
||||||
|
@ -230,9 +235,10 @@ static void test_StrChrIA(void)
|
||||||
static void test_StrChrIW(void)
|
static void test_StrChrIW(void)
|
||||||
{
|
{
|
||||||
WCHAR string[129];
|
WCHAR string[129];
|
||||||
int count;
|
WORD count;
|
||||||
|
|
||||||
ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");
|
/* this test crashes on win2k SP4 */
|
||||||
|
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");*/
|
||||||
|
|
||||||
for (count = 32; count < 128; count++)
|
for (count = 32; count < 128; count++)
|
||||||
string[count] = count;
|
string[count] = count;
|
||||||
|
@ -256,12 +262,13 @@ static void test_StrChrIW(void)
|
||||||
static void test_StrRChrA(void)
|
static void test_StrRChrA(void)
|
||||||
{
|
{
|
||||||
char string[129];
|
char string[129];
|
||||||
int count;
|
WORD count;
|
||||||
|
|
||||||
ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!");
|
/* this test crashes on win2k SP4 */
|
||||||
|
/*ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!");*/
|
||||||
|
|
||||||
for (count = 32; count < 128; count++)
|
for (count = 32; count < 128; count++)
|
||||||
string[count] = count;
|
string[count] = (char)count;
|
||||||
string[128] = '\0';
|
string[128] = '\0';
|
||||||
|
|
||||||
for (count = 32; count < 128; count++)
|
for (count = 32; count < 128; count++)
|
||||||
|
@ -285,31 +292,34 @@ static void test_StrRChrA(void)
|
||||||
|
|
||||||
static void test_StrRChrW(void)
|
static void test_StrRChrW(void)
|
||||||
{
|
{
|
||||||
WCHAR string[16385];
|
WCHAR string[129];
|
||||||
int count;
|
WORD count;
|
||||||
|
|
||||||
ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!");
|
/* this test crashes on win2k SP4 */
|
||||||
|
/*ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!");*/
|
||||||
|
|
||||||
for (count = 32; count < 16384; count++)
|
for (count = 32; count < 128; count++)
|
||||||
string[count] = count;
|
string[count] = count;
|
||||||
string[16384] = '\0';
|
string[128] = '\0';
|
||||||
|
|
||||||
for (count = 32; count < 16384; count++)
|
for (count = 32; count < 128; count++)
|
||||||
{
|
{
|
||||||
LPWSTR result = StrRChrW(string+32, NULL, count);
|
LPWSTR result = StrRChrW(string+32, NULL, count);
|
||||||
ok(result - string == count, "found char %d in wrong place", count);
|
ok(result - string == count,
|
||||||
|
"found char %d in wrong place: got %d, expected %d\n",
|
||||||
|
count, result - string, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (count = 32; count < 16384; count++)
|
for (count = 32; count < 128; count++)
|
||||||
{
|
{
|
||||||
LPWSTR result = StrRChrW(string+count+1, NULL, count);
|
LPWSTR result = StrRChrW(string+count+1, NULL, count);
|
||||||
ok(!result, "found char not in the string");
|
ok(!result, "found char %d not in the string\n", count);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (count = 32; count < 16384; count++)
|
for (count = 32; count < 128; count++)
|
||||||
{
|
{
|
||||||
LPWSTR result = StrRChrW(string+count+1, string + 127, count);
|
LPWSTR result = StrRChrW(string+count+1, string + 127, count);
|
||||||
ok(!result, "found char not in the string");
|
ok(!result, "found char %d not in the string\n", count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,6 +465,8 @@ static void test_StrDupA()
|
||||||
|
|
||||||
static void test_StrFormatByteSize64A(void)
|
static void test_StrFormatByteSize64A(void)
|
||||||
{
|
{
|
||||||
|
/* this test fails on locales which do not use '.' as a decimal separator */
|
||||||
|
#if 0
|
||||||
char szBuff[256];
|
char szBuff[256];
|
||||||
const StrFormatSizeResult* result = StrFormatSize_results;
|
const StrFormatSizeResult* result = StrFormatSize_results;
|
||||||
|
|
||||||
|
@ -462,10 +474,13 @@ static void test_StrFormatByteSize64A(void)
|
||||||
{
|
{
|
||||||
StrFormatByteSize64A(result->value, szBuff, 256);
|
StrFormatByteSize64A(result->value, szBuff, 256);
|
||||||
|
|
||||||
ok(!strcmp(result->byte_size_64, szBuff), "Formatted %lld wrong", result->value);
|
ok(!strcmp(result->byte_size_64, szBuff),
|
||||||
|
"Formatted %lx%08lx wrong: got %s, expected %s\n",
|
||||||
|
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->byte_size_64);
|
||||||
|
|
||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_StrFormatKBSizeW(void)
|
static void test_StrFormatKBSizeW(void)
|
||||||
|
@ -480,8 +495,9 @@ static void test_StrFormatKBSizeW(void)
|
||||||
{
|
{
|
||||||
StrFormatKBSizeW(result->value, szBuffW, 256);
|
StrFormatKBSizeW(result->value, szBuffW, 256);
|
||||||
WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0);
|
WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0);
|
||||||
ok(!strcmp(result->kb_size, szBuff), "Formatted %lld wrong",
|
ok(!strcmp(result->kb_size, szBuff),
|
||||||
result->value);
|
"Formatted %lx%08lx wrong: got %s, expected %s\n",
|
||||||
|
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
|
||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -489,6 +505,7 @@ static void test_StrFormatKBSizeW(void)
|
||||||
|
|
||||||
static void test_StrFormatKBSizeA(void)
|
static void test_StrFormatKBSizeA(void)
|
||||||
{
|
{
|
||||||
|
/* this test fails on locales which do not use '.' as a decimal separator */
|
||||||
#if 0
|
#if 0
|
||||||
char szBuff[256];
|
char szBuff[256];
|
||||||
const StrFormatSizeResult* result = StrFormatSize_results;
|
const StrFormatSizeResult* result = StrFormatSize_results;
|
||||||
|
@ -497,8 +514,9 @@ static void test_StrFormatKBSizeA(void)
|
||||||
{
|
{
|
||||||
StrFormatKBSizeA(result->value, szBuff, 256);
|
StrFormatKBSizeA(result->value, szBuff, 256);
|
||||||
|
|
||||||
ok(!strcmp(result->kb_size, szBuff), "Formatted %lld wrong",
|
ok(!strcmp(result->kb_size, szBuff),
|
||||||
result->value);
|
"Formatted %lx%08lx wrong: got %s, expected %s\n",
|
||||||
|
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
|
||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -74,6 +74,7 @@ extern int wine_cp_wcstombs( const union cptable *table, int flags,
|
||||||
extern int wine_utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen );
|
extern int wine_utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen );
|
||||||
extern int wine_utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen );
|
extern int wine_utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen );
|
||||||
|
|
||||||
|
extern int wine_compare_string( int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2 );
|
||||||
extern int wine_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
|
extern int wine_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
|
||||||
extern int wine_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen );
|
extern int wine_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen );
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
|
extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
|
||||||
|
extern const unsigned int collation_table[];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* flags - normalization NORM_* flags
|
* flags - normalization NORM_* flags
|
||||||
|
@ -28,7 +29,6 @@ extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
|
||||||
*/
|
*/
|
||||||
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
|
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
|
||||||
{
|
{
|
||||||
extern const unsigned int collation_table[];
|
|
||||||
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */
|
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */
|
||||||
int key_len[4];
|
int key_len[4];
|
||||||
char *key_ptr[4];
|
char *key_ptr[4];
|
||||||
|
@ -38,7 +38,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
||||||
key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0;
|
key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0;
|
||||||
for (; srclen; srclen--, src++)
|
for (; srclen; srclen--, src++)
|
||||||
{
|
{
|
||||||
int decomposed_len = get_decomposition(*src, dummy, 4);
|
int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
|
||||||
|
dummy[0] = *src;
|
||||||
if (decomposed_len)
|
if (decomposed_len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -62,18 +63,18 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
||||||
if (ce >> 16) key_len[0] += 2;
|
if (ce >> 16) key_len[0] += 2;
|
||||||
if ((ce >> 8) & 0xff) key_len[1]++;
|
if ((ce >> 8) & 0xff) key_len[1]++;
|
||||||
if ((ce >> 4) & 0x0f) key_len[2]++;
|
if ((ce >> 4) & 0x0f) key_len[2]++;
|
||||||
/*if (ce & 1)
|
if (ce & 1)
|
||||||
{
|
{
|
||||||
if (wch >> 8) key_len[3]++;
|
if (wch >> 8) key_len[3]++;
|
||||||
key_len[3]++;
|
key_len[3]++;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
/*else
|
else
|
||||||
{
|
{
|
||||||
key_len[0] += 2;
|
key_len[0] += 2;
|
||||||
if (wch >> 8) key_len[0]++;
|
if (wch >> 8) key_len[0]++;
|
||||||
if (wch & 0xff) key_len[0]++;
|
if (wch & 0xff) key_len[0]++;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +96,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
||||||
|
|
||||||
for (; srclen; srclen--, src++)
|
for (; srclen; srclen--, src++)
|
||||||
{
|
{
|
||||||
int decomposed_len = get_decomposition(*src, dummy, 4);
|
int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
|
||||||
|
dummy[0] = *src;
|
||||||
if (decomposed_len)
|
if (decomposed_len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -127,19 +129,19 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
||||||
/* make key 2 start from 2 */
|
/* make key 2 start from 2 */
|
||||||
if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1;
|
if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1;
|
||||||
/* key 3 is always a character code */
|
/* key 3 is always a character code */
|
||||||
/*if (ce & 1)
|
if (ce & 1)
|
||||||
{
|
{
|
||||||
if (wch >> 8) *key_ptr[3]++ = wch >> 8;
|
if (wch >> 8) *key_ptr[3]++ = wch >> 8;
|
||||||
if (wch & 0xff) *key_ptr[3]++ = wch & 0xff;
|
if (wch & 0xff) *key_ptr[3]++ = wch & 0xff;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
/*else
|
else
|
||||||
{
|
{
|
||||||
*key_ptr[0]++ = 0xff;
|
*key_ptr[0]++ = 0xff;
|
||||||
*key_ptr[0]++ = 0xfe;
|
*key_ptr[0]++ = 0xfe;
|
||||||
if (wch >> 8) *key_ptr[0]++ = wch >> 8;
|
if (wch >> 8) *key_ptr[0]++ = wch >> 8;
|
||||||
if (wch & 0xff) *key_ptr[0]++ = wch & 0xff;
|
if (wch & 0xff) *key_ptr[0]++ = wch & 0xff;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,3 +154,198 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
||||||
|
|
||||||
return key_ptr[3] - dst;
|
return key_ptr[3] - dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1,
|
||||||
|
const WCHAR *str2, int len2)
|
||||||
|
{
|
||||||
|
unsigned int ce1, ce2;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* 32-bit collation element table format:
|
||||||
|
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||||
|
* case weight - high 4 bit of low 8 bit.
|
||||||
|
*/
|
||||||
|
while (len1 > 0 && len2 > 0)
|
||||||
|
{
|
||||||
|
if (flags & NORM_IGNORESYMBOLS)
|
||||||
|
{
|
||||||
|
int skip = 0;
|
||||||
|
/* FIXME: not tested */
|
||||||
|
if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
str1++;
|
||||||
|
len1--;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
str2++;
|
||||||
|
len2--;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hyphen and apostrophe are treated differently depending on
|
||||||
|
* whether SORT_STRINGSORT specified or not
|
||||||
|
*/
|
||||||
|
if (!(flags & SORT_STRINGSORT))
|
||||||
|
{
|
||||||
|
if (*str1 == '-' || *str1 == '\'')
|
||||||
|
{
|
||||||
|
if (*str2 != '-' && *str2 != '\'')
|
||||||
|
{
|
||||||
|
str1++;
|
||||||
|
len1--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*str2 == '-' || *str2 == '\'')
|
||||||
|
{
|
||||||
|
str2++;
|
||||||
|
len2--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||||
|
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||||
|
|
||||||
|
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||||
|
ret = (ce1 >> 16) - (ce2 >> 16);
|
||||||
|
else
|
||||||
|
ret = *str1 - *str2;
|
||||||
|
|
||||||
|
if (ret) return ret;
|
||||||
|
|
||||||
|
str1++;
|
||||||
|
str2++;
|
||||||
|
len1--;
|
||||||
|
len2--;
|
||||||
|
}
|
||||||
|
return len1 - len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int compare_diacritic_weights(int flags, const WCHAR *str1, int len1,
|
||||||
|
const WCHAR *str2, int len2)
|
||||||
|
{
|
||||||
|
unsigned int ce1, ce2;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* 32-bit collation element table format:
|
||||||
|
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||||
|
* case weight - high 4 bit of low 8 bit.
|
||||||
|
*/
|
||||||
|
while (len1 > 0 && len2 > 0)
|
||||||
|
{
|
||||||
|
if (flags & NORM_IGNORESYMBOLS)
|
||||||
|
{
|
||||||
|
int skip = 0;
|
||||||
|
/* FIXME: not tested */
|
||||||
|
if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
str1++;
|
||||||
|
len1--;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
str2++;
|
||||||
|
len2--;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||||
|
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||||
|
|
||||||
|
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||||
|
ret = ((ce1 >> 8) & 0xff) - ((ce2 >> 8) & 0xff);
|
||||||
|
else
|
||||||
|
ret = *str1 - *str2;
|
||||||
|
|
||||||
|
if (ret) return ret;
|
||||||
|
|
||||||
|
str1++;
|
||||||
|
str2++;
|
||||||
|
len1--;
|
||||||
|
len2--;
|
||||||
|
}
|
||||||
|
return len1 - len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int compare_case_weights(int flags, const WCHAR *str1, int len1,
|
||||||
|
const WCHAR *str2, int len2)
|
||||||
|
{
|
||||||
|
unsigned int ce1, ce2;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* 32-bit collation element table format:
|
||||||
|
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||||
|
* case weight - high 4 bit of low 8 bit.
|
||||||
|
*/
|
||||||
|
while (len1 > 0 && len2 > 0)
|
||||||
|
{
|
||||||
|
if (flags & NORM_IGNORESYMBOLS)
|
||||||
|
{
|
||||||
|
int skip = 0;
|
||||||
|
/* FIXME: not tested */
|
||||||
|
if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
str1++;
|
||||||
|
len1--;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
|
||||||
|
{
|
||||||
|
str2++;
|
||||||
|
len2--;
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||||
|
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||||
|
|
||||||
|
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||||
|
ret = ((ce1 >> 4) & 0x0f) - ((ce2 >> 4) & 0x0f);
|
||||||
|
else
|
||||||
|
ret = *str1 - *str2;
|
||||||
|
|
||||||
|
if (ret) return ret;
|
||||||
|
|
||||||
|
str1++;
|
||||||
|
str2++;
|
||||||
|
len1--;
|
||||||
|
len2--;
|
||||||
|
}
|
||||||
|
return len1 - len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int real_length(const WCHAR *str, int len)
|
||||||
|
{
|
||||||
|
int real_len = 0;
|
||||||
|
while (len-- && *str++) real_len++;
|
||||||
|
return real_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wine_compare_string(int flags, const WCHAR *str1, int len1,
|
||||||
|
const WCHAR *str2, int len2)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
len1 = real_length(str1, len1);
|
||||||
|
len2 = real_length(str2, len2);
|
||||||
|
|
||||||
|
ret = compare_unicode_weights(flags, str1, len1, str2, len2);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
if (!(flags & NORM_IGNORENONSPACE))
|
||||||
|
ret = compare_diacritic_weights(flags, str1, len1, str2, len2);
|
||||||
|
if (!ret && !(flags & NORM_IGNORECASE))
|
||||||
|
ret = compare_case_weights(flags, str1, len1, str2, len2);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int ret = toupperW(*str1) - toupperW(*str2);
|
int ret = tolowerW(*str1) - tolowerW(*str2);
|
||||||
if (ret || !*str1) return ret;
|
if (ret || !*str1) return ret;
|
||||||
str1++;
|
str1++;
|
||||||
str2++;
|
str2++;
|
||||||
|
@ -38,7 +38,7 @@ int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for ( ; n > 0; n--, str1++, str2++)
|
for ( ; n > 0; n--, str1++, str2++)
|
||||||
if ((ret = toupperW(*str1) - toupperW(*str2)) || !*str1) break;
|
if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ EXPORTS
|
||||||
vsprintfW
|
vsprintfW
|
||||||
wine_casemap_lower
|
wine_casemap_lower
|
||||||
wine_casemap_upper
|
wine_casemap_upper
|
||||||
|
wine_compare_string
|
||||||
wine_cp_enum_table
|
wine_cp_enum_table
|
||||||
wine_cp_get_table
|
wine_cp_get_table
|
||||||
wine_cp_mbstowcs
|
wine_cp_mbstowcs
|
||||||
|
|
Loading…
Reference in New Issue