Call CompareStringA with LOCALE_USE_CP_ACP flag set from lstrcmpA and lstrcmpiA

Dmitry Timoshkov dmitry at baikal.ru
Sat Nov 20 05:32:10 CST 2004


Hello,

while analizing one of the relay logs I stumbled of the fact that each
call to lstrcmpA and lstrcmpiA leads to an access to locale resources.
That's because CompareStringA calls get_lcid_codepage which in turn
calls GetLocaleInfo to retrieve locale code page information. It appears
that native versions of lstcmpA and lstrcmpiA pass LOCALE_USE_CP_ACP
flag to CompareStringA which makes them considerably faster, that should
improve performance in Wine as well.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Call CompareStringA with LOCALE_USE_CP_ACP flag set from lstrcmpA
    and lstrcmpiA in order to improve speed. Add a test case confirming
    that CompareString and LCMapString accept LOCALE_USE_CP_ACP.

diff -up cvs/hq/wine/dlls/kernel/locale.c wine/dlls/kernel/locale.c
--- cvs/hq/wine/dlls/kernel/locale.c	2004-11-05 11:05:57.000000000 +0800
+++ wine/dlls/kernel/locale.c	2004-11-20 19:13:45.000000000 +0800
@@ -2141,7 +2141,7 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD
     WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
     LPWSTR srcW, dstW;
     INT ret = 0, srclenW, dstlenW;
-    UINT locale_cp;
+    UINT locale_cp = CP_ACP;
 
     if (!src || !srclen || dstlen < 0)
     {
@@ -2149,7 +2149,7 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD
         return 0;
     }
 
-    locale_cp = get_lcid_codepage(lcid);
+    if (!(flags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
 
     srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260);
     if (srclenW)
@@ -2328,7 +2328,7 @@ INT WINAPI CompareStringW(LCID lcid, DWO
     }
 
     if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
-        SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|0x10000000) )
+        SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|0x10000000) )
     {
         SetLastError(ERROR_INVALID_FLAGS);
         return 0;
@@ -2372,7 +2372,7 @@ INT WINAPI CompareStringA(LCID lcid, DWO
     WCHAR *buf2W = buf1W + 130;
     LPWSTR str1W, str2W;
     INT len1W, len2W, ret;
-    UINT locale_cp;
+    UINT locale_cp = CP_ACP;
 
     if (!str1 || !str2)
     {
@@ -2382,7 +2382,7 @@ INT WINAPI CompareStringA(LCID lcid, DWO
     if (len1 < 0) len1 = strlen(str1);
     if (len2 < 0) len2 = strlen(str2);
 
-    locale_cp = get_lcid_codepage(lcid);
+    if (!(style & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage( lcid );
 
     len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
     if (len1W)
@@ -2444,7 +2444,7 @@ int WINAPI lstrcmpA(LPCSTR str1, LPCSTR 
     if (str1 == NULL) return -1;
     if (str2 == NULL) return 1;
 
-    ret = CompareStringA(GetThreadLocale(), 0, str1, -1, str2, -1);
+    ret = CompareStringA(GetThreadLocale(), LOCALE_USE_CP_ACP, str1, -1, str2, -1);
     if (ret) ret -= 2;
     
     return ret;
@@ -2473,7 +2473,7 @@ int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR
     if (str1 == NULL) return -1;
     if (str2 == NULL) return 1;
 
-    ret = CompareStringA(GetThreadLocale(), NORM_IGNORECASE, str1, -1, str2, -1);
+    ret = CompareStringA(GetThreadLocale(), NORM_IGNORECASE|LOCALE_USE_CP_ACP, str1, -1, str2, -1);
     if (ret) ret -= 2;
     
     return ret;
diff -up cvs/hq/wine/dlls/kernel/tests/locale.c wine/dlls/kernel/tests/locale.c
--- cvs/hq/wine/dlls/kernel/tests/locale.c	2004-11-02 19:10:26.000000000 +0800
+++ wine/dlls/kernel/tests/locale.c	2004-11-20 19:09:50.000000000 +0800
@@ -795,12 +795,19 @@ static void test_CompareStringA()
     ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
     ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
 
+    /* test for CompareStringA flags */
     SetLastError(0xdeadbeef);
     ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
     ok(GetLastError() == ERROR_INVALID_FLAGS,
         "unexpected error code %ld\n", GetLastError());
     ok(!ret, "CompareStringA must fail with invalid flag\n");
 
+    SetLastError(0xdeadbeef);
+    ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, LOCALE_USE_CP_ACP, "NULL", -1, "NULL", -1);
+    ok(GetLastError() == 0xdeadbeef, "unexpected error code %ld\n", GetLastError());
+    ok(ret == CSTR_EQUAL, "CompareStringA error: %d != CSTR_EQUAL\n", ret);
+    /* end of test for CompareStringA flags */
+
     ret = lstrcmpA("", "");
     ok (ret == 0, "lstrcmpA(\"\", \"\") should return 0, got %d\n", ret);
 
@@ -956,6 +963,14 @@ void test_LCMapStringA(void)
     static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
     static const char symbols_stripped[] = "justateststring1";
 
+    SetLastError(0xdeadbeef);
+    ret = LCMapStringA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP | LCMAP_LOWERCASE,
+                       lower_case, -1, buf, sizeof(buf));
+    ok(ret == lstrlenA(lower_case) + 1,
+       "ret %d, error %ld, expected value %d\n",
+       ret, GetLastError(), lstrlenA(lower_case) + 1);
+    ok(!memcmp(buf, lower_case, ret), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
+
     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
                        upper_case, -1, buf, sizeof(buf));
     ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
@@ -969,7 +984,6 @@ void test_LCMapStringA(void)
        "unexpected error code %ld\n", GetLastError());
 
     ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
-
                        upper_case, -1, buf, sizeof(buf));
     ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
     ok(GetLastError() == ERROR_INVALID_FLAGS,






More information about the wine-patches mailing list