re PR libstdc++/9548 (Incorrect results from setf(ios::fixed) and precision(-1) [DR231])

2003-02-06  Paolo Carlini  <pcarlini@unitus.it>

	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.

From-SVN: r62492
This commit is contained in:
Paolo Carlini 2003-02-06 19:08:51 +01:00 committed by Paolo Carlini
parent a1ba6e15ea
commit 5dc911525c
6 changed files with 148 additions and 31 deletions

View File

@ -1,3 +1,16 @@
2003-02-06 Paolo Carlini <pcarlini@unitus.it>
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 <peter.soetens@mech.kuleuven.ac.be>
* config/io/basic_file_libio.h: Fixups.

View File

@ -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

View File

@ -634,6 +634,9 @@ namespace std
if (__prec > static_cast<streamsize>(__max_digits))
__prec = static_cast<streamsize>(__max_digits);
else if (__prec < static_cast<streamsize>(0))
// Default precision.
__prec = static_cast<streamsize>(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<char*>(__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<char*>(__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<char*>(__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);
}

View File

@ -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

View File

@ -0,0 +1,56 @@
// 2003-02-05 Paolo Carlini <pcarlini@unitus.it>
// 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 <locale>
#include <sstream>
#include <testsuite_hooks.h>
// libstdc++/9548 and DR 231
void test01()
{
using namespace std;
bool test = true;
ostringstream oss1, oss2;
const num_put<char>& np1 = use_facet<num_put<char> >(oss1.getloc());
const num_put<char>& np2 = use_facet<num_put<char> >(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;
}

View File

@ -0,0 +1,56 @@
// 2003-02-05 Paolo Carlini <pcarlini@unitus.it>
// 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 <locale>
#include <sstream>
#include <testsuite_hooks.h>
// libstdc++/9548 and DR 231
void test01()
{
using namespace std;
bool test = true;
wostringstream woss1, woss2;
const num_put<wchar_t>& np1 = use_facet<num_put<wchar_t> >(woss1.getloc());
const num_put<wchar_t>& np2 = use_facet<num_put<wchar_t> >(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;
}