[v2 PATCH 4/4] kernelbase: Add some more string handling functions from shlwapi.

Nikolay Sivov nsivov at codeweavers.com
Fri May 17 06:28:20 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/kernelbase/kernelbase.spec |  24 +--
 dlls/kernelbase/string.c        | 302 ++++++++++++++++++++++++++++++++
 2 files changed, 314 insertions(+), 12 deletions(-)

diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 66bc105804..8ca9e1bde4 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -130,7 +130,7 @@
 # @ stub CheckTokenCapability
 @ stdcall CheckTokenMembership(long ptr ptr) advapi32.CheckTokenMembership
 # @ stub CheckTokenMembershipEx
-@ stdcall ChrCmpIA(long long) shlwapi.ChrCmpIA
+@ stdcall ChrCmpIA(long long)
 @ stdcall ChrCmpIW(long long)
 @ stdcall ClearCommBreak(long) kernel32.ClearCommBreak
 @ stdcall ClearCommError(long ptr ptr) kernel32.ClearCommError
@@ -1532,9 +1532,9 @@
 @ stdcall StrCatBuffA(str str long) shlwapi.StrCatBuffA
 @ stdcall StrCatBuffW(wstr wstr long) shlwapi.StrCatBuffW
 @ stdcall StrCatChainW(ptr long long wstr) shlwapi.StrCatChainW
-@ stdcall StrChrA(str long) shlwapi.StrChrA
+@ stdcall StrChrA(str long)
 # @ stub StrChrA_MB
-@ stdcall StrChrIA(str long) shlwapi.StrChrIA
+@ stdcall StrChrIA(str long)
 @ stdcall StrChrIW(wstr long)
 # @ stub StrChrNIW
 @ stdcall StrChrNW(wstr long long)
@@ -1544,8 +1544,8 @@
 @ stdcall StrCmpICA(str str)
 @ stdcall StrCmpICW(wstr wstr)
 @ stdcall StrCmpIW(wstr wstr)
-@ stdcall StrCmpLogicalW(wstr wstr) shlwapi.StrCmpLogicalW
-@ stdcall StrCmpNA(str str long) shlwapi.StrCmpNA
+@ stdcall StrCmpLogicalW(wstr wstr)
+@ stdcall StrCmpNA(str str long)
 @ stdcall StrCmpNCA(str ptr long) shlwapi.StrCmpNCA
 @ stdcall StrCmpNCW(wstr wstr long) shlwapi.StrCmpNCW
 @ stdcall StrCmpNIA(str str long)
@@ -1559,9 +1559,9 @@
 @ stdcall StrCpyNXW(ptr wstr long)
 @ stdcall StrDupA(str)
 @ stdcall StrDupW(wstr)
-@ stdcall StrIsIntlEqualA(long str str long) shlwapi.StrIsIntlEqualA
-@ stdcall StrIsIntlEqualW(long wstr wstr long) shlwapi.StrIsIntlEqualW
-@ stdcall StrPBrkA(str str) shlwapi.StrPBrkA
+@ stdcall StrIsIntlEqualA(long str str long)
+@ stdcall StrIsIntlEqualW(long wstr wstr long)
+@ stdcall StrPBrkA(str str)
 @ stdcall StrPBrkW(wstr wstr)
 @ stdcall StrRChrA(str str long) shlwapi.StrRChrA
 @ stdcall StrRChrIA(str str long) shlwapi.StrRChrIA
@@ -1577,13 +1577,13 @@
 @ stdcall StrStrNIW(wstr wstr long)
 @ stdcall StrStrNW(wstr wstr long)
 @ stdcall StrStrW(wstr wstr)
-@ stdcall StrToInt64ExA(str long ptr) shlwapi.StrToInt64ExA
+@ stdcall StrToInt64ExA(str long ptr)
 @ stdcall StrToInt64ExW(wstr long ptr)
