ntdll: Reimplement wcstol/wcstoul using the msvcrt code.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
650c8e1434
commit
295660b985
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "ntdll_test.h"
|
||||
#include "winnls.h"
|
||||
|
@ -47,6 +48,8 @@ static LPSTR (__cdecl *p_ui64toa)(ULONGLONG, LPSTR, INT);
|
|||
static int (__cdecl *p_wtoi)(LPCWSTR);
|
||||
static LONG (__cdecl *p_wtol)(LPCWSTR);
|
||||
static LONGLONG (__cdecl *p_wtoi64)(LPCWSTR);
|
||||
static LONG (__cdecl *pwcstol)(LPCWSTR,LPWSTR*,INT);
|
||||
static ULONG (__cdecl *pwcstoul)(LPCWSTR,LPWSTR*,INT);
|
||||
static LPWSTR (__cdecl *p_itow)(int, LPWSTR, int);
|
||||
static LPWSTR (__cdecl *p_ltow)(LONG, LPWSTR, INT);
|
||||
static LPWSTR (__cdecl *p_ultow)(ULONG, LPWSTR, INT);
|
||||
|
@ -102,6 +105,8 @@ static void InitFunctionPtrs(void)
|
|||
X(_wtoi);
|
||||
X(_wtol);
|
||||
X(_wtoi64);
|
||||
X(wcstol);
|
||||
X(wcstoul);
|
||||
X(_itow);
|
||||
X(_ltow);
|
||||
X(_ultow);
|
||||
|
@ -1153,6 +1158,72 @@ static void test_wtoi64(void)
|
|||
ok( result == 0, "got %s\n", wine_dbgstr_longlong(result) );
|
||||
}
|
||||
|
||||
static void test_wcstol(void)
|
||||
{
|
||||
static const struct { WCHAR str[24]; LONG res; ULONG ures; int base; } tests[] =
|
||||
{
|
||||
{ L"9", 9, 9, 10 },
|
||||
{ L" ", 0, 0 },
|
||||
{ L"-1234", -1234, -1234 },
|
||||
{ L"\x09\x0a\x0b\x0c\x0d -123", -123, -123 },
|
||||
{ L"\xa0 +44", 44, 44 },
|
||||
{ L"\x2002\x2003 +55", 0, 0 },
|
||||
{ L"\x3000 +66", 0, 0 },
|
||||
{ { 0x3231 }, 0, 0 }, /* PARENTHESIZED IDEOGRAPH STOCK */
|
||||
{ { 0x4e00 }, 0, 0 }, /* CJK Ideograph, First */
|
||||
{ { 0x0bef }, 0, 0 }, /* TAMIL DIGIT NINE */
|
||||
{ { 0x0e59 }, 9, 9 }, /* THAI DIGIT NINE */
|
||||
{ { 0xff19 }, 9, 9 }, /* FULLWIDTH DIGIT NINE */
|
||||
{ { 0x00b9 }, 0, 0 }, /* SUPERSCRIPT ONE */
|
||||
{ { '-',0x0e50,'x',0xff19,'1' }, -0x91, -0x91 },
|
||||
{ { '+',0x0e50,0xff17,'1' }, 071, 071 },
|
||||
{ { 0xff19,'f',0x0e59,0xff46 }, 0x9f9, 0x9f9, 16 },
|
||||
{ L"2147483647", 2147483647, 2147483647 },
|
||||
{ L"2147483648", LONG_MAX, 2147483648 },
|
||||
{ L"4294967295", LONG_MAX, 4294967295 },
|
||||
{ L"4294967296", LONG_MAX, ULONG_MAX },
|
||||
{ L"9223372036854775807", LONG_MAX, ULONG_MAX },
|
||||
{ L"-2147483647", -2147483647, -2147483647 },
|
||||
{ L"-2147483648", LONG_MIN, LONG_MIN },
|
||||
{ L"-4294967295", LONG_MIN, 1 },
|
||||
{ L"-4294967296", LONG_MIN, 1 },
|
||||
{ L"-9223372036854775807", LONG_MIN, 1 },
|
||||
};
|
||||
static const WCHAR zeros[] =
|
||||
{
|
||||
0x0660, 0x06f0, 0x0966, 0x09e6, 0x0a66, 0x0ae6, 0x0b66, 0x0c66, 0x0ce6,
|
||||
0x0d66, 0x0e50, 0x0ed0, 0x0f20, 0x1040, 0x17e0, 0x1810, 0xff10
|
||||
};
|
||||
unsigned int i;
|
||||
LONG res;
|
||||
ULONG ures;
|
||||
WCHAR *endpos;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++)
|
||||
{
|
||||
res = pwcstol( tests[i].str, &endpos, tests[i].base );
|
||||
ok( res == tests[i].res, "%u: %s res %08x\n", i, wine_dbgstr_w(tests[i].str), res );
|
||||
if (!res) ok( endpos == tests[i].str, "%u: wrong endpos %p/%p\n", i, endpos, tests[i].str );
|
||||
ures = pwcstoul( tests[i].str, &endpos, tests[i].base );
|
||||
ok( ures == tests[i].ures, "%u: %s res %08x\n", i, wine_dbgstr_w(tests[i].str), ures );
|
||||
}
|
||||
|
||||
/* Test various unicode digits */
|
||||
for (i = 0; i < ARRAY_SIZE(zeros); ++i)
|
||||
{
|
||||
WCHAR tmp[] = { zeros[i] + 4, zeros[i], zeros[i] + 5, 0 };
|
||||
res = pwcstol(tmp, NULL, 0);
|
||||
ok(res == 405, "with zero = U+%04X: got %d, expected 405\n", zeros[i], res);
|
||||
ures = pwcstoul(tmp, NULL, 0);
|
||||
ok(ures == 405, "with zero = U+%04X: got %u, expected 405\n", zeros[i], ures);
|
||||
tmp[1] = zeros[i] + 10;
|
||||
res = pwcstol(tmp, NULL, 16);
|
||||
ok(res == 4, "with zero = U+%04X: got %d, expected 4\n", zeros[i], res);
|
||||
ures = pwcstoul(tmp, NULL, 16);
|
||||
ok(ures == 4, "with zero = U+%04X: got %u, expected 4\n", zeros[i], ures);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_wcschr(void)
|
||||
{
|
||||
static const WCHAR teststringW[] = {'a','b','r','a','c','a','d','a','b','r','a',0};
|
||||
|
@ -1670,6 +1741,7 @@ START_TEST(string)
|
|||
test_wtoi();
|
||||
test_wtol();
|
||||
test_wtoi64();
|
||||
test_wcstol();
|
||||
test_wcschr();
|
||||
test_wcsrchr();
|
||||
test_wcslwrupr();
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -340,24 +339,6 @@ INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
|
|||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* wcstol (NTDLL.@)
|
||||
*/
|
||||
LONG __cdecl NTDLL_wcstol(LPCWSTR s, LPWSTR *end, INT base)
|
||||
{
|
||||
return strtolW( s, end, base );
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* wcstoul (NTDLL.@)
|
||||
*/
|
||||
ULONG __cdecl NTDLL_wcstoul(LPCWSTR s, LPWSTR *end, INT base)
|
||||
{
|
||||
return strtoulW( s, end, base );
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* iswctype (NTDLL.@)
|
||||
*/
|
||||
|
@ -442,6 +423,117 @@ INT __cdecl NTDLL_iswxdigit( WCHAR wc )
|
|||
}
|
||||
|
||||
|
||||
static int wctoint( WCHAR c )
|
||||
{
|
||||
/* NOTE: MAP_FOLDDIGITS supports too many things. */
|
||||
/* Unicode points that contain digits 0-9; keep this sorted! */
|
||||
static const WCHAR zeros[] =
|
||||
{
|
||||
0x0660, 0x06f0, 0x0966, 0x09e6, 0x0a66, 0x0ae6, 0x0b66, 0x0c66, 0x0ce6,
|
||||
0x0d66, 0x0e50, 0x0ed0, 0x0f20, 0x1040, 0x17e0, 0x1810, 0xff10
|
||||
};
|
||||
int i;
|
||||
|
||||
if ('0' <= c && c <= '9') return c - '0';
|
||||
if ('A' <= c && c <= 'Z') return c - 'A' + 10;
|
||||
if ('a' <= c && c <= 'z') return c - 'a' + 10;
|
||||
for (i = 0; i < ARRAY_SIZE(zeros) && c >= zeros[i]; i++)
|
||||
if (zeros[i] <= c && c <= zeros[i] + 9) return c - zeros[i];
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* wcstol (NTDLL.@)
|
||||
*/
|
||||
LONG __cdecl NTDLL_wcstol(LPCWSTR s, LPWSTR *end, INT base)
|
||||
{
|
||||
BOOL negative = FALSE, empty = TRUE;
|
||||
LONG ret = 0;
|
||||
|
||||
if (base < 0 || base == 1 || base > 36) return 0;
|
||||
if (end) *end = (WCHAR *)s;
|
||||
while (NTDLL_iswspace(*s)) s++;
|
||||
|
||||
if (*s == '-')
|
||||
{
|
||||
negative = TRUE;
|
||||
s++;
|
||||
}
|
||||
else if (*s == '+') s++;
|
||||
|
||||
if ((base == 0 || base == 16) && !wctoint( *s ) && (s[1] == 'x' || s[1] == 'X'))
|
||||
{
|
||||
base = 16;
|
||||
s += 2;
|
||||
}
|
||||
if (base == 0) base = wctoint( *s ) ? 10 : 8;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
int v = wctoint( *s );
|
||||
if (v < 0 || v >= base) break;
|
||||
if (negative) v = -v;
|
||||
s++;
|
||||
empty = FALSE;
|
||||
|
||||
if (!negative && (ret > MAXLONG / base || ret * base > MAXLONG - v))
|
||||
ret = MAXLONG;
|
||||
else if (negative && (ret < (LONG)MINLONG / base || ret * base < (LONG)(MINLONG - v)))
|
||||
ret = MINLONG;
|
||||
else
|
||||
ret = ret * base + v;
|
||||
}
|
||||
|
||||
if (end && !empty) *end = (WCHAR *)s;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* wcstoul (NTDLL.@)
|
||||
*/
|
||||
ULONG __cdecl NTDLL_wcstoul(LPCWSTR s, LPWSTR *end, INT base)
|
||||
{
|
||||
BOOL negative = FALSE, empty = TRUE;
|
||||
ULONG ret = 0;
|
||||
|
||||
if (base < 0 || base == 1 || base > 36) return 0;
|
||||
if (end) *end = (WCHAR *)s;
|
||||
while (NTDLL_iswspace(*s)) s++;
|
||||
|
||||
if (*s == '-')
|
||||
{
|
||||
negative = TRUE;
|
||||
s++;
|
||||
}
|
||||
else if (*s == '+') s++;
|
||||
|
||||
if ((base == 0 || base == 16) && !wctoint( *s ) && (s[1] == 'x' || s[1] == 'X'))
|
||||
{
|
||||
base = 16;
|
||||
s += 2;
|
||||
}
|
||||
if (base == 0) base = wctoint( *s ) ? 10 : 8;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
int v = wctoint( *s );
|
||||
if (v < 0 || v >= base) break;
|
||||
s++;
|
||||
empty = FALSE;
|
||||
|
||||
if (ret > MAXDWORD / base || ret * base > MAXDWORD - v)
|
||||
ret = MAXDWORD;
|
||||
else
|
||||
ret = ret * base + v;
|
||||
}
|
||||
|
||||
if (end && !empty) *end = (WCHAR *)s;
|
||||
return negative ? -ret : ret;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _ultow (NTDLL.@)
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue