From f30208dc296fff25eaca7377749c55c5ddfba6e4 Mon Sep 17 00:00:00 2001 From: paolo Date: Thu, 6 Feb 2003 18:08:51 +0000 Subject: [PATCH] 2003-02-06 Paolo Carlini PR libstdc++/9548 Implement resolution of DR 231 (Ready) * include/bits/locale_facets.h (__num_base::_S_format_float): Change declaration: return void, remove __prec parameter. * src/locale.cc (__num_base::_S_format_float): Implement resolution of DR 231. * include/bits/locale_facets.tcc (num_put::_M_convert_float): Tweak uses. Check for negative precision. * testsuite/22_locale/num_put/put/char/6.cc: Add * testsuite/22_locale/num_put/put/wchar_t/6.cc: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@62492 138bc75d-0d04-0410-961f-82ee72b054a4 --- libstdc++-v3/ChangeLog | 13 +++++ libstdc++-v3/include/bits/locale_facets.h | 5 +- libstdc++-v3/include/bits/locale_facets.tcc | 26 ++++------ libstdc++-v3/src/locale.cc | 23 +++++---- .../testsuite/22_locale/num_put/put/char/6.cc | 56 ++++++++++++++++++++++ .../testsuite/22_locale/num_put/put/wchar_t/6.cc | 56 ++++++++++++++++++++++ 6 files changed, 148 insertions(+), 31 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/num_put/put/char/6.cc create mode 100644 libstdc++-v3/testsuite/22_locale/num_put/put/wchar_t/6.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0dc7487e9a0..716943f133d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2003-02-06 Paolo Carlini + + PR libstdc++/9548 + Implement resolution of DR 231 (Ready) + * include/bits/locale_facets.h (__num_base::_S_format_float): + Change declaration: return void, remove __prec parameter. + * src/locale.cc (__num_base::_S_format_float): Implement + resolution of DR 231. + * include/bits/locale_facets.tcc (num_put::_M_convert_float): + Tweak uses. Check for negative precision. + * testsuite/22_locale/num_put/put/char/6.cc: Add + * testsuite/22_locale/num_put/put/wchar_t/6.cc: Likewise. + 2003-02-06 Peter Soetens * config/io/basic_file_libio.h: Fixups. diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index a2a043c3a8d..59f9d5bb530 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -546,9 +546,8 @@ namespace std // num_put // Construct and return valid scanf format for floating point types. - static bool - _S_format_float(const ios_base& __io, char* __fptr, char __mod, - streamsize __prec); + static void + _S_format_float(const ios_base& __io, char* __fptr, char __mod); // Construct and return valid scanf format for integer types. static void diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index e6e9fbe8697..a30404c0341 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -634,6 +634,9 @@ namespace std if (__prec > static_cast(__max_digits)) __prec = static_cast(__max_digits); + else if (__prec < static_cast(0)) + // Default precision. + __prec = static_cast(6); // Long enough for the max format spec. char __fbuf[16]; @@ -646,24 +649,17 @@ namespace std int __cs_size = __max_digits * 3; char* __cs = static_cast(__builtin_alloca(__cs_size)); - const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); - if (__fp) - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); + _S_format_float(__io, __fbuf, __mod); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); // If the buffer was not large enough, try again with the correct size. if (__len >= __cs_size) { __cs_size = __len + 1; __cs = static_cast(__builtin_alloca(__cs_size)); - if (__fp) - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); } #else // Consider the possibility of long ios_base::fixed outputs @@ -678,10 +674,8 @@ namespace std : __max_digits * 3; char* __cs = static_cast(__builtin_alloca(__cs_size)); - if (_S_format_float(__io, __fbuf, __mod, __prec)) - __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); + _S_format_float(__io, __fbuf, __mod); + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); #endif return _M_widen_float(__s, __io, __fill, __cs, __len); } diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 42972e9de40..4e90f37eac6 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -505,11 +505,12 @@ namespace std const char __num_base::_S_atoms[] = "0123456789eEabcdfABCDF"; - bool - __num_base::_S_format_float(const ios_base& __io, char* __fptr, char __mod, - streamsize __prec) + // _GLIBCPP_RESOLVE_LIB_DEFECTS + // According to the resolution of DR 231, about 22.2.2.2.2, p11, + // "str.precision() is specified in the conversion specification". + void + __num_base::_S_format_float(const ios_base& __io, char* __fptr, char __mod) { - bool __incl_prec = false; ios_base::fmtflags __flags = __io.flags(); *__fptr++ = '%'; // [22.2.2.2.2] Table 60 @@ -517,13 +518,12 @@ namespace std *__fptr++ = '+'; if (__flags & ios_base::showpoint) *__fptr++ = '#'; - // As per [22.2.2.2.2.11] - if (__flags & ios_base::fixed || __prec > 0) - { - *__fptr++ = '.'; - *__fptr++ = '*'; - __incl_prec = true; - } + + // As per DR 231: _always_, not only when + // __flags & ios_base::fixed || __prec > 0 + *__fptr++ = '.'; + *__fptr++ = '*'; + if (__mod) *__fptr++ = __mod; ios_base::fmtflags __fltfield = __flags & ios_base::floatfield; @@ -535,7 +535,6 @@ namespace std else *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g'; *__fptr = '\0'; - return __incl_prec; } void diff --git a/libstdc++-v3/testsuite/22_locale/num_put/put/char/6.cc b/libstdc++-v3/testsuite/22_locale/num_put/put/char/6.cc new file mode 100644 index 00000000000..3cc550710bb --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_put/put/char/6.cc @@ -0,0 +1,56 @@ +// 2003-02-05 Paolo Carlini + +// Copyright (C) 2003 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.2.2.1 num_put members + +#include +#include +#include + +// libstdc++/9548 and DR 231 +void test01() +{ + using namespace std; + bool test = true; + + ostringstream oss1, oss2; + const num_put& np1 = use_facet >(oss1.getloc()); + const num_put& np2 = use_facet >(oss2.getloc()); + + string result1, result2; + + oss1.precision(-1); + oss1.setf(ios_base::fixed, ios_base::floatfield); + np1.put(oss1.rdbuf(), oss1, '+', 30.5); + result1 = oss1.str(); + VERIFY( result1 == "30.500000" ); + + oss2.precision(0); + oss2.setf(ios_base::scientific, ios_base::floatfield); + np2.put(oss2.rdbuf(), oss2, '+', 1.0); + result2 = oss2.str(); + VERIFY( result2 == "1e+00" ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/num_put/put/wchar_t/6.cc b/libstdc++-v3/testsuite/22_locale/num_put/put/wchar_t/6.cc new file mode 100644 index 00000000000..01733603cfc --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_put/put/wchar_t/6.cc @@ -0,0 +1,56 @@ +// 2003-02-05 Paolo Carlini + +// Copyright (C) 2003 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.2.2.1 num_put members + +#include +#include +#include + +// libstdc++/9548 and DR 231 +void test01() +{ + using namespace std; + bool test = true; + + wostringstream woss1, woss2; + const num_put& np1 = use_facet >(woss1.getloc()); + const num_put& np2 = use_facet >(woss2.getloc()); + + wstring result1, result2; + + woss1.precision(-1); + woss1.setf(ios_base::fixed, ios_base::floatfield); + np1.put(woss1.rdbuf(), woss1, '+', 30.5); + result1 = woss1.str(); + VERIFY( result1 == L"30.500000" ); + + woss2.precision(0); + woss2.setf(ios_base::scientific, ios_base::floatfield); + np2.put(woss2.rdbuf(), woss2, '+', 1.0); + result2 = woss2.str(); + VERIFY( result2 == L"1e+00" ); +} + +int main() +{ + test01(); + return 0; +} -- 2.11.0