-@ stdcall StrToIntA(str) shlwapi.StrToIntA
-@ stdcall StrToIntExA(str long ptr) shlwapi.StrToIntExA
+@ stdcall StrToIntA(str)
+@ stdcall StrToIntExA(str long ptr)
 @ stdcall StrToIntExW(wstr long ptr)
 @ stdcall StrToIntW(wstr)
-@ stdcall StrTrimA(str str) shlwapi.StrTrimA
+@ stdcall StrTrimA(str str)
 @ stdcall StrTrimW(wstr wstr)
 @ stdcall SubmitThreadpoolWork(ptr) kernel32.SubmitThreadpoolWork
 # @ stub SubscribeEdpEnabledStateChange
diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c
index fb7bda8828..a858f3a51a 100644
--- a/dlls/kernelbase/string.c
+++ b/dlls/kernelbase/string.c
@@ -37,6 +37,31 @@ static WORD get_char_type(WCHAR ch)
     return type;
 }
 
+static BOOL char_compare(WORD ch1, WORD ch2, DWORD flags)
+{
+    char str1[3], str2[3];
+
+    str1[0] = LOBYTE(ch1);
+    if (IsDBCSLeadByte(str1[0]))
+    {
+        str1[1] = HIBYTE(ch1);
+        str1[2] = '\0';
+    }
+    else
+        str1[1] = '\0';
+
+    str2[0] = LOBYTE(ch2);
+    if (IsDBCSLeadByte(str2[0]))
+    {
+        str2[1] = HIBYTE(ch2);
+        str2[2] = '\0';
+    }
+    else
+        str2[1] = '\0';
+
+    return CompareStringA(GetThreadLocale(), flags, str1, -1, str2, -1) - CSTR_EQUAL;
+}
+
 DWORD WINAPI StrCmpCA(const char *str, const char *cmp)
 {
     return lstrcmpA(str, cmp);
@@ -151,6 +176,23 @@ BOOL WINAPI IsCharUpperW(WCHAR ch)
     return !!(get_char_type(ch) & C1_UPPER);
 }
 
+char * WINAPI StrChrA(const char *str, WORD ch)
+{
+    TRACE("%s, %#x\n", wine_dbgstr_a(str), ch);
+
+    if (!str)
+        return NULL;
+
+    while (*str)
+    {
+        if (!char_compare(*str, ch, 0))
+            return (char *)str;
+        str = CharNextA(str);
+    }
+
+    return NULL;
+}
+
 WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch)
 {
     TRACE("%s, %#x\n", wine_dbgstr_w(str), ch);
@@ -161,6 +203,23 @@ WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch)
     return strchrW(str, ch);
 }
 
+char * WINAPI StrChrIA(const char *str, WORD ch)
+{
+    TRACE("%s, %i\n", wine_dbgstr_a(str), ch);
+
+    if (!str)
+        return NULL;
+
+    while (*str)
+    {
+        if (!ChrCmpIA(*str, ch))
+            return (char *)str;
+        str = CharNextA(str);
+    }
+
+    return NULL;
+}
+
 WCHAR * WINAPI StrChrIW(const WCHAR *str, WCHAR ch)
 {
     TRACE("%s, %#x\n", wine_dbgstr_w(str), ch);
@@ -239,6 +298,13 @@ WCHAR * WINAPI StrDupW(const WCHAR *str)
     return ret;
 }
 
+BOOL WINAPI ChrCmpIA(WORD ch1, WORD ch2)
+{
+    TRACE("%#x, %#x\n", ch1, ch2);
+
+    return char_compare(ch1, ch2, NORM_IGNORECASE);
+}
+
 BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2)
 {
     return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL;
@@ -300,6 +366,12 @@ WCHAR * WINAPI StrStrNIW(const WCHAR *str, const WCHAR *search, UINT max_len)
     return NULL;
 }
 
