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:
parent
23e0d22b7c
commit
4960e415e2
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue