[PATCH] kernelbase: Add remaining string handling functions from shlwapi.

Nikolay Sivov nsivov at codeweavers.com
Mon May 20 08:40:29 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/kernelbase/kernelbase.spec |  34 ++--
 dlls/kernelbase/string.c        | 306 ++++++++++++++++++++++++++++++++
 2 files changed, 323 insertions(+), 17 deletions(-)

diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 48276b8bcf..46163150c1 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -1381,7 +1381,7 @@
 @ stdcall SHRegSetUSValueW( wstr wstr long ptr long long) shlwapi.SHRegSetUSValueW
 @ stdcall SHRegWriteUSValueA(long str long ptr long long) shlwapi.SHRegWriteUSValueA
 @ stdcall SHRegWriteUSValueW(long wstr long ptr long long) shlwapi.SHRegWriteUSValueW
-@ stdcall SHTruncateString(str long) shlwapi.SHTruncateString
+@ stdcall SHTruncateString(str long)
 # @ stub SaveAlternatePackageRootPath
 # @ stub SaveStateRootFolderPath
 @ stdcall ScrollConsoleScreenBufferA(long ptr ptr ptr ptr) kernel32.ScrollConsoleScreenBufferA
@@ -1525,13 +1525,13 @@
 # @ stub StmReduceSize
 # @ stub StmReserve
 # @ stub StmWrite
-@ stdcall StrCSpnA(str str) shlwapi.StrCSpnA
-@ stdcall StrCSpnIA(str str) shlwapi.StrCSpnIA
-@ stdcall StrCSpnIW(wstr wstr) shlwapi.StrCSpnIW
-@ stdcall StrCSpnW(wstr wstr) shlwapi.StrCSpnW
-@ stdcall StrCatBuffA(str str long) shlwapi.StrCatBuffA
-@ stdcall StrCatBuffW(wstr wstr long) shlwapi.StrCatBuffW
-@ stdcall StrCatChainW(ptr long long wstr) shlwapi.StrCatChainW
+@ stdcall StrCSpnA(str str)
+@ stdcall StrCSpnIA(str str)
+@ stdcall StrCSpnIW(wstr wstr)
+@ stdcall StrCSpnW(wstr wstr)
+@ stdcall StrCatBuffA(str str long)
+@ stdcall StrCatBuffW(wstr wstr long)
+@ stdcall StrCatChainW(ptr long long wstr)
 @ stdcall StrChrA(str long)
 # @ stub StrChrA_MB
 @ stdcall StrChrIA(str long)
@@ -1546,8 +1546,8 @@
 @ stdcall StrCmpIW(wstr wstr)
 @ stdcall StrCmpLogicalW(wstr wstr)
 @ stdcall StrCmpNA(str str long)
-@ stdcall StrCmpNCA(str ptr long) shlwapi.StrCmpNCA
-@ stdcall StrCmpNCW(wstr wstr long) shlwapi.StrCmpNCW
+@ stdcall StrCmpNCA(str str long)
+@ stdcall StrCmpNCW(wstr wstr long)
 @ stdcall StrCmpNIA(str str long)
 @ stdcall StrCmpNICA(long long long)
 @ stdcall StrCmpNICW(wstr wstr long)
@@ -1563,16 +1563,16 @@
 @ 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
+@ stdcall StrRChrA(str str long)
+@ stdcall StrRChrIA(str str long)
 @ stdcall StrRChrIW(wstr wstr long)
 @ stdcall StrRChrW(wstr wstr long)
-@ stdcall StrRStrIA(str str str) shlwapi.StrRStrIA
-@ stdcall StrRStrIW(wstr wstr wstr) shlwapi.StrRStrIW
-@ stdcall StrSpnA(str str) shlwapi.StrSpnA
+@ stdcall StrRStrIA(str str str)
+@ stdcall StrRStrIW(wstr wstr wstr)
+@ stdcall StrSpnA(str str)
 @ stdcall StrSpnW(wstr wstr)
-@ stdcall StrStrA(str str) shlwapi.StrStrA
-@ stdcall StrStrIA(str str) shlwapi.StrStrIA
+@ stdcall StrStrA(str str)
+@ stdcall StrStrIA(str str)
 @ stdcall StrStrIW(wstr wstr)
 @ stdcall StrStrNIW(wstr wstr long)
 @ stdcall StrStrNW(wstr wstr long)
diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c
index a858f3a51a..4c18acffe5 100644
--- a/dlls/kernelbase/string.c
+++ b/dlls/kernelbase/string.c
@@ -305,11 +305,45 @@ BOOL WINAPI ChrCmpIA(WORD ch1, WORD ch2)
     return char_compare(ch1, ch2, NORM_IGNORECASE);
 }
 
+static BOOL WINAPI ChrCmpA(WORD ch1, WORD ch2)
+{
+    return char_compare(ch1, ch2, 0);
+}
+
 BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2)
 {
     return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL;
 }
 
