diff options
author | Benjamin Kosnik <bkoz@gcc.gnu.org> | 2001-12-05 22:07:36 +0000 |
---|---|---|
committer | Benjamin Kosnik <bkoz@gcc.gnu.org> | 2001-12-05 22:07:36 +0000 |
commit | 0228de0c4f91cb2cc0381f2f2c403caab6e7d82e (patch) | |
tree | 434f9b1969290c6575921690cf5ef445f97d33ae | |
parent | 0df47f6610ae1ad8b7b3372da8bff6e59230b901 (diff) | |
download | gcc-0228de0c4f91cb2cc0381f2f2c403caab6e7d82e.zip gcc-0228de0c4f91cb2cc0381f2f2c403caab6e7d82e.tar.gz gcc-0228de0c4f91cb2cc0381f2f2c403caab6e7d82e.tar.bz2 |
[multiple changes]
2001-12-05 Benjamin Kosnik <bkoz@redhat.com>
DR/282
* include/bits/locale_facets.tcc (num_put::_M_widen_float): Add
grouping to floating point types.
* testsuite/27_io/ostream_inserter_arith.cc (test02): Add test.
2001-12-04 Paolo Carlini <pcarlini@unitus.it>
libstdc++/4402
* testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase
from the PR.
* include/bits/locale_facets.tcc (num_put::_M_convert_float):
Deal properly with long ios_base::fixed floats.
(num_put::_M_widen_float): use
__len in __builtin_alloca call.
From-SVN: r47696
-rw-r--r-- | libstdc++-v3/ChangeLog | 17 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/locale_facets.tcc | 66 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc | 23 |
3 files changed, 96 insertions, 10 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 84f842f..08d0eb8 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2001-12-05 Benjamin Kosnik <bkoz@redhat.com> + + DR/282 + * include/bits/locale_facets.tcc (num_put::_M_widen_float): Add + grouping to floating point types. + * testsuite/27_io/ostream_inserter_arith.cc (test02): Add test. + +2001-12-04 Paolo Carlini <pcarlini@unitus.it> + + libstdc++/4402 + * testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase + from the PR. + * include/bits/locale_facets.tcc (num_put::_M_convert_float): + Deal properly with long ios_base::fixed floats. + (num_put::_M_widen_float): use + __len in __builtin_alloca call. + 2001-12-04 Benjamin Kosnik <bkoz@redhat.com> * src/Makefile.am (sources): Add ext-inst.cc. diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 835a0ae..95cbee5 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -711,15 +711,23 @@ namespace std _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, _ValueT __v) const { - const streamsize __max_prec = numeric_limits<_ValueT>::digits10; + const int __max_digits = numeric_limits<_ValueT>::digits10; streamsize __prec = __io.precision(); // Protect against sprintf() buffer overflows. - if (__prec > __max_prec) - __prec = __max_prec; + if (__prec > static_cast<streamsize>(__max_digits)) + __prec = static_cast<streamsize>(__max_digits); // Long enough for the max format spec. char __fbuf[16]; - char __cs[64]; + + // Consider the possibility of long ios_base::fixed outputs + const bool __fixed = __io.flags() & ios_base::fixed; + const int __max_exp = numeric_limits<_ValueT>::max_exponent10; + // XXX Why + 4? Why * 4? What's going on? Who's on first? + const int __cs_size = __fixed ? __max_exp + __max_digits + 4 + : __max_digits * 4; + char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); + int __len; // [22.2.2.2.2] Stage 1, numeric conversion to character. if (_S_format_float(__io, __fbuf, __mod, __prec)) @@ -757,14 +765,47 @@ namespace std // numpunct.decimal_point() values for '.' and adding grouping. const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + // Grouping can add (almost) as many separators as the number of + // digits, but no more. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); __ctype.widen(__cs, __cs + __len, __ws); - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); // Replace decimal point. const _CharT* __p; + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.'))) __ws[__p - __ws] = __np.decimal_point(); + +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS +//282. What types does numpunct grouping refer to? + // Add grouping, if necessary. + const string __grouping = __np.grouping(); + ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; + if (__grouping.size()) + { + _CharT* __p2; + int __declen = __p ? __p - __ws : __len; + __p2 = __add_grouping(__ws2, __np.thousands_sep(), + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __ws, __ws + __declen); + int __newlen = __p2 - __ws2; + + // Tack on decimal part. + if (__p) + { + char_traits<_CharT>::copy(__p2, __p, __len - __declen); + __newlen += __len - __declen; + } + + // Switch strings, establish correct new length. + __ws = __ws2; + __len = __newlen; + } +#endif return _M_insert(__s, __io, __fill, __ws, __len); } @@ -778,13 +819,17 @@ namespace std // numpunct.decimal_point() values for '.' and adding grouping. const locale __loc = __io.getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + // Grouping can add (almost) as many separators as the number of + // digits, but no more. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); __ctype.widen(__cs, __cs + __len, __ws); // Add grouping, if necessary. const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); - string __grouping = __np.grouping(); + const string __grouping = __np.grouping(); ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; bool __dec = __basefield != ios_base::oct && __basefield != ios_base::hex; @@ -810,8 +855,9 @@ namespace std int __len) const { // [22.2.2.2.2] Stage 3. - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); streamsize __w = __io.width(); + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); if (__w > static_cast<streamsize>(__len)) { __pad(__io, __fill, __ws2, __ws, __w, __len, true); diff --git a/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc b/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc index 2e57922..580730b 100644 --- a/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc +++ b/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc @@ -272,6 +272,29 @@ test02() #endif VERIFY(os && os.str() == largebuf); + // Make sure we can output a long float in fixed format + // without seg-faulting (libstdc++/4402) + double val2 = 3.5e230; + + ostringstream os2; + os2.precision(3); + os2.setf(ios::fixed); + os2 << val2; + + sprintf(largebuf, "%.*f", 3, val2); +#ifdef TEST_NUMPUT_VERBOSE + cout << "expect: " << largebuf << endl; + cout << "result: " << os2.str() << endl; +#endif + VERIFY(os2 && os2.str() == largebuf); + + // Check it can be done in a locale with grouping on. + locale loc2("de_DE"); + os2.imbue(loc2); + os2 << fixed << setprecision(3) << val2 << endl; + os2 << endl; + os2 << fixed << setprecision(1) << val2 << endl; + return 0; } |