Commit 585ea9cd authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcrt: Added _strtoi64 implementation.

parent 8c954c09
......@@ -958,8 +958,8 @@
@ cdecl _strtime(ptr) msvcrt._strtime
@ stub _strtime_s
@ stub _strtod_l
@ stub _strtoi64
@ stub _strtoi64_l
@ 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
......
......@@ -944,8 +944,8 @@
@ cdecl _strtime(ptr) msvcrt._strtime
@ stub _strtime_s
@ stub _strtod_l
@ stub _strtoi64
@ stub _strtoi64_l
@ 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
......
......@@ -43,6 +43,9 @@
#define MSVCRT_LONG_MAX 0x7fffffffL
#define MSVCRT_ULONG_MAX 0xffffffffUL
#define MSVCRT_I64_MAX (((__int64)0x7fffffff << 32) | 0xffffffff)
#define MSVCRT_I64_MIN (-MSVCRT_I64_MAX-1)
#define MSVCRT_UI64_MAX (((unsigned __int64)0xffffffff << 32) | 0xffffffff)
typedef unsigned short MSVCRT_wchar_t;
typedef unsigned short MSVCRT_wint_t;
......@@ -739,6 +742,47 @@ int __cdecl MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, unsigned int len,
const MSVCRT_wchar_t *format, __ms_va_list valist );
int __cdecl MSVCRT_raise(int sig);
typedef struct MSVCRT_tagLC_ID {
unsigned short wLanguage;
unsigned short wCountry;
unsigned short wCodePage;
} MSVCRT_LC_ID, *MSVCRT_LPLC_ID;
typedef struct MSVCRT_threadlocaleinfostruct {
int refcount;
unsigned int lc_codepage;
unsigned int lc_collate_cp;
unsigned long lc_handle[6];
MSVCRT_LC_ID lc_id[6];
struct {
char *locale;
wchar_t *wlocale;
int *refcount;
int *wrefcount;
} lc_category[6];
int lc_clike;
int mb_cur_max;
int *lconv_intl_refcount;
int *lconv_num_refcount;
int *lconv_mon_refcount;
struct lconv *lconv;
int *ctype1_refcount;
unsigned short *ctype1;
const unsigned short *pctype;
const unsigned char *pclmap;
const unsigned char *pcumap;
struct __lc_time_data *lc_time_curr;
} MSVCRT_threadlocinfo;
typedef struct MSVCRT_threadlocaleinfostruct *MSVCRT_pthreadlocinfo;
typedef struct MSVCRT_threadmbcinfostruct *MSVCRT_pthreadmbcinfo;
typedef struct MSVCRT_localeinfo_struct
{
MSVCRT_pthreadlocinfo locinfo;
MSVCRT_pthreadmbcinfo mbcinfo;
} MSVCRT__locale_tstruct, *MSVCRT__locale_t;
#ifndef __WINE_MSVCRT_TEST
int __cdecl MSVCRT__write(int,const void*,unsigned int);
int __cdecl _getch(void);
......
......@@ -891,8 +891,8 @@
@ cdecl _strtime(ptr)
# stub _strtime_s
# stub _strtod_l
# stub _strtoi64
# stub _strtoi64_l
@ 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
......
......@@ -327,3 +327,83 @@ MSVCRT_size_t CDECL MSVCRT_strnlen(const char *s, MSVCRT_size_t maxlen)
return i;
}
/*********************************************************************
* _strtoi64_l (MSVCR90.@)
*
* FIXME: locale parameter is ignored
*/
__int64 CDECL MSVCRT_strtoi64_l(const char *nptr, char **endptr, int base, MSVCRT__locale_t locale)
{
BOOL negative = FALSE;
__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 = cur-'0';
} else {
if(cur<'a' || cur>='a'+base-10)
break;
v = cur-'a'+10;
}
if(negative)
v = -v;
nptr++;
if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
ret = MSVCRT_I64_MAX;
*MSVCRT__errno() = ERANGE;
} else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
ret = MSVCRT_I64_MIN;
*MSVCRT__errno() = ERANGE;
} else
ret = ret*base + v;
}
if(endptr)
*endptr = (char*)nptr;
return ret;
}
/*********************************************************************
* _strtoi64 (MSVCR90.@)
*/
__int64 CDECL MSVCRT_strtoi64(const char *nptr, char **endptr, int base)
{
return MSVCRT_strtoi64_l(nptr, endptr, base, NULL);
}
......@@ -27,6 +27,7 @@
#include <mbctype.h>
#include <locale.h>
#include <errno.h>
#include <limits.h>
static char *buf_to_string(const unsigned char *bin, int len, int nr)
{
......@@ -53,6 +54,7 @@ static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsig
static int (__cdecl *p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wcSrc);
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 _invalid_parameter_handler *p_invalid_parameter;
static int *p__mb_cur_max;
static unsigned char *p_mbctype;
......@@ -944,6 +946,125 @@ static void test_strnlen(void)
ok(res == 0, "Returned length = %d\n", (int)res);
}
static void test__strtoi64(void)
{
static const char no1[] = "31923";
static const char no2[] = "-213312";
static const char no3[] = "12aa";
static const char no4[] = "abc12";
static const char overflow[] = "99999999999999999999";
static const char neg_overflow[] = "-99999999999999999999";
static const char hex[] = "0x123";
static const char oct[] = "000123";
static const char blanks[] = " 12 212.31";
__int64 res;
char *endpos;
if(!p_strtoi64) {
win_skip("_strtoi64 not found\n");
return;
}
if(p_invalid_parameter) {
errno = 0xdeadbeef;
res = p_strtoi64(NULL, NULL, 10);
ok(res == 0, "res != 0\n");
res = p_strtoi64(no1, NULL, 1);
ok(res == 0, "res != 0\n");
res = p_strtoi64(no1, NULL, 37);
ok(res == 0, "res != 0\n");
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
}
errno = 0xdeadbeef;
res = p_strtoi64(no1, NULL, 10);
ok(res == 31923, "res != 31923\n");
res = p_strtoi64(no2, NULL, 10);
ok(res == -213312, "res != -213312\n");
res = p_strtoi64(no3, NULL, 10);
ok(res == 12, "res != 12\n");
res = p_strtoi64(no4, &endpos, 10);
ok(res == 0, "res != 0\n");
ok(endpos == no4, "Scanning was not stopped on first character\n");
res = p_strtoi64(hex, &endpos, 10);
ok(res == 0, "res != 0\n");
ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
res = p_strtoi64(oct, &endpos, 10);
ok(res == 123, "res != 123\n");
ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
res = p_strtoi64(blanks, &endpos, 10);
ok(res == 12, "res != 12");
ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
errno = 0xdeadbeef;
res = p_strtoi64(overflow, &endpos, 10);
ok(res == _I64_MAX, "res != _I64_MAX\n");
ok(endpos == overflow+strlen(overflow), "Incorrect endpos (%p-%p)\n", overflow, endpos);
ok(errno == ERANGE, "errno = %x\n", errno);
errno = 0xdeadbeef;
res = p_strtoi64(neg_overflow, &endpos, 10);
ok(res == _I64_MIN, "res != _I64_MIN\n");
ok(endpos == neg_overflow+strlen(neg_overflow), "Incorrect endpos (%p-%p)\n", neg_overflow, endpos);
ok(errno == ERANGE, "errno = %x\n", errno);
errno = 0xdeadbeef;
res = p_strtoi64(no1, &endpos, 16);
ok(res == 203043, "res != 203043\n");
ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
res = p_strtoi64(no2, &endpos, 16);
ok(res == -2175762, "res != -2175762\n");
ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
res = p_strtoi64(no3, &endpos, 16);
ok(res == 4778, "res != 4778\n");
ok(endpos == no3+strlen(no3), "Incorrect endpos (%p-%p)\n", no3, endpos);
res = p_strtoi64(no4, &endpos, 16);
ok(res == 703506, "res != 703506\n");
ok(endpos == no4+strlen(no4), "Incorrect endpos (%p-%p)\n", no4, endpos);
res = p_strtoi64(hex, &endpos, 16);
ok(res == 291, "res != 291\n");
ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
res = p_strtoi64(oct, &endpos, 16);
ok(res == 291, "res != 291\n");
ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
res = p_strtoi64(blanks, &endpos, 16);
ok(res == 18, "res != 18\n");
ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
errno = 0xdeadbeef;
res = p_strtoi64(hex, &endpos, 36);
ok(res == 1541019, "res != 1541019\n");
ok(endpos == hex+strlen(hex), "Incorrect endpos (%p-%p)\n", hex, endpos);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
errno = 0xdeadbeef;
res = p_strtoi64(no1, &endpos, 0);
ok(res == 31923, "res != 31923\n");
ok(endpos == no1+strlen(no1), "Incorrect endpos (%p-%p)\n", no1, endpos);
res = p_strtoi64(no2, &endpos, 0);
ok(res == -213312, "res != -213312\n");
ok(endpos == no2+strlen(no2), "Incorrect endpos (%p-%p)\n", no2, endpos);
res = p_strtoi64(no3, &endpos, 10);
ok(res == 12, "res != 12\n");
ok(endpos == no3+2, "Incorrect endpos (%p-%p)\n", no3, endpos);
res = p_strtoi64(no4, &endpos, 10);
ok(res == 0, "res != 0\n");
ok(endpos == no4, "Incorrect endpos (%p-%p)\n", no4, endpos);
res = p_strtoi64(hex, &endpos, 10);
ok(res == 0, "res != 0\n");
ok(endpos == hex+1, "Incorrect endpos (%p-%p)\n", hex, endpos);
res = p_strtoi64(oct, &endpos, 10);
ok(res == 123, "res != 123\n");
ok(endpos == oct+strlen(oct), "Incorrect endpos (%p-%p)\n", oct, endpos);
res = p_strtoi64(blanks, &endpos, 10);
ok(res == 12, "res != 12\n");
ok(endpos == blanks+10, "Incorrect endpos (%p-%p)\n", blanks, endpos);
ok(errno == 0xdeadbeef, "errno = %x\n", errno);
}
START_TEST(string)
{
char mem[100];
......@@ -967,6 +1088,7 @@ START_TEST(string)
p_wcscpy_s = (void *)GetProcAddress( hMsvcrt,"wcscpy_s" );
p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" );
p_strnlen = (void *)GetProcAddress( hMsvcrt,"strnlen" );
p_strtoi64 = (void *) GetProcAddress(hMsvcrt, "_strtoi64");
/* MSVCRT memcpy behaves like memmove for overlapping moves,
MFC42 CString::Insert seems to rely on that behaviour */
......@@ -997,4 +1119,5 @@ START_TEST(string)
test__wcsupr_s();
test_strtol();
test_strnlen();
test__strtoi64();
}
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