+static char * strstr_helper(const char *str, const char *search,
+        INT (WINAPI *cmp_func)(const char *, const char *, int))
+{
+    const char *end;
+    size_t len;
+
+    if (!str || !search || !*search)
+        return NULL;
+
+    len = strlen(search);
+    end = str + strlen(str);
+
+    while (str + len <= end)
+    {
+        if (!cmp_func(str, search, len))
+            return (char *)str;
+        str = CharNextA(str);
+    }
+
+    return NULL;
+}
+
+char * WINAPI StrStrA(const char *str, const char *search)
+{
+    TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(search));
+
+    return strstr_helper(str, search, StrCmpNA);
+}
+
 WCHAR * WINAPI StrStrW(const WCHAR *str, const WCHAR *search)
 {
     TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(search));
@@ -378,6 +412,16 @@ int WINAPI StrCmpNW(const WCHAR *str, const WCHAR *comp, int len)
     return CompareStringW(GetThreadLocale(), 0, str, len, comp, len) - CSTR_EQUAL;
 }
 
+DWORD WINAPI StrCmpNCA(const char *str, const char *comp, int len)
+{
+    return StrCmpNA(str, comp, len);
+}
+
+DWORD WINAPI StrCmpNCW(const WCHAR *str, const WCHAR *comp, int len)
+{
+    return StrCmpNW(str, comp, len);
+}
+
 int WINAPI StrCmpNIW(const WCHAR *str, const WCHAR *comp, int len)
 {
     TRACE("%s, %s, %i\n", wine_dbgstr_w(str), wine_dbgstr_w(comp), len);
@@ -416,6 +460,13 @@ WCHAR * WINAPI StrCpyNW(WCHAR *dst, const WCHAR *src, int count)
     return dst;
 }
 
+char * WINAPI StrStrIA(const char *str, const char *search)
+{
+    TRACE("%s, %s\n", wine_dbgstr_a(str), debugstr_a(search));
+
+    return strstr_helper(str, search, StrCmpNIA);
+}
+
 WCHAR * WINAPI StrStrIW(const WCHAR *str, const WCHAR *search)
 {
     unsigned int len;
@@ -439,12 +490,111 @@ WCHAR * WINAPI StrStrIW(const WCHAR *str, const WCHAR *search)
     return NULL;
 }
 
+static int strspn_helper(const char *str, const char *match, char * (WINAPI *func)(const char *, WORD), BOOL invert)
+{
+    const char *ptr = str;
+
+    if (!str || !*str || !match)
+        return 0;
+
+    while (*ptr)
+    {
+        const char *test = func(match, *ptr);
+
+        if (!invert && !test)
+            break;
+        if (invert && test)
+            break;
+
+        ptr = CharNextA(ptr);
+    };
+
+    return ptr - str;
+}
+
+int WINAPI StrSpnA(const char *str, const char *match)
+{
+    TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(match));
+
+    return strspn_helper(str, match, StrChrA, FALSE);
+}
+
 int WINAPI StrSpnW(const WCHAR *str, const WCHAR *match)
 {
     if (!str || !match) return 0;
     return strspnW(str, match);
 }
 
+int WINAPI StrCSpnA(const char *str, const char *match)
+{
+    TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(match));
+
+    return strspn_helper(str, match, StrChrA, TRUE);
+}
+
+int WINAPI StrCSpnW(const WCHAR *str, const WCHAR *match)
+{
+    if (!str || !match)
+        return 0;
+
+    return strcspnW(str, match);
+}
+
+int WINAPI StrCSpnIA(const char *str, const char *match)
+{
+    TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(match));
+
+    return strspn_helper(str, match, StrChrIA, TRUE);
+}
+
+int WINAPI StrCSpnIW(const WCHAR *str, const WCHAR *match)
+{
+    const WCHAR *ptr = str;
+
+    TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(match));
+
+    if (!str || !*str || !match)
+        return 0;
+
+    while (*ptr)
+    {
+        if (StrChrIW(match, *ptr)) break;
+        ptr++;
+    }
+
+    return ptr - str;
+}
+
+static LPSTR strrchra_helper(const char *str, const char *end, WORD ch, BOOL (WINAPI *cmp_func)(WORD, WORD))
+{
+    const char *ret = NULL;
+    WORD ch2;
+
+    if (!str)
+        return NULL;
+
+    if (!end)
+        end = str + lstrlenA(str);
+
+    while (*str && str <= end)
+    {
+        ch2 = IsDBCSLeadByte(*str) ? *str << 8 | str[1] : *str;
+
+        if (!cmp_func(ch, ch2))
+            ret = str;
+        str = CharNextA(str);
+    }
+
+    return (char *)ret;
+}
+
+char * WINAPI StrRChrA(const char *str, const char *end, WORD ch)
+{
+    TRACE("%s, %s, %#x\n", wine_dbgstr_a(str), wine_dbgstr_a(end), ch);
+
+    return strrchra_helper(str, end, ch, ChrCmpA);
+}
+
 WCHAR * WINAPI StrRChrW(const WCHAR *str, const WCHAR *end, WORD ch)
 {
     WCHAR *ret = NULL;
@@ -459,6 +609,13 @@ WCHAR * WINAPI StrRChrW(const WCHAR *str, const WCHAR *end, WORD ch)
     return ret;
 }
 
