From: Benjamin Kosnik Date: Wed, 5 Dec 2001 22:07:36 +0000 (+0000) Subject: [multiple changes] X-Git-Tag: prereleases/libstdc++-3.0.95~431 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0228de0c4f91cb2cc0381f2f2c403caab6e7d82e;p=thirdparty%2Fgcc.git [multiple changes] 2001-12-05 Benjamin Kosnik 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 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 84f842f2c4a7..08d0eb8cf184 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2001-12-05 Benjamin Kosnik + + 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 + + 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 * 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 835a0ae62a63..95cbee5d8f14 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(__max_digits)) + __prec = static_cast(__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(__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 >(__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 >(__loc); // Replace decimal point. const _CharT* __p; + const numpunct<_CharT>& __np = use_facet >(__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 >(__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 >(__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(__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 2e57922b1e9c..580730b42cd9 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; }