kernelbase: Add remaining string handling functions from shlwapi.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2019-05-20 16:40:29 +03:00 committed by Alexandre Julliard
parent 23e0d22b7c
commit 4960e415e2
2 changed files with 323 additions and 17 deletions

View File

@ -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)

View File

@ -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;
}