+int WINAPI StrCmpNA(const char *str, const char *comp, int len)
+{
+    TRACE("%s, %s, %i\n", wine_dbgstr_a(str), wine_dbgstr_a(comp), len);
+    return CompareStringA(GetThreadLocale(), 0, str, len, comp, len) - CSTR_EQUAL;
+}
+
 int WINAPI StrCmpNW(const WCHAR *str, const WCHAR *comp, int len)
 {
     TRACE("%s, %s, %i\n", wine_dbgstr_w(str), wine_dbgstr_w(comp), len);
@@ -401,12 +473,67 @@ WCHAR * WINAPI StrRChrIW(const WCHAR *str, const WCHAR *end, WORD ch)
     return ret;
 }
 
+char * WINAPI StrPBrkA(const char *str, const char *match)
+{
+    TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(match));
+
+    if (!str || !match || !*match)
+        return NULL;
+
+    while (*str)
+    {
+        if (StrChrA(match, *str))
+            return (char *)str;
+        str = CharNextA(str);
+    }
+
+    return NULL;
+}
+
 WCHAR * WINAPI StrPBrkW(const WCHAR *str, const WCHAR *match)
 {
     if (!str || !match) return NULL;
     return strpbrkW(str, match);
 }
 
+BOOL WINAPI StrTrimA(char *str, const char *trim)
+{
+    unsigned int len;
+    BOOL ret = FALSE;
+    char *ptr = str;
+
+    TRACE("%s, %s\n", debugstr_a(str), debugstr_a(trim));
+
+    if (!str || !*str)
+        return FALSE;
+
+    while (*ptr && StrChrA(trim, *ptr))
+        ptr = CharNextA(ptr); /* Skip leading matches */
+
+    len = strlen(ptr);
+
+    if (ptr != str)
+    {
+        memmove(str, ptr, len + 1);
+        ret = TRUE;
+    }
+
+    if (len > 0)
+    {
+        ptr = str + len;
+        while (StrChrA(trim, ptr[-1]))
+            ptr = CharPrevA(str, ptr); /* Skip trailing matches */
+
+        if (ptr != str + len)
+        {
+            *ptr = '\0';
+            ret = TRUE;
+        }
+    }
+
+    return ret;
+}
+
 BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim)
 {
     unsigned int len;
@@ -445,6 +572,68 @@ BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim)
     return ret;
 }
 
+BOOL WINAPI StrToInt64ExA(const char *str, DWORD flags, LONGLONG *ret)
+{
+    BOOL negative = FALSE;
+    LONGLONG value = 0;
+
+    TRACE("%s, %#x, %p\n", wine_dbgstr_a(str), flags, ret);
+
+    if (!str || !ret)
+        return FALSE;
+
+    if (flags > STIF_SUPPORT_HEX)
+        WARN("Unknown flags %#x\n", flags);
+
+    /* Skip leading space, '+', '-' */
+    while (isspace(*str))
+        str = CharNextA(str);
+
+    if (*str == '-')
+    {
+        negative = TRUE;
+        str++;
+    }
+    else if (*str == '+')
+        str++;
+
+    if (flags & STIF_SUPPORT_HEX && *str == '0' && tolower(str[1]) == 'x')
+    {
+        /* Read hex number */
+        str += 2;
+
+        if (!isxdigit(*str))
+            return FALSE;
+
+        while (isxdigit(*str))
+        {
+            value *= 16;
+            if (isdigit(*str))
+                value += (*str - '0');
+            else
+                value += 10 + (tolower(*str) - 'a');
+            str++;
+        }
+
+        *ret = value;
+        return TRUE;
+    }
+
+    /* Read decimal number */
+    if (!isdigit(*str))
+        return FALSE;
+
+    while (isdigit(*str))
+    {
+        value *= 10;
+        value += (*str - '0');
+        str++;
+    }
+
+    *ret = negative ? -value : value;
+    return TRUE;
+}
+
 BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret)
 {
     BOOL negative = FALSE;
@@ -507,6 +696,18 @@ BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret)
     return TRUE;
 }
 
