Various CompareString fixes
Dmitry Timoshkov
dmitry at baikal.ru
Mon Nov 3 07:55:59 CST 2003
Hello,
now all is remaining is a collation table patch to make it
MS compatible.
Changelog:
Dmitry Timoshkov <dmitry at codeweavers.com>
Move CompareString implementation to libwine_unicode,
add a bunch of CompareString tests.
diff -u cvs/hq/wine/dlls/kernel/locale.c wine/dlls/kernel/locale.c
--- cvs/hq/wine/dlls/kernel/locale.c Sun Oct 26 16:11:31 2003
+++ wine/dlls/kernel/locale.c Mon Nov 3 18:05:16 2003
@@ -1971,6 +1971,12 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD
}
}
+ if (srclen)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return 0;
+ }
+
return dst_ptr - dst;
}
@@ -1994,7 +2000,7 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
LPSTR dst, INT dstlen)
{
- WCHAR bufW[128];
+ WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
LPWSTR srcW, dstW;
INT ret = 0, srclenW, dstlenW;
UINT locale_cp;
@@ -2007,7 +2013,7 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD
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)
srcW = bufW;
else
@@ -2040,6 +2046,9 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD
}
dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0);
+ if (!dstlenW)
+ goto map_string_exit;
+
dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
if (!dstW)
{
@@ -2172,7 +2181,7 @@ INT WINAPI FoldStringW(DWORD dwFlags, LP
INT WINAPI CompareStringW(LCID lcid, DWORD style,
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
{
- INT ret, len;
+ INT ret;
if (!str1 || !str2)
{
@@ -2180,19 +2189,24 @@ INT WINAPI CompareStringW(LCID lcid, DWO
return 0;
}
- if (len1 < 0) len1 = lstrlenW(str1);
- if (len2 < 0) len2 = lstrlenW(str2);
+ if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
+ SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|0x10000000) )
+ {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return 0;
+ }
+
+ if (style & 0x10000000)
+ FIXME("Ignoring unknown style 0x10000000\n");
- len = (len1 < len2) ? len1 : len2;
- ret = (style & NORM_IGNORECASE) ? strncmpiW(str1, str2, len) :
- 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 */
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
-
- if (len1 == len2) return CSTR_EQUAL;
- /* the longer one is lexically greater */
- return (len1 < len2) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
+ return CSTR_EQUAL;
}
/******************************************************************************
@@ -2216,7 +2230,8 @@ INT WINAPI CompareStringW(LCID lcid, DWO
INT WINAPI CompareStringA(LCID lcid, DWORD style,
LPCSTR str1, INT len1, LPCSTR str2, INT len2)
{
- WCHAR buf1W[128], buf2W[128];
+ WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
+ WCHAR *buf2W = buf1W + 130;
LPWSTR str1W, str2W;
INT len1W, len2W, ret;
UINT locale_cp;
@@ -2226,13 +2241,12 @@ INT WINAPI CompareStringA(LCID lcid, DWO
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
-
if (len1 < 0) len1 = strlen(str1);
if (len2 < 0) len2 = strlen(str2);
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)
str1W = buf1W;
else
@@ -2246,7 +2260,7 @@ INT WINAPI CompareStringA(LCID lcid, DWO
}
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)
str2W = buf2W;
else
diff -u cvs/hq/wine/dlls/kernel/tests/locale.c wine/dlls/kernel/tests/locale.c
--- cvs/hq/wine/dlls/kernel/tests/locale.c Thu Oct 30 14:47:28 2003
+++ wine/dlls/kernel/tests/locale.c Mon Nov 3 19:11:43 2003
@@ -24,6 +24,9 @@
* 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.
*/
+
+#include <assert.h>
+#include <stdlib.h>
#include <stdarg.h>
#include "wine/test.h"
@@ -774,8 +777,140 @@ static void test_CompareStringA()
ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
- ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "SaLuT", -1);
- ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
+ ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
+ 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);
+
+todo_wine /* this requires collation table patch to make it MS compatible */
+{
+ 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);
+} /* todo_wine */
+
+ 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)
@@ -834,6 +969,13 @@ void test_LCMapStringA(void)
ret, GetLastError(), lstrlenA(lower_case) + 1);
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 */
lstrcpyA(buf, lower_case);
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
@@ -924,6 +1066,13 @@ void test_LCMapStringA(void)
ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
lstrlenA(symbols_stripped) + 1, ret);
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)
@@ -988,6 +1137,13 @@ void test_LCMapStringW(void)
ret, GetLastError(), lstrlenW(lower_case) + 1);
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 */
lstrcpyW(buf, lower_case);
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
@@ -1069,9 +1225,144 @@ void test_LCMapStringW(void)
ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
lstrlenW(symbols_stripped) + 1, ret);
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)
+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));
+
+todo_wine /* this requires collation table patch to make it MS compatible */
+{
+ /* 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);
+ }
+} /* todo_wine */
+}
+
+static void test_FoldStringA(void)
{
int ret, i;
char src[256], dst[256];
@@ -1118,6 +1409,13 @@ void test_FoldStringA(void)
if (!pFoldStringA)
return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
+ /* these tests are locale specific */
+ if (PRIMARYLANGID(LANGIDFROMLCID(GetUserDefaultLCID())) != LANG_ENGLISH)
+ {
+ trace("Skipping FoldStringA tests for a not English locale\n");
+ return;
+ }
+
/* MAP_FOLDDIGITS */
SetLastError(0);
ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
@@ -1212,7 +1510,7 @@ void test_FoldStringA(void)
}
}
-void test_FoldStringW(void)
+static void test_FoldStringW(void)
{
int ret;
size_t i, j;
@@ -1710,4 +2008,5 @@ START_TEST(locale)
test_EnumSystemLanguageGroupsA();
test_EnumLanguageGroupLocalesA();
test_SetLocaleInfoA();
+ test_sorting();
}
diff -u cvs/hq/wine/include/wine/unicode.h wine/include/wine/unicode.h
--- cvs/hq/wine/include/wine/unicode.h Mon Oct 20 13:17:21 2003
+++ wine/include/wine/unicode.h Mon Nov 3 18:05:16 2003
@@ -74,6 +74,7 @@ extern int wine_cp_wcstombs( const union
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_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_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen );
diff -u cvs/hq/wine/libs/unicode/collation.c wine/libs/unicode/collation.c
--- cvs/hq/wine/libs/unicode/collation.c Fri Jun 27 13:04:59 2003
+++ wine/libs/unicode/collation.c Mon Nov 3 18:05:16 2003
@@ -2,7 +2,7 @@
/* generated from www.unicode.org/reports/tr10/allkeys.txt */
/* DO NOT EDIT!! */
-const unsigned int collation_table[12800] =
+const unsigned int unicode_collation_table[12800] =
{
/* index */
0x00000200, 0x00000300, 0x00000400, 0x00000500, 0x00000600, 0x00000700, 0x00000800, 0x00000900,
diff -u cvs/hq/wine/libs/unicode/cpmap.pl wine/libs/unicode/cpmap.pl
--- cvs/hq/wine/libs/unicode/cpmap.pl Thu Oct 30 14:47:33 2003
+++ wine/libs/unicode/cpmap.pl Mon Nov 3 18:05:16 2003
@@ -607,7 +607,7 @@ sub DUMP_SORTKEYS
printf OUTPUT "/* generated from %s */\n", $SORTKEYS;
printf OUTPUT "/* DO NOT EDIT!! */\n\n";
- printf OUTPUT "const unsigned int collation_table[%d] =\n{\n", $ranges*256;
+ printf OUTPUT "const unsigned int unicode_collation_table[%d] =\n{\n", $ranges*256;
printf OUTPUT " /* index */\n";
printf OUTPUT "%s,\n", DUMP_ARRAY( "0x%08x", 0, @offsets );
diff -u cvs/hq/wine/libs/unicode/sortkey.c wine/libs/unicode/sortkey.c
--- cvs/hq/wine/libs/unicode/sortkey.c Sat Jun 28 04:02:23 2003
+++ wine/libs/unicode/sortkey.c Mon Nov 3 18:05:16 2003
@@ -28,7 +28,7 @@ extern int get_decomposition(WCHAR src,
*/
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
{
- extern const unsigned int collation_table[];
+ extern const unsigned int unicode_collation_table[];
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */
int key_len[4];
char *key_ptr[4];
@@ -38,7 +38,8 @@ int wine_get_sortkey(int flags, const WC
key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0;
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)
{
int i;
@@ -56,24 +57,24 @@ int wine_get_sortkey(int flags, const WC
if (flags & NORM_IGNORECASE) wch = tolowerW(wch);
- ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)];
+ ce = unicode_collation_table[unicode_collation_table[wch >> 8] + (wch & 0xff)];
if (ce != (unsigned int)-1)
{
if (ce >> 16) key_len[0] += 2;
if ((ce >> 8) & 0xff) key_len[1]++;
if ((ce >> 4) & 0x0f) key_len[2]++;
- /*if (ce & 1)
+ if (ce & 1)
{
if (wch >> 8) key_len[3]++;
key_len[3]++;
- }*/
+ }
}
- /*else
+ else
{
key_len[0] += 2;
if (wch >> 8) key_len[0]++;
if (wch & 0xff) key_len[0]++;
- }*/
+ }
}
}
}
@@ -95,7 +96,8 @@ int wine_get_sortkey(int flags, const WC
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)
{
int i;
@@ -113,7 +115,7 @@ int wine_get_sortkey(int flags, const WC
if (flags & NORM_IGNORECASE) wch = tolowerW(wch);
- ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)];
+ ce = unicode_collation_table[unicode_collation_table[wch >> 8] + (wch & 0xff)];
if (ce != (unsigned int)-1)
{
WCHAR key;
@@ -127,19 +129,19 @@ int wine_get_sortkey(int flags, const WC
/* make key 2 start from 2 */
if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1;
/* key 3 is always a character code */
- /*if (ce & 1)
+ if (ce & 1)
{
if (wch >> 8) *key_ptr[3]++ = wch >> 8;
if (wch & 0xff) *key_ptr[3]++ = wch & 0xff;
- }*/
+ }
}
- /*else
+ else
{
*key_ptr[0]++ = 0xff;
*key_ptr[0]++ = 0xfe;
if (wch >> 8) *key_ptr[0]++ = wch >> 8;
if (wch & 0xff) *key_ptr[0]++ = wch & 0xff;
- }*/
+ }
}
}
}
@@ -151,4 +153,201 @@ int wine_get_sortkey(int flags, const WC
*key_ptr[3] = 0;
return key_ptr[3] - dst;
+}
+
+static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1,
+ const WCHAR *str2, int len2)
+{
+ extern const unsigned int unicode_collation_table[];
+ 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))
+ {
+ int skip = 0;
+ if (*str1 == '-' || *str1 == '\'')
+ {
+ str1++;
+ len1--;
+ skip = 1;
+ }
+ if (*str2 == '-' || *str2 == '\'')
+ {
+ str2++;
+ len2--;
+ skip = 1;
+ }
+ if (skip) continue;
+ }
+
+ ce1 = unicode_collation_table[unicode_collation_table[*str1 >> 8] + (*str1 & 0xff)];
+ ce2 = unicode_collation_table[unicode_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)
+{
+ extern const unsigned int unicode_collation_table[];
+ 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 = unicode_collation_table[unicode_collation_table[*str1 >> 8] + (*str1 & 0xff)];
+ ce2 = unicode_collation_table[unicode_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)
+{
+ extern const unsigned int unicode_collation_table[];
+ 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 = unicode_collation_table[unicode_collation_table[*str1 >> 8] + (*str1 & 0xff)];
+ ce2 = unicode_collation_table[unicode_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;
}
diff -u cvs/hq/wine/libs/unicode/string.c wine/libs/unicode/string.c
--- cvs/hq/wine/libs/unicode/string.c Mon Jul 21 19:06:51 2003
+++ wine/libs/unicode/string.c Mon Nov 3 18:05:16 2003
@@ -27,7 +27,7 @@ int strcmpiW( const WCHAR *str1, const W
{
for (;;)
{
- int ret = toupperW(*str1) - toupperW(*str2);
+ int ret = tolowerW(*str1) - tolowerW(*str2);
if (ret || !*str1) return ret;
str1++;
str2++;
@@ -38,7 +38,7 @@ int strncmpiW( const WCHAR *str1, const
{
int ret = 0;
for ( ; n > 0; n--, str1++, str2++)
- if ((ret = toupperW(*str1) - toupperW(*str2)) || !*str1) break;
+ if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
return ret;
}
diff -u cvs/hq/wine/libs/unicode/wine_unicode.def wine/libs/unicode/wine_unicode.def
--- cvs/hq/wine/libs/unicode/wine_unicode.def Mon Oct 20 13:17:22 2003
+++ wine/libs/unicode/wine_unicode.def Mon Nov 3 18:05:16 2003
@@ -12,6 +12,7 @@ EXPORTS
vsprintfW
wine_casemap_lower
wine_casemap_upper
+ wine_compare_string
wine_cp_enum_table
wine_cp_get_table
wine_cp_mbstowcs
More information about the wine-patches
mailing list