Piotr Caban : libwine: Add helper function to compare character weights.
Alexandre Julliard
julliard at winehq.org
Wed May 22 15:52:06 CDT 2019
Module: wine
Branch: master
Commit: ac5ac588f3965e5116c8933ad354fb6bf3502709
URL: https://source.winehq.org/git/wine.git/?a=commit;h=ac5ac588f3965e5116c8933ad354fb6bf3502709
Author: Piotr Caban <piotr at codeweavers.com>
Date: Tue May 21 17:19:44 2019 +0200
libwine: Add helper function to compare character weights.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
libs/port/sortkey.c | 169 +++++++++++-----------------------------------------
1 file changed, 36 insertions(+), 133 deletions(-)
diff --git a/libs/port/sortkey.c b/libs/port/sortkey.c
index c61a7e5..7ca1a20 100644
--- a/libs/port/sortkey.c
+++ b/libs/port/sortkey.c
@@ -153,11 +153,37 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
return key_ptr[3] - dst;
}
-static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1,
- const WCHAR *str2, int len2)
+enum weight
+{
+ UNICODE_WEIGHT,
+ DIACRITIC_WEIGHT,
+ CASE_WEIGHT
+};
+
+static unsigned int get_weight(WCHAR ch, enum weight type)
+{
+ unsigned int ret;
+
+ ret = collation_table[collation_table[ch >> 8] + (ch & 0xff)];
+ if (ret == (unsigned int)-1)
+ return ch;
+
+ switch(type)
+ {
+ case UNICODE_WEIGHT:
+ return ret >> 16;
+ case DIACRITIC_WEIGHT:
+ return (ret >> 8) & 0xff;
+ case CASE_WEIGHT:
+ default:
+ return (ret >> 4) & 0x0f;
+ }
+}
+
+static inline int compare_weights(int flags, const WCHAR *str1, int len1,
+ const WCHAR *str2, int len2, enum weight type)
{
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,
@@ -187,7 +213,7 @@ static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1
/* hyphen and apostrophe are treated differently depending on
* whether SORT_STRINGSORT specified or not
*/
- if (!(flags & SORT_STRINGSORT))
+ if (type == UNICODE_WEIGHT && !(flags & SORT_STRINGSORT))
{
if (*str1 == '-' || *str1 == '\'')
{
@@ -206,133 +232,10 @@ static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1
}
}
- 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--;
- }
- while (len1 && !*str1)
- {
- str1++;
- len1--;
- }
- while (len2 && !*str2)
- {
- str2++;
- 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--;
- }
- while (len1 && !*str1)
- {
- str1++;
- len1--;
- }
- while (len2 && !*str2)
- {
- str2++;
- 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;
+ ce1 = get_weight(*str1, type);
+ ce2 = get_weight(*str2, type);
- if (ret) return ret;
+ if (ce1 - ce2) return ce1 - ce2;
str1++;
str2++;
@@ -357,13 +260,13 @@ int wine_compare_string(int flags, const WCHAR *str1, int len1,
{
int ret;
- ret = compare_unicode_weights(flags, str1, len1, str2, len2);
+ ret = compare_weights(flags, str1, len1, str2, len2, UNICODE_WEIGHT);
if (!ret)
{
if (!(flags & NORM_IGNORENONSPACE))
- ret = compare_diacritic_weights(flags, str1, len1, str2, len2);
+ ret = compare_weights(flags, str1, len1, str2, len2, DIACRITIC_WEIGHT);
if (!ret && !(flags & NORM_IGNORECASE))
- ret = compare_case_weights(flags, str1, len1, str2, len2);
+ ret = compare_weights(flags, str1, len1, str2, len2, CASE_WEIGHT);
}
return ret;
}
More information about the wine-cvs
mailing list