+BOOL WINAPI StrToIntExA(const char *str, DWORD flags, INT *ret)
+{
+    LONGLONG value;
+    BOOL res;
+
+    TRACE("%s, %#x, %p\n", wine_dbgstr_a(str), flags, ret);
+
+    res = StrToInt64ExA(str, flags, &value);
+    if (res) *ret = value;
+    return res;
+}
+
 BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret)
 {
     LONGLONG value;
@@ -519,6 +720,21 @@ BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret)
     return res;
 }
 
+int WINAPI StrToIntA(const char *str)
+{
+    int value = 0;
+
+    TRACE("%s\n", wine_dbgstr_a(str));
+
+    if (!str)
+        return 0;
+
+    if (*str == '-' || isdigit(*str))
+        StrToIntExA(str, 0, &value);
+
+    return value;
+}
+
 int WINAPI StrToIntW(const WCHAR *str)
 {
     int value = 0;
@@ -818,3 +1034,89 @@ INT WINAPI DECLSPEC_HOTPATCH LoadStringA(HINSTANCE instance, UINT resource_id, L
     TRACE("returning %s\n", debugstr_a(buffer));
     return retval;
 }
+
+int WINAPI StrCmpLogicalW(const WCHAR *str, const WCHAR *comp)
+{
+    TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(comp));
+
+    if (!str || !comp)
+        return 0;
+
+    while (*str)
+    {
+        if (!*comp)
+            return 1;
+        else if (isdigitW(*str))
+        {
+            int str_value, comp_value;
+
+            if (!isdigitW(*comp))
+                return -1;
+
+            /* Compare the numbers */
+            StrToIntExW(str, 0, &str_value);
+            StrToIntExW(comp, 0, &comp_value);
+
+            if (str_value < comp_value)
+                return -1;
+            else if (str_value > comp_value)
+                return 1;
+
+            /* Skip */
+            while (isdigitW(*str))
+                str++;
+            while (isdigitW(*comp))
+                comp++;
+        }
+        else if (isdigitW(*comp))
+            return 1;
+        else
+        {
+            int diff = ChrCmpIW(*str, *comp);
+            if (diff > 0)
+                return 1;
+            else if (diff < 0)
+                return -1;
+
+            str++;
+            comp++;
+        }
+    }
+
+    if (*comp)
+      return -1;
+
+    return 0;
+}
+
+BOOL WINAPI StrIsIntlEqualA(BOOL case_sensitive, const char *str, const char *cmp, int len)
+{
+    DWORD flags;
+
+    TRACE("%d, %s, %s, %d\n", case_sensitive, wine_dbgstr_a(str), wine_dbgstr_a(cmp), len);
+
+    /* FIXME: This flag is undocumented and unknown by our CompareString.
+     *        We need a define for it.
+     */
+    flags = 0x10000000;
+    if (!case_sensitive)
+        flags |= NORM_IGNORECASE;
+
+    return (CompareStringA(GetThreadLocale(), flags, str, len, cmp, len) == CSTR_EQUAL);
+}
+
+BOOL WINAPI StrIsIntlEqualW(BOOL case_sensitive, const WCHAR *str, const WCHAR *cmp, int len)
+{
+    DWORD flags;
+
+    TRACE("%d, %s, %s, %d\n", case_sensitive, debugstr_w(str), debugstr_w(cmp), len);
+
+    /* FIXME: This flag is undocumented and unknown by our CompareString.
+     *        We need a define for it.
+     */
+    flags = 0x10000000;
+    if (!case_sensitive)
+        flags |= NORM_IGNORECASE;
+
+    return (CompareStringW(GetThreadLocale(), flags, str, len, cmp, len) == CSTR_EQUAL);
+}
-- 
2.20.1




More information about the wine-devel mailing list