locale_facets.tcc (num_get<>::_M_extract_float): Evaluate *__beg the exact strict minimum number of times...

2004-11-01  Paolo Carlini  <pcarlini@suse.de>

	* include/bits/locale_facets.tcc (num_get<>::_M_extract_float):
	Evaluate *__beg the exact strict minimum number of times; likewise
	for __beg != __end; in the main parsing loop, call ++__beg in two
	places only. The former is also a correctness issue, because,
	according to the standard (22.2.2.1.2, Stage 2), 'in' shall be
	dereferenced only one time for each increment.

From-SVN: r89940
This commit is contained in:
Paolo Carlini 2004-11-01 11:31:44 +00:00 committed by Paolo Carlini
parent c4f731746a
commit 8dc5fa3267
2 changed files with 67 additions and 47 deletions

View File

@ -1,3 +1,12 @@
2004-11-01 Paolo Carlini <pcarlini@suse.de>
* include/bits/locale_facets.tcc (num_get<>::_M_extract_float):
Evaluate *__beg the exact strict minimum number of times; likewise
for __beg != __end; in the main parsing loop, call ++__beg in two
places only. The former is also a correctness issue, because,
according to the standard (22.2.2.1.2, Stage 2), 'in' shall be
dereferenced only one time for each increment.
2004-10-31 Benjamin Kosnik <bkoz@redhat.com> 2004-10-31 Benjamin Kosnik <bkoz@redhat.com>
PR c++/16728 PR c++/16728

View File

@ -279,28 +279,34 @@ namespace std
const locale& __loc = __io._M_getloc(); const locale& __loc = __io._M_getloc();
const __cache_type* __lc = __uc(__loc); const __cache_type* __lc = __uc(__loc);
const _CharT* __lit = __lc->_M_atoms_in; const _CharT* __lit = __lc->_M_atoms_in;
char_type __c = char_type();
// True if a mantissa is found. // True if __beg becomes equal to __end.
bool __found_mantissa = false; bool __testeof = __beg == __end;
// First check for sign. // First check for sign.
if (__beg != __end) if (!__testeof)
{ {
const char_type __c = *__beg; __c = *__beg;
const bool __plus = __c == __lit[__num_base::_S_iplus]; const bool __plus = __c == __lit[__num_base::_S_iplus];
if ((__plus || __c == __lit[__num_base::_S_iminus]) if ((__plus || __c == __lit[__num_base::_S_iminus])
&& !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
&& !(__c == __lc->_M_decimal_point)) && !(__c == __lc->_M_decimal_point))
{ {
__xtrc += __plus ? '+' : '-'; __xtrc += __plus ? '+' : '-';
++__beg; if (++__beg != __end)
__c = *__beg;
else
__testeof = true;
} }
} }
// True if a mantissa is found.
bool __found_mantissa = false;
// Next, look for leading zeros. // Next, look for leading zeros.
while (__beg != __end) while (!__testeof)
{ {
const char_type __c = *__beg;
if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
|| __c == __lc->_M_decimal_point) || __c == __lc->_M_decimal_point)
break; break;
@ -311,7 +317,10 @@ namespace std
__xtrc += '0'; __xtrc += '0';
__found_mantissa = true; __found_mantissa = true;
} }
++__beg; if (++__beg != __end)
__c = *__beg;
else
__testeof = true;
} }
else else
break; break;
@ -324,12 +333,12 @@ namespace std
if (__lc->_M_use_grouping) if (__lc->_M_use_grouping)
__found_grouping.reserve(32); __found_grouping.reserve(32);
int __sep_pos = 0; int __sep_pos = 0;
const char_type* __q;
const char_type* __lit_zero = __lit + __num_base::_S_izero; const char_type* __lit_zero = __lit + __num_base::_S_izero;
while (__beg != __end) while (!__testeof)
{ {
// According to 22.2.2.1.2, p8-9, first look for thousands_sep // According to 22.2.2.1.2, p8-9, first look for thousands_sep
// and decimal_point. // and decimal_point.
char_type __c = *__beg;
if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
{ {
if (!__found_dec && !__found_sci) if (!__found_dec && !__found_sci)
@ -340,7 +349,6 @@ namespace std
{ {
__found_grouping += static_cast<char>(__sep_pos); __found_grouping += static_cast<char>(__sep_pos);
__sep_pos = 0; __sep_pos = 0;
++__beg;
} }
else else
{ {
@ -362,50 +370,53 @@ namespace std
__found_grouping += static_cast<char>(__sep_pos); __found_grouping += static_cast<char>(__sep_pos);
__xtrc += '.'; __xtrc += '.';
__found_dec = true; __found_dec = true;
++__beg;
} }
else else
break; break;
} }
else else if ((__q = __traits_type::find(__lit_zero, 10, __c)))
{ {
const char_type* __q = __traits_type::find(__lit_zero, 10, __c); __xtrc += __num_base::_S_atoms_in[__q - __lit];
if (__q) __found_mantissa = true;
{ ++__sep_pos;
__xtrc += __num_base::_S_atoms_in[__q - __lit]; }
__found_mantissa = true; else if ((__c == __lit[__num_base::_S_ie]
++__sep_pos; || __c == __lit[__num_base::_S_iE])
++__beg; && __found_mantissa && !__found_sci)
} {
else if ((__c == __lit[__num_base::_S_ie] // Scientific notation.
|| __c == __lit[__num_base::_S_iE]) if (__found_grouping.size() && !__found_dec)
&& __found_mantissa && !__found_sci) __found_grouping += static_cast<char>(__sep_pos);
{ __xtrc += 'e';
// Scientific notation. __found_sci = true;
if (__found_grouping.size() && !__found_dec)
__found_grouping += static_cast<char>(__sep_pos);
__xtrc += 'e';
__found_sci = true;
// Remove optional plus or minus sign, if they exist. // Remove optional plus or minus sign, if they exist.
if (++__beg != __end) if (++__beg != __end)
{ {
__c = *__beg; __c = *__beg;
const bool __plus = __c == __lit[__num_base::_S_iplus]; const bool __plus = __c == __lit[__num_base::_S_iplus];
if ((__plus || __c == __lit[__num_base::_S_iminus]) if ((__plus || __c == __lit[__num_base::_S_iminus])
&& !(__lc->_M_use_grouping && !(__lc->_M_use_grouping
&& __c == __lc->_M_thousands_sep) && __c == __lc->_M_thousands_sep)
&& !(__c == __lc->_M_decimal_point)) && !(__c == __lc->_M_decimal_point))
{ __xtrc += __plus ? '+' : '-';
__xtrc += __plus ? '+' : '-'; else
++__beg; continue;
}
}
} }
else else
// Not a valid input item. {
break; __testeof = true;
break;
}
} }
else
// Not a valid input item.
break;
if (++__beg != __end)
__c = *__beg;
else
__testeof = true;
} }
// Digit grouping is checked. If grouping and found_grouping don't // Digit grouping is checked. If grouping and found_grouping don't
@ -423,7 +434,7 @@ namespace std
} }
// Finish up. // Finish up.
if (__beg == __end) if (__testeof)
__err |= ios_base::eofbit; __err |= ios_base::eofbit;
return __beg; return __beg;
} }