Commit 9a8fe967 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcrt: Added _strtoui64 implementation.

parent 585ea9cd
...@@ -961,8 +961,8 @@ ...@@ -961,8 +961,8 @@
@ cdecl _strtoi64(str ptr long) msvcrt._strtoi64 @ cdecl _strtoi64(str ptr long) msvcrt._strtoi64
@ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l @ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l
@ stub _strtol_l @ stub _strtol_l
@ stub _strtoui64 @ cdecl _strtoui64(str ptr long) msvcrt._strtoui64
@ stub _strtoui64_l @ cdecl _strtoui64_l(str ptr long ptr) msvcrt._strtoui64_l
@ stub _strtoul_l @ stub _strtoul_l
@ cdecl _strupr(str) msvcrt._strupr @ cdecl _strupr(str) msvcrt._strupr
@ stub _strupr_l @ stub _strupr_l
......
...@@ -947,8 +947,8 @@ ...@@ -947,8 +947,8 @@
@ cdecl _strtoi64(str ptr long) msvcrt._strtoi64 @ cdecl _strtoi64(str ptr long) msvcrt._strtoi64
@ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l @ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l
@ stub _strtol_l @ stub _strtol_l
@ stub _strtoui64 @ cdecl _strtoui64(str ptr long) msvcrt._strtoui64
@ stub _strtoui64_l @ cdecl _strtoui64_l(str ptr long ptr) msvcrt._strtoui64_l
@ stub _strtoul_l @ stub _strtoul_l
@ cdecl _strupr(str) msvcrt._strupr @ cdecl _strupr(str) msvcrt._strupr
@ stub _strupr_l @ stub _strupr_l
......
...@@ -894,8 +894,8 @@ ...@@ -894,8 +894,8 @@
@ cdecl _strtoi64(str ptr long) MSVCRT_strtoi64 @ cdecl _strtoi64(str ptr long) MSVCRT_strtoi64
@ cdecl _strtoi64_l(str ptr long ptr) MSVCRT_strtoi64_l @ cdecl _strtoi64_l(str ptr long ptr) MSVCRT_strtoi64_l
# stub _strtol_l # stub _strtol_l
# stub _strtoui64 @ cdecl _strtoui64(str ptr long) MSVCRT_strtoui64
# stub _strtoui64_l @ cdecl _strtoui64_l(str ptr long ptr) MSVCRT_strtoui64_l
# stub _strtoul_l # stub _strtoul_l
@ cdecl _strupr(str) ntdll._strupr @ cdecl _strupr(str) ntdll._strupr
# stub _strupr_l # stub _strupr_l
......
...@@ -407,3 +407,77 @@ __int64 CDECL MSVCRT_strtoi64(const char *nptr, char **endptr, int base) ...@@ -407,3 +407,77 @@ __int64 CDECL MSVCRT_strtoi64(const char *nptr, char **endptr, int base)
{ {
return MSVCRT_strtoi64_l(nptr, endptr, base, NULL); return MSVCRT_strtoi64_l(nptr, endptr, base, NULL);
} }
/*********************************************************************
* _strtoui64_l (MSVCR90.@)
*
* FIXME: locale parameter is ignored
*/
unsigned __int64 CDECL MSVCRT_strtoui64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
{
BOOL negative = FALSE;
unsigned __int64 ret = 0;
TRACE("(%s %p %d %p)\n", nptr, endptr, base, locale);
if(!nptr || base<0 || base>36 || base==1) {
MSVCRT_invalid_parameter(NULL, NULL, NULL, 0, NULL);
return 0;
}
while(isspace(*nptr)) nptr++;
if(*nptr == '-') {
negative = TRUE;
nptr++;
} else if(*nptr == '+')
nptr++;
if((base==0 || base==16) && *nptr=='0' && tolower(*(nptr+1))=='x') {
base = 16;
nptr += 2;
}
if(base == 0) {
if(*nptr=='0')
base = 8;
else
base = 10;
}
while(*nptr) {
char cur = tolower(*nptr);
int v;
if(isdigit(cur)) {
if(cur >= '0'+base)
break;
v = *nptr-'0';
} else {
if(cur<'a' || cur>='a'+base-10)
break;
v = cur-'a'+10;
}
nptr++;
if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
ret = MSVCRT_UI64_MAX;
*MSVCRT__errno() = ERANGE;
} else
ret = ret*base + v;
}
if(endptr)
*endptr = (char*)nptr;
return negative ? -ret : ret;
}
/*********************************************************************
* _strtoui64 (MSVCR90.@)
*/
unsigned __int64 CDECL MSVCRT_strtoui64(const char *nptr, char **endptr, int base)
{
return MSVCRT_strtoui64_l(nptr, endptr, base, NULL);
}
...@@ -55,6 +55,7 @@ static int (__cdecl *p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wc ...@@ -55,6 +55,7 @@ static int (__cdecl *p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wc
static int (__cdecl *p_wcsupr_s)(wchar_t *str, size_t size); static int (__cdecl *p_wcsupr_s)(wchar_t *str, size_t size);
static size_t (__cdecl *p_strnlen)(const char *, size_t); static size_t (__cdecl *p_strnlen)(const char *, size_t);
static __int64 (__cdecl *p_strtoi64)(const char *, char **, int); static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
static _invalid_parameter_handler *p_invalid_parameter; static _invalid_parameter_handler *p_invalid_parameter;
static int *p__mb_cur_max; static int *p__mb_cur_max;
static unsigned char *p_mbctype; static unsigned char *p_mbctype;
...@@ -959,10 +960,11 @@ static void test__strtoi64(void) ...@@ -959,10 +960,11 @@ static void test__strtoi64(void)
static const char blanks[] = " 12 212.31"; static const char blanks[] = " 12 212.31";
__int64 res; __int64 res;
unsigned __int64 ures;
char *endpos; char *endpos;
if(!p_strtoi64) { if(!p_strtoi64 || !p_strtoui64) {
win_skip("_strtoi64 not found\n"); win_skip("_strtoi64 or _strtoui64 not found\n");
return; return;
} }
...@@ -974,6 +976,12 @@ static void test__strtoi64(void) ...@@ -974,6 +976,12 @@ static void test__strtoi64(void)
ok(res == 0, "res != 0\n"); ok(res == 0, "res != 0\n");
res = p_strtoi64(no1, NULL, 37); res = p_strtoi64(no1, NULL, 37);
ok(res == 0, "res != 0\n"); ok(res == 0, "res != 0\n");
ures = p_strtoui64(NULL, NULL, 10);
ok(ures == 0, "res = %d\n", (int)ures);
ures = p_strtoui64(no1, NULL, 1);
ok(ures == 0, "res = %d\n", (int)ures);
ures = p_strtoui64(no1, NULL, 37);
ok(ures == 0, "res = %d\n", (int)ures);
ok(errno == 0xdeadbeef, "errno = %x\n", errno); ok(errno == 0xdeadbeef, "errno = %x\n", errno);
} }
...@@ -1063,6 +1071,42 @@ static void test__strtoi64(void) ...@@ -1063,6 +1071,42 @@ static void test__strtoi64(void)
ok(res == 12, "res != 12\n"); ok(res == 12, "res != 12\n");
ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos); ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
ok(errno == 0xdeadbeef, "errno = %x\n", errno); ok(errno == 0xdeadbeef, "errno = %x\n", errno);
errno = 0xdeadbeef;
ures = p_strtoui64(no1, &endpos, 0);
ok(ures == 31923, "ures != 31923\n");
ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
ures = p_strtoui64(no2, &endpos, 0);
ok(ures == -213312, "ures != -213312\n");
ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
ures = p_strtoui64(no3, &endpos, 10);
ok(ures == 12, "ures != 12\n");
ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
ures = p_strtoui64(no4, &endpos, 10);
ok(ures == 0, "ures != 0\n");
ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
ures = p_strtoui64(hex, &endpos, 10);
ok(ures == 0, "ures != 0\n");
ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
ures = p_strtoui64(oct, &endpos, 10);
ok(ures == 123, "ures != 123\n");
ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
ures = p_strtoui64(blanks, &endpos, 10);
ok(ures == 12, "ures != 12\n");
ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
errno = 0xdeadbeef;
ures = p_strtoui64(overflow, &endpos, 10);
ok(ures == _UI64_MAX, "ures != _UI64_MAX\n");
ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
ok(errno == ERANGE, "errno = %x\n", errno);
errno = 0xdeadbeef;
ures = p_strtoui64(neg_overflow, &endpos, 10);
ok(ures == 1, "ures != 1\n");
ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
ok(errno == ERANGE, "errno = %x\n", errno);
} }
START_TEST(string) START_TEST(string)
...@@ -1089,6 +1133,7 @@ START_TEST(string) ...@@ -1089,6 +1133,7 @@ START_TEST(string)
p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" ); p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" );
p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" ); p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" );
p_strtoi64 = (void *) GetProcAddress(hMsvcrt, "_strtoi64"); p_strtoi64 = (void *) GetProcAddress(hMsvcrt, "_strtoi64");
p_strtoui64 = (void *) GetProcAddress(hMsvcrt, "_strtoui64");
/* MSVCRT memcpy behaves like memmove for overlapping moves, /* MSVCRT memcpy behaves like memmove for overlapping moves,
MFC42 CString::Insert seems to rely on that behaviour */ MFC42 CString::Insert seems to rely on that behaviour */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment