Piotr Caban : libwine: Decompose characters before comparing in wine_compare_string.
Alexandre Julliard
julliard at winehq.org
Wed May 22 15:52:06 CDT 2019
Module: wine
Branch: master
Commit: 40a1a9e9a242aa694bd28f640f51f66ce9eb99ba
URL: https://source.winehq.org/git/wine.git/?a=commit;h=40a1a9e9a242aa694bd28f640f51f66ce9eb99ba
Author: Piotr Caban <piotr at codeweavers.com>
Date: Tue May 21 17:19:48 2019 +0200
libwine: Decompose characters before comparing in wine_compare_string.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/kernel32/tests/locale.c | 24 +++++++++++-----------
libs/port/sortkey.c | 48 ++++++++++++++++++++++++++------------------
2 files changed, 41 insertions(+), 31 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index a8d6e4c..1c632cc 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -1975,7 +1975,7 @@ static void test_CompareStringA(void)
/* \xB9 character lies between a and b */
ret = CompareStringA(lcid, 0, "a", 1, "\xB9", 1);
- todo_wine ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be greater than \'a\'\n");
+ ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be greater than \'a\'\n");
ret = CompareStringA(lcid, 0, "\xB9", 1, "b", 1);
ok(ret == CSTR_LESS_THAN, "\'\\xB9\' character should be smaller than \'b\'\n");
@@ -2047,14 +2047,14 @@ static void test_CompareStringW(void)
ret = CompareStringW(CP_ACP, 0, ABC_EE, 4, A_ACUTE_BC_DECOMP, 5);
todo_wine ok(ret == CSTR_LESS_THAN, "expected CSTR_LESS_THAN, got %d\n", ret);
ret = CompareStringW(CP_ACP, 0, A_ACUTE_BC, 4, A_ACUTE_BC_DECOMP, 5);
- todo_wine ok(ret == CSTR_EQUAL, "expected CSTR_EQUAL, got %d\n", ret);
+ ok(ret == CSTR_EQUAL, "expected CSTR_EQUAL, got %d\n", ret);
ret = CompareStringW(CP_ACP, NORM_IGNORENONSPACE, ABC_EE, 3, A_ACUTE_BC, 4);
- ok(ret == CSTR_EQUAL, "expected CSTR_EQUAL, got %d\n", ret);
+ todo_wine ok(ret == CSTR_EQUAL, "expected CSTR_EQUAL, got %d\n", ret);
ret = CompareStringW(CP_ACP, NORM_IGNORENONSPACE, ABC_EE, 4, A_ACUTE_BC_DECOMP, 5);
todo_wine ok(ret == CSTR_EQUAL, "expected CSTR_EQUAL, got %d\n", ret);
ret = CompareStringW(CP_ACP, NORM_IGNORENONSPACE, A_ACUTE_BC, 4, A_ACUTE_BC_DECOMP, 5);
- todo_wine ok(ret == CSTR_EQUAL, "expected CSTR_EQUAL, got %d\n", ret);
+ ok(ret == CSTR_EQUAL, "expected CSTR_EQUAL, got %d\n", ret);
ret = CompareStringW(CP_ACP, 0, ABC_EE, 4, A_NULL_BC, 4);
todo_wine ok(ret == CSTR_EQUAL, "expected CSTR_LESS_THAN, got %d\n", ret);
@@ -2098,7 +2098,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 3 */
"tr-TR", 0,
- {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 4 */
"tr-TR", 0,
@@ -2115,7 +2115,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 7 */
"tr-TR", NORM_IGNORECASE,
- {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 8 */
"tr-TR", NORM_IGNORECASE,
@@ -2123,7 +2123,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 9 */
"tr-TR", NORM_IGNORECASE,
- {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 10 */
"tr-TR", NORM_IGNORECASE,
@@ -2148,7 +2148,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 15 */
"tr-TR", NORM_LINGUISTIC_CASING,
- {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 16 */
"tr-TR", NORM_LINGUISTIC_CASING,
@@ -2173,7 +2173,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 21 */
"tr-TR", LINGUISTIC_IGNORECASE,
- {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 22 */
"tr-TR", LINGUISTIC_IGNORECASE,
@@ -2190,7 +2190,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 25 */
"tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
- {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, FALSE
+ {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
},
{ /* 26 */
"tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
@@ -2198,7 +2198,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 27 */
"tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
- {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 28 */
"tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
@@ -2223,7 +2223,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 33 */
"tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
- {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 34 */
"tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
diff --git a/libs/port/sortkey.c b/libs/port/sortkey.c
index 7ca1a20..5d83fcd 100644
--- a/libs/port/sortkey.c
+++ b/libs/port/sortkey.c
@@ -180,9 +180,22 @@ static unsigned int get_weight(WCHAR ch, enum weight type)
}
}
+static void inc_str_pos(const WCHAR **str, int *len, int *dpos, int *dlen)
+{
+ (*dpos)++;
+ if (*dpos == *dlen)
+ {
+ *dpos = *dlen = 0;
+ (*str)++;
+ (*len)--;
+ }
+}
+
static inline int compare_weights(int flags, const WCHAR *str1, int len1,
const WCHAR *str2, int len2, enum weight type)
{
+ int dpos1 = 0, dpos2 = 0, dlen1 = 0, dlen2 = 0;
+ WCHAR dstr1[4], dstr2[4];
unsigned int ce1, ce2;
/* 32-bit collation element table format:
@@ -191,20 +204,21 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1,
*/
while (len1 > 0 && len2 > 0)
{
+ if (!dlen1) dlen1 = wine_decompose(0, *str1, dstr1, 4);
+ if (!dlen2) dlen2 = wine_decompose(0, *str2, dstr2, 4);
+
if (flags & NORM_IGNORESYMBOLS)
{
int skip = 0;
/* FIXME: not tested */
- if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
+ if (get_char_typeW(dstr1[dpos1]) & (C1_PUNCT | C1_SPACE))
{
- str1++;
- len1--;
+ inc_str_pos(&str1, &len1, &dpos1, &dlen1);
skip = 1;
}
- if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
+ if (!dlen2 && get_char_typeW(dstr2[dpos2]) & (C1_PUNCT | C1_SPACE))
{
- str2++;
- len2--;
+ inc_str_pos(&str2, &len2, &dpos2, &dlen2);
skip = 1;
}
if (skip) continue;
@@ -215,32 +229,28 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1,
*/
if (type == UNICODE_WEIGHT && !(flags & SORT_STRINGSORT))
{
- if (*str1 == '-' || *str1 == '\'')
+ if (dstr1[dpos1] == '-' || dstr1[dpos1] == '\'')
{
- if (*str2 != '-' && *str2 != '\'')
+ if (dstr2[dpos2] != '-' && dstr2[dpos2] != '\'')
{
- str1++;
- len1--;
+ inc_str_pos(&str1, &len1, &dpos1, &dlen1);
continue;
}
}
- else if (*str2 == '-' || *str2 == '\'')
+ else if (dstr2[dpos2] == '-' || dstr2[dpos2] == '\'')
{
- str2++;
- len2--;
+ inc_str_pos(&str2, &len2, &dpos2, &dlen2);
continue;
}
}
- ce1 = get_weight(*str1, type);
- ce2 = get_weight(*str2, type);
+ ce1 = get_weight(dstr1[dpos1], type);
+ ce2 = get_weight(dstr2[dpos2], type);
if (ce1 - ce2) return ce1 - ce2;
- str1++;
- str2++;
- len1--;
- len2--;
+ inc_str_pos(&str1, &len1, &dpos1, &dlen1);
+ inc_str_pos(&str2, &len2, &dpos2, &dlen2);
}
while (len1 && !*str1)
{
More information about the wine-cvs
mailing list