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