kernelbase: Add some more 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-17 14:28:20 +03:00 committed by Alexandre Julliard
parent 44a6b49577
commit 9959e4144f
2 changed files with 314 additions and 12 deletions

View file

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

View file

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