[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