+char * WINAPI StrRChrIA(const char *str, const char *end, WORD ch)
+{
+    TRACE("%s, %s, %#x\n", wine_dbgstr_a(str), wine_dbgstr_a(end), ch);
+
+    return strrchra_helper(str, end, ch, ChrCmpIA);
+}
+
 WCHAR * WINAPI StrRChrIW(const WCHAR *str, const WCHAR *end, WORD ch)
 {
     WCHAR *ret = NULL;
@@ -473,6 +630,73 @@ WCHAR * WINAPI StrRChrIW(const WCHAR *str, const WCHAR *end, WORD ch)
     return ret;
 }
 
+char * WINAPI StrRStrIA(const char *str, const char *end, const char *search)
+{
+    char *ret = NULL;
+    WORD ch1, ch2;
+    int len;
+
+    TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(search));
+
+    if (!str || !search || !*search)
+        return NULL;
+
+    if (IsDBCSLeadByte(*search))
+        ch1 = *search << 8 | (UCHAR)search[1];
+    else
+        ch1 = *search;
+    len = lstrlenA(search);
+
+    if (!end)
+        end = str + lstrlenA(str);
+    else /* reproduce the broken behaviour on Windows */
+        end += min(len - 1, lstrlenA(end));
+
+    while (str + len <= end && *str)
+    {
+        ch2 = IsDBCSLeadByte(*str) ? *str << 8 | (UCHAR)str[1] : *str;
+        if (!ChrCmpIA(ch1, ch2))
+        {
+            if (!StrCmpNIA(str, search, len))
+                ret = (char *)str;
+        }
+
+        str = CharNextA(str);
+    }
+
+    return ret;
+}
+
+WCHAR * WINAPI StrRStrIW(const WCHAR *str, const WCHAR *end, const WCHAR *search)
+{
+    WCHAR *ret = NULL;
+    int len;
+
+    TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(search));
+
+    if (!str || !search || !*search)
+        return NULL;
+
+    len = strlenW(search);
+
+    if (!end)
+        end = str + strlenW(str);
+    else
+        end += min(len - 1, lstrlenW(end));
+
+    while (str + len <= end && *str)
+    {
+        if (!ChrCmpIW(*search, *str))
+        {
+            if (!StrCmpNIW(str, search, len))
+                ret = (WCHAR *)str;
+        }
+        str++;
+    }
+
+    return ret;
+}
+
 char * WINAPI StrPBrkA(const char *str, const char *match)
 {
     TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(match));
@@ -1120,3 +1344,85 @@ BOOL WINAPI StrIsIntlEqualW(BOOL case_sensitive, const WCHAR *str, const WCHAR *
 
     return (CompareStringW(GetThreadLocale(), flags, str, len, cmp, len) == CSTR_EQUAL);
 }
+
+char * WINAPI StrCatBuffA(char *str, const char *cat, INT max_len)
+{
+    INT len;
+
+    TRACE("%p, %s, %d\n", str, wine_dbgstr_a(cat), max_len);
+
+    if (!str)
+        return NULL;
+
+    len = strlen(str);
+    max_len -= len;
+    if (max_len > 0)
+        StrCpyNA(str + len, cat, max_len);
+
+    return str;
+}
+
+WCHAR * WINAPI StrCatBuffW(WCHAR *str, const WCHAR *cat, INT max_len)
+{
+    INT len;
+
+    TRACE("%p, %s, %d\n", str, wine_dbgstr_w(cat), max_len);
+
+    if (!str)
+        return NULL;
+
+    len = strlenW(str);
+    max_len -= len;
+    if (max_len > 0)
+        StrCpyNW(str + len, cat, max_len);
+
+    return str;
+}
+
+DWORD WINAPI StrCatChainW(WCHAR *str, DWORD max_len, DWORD at, const WCHAR *cat)
+{
+    TRACE("%s, %u, %d, %s\n", wine_dbgstr_w(str), max_len, at, wine_dbgstr_w(cat));
+
+    if (at == -1)
+        at = strlenW(str);
+
+    if (!max_len)
+        return at;
+
+    if (at == max_len)
+        at--;
+
+    if (cat && at < max_len)
+    {
+        str += at;
+        while (at < max_len - 1 && *cat)
+        {
+            *str++ = *cat++;
+            at++;
+        }
+        *str = 0;
+    }
+
+    return at;
+}
+
+DWORD WINAPI SHTruncateString(char *str, DWORD size)
+{
+    char *last_byte;
+
+    if (!str || !size)
+        return 0;
+
+    last_byte = str + size - 1;
+
+    while (str < last_byte)
+        str += IsDBCSLeadByte(*str) ? 2 : 1;
+
+    if (str == last_byte && IsDBCSLeadByte(*str))
+    {
+        *str = '\0';
+        size--;
+    }
+
+    return size;
+}
-- 
2.20.1




More information about the wine-devel mailing list