From 9a8fe9679b3edd928107c6831015b53eebf3eb46 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Mon, 29 Mar 2010 00:04:32 +0200 Subject: [PATCH] msvcrt: Added _strtoui64 implementation. --- dlls/msvcr80/msvcr80.spec | 4 +-- dlls/msvcr90/msvcr90.spec | 4 +-- dlls/msvcrt/msvcrt.spec | 4 +-- dlls/msvcrt/string.c | 74 ++++++++++++++++++++++++++++++++++++++ dlls/msvcrt/tests/string.c | 49 +++++++++++++++++++++++-- 5 files changed, 127 insertions(+), 8 deletions(-) diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index e44ad0f85e5..541cf683730 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -961,8 +961,8 @@ @ cdecl _strtoi64(str ptr long) msvcrt._strtoi64 @ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l @ stub _strtol_l -@ stub _strtoui64 -@ stub _strtoui64_l +@ cdecl _strtoui64(str ptr long) msvcrt._strtoui64 +@ cdecl _strtoui64_l(str ptr long ptr) msvcrt._strtoui64_l @ stub _strtoul_l @ cdecl _strupr(str) msvcrt._strupr @ stub _strupr_l diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index 1cec19c68b4..296466ac919 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -947,8 +947,8 @@ @ cdecl _strtoi64(str ptr long) msvcrt._strtoi64 @ cdecl _strtoi64_l(str ptr long ptr) msvcrt._strtoi64_l @ stub _strtol_l -@ stub _strtoui64 -@ stub _strtoui64_l +@ cdecl _strtoui64(str ptr long) msvcrt._strtoui64 +@ cdecl _strtoui64_l(str ptr long ptr) msvcrt._strtoui64_l @ stub _strtoul_l @ cdecl _strupr(str) msvcrt._strupr @ stub _strupr_l diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index d25bcc43d62..2b6be16aeb4 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -894,8 +894,8 @@ @ cdecl _strtoi64(str ptr long) MSVCRT_strtoi64 @ cdecl _strtoi64_l(str ptr long ptr) MSVCRT_strtoi64_l # stub _strtol_l -# stub _strtoui64 -# stub _strtoui64_l +@ cdecl _strtoui64(str ptr long) MSVCRT_strtoui64 +@ cdecl _strtoui64_l(str ptr long ptr) MSVCRT_strtoui64_l # stub _strtoul_l @ cdecl _strupr(str) ntdll._strupr # stub _strupr_l diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index d64cd45dd35..5432a304888 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -407,3 +407,77 @@ __int64 CDECL MSVCRT_strtoi64(const char *nptr, char **endptr, int base) { 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); +} diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index 87c84609cbe..a4926d969c1 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -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 size_t (__cdecl *p_strnlen)(const char *, size_t); 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 int *p__mb_cur_max; static unsigned char *p_mbctype; @@ -959,10 +960,11 @@ static void test__strtoi64(void) static const char blanks[] = " 12 212.31"; __int64 res; + unsigned __int64 ures; char *endpos; - if(!p_strtoi64) { - win_skip("_strtoi64 not found\n"); + if(!p_strtoi64 || !p_strtoui64) { + win_skip("_strtoi64 or _strtoui64 not found\n"); return; } @@ -974,6 +976,12 @@ static void test__strtoi64(void) ok(res == 0, "res != 0\n"); res = p_strtoi64(no1, NULL, 37); 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); } @@ -1063,6 +1071,42 @@ static void test__strtoi64(void) ok(res == 12, "res != 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(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) @@ -1089,6 +1133,7 @@ START_TEST(string) p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" ); p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" ); p_strtoi64 = (void *) GetProcAddress(hMsvcrt, "_strtoi64"); + p_strtoui64 = (void *) GetProcAddress(hMsvcrt, "_strtoui64"); /* MSVCRT memcpy behaves like memmove for overlapping moves, MFC42 CString::Insert seems to rely on that behaviour */