From 40a1a9e9a242aa694bd28f640f51f66ce9eb99ba Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Tue, 21 May 2019 17:19:48 +0200 Subject: [PATCH] libwine: Decompose characters before comparing in wine_compare_string. Signed-off-by: Piotr Caban Signed-off-by: Alexandre Julliard --- 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 a8d6e4cc40b..1c632cc4356 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 7ca1a206aec..5d83fcd5945 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) {