msvcp90: Fix num_get<>::_Getffld.
This commit is contained in:
parent
4c357de5d3
commit
82c1fb41aa
|
@ -4408,11 +4408,12 @@ static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator
|
|||
istreambuf_iterator_wchar *last, const locale *loc, numpunct_wchar *numpunct)
|
||||
{
|
||||
basic_string_char grouping_bstr;
|
||||
basic_string_char groups_found;
|
||||
int i, groups_no = 0, cur_group = 0, exp = 0;
|
||||
char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31, *groups = NULL;
|
||||
char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31;
|
||||
wchar_t sep, digits[11], *digits_pos;
|
||||
const char *grouping;
|
||||
BOOL error = FALSE, got_digit = FALSE, dest_empty = TRUE;
|
||||
const char *grouping, *groups;
|
||||
BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
|
||||
|
||||
TRACE("(%p %p %p %p)\n", dest, first, last, loc);
|
||||
|
||||
|
@ -4424,7 +4425,11 @@ static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator
|
|||
grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
|
||||
sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : (wchar_t)0;
|
||||
|
||||
if(sep)
|
||||
MSVCP_basic_string_char_ctor(&groups_found);
|
||||
|
||||
istreambuf_iterator_wchar_val(first);
|
||||
/* get sign */
|
||||
if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
|
||||
*dest++ = '-';
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
|
@ -4433,45 +4438,99 @@ static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator
|
|||
istreambuf_iterator_wchar_inc(first);
|
||||
}
|
||||
|
||||
if(sep) {
|
||||
groups_no = strlen(grouping)+2;
|
||||
groups = calloc(groups_no, sizeof(char));
|
||||
}
|
||||
|
||||
/* read possibly grouped numbers before decimal */
|
||||
for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
|
||||
if(!(digits_pos = wcschr(digits, first->val))) {
|
||||
if(sep && first->val==sep) {
|
||||
if(cur_group == groups_no+1) {
|
||||
if(groups[1] != groups[2]) {
|
||||
error = TRUE;
|
||||
break;
|
||||
}else {
|
||||
memmove(groups+1, groups+2, groups_no);
|
||||
groups[cur_group] = 0;
|
||||
}
|
||||
}else {
|
||||
cur_group++;
|
||||
}
|
||||
if(!groups_no) break; /* empty group - stop parsing */
|
||||
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
|
||||
groups_no = 0;
|
||||
++cur_group;
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}else {
|
||||
got_digit = TRUE;
|
||||
if(dest_empty && first->val == digits[0])
|
||||
got_digit = TRUE; /* found a digit, zero or non-zero */
|
||||
/* write digit to dest if not a leading zero (to not waste dest buffer) */
|
||||
if(!got_nonzero && first->val == digits[0])
|
||||
{
|
||||
++groups_no;
|
||||
continue;
|
||||
dest_empty = FALSE;
|
||||
}
|
||||
got_nonzero = TRUE;
|
||||
if(dest < num_end)
|
||||
*dest++ = '0'+digits_pos-digits;
|
||||
else
|
||||
exp++;
|
||||
if(sep && groups[cur_group]<CHAR_MAX)
|
||||
groups[cur_group]++;
|
||||
exp++; /* too many digits, just multiply by 10 */
|
||||
if(sep && groups_no<CHAR_MAX)
|
||||
++groups_no;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_group && !groups[cur_group])
|
||||
/* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
|
||||
if(got_digit && !got_nonzero)
|
||||
*dest++ = '0';
|
||||
|
||||
/* get decimal, if any */
|
||||
if(first->strbuf && first->val==numpunct_wchar_decimal_point(numpunct)) {
|
||||
if(dest < num_end)
|
||||
*dest++ = *localeconv()->decimal_point;
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
}
|
||||
|
||||
/* read non-grouped after decimal */
|
||||
for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
|
||||
if(!(digits_pos = wcschr(digits, first->val)))
|
||||
break;
|
||||
else if(dest<num_end) {
|
||||
got_digit = TRUE;
|
||||
*dest++ = '0'+digits_pos-digits;
|
||||
}
|
||||
}
|
||||
|
||||
/* read exponent, if any */
|
||||
if(first->strbuf && (first->val==mb_to_wc('e', &this->cvt) || first->val==mb_to_wc('E', &this->cvt))) {
|
||||
*dest++ = 'e';
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
|
||||
if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
|
||||
*dest++ = '-';
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
}else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
|
||||
*dest++ = '+';
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
}
|
||||
|
||||
got_digit = got_nonzero = FALSE;
|
||||
error = TRUE;
|
||||
else if(!cur_group)
|
||||
/* skip any leading zeroes */
|
||||
for(; first->strbuf && first->val==digits[0]; istreambuf_iterator_wchar_inc(first))
|
||||
error = FALSE;
|
||||
|
||||
for(; first->strbuf && (digits_pos = wcschr(digits, first->val)); istreambuf_iterator_wchar_inc(first)) {
|
||||
got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
|
||||
error = FALSE;
|
||||
if(dest<exp_end)
|
||||
*dest++ = '0'+digits_pos-digits;
|
||||
}
|
||||
|
||||
/* if just found zeroes for exponent, use that */
|
||||
if(got_digit && !got_nonzero)
|
||||
{
|
||||
error = FALSE;
|
||||
if(dest<exp_end)
|
||||
*dest++ = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if(sep && groups_no)
|
||||
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
|
||||
|
||||
groups = MSVCP_basic_string_char_c_str(&groups_found);
|
||||
if(cur_group && !groups[cur_group])
|
||||
{
|
||||
error = TRUE; /* trailing empty */
|
||||
}else if(!cur_group) /* no groups, skip loop */
|
||||
cur_group--;
|
||||
|
||||
for(; cur_group>=0 && !error; cur_group--) {
|
||||
|
@ -4488,75 +4547,13 @@ static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator
|
|||
}
|
||||
}
|
||||
MSVCP_basic_string_char_dtor(&grouping_bstr);
|
||||
free(groups);
|
||||
if(sep)
|
||||
MSVCP_basic_string_char_dtor(&groups_found);
|
||||
|
||||
if(error) {
|
||||
*dest_beg = '\0';
|
||||
return 0;
|
||||
}else if(dest_empty) {
|
||||
*dest++ = '0';
|
||||
}
|
||||
|
||||
if(first->strbuf && first->val==numpunct_wchar_decimal_point(numpunct)) {
|
||||
if(dest < num_end)
|
||||
*dest++ = *localeconv()->decimal_point;
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
|
||||
if(dest_empty) {
|
||||
for(; first->strbuf && first->val==digits[0]; istreambuf_iterator_wchar_inc(first)) {
|
||||
got_digit = TRUE;
|
||||
exp--;
|
||||
}
|
||||
|
||||
if(!first->strbuf || !wcschr(digits, first->val))
|
||||
dest--;
|
||||
}
|
||||
}
|
||||
|
||||
for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
|
||||
if(!(digits_pos = wcschr(digits, first->val)))
|
||||
break;
|
||||
else if(dest<num_end) {
|
||||
got_digit = TRUE;
|
||||
*dest++ = '0'+digits_pos-digits;
|
||||
}
|
||||
}
|
||||
|
||||
if(!got_digit) {
|
||||
*dest_beg = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(first->strbuf && (first->val==mb_to_wc('e', &this->cvt) || first->val==mb_to_wc('E', &this->cvt))) {
|
||||
*dest++ = 'e';
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
|
||||
if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
|
||||
*dest++ = '-';
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
}else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
|
||||
*dest++ = '+';
|
||||
istreambuf_iterator_wchar_inc(first);
|
||||
}
|
||||
|
||||
error = dest_empty = TRUE;
|
||||
for(; first->strbuf && first->val==digits[0]; istreambuf_iterator_wchar_inc(first))
|
||||
error = FALSE;
|
||||
|
||||
for(; first->strbuf && (digits_pos = wcschr(digits, first->val)); istreambuf_iterator_wchar_inc(first)) {
|
||||
error = dest_empty = FALSE;
|
||||
if(dest<exp_end)
|
||||
*dest++ = '0'+digits_pos-digits;
|
||||
}
|
||||
|
||||
if(error) {
|
||||
*dest_beg = '\0';
|
||||
return 0;
|
||||
}else if(dest_empty) {
|
||||
*dest++ = '0';
|
||||
}
|
||||
}
|
||||
|
||||
*dest++ = '\0';
|
||||
return exp;
|
||||
}
|
||||
|
@ -5532,10 +5529,11 @@ int __cdecl num_get_char__Getffld(const num_get *this, char *dest, istreambuf_it
|
|||
{
|
||||
numpunct_char *numpunct = numpunct_char_use_facet(loc);
|
||||
basic_string_char grouping_bstr;
|
||||
basic_string_char groups_found;
|
||||
int groups_no = 0, cur_group = 0, exp = 0;
|
||||
char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31, *groups = NULL, sep;
|
||||
const char *grouping;
|
||||
BOOL error = FALSE, got_digit = FALSE, dest_empty = TRUE;
|
||||
char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31, sep;
|
||||
const char *grouping, *groups;
|
||||
BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
|
||||
|
||||
TRACE("(%p %p %p %p)\n", dest, first, last, loc);
|
||||
|
||||
|
@ -5543,51 +5541,106 @@ int __cdecl num_get_char__Getffld(const num_get *this, char *dest, istreambuf_it
|
|||
grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
|
||||
sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
|
||||
|
||||
if(sep)
|
||||
MSVCP_basic_string_char_ctor(&groups_found);
|
||||
|
||||
istreambuf_iterator_char_val(first);
|
||||
/* get sign */
|
||||
if(first->strbuf && (first->val=='-' || first->val=='+')) {
|
||||
*dest++ = first->val;
|
||||
istreambuf_iterator_char_inc(first);
|
||||
}
|
||||
|
||||
if(sep) {
|
||||
groups_no = strlen(grouping)+2;
|
||||
groups = calloc(groups_no, sizeof(char));
|
||||
}
|
||||
|
||||
/* read possibly grouped numbers before decimal */
|
||||
for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
|
||||
if(first->val<'0' || first->val>'9') {
|
||||
if(sep && first->val==sep) {
|
||||
if(cur_group == groups_no+1) {
|
||||
if(groups[1] != groups[2]) {
|
||||
error = TRUE;
|
||||
break;
|
||||
}else {
|
||||
memmove(groups+1, groups+2, groups_no);
|
||||
groups[cur_group] = 0;
|
||||
}
|
||||
}else {
|
||||
cur_group++;
|
||||
}
|
||||
if(!groups_no) break; /* empty group - stop parsing */
|
||||
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
|
||||
groups_no = 0;
|
||||
++cur_group;
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}else {
|
||||
got_digit = TRUE;
|
||||
if(dest_empty && first->val == '0')
|
||||
got_digit = TRUE; /* found a digit, zero or non-zero */
|
||||
/* write digit to dest if not a leading zero (to not waste dest buffer) */
|
||||
if(!got_nonzero && first->val == '0')
|
||||
{
|
||||
++groups_no;
|
||||
continue;
|
||||
dest_empty = FALSE;
|
||||
}
|
||||
got_nonzero = TRUE;
|
||||
if(dest < num_end)
|
||||
*dest++ = first->val;
|
||||
else
|
||||
exp++;
|
||||
if(sep && groups[cur_group]<CHAR_MAX)
|
||||
groups[cur_group]++;
|
||||
exp++; /* too many digits, just multiply by 10 */
|
||||
if(sep && groups_no<CHAR_MAX)
|
||||
++groups_no;
|
||||
}
|
||||
}
|
||||
|
||||
if(cur_group && !groups[cur_group])
|
||||
/* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
|
||||
if(got_digit && !got_nonzero)
|
||||
*dest++ = '0';
|
||||
|
||||
/* get decimal, if any */
|
||||
if(first->strbuf && first->val==numpunct_char_decimal_point(numpunct)) {
|
||||
if(dest < num_end)
|
||||
*dest++ = *localeconv()->decimal_point;
|
||||
istreambuf_iterator_char_inc(first);
|
||||
}
|
||||
|
||||
/* read non-grouped after decimal */
|
||||
for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
|
||||
if(first->val<'0' || first->val>'9')
|
||||
break;
|
||||
else if(dest<num_end) {
|
||||
got_digit = TRUE;
|
||||
*dest++ = first->val;
|
||||
}
|
||||
}
|
||||
|
||||
/* read exponent, if any */
|
||||
if(first->strbuf && (first->val=='e' || first->val=='E')) {
|
||||
*dest++ = first->val;
|
||||
istreambuf_iterator_char_inc(first);
|
||||
|
||||
if(first->strbuf && (first->val=='-' || first->val=='+')) {
|
||||
*dest++ = first->val;
|
||||
istreambuf_iterator_char_inc(first);
|
||||
}
|
||||
|
||||
got_digit = got_nonzero = FALSE;
|
||||
error = TRUE;
|
||||
else if(!cur_group)
|
||||
/* skip any leading zeroes */
|
||||
for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
|
||||
got_digit = TRUE;
|
||||
|
||||
for(; first->strbuf && first->val>='0' && first->val<='9'; istreambuf_iterator_char_inc(first)) {
|
||||
got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
|
||||
error = FALSE;
|
||||
if(dest<exp_end)
|
||||
*dest++ = first->val;
|
||||
}
|
||||
|
||||
/* if just found zeroes for exponent, use that */
|
||||
if(got_digit && !got_nonzero)
|
||||
{
|
||||
error = FALSE;
|
||||
if(dest<exp_end)
|
||||
*dest++ = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if(sep && groups_no)
|
||||
MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
|
||||
|
||||
groups = MSVCP_basic_string_char_c_str(&groups_found);
|
||||
if(cur_group && !groups[cur_group])
|
||||
{
|
||||
error = TRUE; /* trailing empty */
|
||||
}else if(!cur_group) /* no groups, skip loop */
|
||||
cur_group--;
|
||||
|
||||
for(; cur_group>=0 && !error; cur_group--) {
|
||||
|
@ -5604,72 +5657,13 @@ int __cdecl num_get_char__Getffld(const num_get *this, char *dest, istreambuf_it
|
|||
}
|
||||
}
|
||||
MSVCP_basic_string_char_dtor(&grouping_bstr);
|
||||
free(groups);
|
||||
if(sep)
|
||||
MSVCP_basic_string_char_dtor(&groups_found);
|
||||
|
||||
if(error) {
|
||||
*dest_beg = '\0';
|
||||
return 0;
|
||||
}else if(dest_empty) {
|
||||
*dest++ = '0';
|
||||
}
|
||||
|
||||
if(first->strbuf && first->val==numpunct_char_decimal_point(numpunct)) {
|
||||
if(dest < num_end)
|
||||
*dest++ = *localeconv()->decimal_point;
|
||||
istreambuf_iterator_char_inc(first);
|
||||
|
||||
if(dest_empty) {
|
||||
for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first)) {
|
||||
got_digit = TRUE;
|
||||
exp--;
|
||||
}
|
||||
|
||||
if(!first->strbuf || first->val<'1' || first->val>'9')
|
||||
dest--;
|
||||
}
|
||||
}
|
||||
|
||||
for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
|
||||
if(first->val<'0' || first->val>'9')
|
||||
break;
|
||||
else if(dest<num_end) {
|
||||
got_digit = TRUE;
|
||||
*dest++ = first->val;
|
||||
}
|
||||
}
|
||||
|
||||
if(!got_digit) {
|
||||
*dest_beg = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(first->strbuf && (first->val=='e' || first->val=='E')) {
|
||||
*dest++ = first->val;
|
||||
istreambuf_iterator_char_inc(first);
|
||||
|
||||
if(first->strbuf && (first->val=='-' || first->val=='+')) {
|
||||
*dest++ = first->val;
|
||||
istreambuf_iterator_char_inc(first);
|
||||
}
|
||||
|
||||
error = dest_empty = TRUE;
|
||||
for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
|
||||
error = FALSE;
|
||||
|
||||
for(; first->strbuf && first->val>='0' && first->val<='9'; istreambuf_iterator_char_inc(first)) {
|
||||
error = dest_empty = FALSE;
|
||||
if(dest<exp_end)
|
||||
*dest++ = first->val;
|
||||
}
|
||||
|
||||
if(error) {
|
||||
*dest_beg = '\0';
|
||||
return 0;
|
||||
}else if(dest_empty) {
|
||||
*dest++ = '0';
|
||||
}
|
||||
}
|
||||
|
||||
*dest++ = '\0';
|
||||
return exp;
|
||||
}
|
||||
|
|
|
@ -348,9 +348,11 @@ static void (*__thiscall p_basic_stringstream_wchar_vbase_dtor)(basic_stringstre
|
|||
|
||||
/* istream */
|
||||
static basic_istream_char* (*__thiscall p_basic_istream_char_read_uint64)(basic_istream_char*, unsigned __int64*);
|
||||
static basic_istream_char* (*__thiscall p_basic_istream_char_read_double)(basic_istream_char*, double*);
|
||||
static int (*__thiscall p_basic_istream_char_get)(basic_istream_char*);
|
||||
|
||||
static basic_istream_wchar* (*__thiscall p_basic_istream_wchar_read_uint64)(basic_istream_wchar*, unsigned __int64*);
|
||||
static basic_istream_wchar* (*__thiscall p_basic_istream_wchar_read_double)(basic_istream_wchar*, double *);
|
||||
static int (*__thiscall p_basic_istream_wchar_get)(basic_istream_wchar*);
|
||||
|
||||
/* basic_ios */
|
||||
|
@ -477,11 +479,15 @@ static BOOL init(void)
|
|||
|
||||
SET(p_basic_istream_char_read_uint64,
|
||||
"??5?$basic_istream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@AEA_K@Z");
|
||||
SET(p_basic_istream_char_read_double,
|
||||
"??5?$basic_istream@DU?$char_traits@D@std@@@std@@QEAAAEAV01@AEAN@Z");
|
||||
SET(p_basic_istream_char_get,
|
||||
"?get@?$basic_istream@DU?$char_traits@D@std@@@std@@QEAAHXZ");
|
||||
|
||||
SET(p_basic_istream_wchar_read_uint64,
|
||||
"??5?$basic_istream@_WU?$char_traits@_W@std@@@std@@QEAAAEAV01@AEA_K@Z");
|
||||
SET(p_basic_istream_wchar_read_double,
|
||||
"??5?$basic_istream@_WU?$char_traits@_W@std@@@std@@QEAAAEAV01@AEAN@Z");
|
||||
SET(p_basic_istream_wchar_get,
|
||||
"?get@?$basic_istream@_WU?$char_traits@_W@std@@@std@@QEAAGXZ");
|
||||
|
||||
|
@ -523,11 +529,15 @@ static BOOL init(void)
|
|||
|
||||
SET(p_basic_istream_char_read_uint64,
|
||||
"??5?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV01@AA_K@Z");
|
||||
SET(p_basic_istream_char_read_double,
|
||||
"??5?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV01@AAN@Z");
|
||||
SET(p_basic_istream_char_get,
|
||||
"?get@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEHXZ");
|
||||
|
||||
SET(p_basic_istream_wchar_read_uint64,
|
||||
"??5?$basic_istream@_WU?$char_traits@_W@std@@@std@@QAEAAV01@AA_K@Z");
|
||||
SET(p_basic_istream_wchar_read_double,
|
||||
"??5?$basic_istream@_WU?$char_traits@_W@std@@@std@@QAEAAV01@AAN@Z");
|
||||
SET(p_basic_istream_wchar_get,
|
||||
"?get@?$basic_istream@_WU?$char_traits@_W@std@@@std@@QAEGXZ");
|
||||
|
||||
|
@ -707,12 +717,162 @@ static void test_num_get_get_uint64(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void test_num_get_get_double(void)
|
||||
{
|
||||
unsigned short testus, nextus;
|
||||
basic_stringstream_wchar wss;
|
||||
basic_stringstream_char ss;
|
||||
basic_string_wchar wstr;
|
||||
basic_string_char str;
|
||||
IOSB_iostate state;
|
||||
locale lcl, retlcl;
|
||||
wchar_t wide[64];
|
||||
int i, next;
|
||||
double val;
|
||||
|
||||
/* makes tables narrower */
|
||||
const IOSB_iostate IOSTATE_faileof = IOSTATE_failbit|IOSTATE_eofbit;
|
||||
|
||||
struct _test_num_get {
|
||||
const char *str;
|
||||
const char *lcl;
|
||||
IOSB_iostate state;
|
||||
double val;
|
||||
int next;
|
||||
} tests[] = {
|
||||
/* simple cases */
|
||||
{ "0", NULL, IOSTATE_eofbit, 0.0, EOF },
|
||||
{ "10", NULL, IOSTATE_eofbit, 10.0, EOF },
|
||||
{ "+10", NULL, IOSTATE_eofbit, 10.0, EOF },
|
||||
{ "-10", NULL, IOSTATE_eofbit, -10.0, EOF },
|
||||
{ "+010", NULL, IOSTATE_eofbit, 10.0, EOF }, /* leading zero */
|
||||
|
||||
/* test grouping - default/"C" has no grouping, named English/German locales do */
|
||||
{ "1,000", NULL, IOSTATE_goodbit, 1.0, ',' }, /* with comma */
|
||||
{ "1,000", "English", IOSTATE_eofbit, 1000.0, EOF },
|
||||
{ "1,000", "German", IOSTATE_eofbit, 1.0, EOF },
|
||||
|
||||
{ "1.000", NULL, IOSTATE_eofbit, 1.0, EOF }, /* with period */
|
||||
{ "1.000", "English", IOSTATE_eofbit, 1.0, EOF },
|
||||
{ "1.000", "German", IOSTATE_eofbit, 1000.0, EOF },
|
||||
|
||||
{ "1,234.", NULL, IOSTATE_goodbit, 1.0, ',' },
|
||||
{ "1,234.", "English", IOSTATE_eofbit, 1234.0, EOF }, /* trailing decimal */
|
||||
{ "1,234.", "German", IOSTATE_goodbit, 1.234, '.' },
|
||||
{ "1,234.5", "English", IOSTATE_eofbit, 1234.5, EOF }, /* group + decimal */
|
||||
{ "1,234.5", "German", IOSTATE_goodbit, 1.234, '.' },
|
||||
|
||||
{ "1,234,567,890", NULL, IOSTATE_goodbit, 1.0, ',' }, /* more groups */
|
||||
{ "1,234,567,890", "English", IOSTATE_eofbit, 1234567890.0, EOF },
|
||||
{ "1,234,567,890", "German", IOSTATE_goodbit, 1.234, ',' },
|
||||
{ "1.234.567.890", "German", IOSTATE_eofbit, 1234567890.0, EOF },
|
||||
|
||||
/* extra digits and stuff */
|
||||
{ "00000.123456", NULL, IOSTATE_eofbit, 0.123456, EOF },
|
||||
{ "0.1234560000", NULL, IOSTATE_eofbit, 0.123456, EOF },
|
||||
{ "100aaaa", NULL, IOSTATE_goodbit, 100.0, 'a' },
|
||||
|
||||
/* exponent */
|
||||
{ "10e10", NULL, IOSTATE_eofbit, 10e10, EOF }, /* lowercase e */
|
||||
{ "10E10", NULL, IOSTATE_eofbit, 10E10, EOF }, /* uppercase E */
|
||||
{ "10e+10", NULL, IOSTATE_eofbit, 10e10, EOF }, /* sign */
|
||||
{ "10e-10", NULL, IOSTATE_eofbit, 10e-10, EOF },
|
||||
{ "10.e10", NULL, IOSTATE_eofbit, 10e10, EOF }, /* trailing decimal before exponent */
|
||||
{ "-10.e-10", NULL, IOSTATE_eofbit, -10e-10, EOF },
|
||||
{ "-12.345e-10", NULL, IOSTATE_eofbit, -12.345e-10, EOF },
|
||||
{ "1,234e10", NULL, IOSTATE_goodbit, 1.0, ',' },
|
||||
{ "1,234e10", "English", IOSTATE_eofbit, 1234.0e10, EOF },
|
||||
{ "1,234e10", "German", IOSTATE_eofbit, 1.234e10, EOF },
|
||||
{ "1.0e999", NULL, IOSTATE_faileof, 42.0, EOF }, /* too big */
|
||||
{ "1.0e-999", NULL, IOSTATE_faileof, 42.0, EOF }, /* too small */
|
||||
|
||||
/* bad form */
|
||||
{ "1,000,", NULL, IOSTATE_goodbit, 1.0, ',' }, /* trailing group */
|
||||
{ "1,000,", "English", IOSTATE_faileof, 42.0, EOF },
|
||||
{ "1.000.", "German", IOSTATE_faileof, 42.0, EOF },
|
||||
|
||||
{ "1,,000", NULL, IOSTATE_goodbit, 1.0, ',' }, /* empty group */
|
||||
{ "1,,000", "English", IOSTATE_failbit, 42.0, EOF },
|
||||
{ "1..000", "German", IOSTATE_failbit, 42.0, EOF },
|
||||
|
||||
{ "1.0,00", "English", IOSTATE_goodbit, 1.0, ',' },
|
||||
{ "1.0,00", "German", IOSTATE_faileof, 42.0, EOF },
|
||||
|
||||
{ "1.0ee10", NULL, IOSTATE_failbit, 42.0, EOF }, /* dup exp */
|
||||
{ "1.0e1.0", NULL, IOSTATE_goodbit, 10.0, '.' }, /* decimal in exponent */
|
||||
{ "1.0e1,0", NULL, IOSTATE_goodbit, 10.0, ',' }, /* group in exponent */
|
||||
};
|
||||
|
||||
for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
|
||||
/* char version */
|
||||
call_func2(p_basic_string_char_ctor_cstr, &str, tests[i].str);
|
||||
call_func4(p_basic_stringstream_char_ctor_str, &ss, &str, OPENMODE_out|OPENMODE_in, TRUE);
|
||||
|
||||
if(tests[i].lcl) {
|
||||
call_func3(p_locale_ctor_cstr, &lcl, tests[i].lcl, 0x3f /* FIXME: support categories */);
|
||||
call_func3(p_basic_ios_char_imbue, &ss.basic_ios, &retlcl, &lcl);
|
||||
}
|
||||
|
||||
val = 42.0;
|
||||
call_func2(p_basic_istream_char_read_double, &ss.base.base1, &val);
|
||||
state = (IOSB_iostate)call_func1(p_ios_base_rdstate, &ss.basic_ios.base);
|
||||
next = (int)call_func1(p_basic_istream_char_get, &ss.base.base1);
|
||||
|
||||
if(strlen(tests[i].str) == 0) {
|
||||
/* a later patch to istream<>::_Ipfx will handle empty string */
|
||||
todo_wine ok(tests[i].state == state, "wrong state, expected = %x found = %x\n", tests[i].state, state);
|
||||
} else
|
||||
ok(tests[i].state == state, "wrong state, expected = %x found = %x\n", tests[i].state, state);
|
||||
ok(tests[i].val == val, "wrong val, expected = %g found %g\n", tests[i].val, val);
|
||||
ok(tests[i].next == next, "wrong next, expected = %c (%i) found = %c (%i)\n", tests[i].next, tests[i].next, next, next);
|
||||
|
||||
if(tests[i].lcl)
|
||||
call_func1(p_locale_dtor, &lcl);
|
||||
|
||||
call_func1(p_basic_stringstream_char_vbase_dtor, &ss);
|
||||
call_func1(p_basic_string_char_dtor, &str);
|
||||
|
||||
/* wchar_t version */
|
||||
AtoW(wide, tests[i].str, strlen(tests[i].str));
|
||||
call_func2(p_basic_string_wchar_ctor_cstr, &wstr, wide);
|
||||
call_func4(p_basic_stringstream_wchar_ctor_str, &wss, &wstr, OPENMODE_out|OPENMODE_in, TRUE);
|
||||
|
||||
if(tests[i].lcl) {
|
||||
call_func3(p_locale_ctor_cstr, &lcl, tests[i].lcl, 0x3f /* FIXME: support categories */);
|
||||
call_func3(p_basic_ios_wchar_imbue, &wss.basic_ios, &retlcl, &lcl);
|
||||
}
|
||||
|
||||
val = 42.0;
|
||||
call_func2(p_basic_istream_wchar_read_double, &wss.base.base1, &val);
|
||||
state = (IOSB_iostate)call_func1(p_ios_base_rdstate, &wss.basic_ios.base);
|
||||
nextus = (unsigned short)(int)call_func1(p_basic_istream_wchar_get, &wss.base.base1);
|
||||
|
||||
if(strlen(tests[i].str) == 0) {
|
||||
/* a later patch to istream<>::_Ipfx will handle empty string */
|
||||
todo_wine ok(tests[i].state == state, "wrong state, expected = %x found = %x\n", tests[i].state, state);
|
||||
} else
|
||||
ok(tests[i].state == state, "wrong state, expected = %x found = %x\n", tests[i].state, state);
|
||||
ok(tests[i].val == val, "wrong val, expected = %g found %g\n", tests[i].val, val);
|
||||
testus = tests[i].next == EOF ? WEOF : (unsigned short)tests[i].next;
|
||||
ok(testus == nextus, "wrong next, expected = %c (%i) found = %c (%i)\n", testus, testus, nextus, nextus);
|
||||
|
||||
if(tests[i].lcl)
|
||||
call_func1(p_locale_dtor, &lcl);
|
||||
|
||||
call_func1(p_basic_stringstream_wchar_vbase_dtor, &wss);
|
||||
call_func1(p_basic_string_wchar_dtor, &wstr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
START_TEST(ios)
|
||||
{
|
||||
if(!init())
|
||||
return;
|
||||
|
||||
test_num_get_get_uint64();
|
||||
test_num_get_get_double();
|
||||
|
||||
ok(!invalid_parameter, "invalid_parameter_handler was invoked too many times\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue