Alexandre Julliard : kernelbase: Add a helper function to map an entire buffer to half width.

Alexandre Julliard julliard at winehq.org
Thu Jun 2 16:26:08 CDT 2022


Module: wine
Branch: master
Commit: 86941c44d90fd449c9411ea8679b8ac615a49aab
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=86941c44d90fd449c9411ea8679b8ac615a49aab

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jun  2 10:10:44 2022 +0200

kernelbase: Add a helper function to map an entire buffer to half width.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/locale.c |  6 +++
 dlls/kernelbase/locale.c     | 98 ++++++++++++++++++--------------------------
 2 files changed, 45 insertions(+), 59 deletions(-)

diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 87c12430dac..4e86da2be34 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -2515,6 +2515,12 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
     ret2 = func_ptr(LCMAP_HALFWIDTH | LCMAP_KATAKANA, japanese_text, -1, NULL, 0);
     ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
 
+    /* LCMAP_HALFWIDTH | LCMAP_HIRAGANA maps to Hiragana first */
+    ret = func_ptr(LCMAP_HALFWIDTH | LCMAP_HIRAGANA, japanese_text, -1, buf, ARRAY_SIZE(buf));
+    ret2 = func_ptr(LCMAP_HALFWIDTH, hiragana_text, -1, buf2, ARRAY_SIZE(buf2));
+    ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
+    ok(!lstrcmpW(buf, buf2), "%s string compare mismatch %s vs %s\n", func_name, debugstr_w(buf), debugstr_w(buf2));
+
     /* test buffer overflow */
     SetLastError(0xdeadbeef);
     ret = func_ptr(LCMAP_UPPERCASE,
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index a0e4a74658f..9283c17e926 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -3902,7 +3902,7 @@ static int find_substring( const struct sortguid *sortid, DWORD flags, const WCH
 
 
 /* map buffer to full-width katakana */
-static int map_to_fullwidth( const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
+static int map_to_fullwidth( const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
 {
     int pos;
 
@@ -3945,13 +3945,13 @@ static int map_to_fullwidth( const WCHAR *src, int srclen, WCHAR *dst, int dstle
                 break;
             }
         }
-        if (pos < dstlen) dst[pos] = wch;
+        if (pos < dstlen) dst[pos] = table ? casemap( table, wch ) : wch;
     }
     return pos;
 }
 
-/* map single full-width character to single or double half-width characters. */
-static int map_to_halfwidth( WCHAR c, WCHAR *dst, int dstlen )
+/* map full-width characters to single or double half-width characters. */
+static int map_to_halfwidth( const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
 {
     static const BYTE katakana_map[] =
     {
@@ -3967,20 +3967,30 @@ static int map_to_halfwidth( WCHAR c, WCHAR *dst, int dstlen )
         0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x08, /* U+30f0- */
         0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x01        /* U+30f8- */
     };
-    USHORT shift = c - 0x30ac;
-    BYTE k;
+    int pos;
 
-    if (shift < ARRAY_SIZE(katakana_map) && (k = katakana_map[shift]))
+    for (pos = 0; srclen; src++, srclen--)
     {
-        if (dstlen >= 2)
+        WCHAR ch = table ? casemap( table, *src ) : *src;
+        USHORT shift = ch - 0x30ac;
+        BYTE k;
+
+        if (shift < ARRAY_SIZE(katakana_map) && (k = katakana_map[shift]))
+        {
+            if (pos < dstlen - 1)
+            {
+                dst[pos] = casemap( charmaps[CHARMAP_HALFWIDTH], ch - k );
+                dst[pos + 1] = (k == 2) ? 0xff9f : 0xff9e;
+            }
+            pos += 2;
+        }
+        else
         {
-            dst[0] = casemap( charmaps[CHARMAP_HALFWIDTH], c - k );
-            dst[1] = (k == 2) ? 0xff9f : 0xff9e;
+            if (pos < dstlen) dst[pos] = casemap( charmaps[CHARMAP_HALFWIDTH], ch );
+            pos++;
         }
-        return 2;
     }
-    if (dstlen >= 1) dst[0] = casemap( charmaps[CHARMAP_HALFWIDTH], c );
-    return 1;
+    return pos;
 }
 
 
@@ -6386,17 +6396,12 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co
         }
         else if (flags & LCMAP_FULLWIDTH)
         {
-            len = map_to_fullwidth( src, srclen, NULL, 0 );
+            len = map_to_fullwidth( NULL, src, srclen, NULL, 0 );
         }
         else if (flags & LCMAP_HALFWIDTH)
         {
-            for (len = 0; srclen; src++, srclen--, len++)
-            {
-                WCHAR wch = *src;
-                /* map Hiragana to Katakana before decomposition if needed */
-                if (flags & LCMAP_KATAKANA) wch = casemap( charmaps[CHARMAP_KATAKANA], wch );
-                if (map_to_halfwidth( wch, NULL, 0 ) == 2) len++;
-            }
+            len = map_to_halfwidth( (flags & LCMAP_KATAKANA) ? charmaps[CHARMAP_KATAKANA] : NULL,
+                                    src, srclen, NULL, 0 );
         }
         else len = srclen;
         return len;
@@ -6434,47 +6439,27 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co
 
     if (flags & (LCMAP_FULLWIDTH | LCMAP_HALFWIDTH | LCMAP_HIRAGANA | LCMAP_KATAKANA))
     {
-        if (flags & LCMAP_FULLWIDTH)
-        {
-            len = map_to_fullwidth( src, srclen, dst, dstlen );
-            if (dstlen && dstlen < len)
-            {
-                SetLastError( ERROR_INSUFFICIENT_BUFFER );
-                return 0;
-            }
-            srclen = len;
-            src = dst;
-        }
-        for (len = dstlen, dst_ptr = dst; len && srclen; src++, srclen--, len--, dst_ptr++)
-        {
-            WCHAR wch = *src;
+        const USHORT *table = NULL;
 
-            if (flags & LCMAP_KATAKANA) wch = casemap( charmaps[CHARMAP_KATAKANA], wch );
-            else if (flags & LCMAP_HIRAGANA) wch = casemap( charmaps[CHARMAP_HIRAGANA], wch );
+        if (flags & LCMAP_KATAKANA) table = charmaps[CHARMAP_KATAKANA];
+        else if (flags & LCMAP_HIRAGANA) table = charmaps[CHARMAP_HIRAGANA];
 
-            if (flags & LCMAP_HALFWIDTH)
-            {
-                /* map full-width character to half-width one,
-                   e.g. U+30A2 -> U+FF71, U+30D7 -> U+FF8C U+FF9F. */
-                if (map_to_halfwidth(wch, dst_ptr, len) == 2)
-                {
-                    len--;
-                    dst_ptr++;
-                    if (!len) break;
-                }
-            }
-            else *dst_ptr = wch;
-        }
-        if (srclen)
+        if (flags & LCMAP_FULLWIDTH)
+            len = map_to_fullwidth( table, src, srclen, dst, dstlen );
+        else if (flags & LCMAP_HALFWIDTH)
+            len = map_to_halfwidth( table, src, srclen, dst, dstlen );
+        else
+            len = casemap_string( table, src, srclen, dst, dstlen );
+
+        if (dstlen && dstlen < len)
         {
             SetLastError( ERROR_INSUFFICIENT_BUFFER );
             return 0;
         }
-        len = dst_ptr - dst;
-        if (!(flags & (LCMAP_UPPERCASE | LCMAP_LOWERCASE)) || srclen) goto done;
-        srclen = dst_ptr - dst;
         src = dst;
+        srclen = len;
     }
+    else len = 0;
 
     if (flags & (LCMAP_UPPERCASE | LCMAP_LOWERCASE))
     {
@@ -6482,11 +6467,6 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co
         table = table + 2 + (flags & LCMAP_LOWERCASE ? table[1] : 0);
         len = casemap_string( table, src, srclen, dst, dstlen );
     }
-    else
-    {
-        len = srclen;
-        memcpy( dst, src, min( srclen, dstlen ) * sizeof(WCHAR) );
-    }
 
 done:
     if (dstlen && dstlen < len)




More information about the wine-cvs mailing list