Commit 86ade44c by Benjamin Kosnik Committed by Benjamin Kosnik

Numeric facets cleanup.


2001-11-27  Benjamin Kosnik  <bkoz@redhat.com>

	Numeric facets cleanup.
	* include/bits/locale_facets.h (__num_base::_S_atoms): Add, remove
	+ and - signs.
	(__num_base::_M_zero): Add
	(__num_base::_M_e): Add.
	(__num_base::_M_E): Add.
	* include/bits/locale_facets.tcc (num_get::_M_extract): Remove.
	(num_get::_M_extract_float): New.
	(num_get::_M_extract_int): New.
	* src/locale.cc (num_get::_M_extract): Remove.

	* include/bits/locale_facets.tcc (num_put::_M_insert_float):
	Simplify, use _M_insert.
	(num_put::do_put(bool)): Simplify, remove __pad.
	(__pad): Remove.
	(__pad_output): Change to __pad.
	* include/bits/ostream.tcc: And here.
	* src/locale-inst: Remove instantiations.

	* include/bits/locale_facets.h: Move helper functions in to class
	num_put.
	(num_put::_M_insert_float): Same, for __output_integer.
	(num_put::_M_insert_int): Same, for __output_float.
	(num_put::_M_insert): New.
	(__num_base): Add.
	(__num_base::_S_format_float): Move
	__build_float_format into class __num_base.
	(__num_base::_S_format_int): Move __build_int_format into class
	__num_base.
	* include/bits/locale_facets.tcc (__group_digits): Change to
	(__add_grouping): This.
	* src/locale-inst.cc: And here. Tweak instantiations.
	* src/misc-inst.cc: Remove instantiations.

	* include/bits/ostream.tcc (__pad_char): Rename, adjust inserters
	for new calling conventions, move to...
	* include/bits/locale_facets.tcc (__pad_output): Here. Adjust
	signature to make it useful for both ostream and num_put.
	(__pad_numeric): Remove.
	* src/misc-inst.cc: Remove instantiations.
	* src/locale-inst.cc: Same.

	* include/bits/locale_facets.h (_Numeric_get): Remove.
 	(_Numeric_put): Remove.
	(num_get::get(short)): Remove.
	(num_get::get(int)): Remove.
	(num_get::do_get(short)): Remove.
	(num_get::do_get(int)): Remove.
	* include/bits/istream.tcc (istream::operator>>(short)): Fix as
	per DR 118.
	(istream::operator>>(int)): Same.

	* include/bits/locale_facets.h (_Format_cache): Remove.
	* include/bits/locale_facets.tcc: Same.
	* src/locale.cc: Same.
	* src/locale-inst.cc: Same.
	* include/bits/ostream.tcc: Same.
	* src/ios.cc (ios_base::imbue): Remove here as well.

	* testsuite/22_locale/num_get.cc: New file.
	* testsuite/22_locale/num_get_members_char.cc: New file.
	* testsuite/22_locale/num_get_members_wchar_t.cc: New.
	* testsuite/22_locale/numpunct_members_wchar_t.cc: New file.
	* testsuite/22_locale/num_put.cc: New file.
	* testsuite/22_locale/num_put_members_char.cc: New file.
	* testsuite/22_locale/num_put_members_wchar_t.cc: New file.
	* testsuite/27_io/ostream_inserter_arith.cc: Fix.
	* testsuite/27_io/istream_extractor_arith.cc: Fix.

From-SVN: r47397
parent 59a64a46
2001-11-27 Benjamin Kosnik <bkoz@redhat.com>
Numeric facets cleanup.
* include/bits/locale_facets.h (__num_base::_S_atoms): Add, remove
+ and - signs.
(__num_base::_M_zero): Add
(__num_base::_M_e): Add.
(__num_base::_M_E): Add.
* include/bits/locale_facets.tcc (num_get::_M_extract): Remove.
(num_get::_M_extract_float): New.
(num_get::_M_extract_int): New.
* src/locale.cc (num_get::_M_extract): Remove.
* include/bits/locale_facets.tcc (num_put::_M_insert_float):
Simplify, use _M_insert.
(num_put::do_put(bool)): Simplify, remove __pad.
(__pad): Remove.
(__pad_output): Change to __pad.
* include/bits/ostream.tcc: And here.
* src/locale-inst: Remove instantiations.
* include/bits/locale_facets.h: Move helper functions in to class
num_put.
(num_put::_M_insert_float): Same, for __output_integer.
(num_put::_M_insert_int): Same, for __output_float.
(num_put::_M_insert): New.
(__num_base): Add.
(__num_base::_S_format_float): Move
__build_float_format into class __num_base.
(__num_base::_S_format_int): Move __build_int_format into class
__num_base.
* include/bits/locale_facets.tcc (__group_digits): Change to
(__add_grouping): This.
* src/locale-inst.cc: And here. Tweak instantiations.
* src/misc-inst.cc: Remove instantiations.
* include/bits/ostream.tcc (__pad_char): Rename, adjust inserters
for new calling conventions, move to...
* include/bits/locale_facets.tcc (__pad_output): Here. Adjust
signature to make it useful for both ostream and num_put.
(__pad_numeric): Remove.
* src/misc-inst.cc: Remove instantiations.
* src/locale-inst.cc: Same.
* include/bits/locale_facets.h (_Numeric_get): Remove.
(_Numeric_put): Remove.
(num_get::get(short)): Remove.
(num_get::get(int)): Remove.
(num_get::do_get(short)): Remove.
(num_get::do_get(int)): Remove.
* include/bits/istream.tcc (istream::operator>>(short)): Fix as
per DR 118.
(istream::operator>>(int)): Same.
* include/bits/locale_facets.h (_Format_cache): Remove.
* include/bits/locale_facets.tcc: Same.
* src/locale.cc: Same.
* src/locale-inst.cc: Same.
* include/bits/ostream.tcc: Same.
* src/ios.cc (ios_base::imbue): Remove here as well.
* testsuite/22_locale/num_get.cc: New file.
* testsuite/22_locale/num_get_members_char.cc: New file.
* testsuite/22_locale/num_get_members_wchar_t.cc: New.
* testsuite/22_locale/numpunct_members_wchar_t.cc: New file.
* testsuite/22_locale/num_put.cc: New file.
* testsuite/22_locale/num_put_members_char.cc: New file.
* testsuite/22_locale/num_put_members_wchar_t.cc: New file.
* testsuite/27_io/ostream_inserter_arith.cc: Fix.
* testsuite/27_io/istream_extractor_arith.cc: Fix.
2001-11-27 Phil Edwards <pme@gcc.gnu.org> 2001-11-27 Phil Edwards <pme@gcc.gnu.org>
* docs/html/explanations.html: New section, empty for now. * docs/html/explanations.html: New section, empty for now.
......
...@@ -134,8 +134,18 @@ namespace std ...@@ -134,8 +134,18 @@ namespace std
try try
{ {
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
long __l;
if (_M_check_facet(_M_fnumget)) if (_M_check_facet(_M_fnumget))
_M_fnumget->get(*this, 0, *this, __err, __n); _M_fnumget->get(*this, 0, *this, __err, __l);
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// 118. basic_istream uses nonexistent num_get member functions.
if (!(__err & ios_base::failbit)
&& (numeric_limits<short>::min() <= __l
&& __l <= numeric_limits<short>::max()))
__n = __l;
else
__err |= ios_base::failbit;
#endif
this->setstate(__err); this->setstate(__err);
} }
catch(exception& __fail) catch(exception& __fail)
...@@ -188,8 +198,18 @@ namespace std ...@@ -188,8 +198,18 @@ namespace std
try try
{ {
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
long __l;
if (_M_check_facet(_M_fnumget)) if (_M_check_facet(_M_fnumget))
_M_fnumget->get(*this, 0, *this, __err, __n); _M_fnumget->get(*this, 0, *this, __err, __l);
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// 118. basic_istream uses nonexistent num_get member functions.
if (!(__err & ios_base::failbit)
&& (numeric_limits<int>::min() <= __l
&& __l <= numeric_limits<int>::max()))
__n = __l;
else
__err |= ios_base::failbit;
#endif
this->setstate(__err); this->setstate(__err);
} }
catch(exception& __fail) catch(exception& __fail)
...@@ -1252,4 +1272,3 @@ namespace std ...@@ -1252,4 +1272,3 @@ namespace std
// Local Variables: // Local Variables:
// mode:C++ // mode:C++
// End: // End:
...@@ -415,162 +415,157 @@ namespace std ...@@ -415,162 +415,157 @@ namespace std
// 22.2.1.5 Template class codecvt // 22.2.1.5 Template class codecvt
#include <bits/codecvt.h> #include <bits/codecvt.h>
template<typename _CharT, typename _InIter>
class _Numeric_get; // forward
// _Format_cache holds the information extracted from the numpunct<> class __num_base
// and moneypunct<> facets in a form optimized for parsing and {
// formatting. It is stored via a void* pointer in the pword() public:
// array of an iosbase object passed to the _get and _put facets. // String literal of acceptable (narrow) input, for num_get.
// NB: contains no user-serviceable parts. // "0123456789eEabcdfxABCDFX"
static const char _S_atoms[];
enum
{
_M_zero,
_M_e = _M_zero + 10,
_M_E = _M_zero + 11,
_M_size = 23 + 1
};
// 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);
// Construct and return valid scanf format for integer types.
static void
_S_format_int(const ios_base& __io, char* __fptr, char __mod, char __modl);
};
template<typename _CharT> template<typename _CharT>
class _Format_cache class numpunct : public locale::facet
{ {
public: public:
// Types: // Types:
typedef _CharT char_type; typedef _CharT char_type;
typedef char_traits<_CharT> traits_type; typedef basic_string<_CharT> string_type;
typedef basic_string<_CharT> string_type;
typedef typename string_type::size_type size_type;
// Forward decls and Friends:
friend class locale;
template<typename _Char, typename _InIter>
friend class _Numeric_get;
friend class num_get<_CharT>;
friend class num_put<_CharT>;
friend class time_get<_CharT>;
friend class money_get<_CharT>;
friend class time_put<_CharT>;
friend class money_put<_CharT>;
// Data Members: static locale::id id;
// ios_base::pword() reserved cell private:
static int _S_pword_ix; char_type _M_decimal_point;
char_type _M_thousands_sep;
// True iff data members are consistent with the current locale, string _M_grouping;
// ie imbue sets this to false. string_type _M_truename;
bool _M_valid; string_type _M_falsename;
// A list of valid numeric literals: for the standard "C" locale,
// this would usually be: "-+xX0123456789abcdef0123456789ABCDEF"
static const char _S_literals[];
// NB: Code depends on the order of definitions of the names
// these are indices into _S_literals, above.
// This string is formatted for putting, not getting. (output, not input)
enum
{
_S_minus,
_S_plus,
_S_x,
_S_X,
_S_digits,
_S_digits_end = _S_digits + 16,
_S_udigits = _S_digits_end,
_S_udigits_end = _S_udigits + 16,
_S_ee = _S_digits + 14, // For scientific notation, 'E'
_S_Ee = _S_udigits + 14 // For scientific notation, 'e'
};
// The sign used to separate decimal values: for standard US
// locales, this would usually be: "."
// Abstracted from numpunct::decimal_point().
char_type _M_decimal_point;
// The sign used to separate groups of digits into smaller
// strings that the eye can parse with less difficulty: for
// standard US locales, this would usually be: ","
// Abstracted from numpunct::thousands_sep().
char_type _M_thousands_sep;
// However the US's "false" and "true" are translated.
// From numpunct::truename() and numpunct::falsename(), respectively.
string_type _M_truename;
string_type _M_falsename;
// If we are checking groupings. This should be equivalent to
// numpunct::groupings().size() != 0
bool _M_use_grouping;
// If we are using numpunct's groupings, this is the current
// grouping string in effect (from numpunct::grouping()).
string _M_grouping;
_Format_cache();
~_Format_cache() throw() { }
// Given a member of the ios hierarchy as an argument, extract
// out all the current formatting information into a
// _Format_cache object and return a pointer to it.
static _Format_cache<_CharT>*
_S_get(ios_base& __ios);
void public:
_M_populate(ios_base&); explicit
numpunct(size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(); }
explicit
numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(__cloc); }
char_type
decimal_point() const
{ return this->do_decimal_point(); }
char_type
thousands_sep() const
{ return this->do_thousands_sep(); }
string
grouping() const
{ return this->do_grouping(); }
string_type
truename() const
{ return this->do_truename(); }
string_type
falsename() const
{ return this->do_falsename(); }
protected:
virtual
~numpunct() { }
virtual char_type
do_decimal_point() const
{ return _M_decimal_point; }
static void virtual char_type
_S_callback(ios_base::event __event, ios_base& __ios, int __ix) throw(); do_thousands_sep() const
{ return _M_thousands_sep; }
virtual string
do_grouping() const
{ return _M_grouping; }
virtual string_type
do_truename() const
{ return _M_truename; }
virtual string_type
do_falsename() const
{ return _M_falsename; }
// For use at construction time only.
void
_M_initialize_numpunct(__c_locale __cloc = NULL);
}; };
template<typename _CharT> template<typename _CharT>
int _Format_cache<_CharT>::_S_pword_ix; locale::id numpunct<_CharT>::id;
// NB: Cannot be made generic.
template<typename _CharT> template<typename _CharT>
const char _Format_cache<_CharT>:: void
_S_literals[] = "-+xX0123456789abcdef0123456789ABCDEF"; numpunct<_CharT>::_M_initialize_numpunct(__c_locale)
{ }
template<> _Format_cache<char>::_Format_cache(); template<>
void
numpunct<char>::_M_initialize_numpunct(__c_locale __cloc);
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
template<> _Format_cache<wchar_t>::_Format_cache(); template<>
void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc);
#endif #endif
// _Numeric_get is used by num_get, money_get, and time_get to help template<typename _CharT>
// in parsing out numbers. class numpunct_byname : public numpunct<_CharT>
template<typename _CharT, typename _InIter>
class _Numeric_get
{ {
// Data Member.
__c_locale _M_c_locale_numpunct;
public: public:
// Types: typedef _CharT char_type;
typedef _CharT char_type; typedef basic_string<_CharT> string_type;
typedef _InIter iter_type;
// Forward decls and Friends:
template<typename _Char, typename _InIterT>
friend class num_get;
template<typename _Char, typename _InIterT>
friend class time_get;
template<typename _Char, typename _InIterT>
friend class money_get;
template<typename _Char, typename _InIterT>
friend class num_put;
template<typename _Char, typename _InIterT>
friend class time_put;
template<typename _Char, typename _InIterT>
friend class money_put;
private:
explicit explicit
_Numeric_get() { } numpunct_byname(const char* __s, size_t __refs = 0)
: numpunct<_CharT>(__refs)
{
_S_create_c_locale(_M_c_locale_numpunct, __s);
_M_initialize_numpunct(_M_c_locale_numpunct);
}
protected:
virtual virtual
~_Numeric_get() { } ~numpunct_byname()
{ _S_destroy_c_locale(_M_c_locale_numpunct); }
iter_type
_M_get_digits(iter_type __in, iter_type __end) const;
}; };
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
class num_get : public locale::facet class num_get : public locale::facet, public __num_base
{ {
public: public:
// Types: // Types:
typedef _CharT char_type; typedef _CharT char_type;
typedef _InIter iter_type; typedef _InIter iter_type;
typedef char_traits<_CharT> __traits_type;
static locale::id id; static locale::id id;
...@@ -580,118 +575,99 @@ namespace std ...@@ -580,118 +575,99 @@ namespace std
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, bool& __v) const ios_base::iostate& __err, bool& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
//XXX. What number?
iter_type
get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, short& __v) const
{ return do_get(__in, __end, __io, __err, __v); }
iter_type
get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, int& __v) const
{ return do_get(__in, __end, __io, __err, __v); }
#endif
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, long& __v) const ios_base::iostate& __err, long& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
#ifdef _GLIBCPP_USE_LONG_LONG
iter_type
get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, long long& __v) const
{ return do_get(__in, __end, __io, __err, __v); }
#endif
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, unsigned short& __v) const ios_base::iostate& __err, unsigned short& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, unsigned int& __v) const ios_base::iostate& __err, unsigned int& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, unsigned long& __v) const ios_base::iostate& __err, unsigned long& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
#ifdef _GLIBCPP_USE_LONG_LONG #ifdef _GLIBCPP_USE_LONG_LONG
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, long long& __v) const
{ return this->do_get(__in, __end, __io, __err, __v); }
iter_type
get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, unsigned long long& __v) const ios_base::iostate& __err, unsigned long long& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
#endif #endif
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, float& __v) const ios_base::iostate& __err, float& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, double& __v) const ios_base::iostate& __err, double& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, long double& __v) const ios_base::iostate& __err, long double& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
iter_type iter_type
get(iter_type __in, iter_type __end, ios_base& __io, get(iter_type __in, iter_type __end, ios_base& __io,
ios_base::iostate& __err, void*& __v) const ios_base::iostate& __err, void*& __v) const
{ return do_get(__in, __end, __io, __err, __v); } { return this->do_get(__in, __end, __io, __err, __v); }
protected: protected:
virtual ~num_get() { } virtual ~num_get() { }
// This consolidates the extraction, storage and
// error-processing parts of the do_get(...) overloaded member
// functions.
// NB: This is specialized for char.
void void
_M_extract(iter_type __beg, iter_type __end, ios_base& __io, _M_extract_float(iter_type, iter_type, ios_base&, ios_base::iostate&,
ios_base::iostate& __err, char* __xtrc, char* __xtrc) const;
int& __base, bool __fp = true) const;
void
_M_extract_int(iter_type, iter_type, ios_base&, ios_base::iostate&,
char* __xtrc, int& __base) const;
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, bool&) const; do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, bool&) const;
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
//XXX. What number?
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, short&) const; do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, long&) const;
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, int&) const; do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
#endif unsigned short&) const;
virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
unsigned int&) const;
virtual iter_type virtual iter_type
do_get (iter_type, iter_type, ios_base&, ios_base::iostate&, long&) const; do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
unsigned long&) const;
#ifdef _GLIBCPP_USE_LONG_LONG #ifdef _GLIBCPP_USE_LONG_LONG
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
long long&) const; long long&) const;
#endif
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
unsigned short&) const; unsigned long long&) const;
virtual iter_type
do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& __err, unsigned int&) const;
virtual iter_type
do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& __err, unsigned long&) const;
#ifdef _GLIBCPP_USE_LONG_LONG
virtual iter_type
do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& __err, unsigned long long&) const;
#endif #endif
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
float&) const; float&) const;
...@@ -701,8 +677,8 @@ namespace std ...@@ -701,8 +677,8 @@ namespace std
double&) const; double&) const;
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
ios_base::iostate& __err, long double&) const; long double&) const;
virtual iter_type virtual iter_type
do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err,
...@@ -712,38 +688,13 @@ namespace std ...@@ -712,38 +688,13 @@ namespace std
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
locale::id num_get<_CharT, _InIter>::id; locale::id num_get<_CharT, _InIter>::id;
// Declare specialized extraction member function.
template<>
void
num_get<char, istreambuf_iterator<char> >::
_M_extract(istreambuf_iterator<char> __beg,
istreambuf_iterator<char> __end, ios_base& __io,
ios_base::iostate& __err, char* __xtrc,
int& __base, bool __fp) const;
// _Numeric_put is used by num_put, money_put, and time_put
// to help in formatting out numbers.
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
class _Numeric_put class num_put : public locale::facet, public __num_base
{
public:
typedef _CharT char_type;
typedef _OutIter iter_type;
protected:
explicit
_Numeric_put() { }
virtual
~_Numeric_put() { }
};
template<typename _CharT, typename _OutIter>
class num_put : public locale::facet
{ {
public: public:
// Types: // Types:
typedef _CharT char_type; typedef _CharT char_type;
typedef _OutIter iter_type; typedef _OutIter iter_type;
static locale::id id; static locale::id id;
...@@ -752,43 +703,65 @@ namespace std ...@@ -752,43 +703,65 @@ namespace std
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, bool __v) const put(iter_type __s, ios_base& __f, char_type __fill, bool __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, long __v) const put(iter_type __s, ios_base& __f, char_type __fill, long __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, put(iter_type __s, ios_base& __f, char_type __fill,
unsigned long __v) const unsigned long __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
#ifdef _GLIBCPP_USE_LONG_LONG #ifdef _GLIBCPP_USE_LONG_LONG
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, long long __v) const put(iter_type __s, ios_base& __f, char_type __fill, long long __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, put(iter_type __s, ios_base& __f, char_type __fill,
unsigned long long __v) const unsigned long long __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
#endif #endif
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, double __v) const put(iter_type __s, ios_base& __f, char_type __fill, double __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, put(iter_type __s, ios_base& __f, char_type __fill,
long double __v) const long double __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
iter_type iter_type
put(iter_type __s, ios_base& __f, char_type __fill, put(iter_type __s, ios_base& __f, char_type __fill,
const void* __v) const const void* __v) const
{ return do_put(__s, __f, __fill, __v); } { return this->do_put(__s, __f, __fill, __v); }
protected: protected:
template<typename _ValueT>
iter_type
_M_convert_float(iter_type, ios_base& __io, char_type __fill,
char __mod, _ValueT __v) const;
template<typename _ValueT>
iter_type
_M_convert_int(iter_type, ios_base& __io, char_type __fill,
char __mod, char __modl, _ValueT __v) const;
iter_type
_M_widen_float(iter_type, ios_base& __io, char_type __fill, char* __cs,
int __len) const;
iter_type
_M_widen_int(iter_type, ios_base& __io, char_type __fill, char* __cs,
int __len) const;
iter_type
_M_insert(iter_type, ios_base& __io, char_type __fill,
const char_type* __ws, int __len) const;
virtual virtual
~num_put() { }; ~num_put() { };
...@@ -798,15 +771,13 @@ namespace std ...@@ -798,15 +771,13 @@ namespace std
virtual iter_type virtual iter_type
do_put(iter_type, ios_base&, char_type __fill, long __v) const; do_put(iter_type, ios_base&, char_type __fill, long __v) const;
#ifdef _GLIBCPP_USE_LONG_LONG
virtual iter_type virtual iter_type
do_put(iter_type, ios_base&, char_type __fill, long long __v) const; do_put(iter_type, ios_base&, char_type __fill, unsigned long) const;
#endif
#ifdef _GLIBCPP_USE_LONG_LONG
virtual iter_type virtual iter_type
do_put(iter_type, ios_base&, char_type __fill, unsigned long) const; do_put(iter_type, ios_base&, char_type __fill, long long __v) const;
#ifdef _GLIBCPP_USE_LONG_LONG
virtual iter_type virtual iter_type
do_put(iter_type, ios_base&, char_type __fill, unsigned long long) const; do_put(iter_type, ios_base&, char_type __fill, unsigned long long) const;
#endif #endif
...@@ -826,126 +797,6 @@ namespace std ...@@ -826,126 +797,6 @@ namespace std
template<typename _CharT> template<typename _CharT>
class numpunct : public locale::facet
{
public:
// Types:
typedef _CharT char_type;
typedef basic_string<_CharT> string_type;
static locale::id id;
private:
char_type _M_decimal_point;
char_type _M_thousands_sep;
string _M_grouping;
string_type _M_truename;
string_type _M_falsename;
public:
explicit
numpunct(size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(); }
explicit
numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs)
{ _M_initialize_numpunct(__cloc); }
char_type
decimal_point() const
{ return this->do_decimal_point(); }
char_type
thousands_sep() const
{ return this->do_thousands_sep(); }
string
grouping() const
{ return this->do_grouping(); }
string_type
truename() const
{ return this->do_truename(); }
string_type
falsename() const
{ return this->do_falsename(); }
protected:
virtual
~numpunct() { }
virtual char_type
do_decimal_point() const
{ return _M_decimal_point; }
virtual char_type
do_thousands_sep() const
{ return _M_thousands_sep; }
virtual string
do_grouping() const
{ return _M_grouping; }
virtual string_type
do_truename() const
{ return _M_truename; }
virtual string_type
do_falsename() const
{ return _M_falsename; }
// For use at construction time only.
void
_M_initialize_numpunct(__c_locale __cloc = NULL);
};
template<typename _CharT>
locale::id numpunct<_CharT>::id;
// NB: Cannot be made generic.
template<typename _CharT>
void
numpunct<_CharT>::_M_initialize_numpunct(__c_locale)
{ }
template<>
void
numpunct<char>::_M_initialize_numpunct(__c_locale __cloc);
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc);
#endif
template<typename _CharT>
class numpunct_byname : public numpunct<_CharT>
{
// Data Member.
__c_locale _M_c_locale_numpunct;
public:
typedef _CharT char_type;
typedef basic_string<_CharT> string_type;
explicit
numpunct_byname(const char* __s, size_t __refs = 0)
: numpunct<_CharT>(__refs)
{
_S_create_c_locale(_M_c_locale_numpunct, __s);
_M_initialize_numpunct(_M_c_locale_numpunct);
}
protected:
virtual
~numpunct_byname()
{ _S_destroy_c_locale(_M_c_locale_numpunct); }
};
template<typename _CharT>
class collate : public locale::facet class collate : public locale::facet
{ {
public: public:
...@@ -1466,8 +1317,9 @@ namespace std ...@@ -1466,8 +1317,9 @@ namespace std
}; };
struct money_base class money_base
{ {
public:
enum part { none, space, symbol, sign, value }; enum part { none, space, symbol, sign, value };
struct pattern { char field[4]; }; struct pattern { char field[4]; };
......
...@@ -59,18 +59,17 @@ namespace std ...@@ -59,18 +59,17 @@ namespace std
const basic_string<_CharT, _Traits, _Alloc>& __s2) const const basic_string<_CharT, _Traits, _Alloc>& __s2) const
{ {
typedef std::collate<_CharT> __collate_type; typedef std::collate<_CharT> __collate_type;
const __collate_type* __fcoll = &use_facet<__collate_type>(*this); const __collate_type& __collate = use_facet<__collate_type>(*this);
return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(), return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
__s2.data(), __s2.data() + __s2.length()) < 0); __s2.data(), __s2.data() + __s2.length()) < 0);
} }
template<typename _Facet> template<typename _Facet>
const _Facet& const _Facet&
use_facet(const locale& __loc) use_facet(const locale& __loc)
{ {
typedef locale::_Impl::__vec_facet __vec_facet;
size_t __i = _Facet::id._M_index; size_t __i = _Facet::id._M_index;
__vec_facet* __facet = __loc._M_impl->_M_facets; locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
const locale::facet* __fp = (*__facet)[__i]; const locale::facet* __fp = (*__facet)[__i];
if (__fp == 0 || __i >= __facet->size()) if (__fp == 0 || __i >= __facet->size())
__throw_bad_cast(); __throw_bad_cast();
...@@ -81,52 +80,262 @@ namespace std ...@@ -81,52 +80,262 @@ namespace std
bool bool
has_facet(const locale& __loc) throw() has_facet(const locale& __loc) throw()
{ {
typedef locale::_Impl::__vec_facet __vec_facet;
size_t __i = _Facet::id._M_index; size_t __i = _Facet::id._M_index;
__vec_facet* __facet = __loc._M_impl->_M_facets; locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
return (__i < __facet->size() && (*__facet)[__i] != 0); return (__i < __facet->size() && (*__facet)[__i] != 0);
} }
// This member function takes an (w)istreambuf_iterator object and
// parses it into a generic char array suitable for parsing with
// strto[l,ll,f,d]. The thought was to encapsulate the conversion
// into this one function, and thus the num_get::do_get member
// functions can just adjust for the type of the overloaded
// argument and process the char array returned from _M_extract.
// Other things were also considered, including a fused
// multiply-add loop that would obviate the need for any call to
// strto... at all: however, it would b e a bit of a pain, because
// you'd have to be able to return either floating or integral
// types, etc etc. The current approach seems to be smack dab in
// the middle between an unoptimized approach using sscanf, and
// some kind of hyper-optimized approach alluded to above.
// XXX
// Need to do partial specialization to account for differences
// between character sets. For char, this is pretty
// straightforward, but for wchar_t, the conversion to a plain-jane
// char type is a bit more involved.
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
void void
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
_M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/, _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
ios_base::iostate& /*__err*/, char* /*__xtrc*/, ios_base::iostate& __err, char* __xtrc) const
int& /*__base*/, bool /*__fp*/) const
{ {
// XXX Not currently done: need to expand upon char version below. const locale __loc = __io.getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
int __pos = 0;
char_type __c = *__beg;
// Check first for sign.
const char_type __plus = __ctype.widen('+');
const char_type __minus = __ctype.widen('-');
if ((__c == __plus || __c == __minus) && __beg != __end)
{
__xtrc[__pos++] = __ctype.narrow(__c, char());
__c = *(++__beg);
}
// Next, strip leading zeros.
const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
bool __found_zero = false;
while (__c == __zero && __beg != __end)
{
__c = *(++__beg);
__found_zero = true;
}
if (__found_zero)
__xtrc[__pos++] = _S_atoms[_M_zero];
// Only need acceptable digits for floating point numbers.
const size_t __len = _M_E - _M_zero + 1;
char_type __watoms[__len];
__ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
bool __found_dec = false;
bool __found_sci = false;
const char_type __dec = __np.decimal_point();
string __found_grouping;
const string __grouping = __np.grouping();
bool __check_grouping = __grouping.size();
int __sep_pos = 0;
const char_type __sep = __np.thousands_sep();
while (__beg != __end)
{
// Only look in digits.
typedef char_traits<_CharT> __traits_type;
const char_type* __p = __traits_type::find(__watoms, 10, __c);
// NB: strchr returns true for __c == 0x0
if (__p && __c)
{
// Try first for acceptable digit; record it if found.
__xtrc[__pos++] = _S_atoms[__p - __watoms];
++__sep_pos;
__c = *(++__beg);
}
else if (__c == __sep && __check_grouping && !__found_dec)
{
// NB: Thousands separator at the beginning of a string
// is a no-no, as is two consecutive thousands separators.
if (__sep_pos)
{
__found_grouping += static_cast<char>(__sep_pos);
__sep_pos = 0;
__c = *(++__beg);
}
else
{
__err |= ios_base::failbit;
break;
}
}
else if (__c == __dec && !__found_dec)
{
__found_grouping += static_cast<char>(__sep_pos);
__xtrc[__pos++] = '.';
__c = *(++__beg);
__found_dec = true;
}
else if ((__c == __watoms[_M_e] || __c == __watoms[_M_E])
&& !__found_sci && __pos)
{
// Scientific notation.
__xtrc[__pos++] = __ctype.narrow(__c, char());
__c = *(++__beg);
// Remove optional plus or minus sign, if they exist.
if (__c == __plus || __c == __minus)
{
__xtrc[__pos++] = __ctype.narrow(__c, char());
__c = *(++__beg);
}
__found_sci = true;
}
else
// Not a valid input item.
break;
}
// Digit grouping is checked. If grouping and found_grouping don't
// match, then get very very upset, and set failbit.
if (__check_grouping && __found_grouping.size())
{
// Add the ending grouping if a decimal wasn't found.
if (!__found_dec)
__found_grouping += static_cast<char>(__sep_pos);
if (!__verify_grouping(__grouping, __found_grouping))
{
__err |= ios_base::failbit;
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
return;
}
}
// Finish up
__xtrc[__pos] = char_type();
if (__beg == __end)
__err |= ios_base::eofbit;
} }
template<> template<typename _CharT, typename _InIter>
void void
num_get<char, istreambuf_iterator<char> >:: num_get<_CharT, _InIter>::
_M_extract(istreambuf_iterator<char> __beg, _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
istreambuf_iterator<char> __end, ios_base& __io, ios_base::iostate& __err, char* __xtrc, int& __base) const
ios_base::iostate& __err, char* __xtrc, int& __base, {
bool __fp) const; // Stage 1: determine a conversion specifier.
ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
if (__basefield == ios_base::oct)
__base = 8;
else if (__basefield == ios_base::hex)
__base = 16;
else
__base = 10;
const locale __loc = __io.getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
int __pos = 0;
char_type __c = *__beg;
// Check first for sign.
if ((__c == __ctype.widen('+') || __c == __ctype.widen('-'))
&& __beg != __end)
{
__xtrc[__pos++] = __ctype.narrow(__c, char());
__c = *(++__beg);
}
// Next, strip leading zeros
const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
bool __found_zero = false;
while (__base == 10 && __c == __zero && __beg != __end)
{
__c = *(++__beg);
__found_zero = true;
}
if (__found_zero)
{
__xtrc[__pos++] = _S_atoms[_M_zero];
if (__basefield == 0)
{
// Depending on what is discovered, the base may change.
if (__c == __ctype.widen('x') || __c == __ctype.widen('X'))
__base = 16;
else
__base = 8;
}
}
// At this point, base is determined. If not hex, only allow
// base digits as valid input.
size_t __len;
if (__base == 16)
__len = _M_size;
else
__len = __base;
char_type __watoms[_M_size];
__ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
string __found_grouping;
const string __grouping = __np.grouping();
bool __check_grouping = __grouping.size() && __base == 10;
int __sep_pos = 0;
const char_type __sep = __np.thousands_sep();
while (__beg != __end)
{
typedef char_traits<_CharT> __traits_type;
const char_type* __p = __traits_type::find(__watoms, __len, __c);
// NB: strchr returns true for __c == 0x0
if (__p && __c)
{
// Try first for acceptable digit; record it if found.
__xtrc[__pos++] = _S_atoms[__p - __watoms];
++__sep_pos;
__c = *(++__beg);
}
else if (__c == __sep && __check_grouping)
{
// NB: Thousands separator at the beginning of a string
// is a no-no, as is two consecutive thousands separators.
if (__sep_pos)
{
__found_grouping += static_cast<char>(__sep_pos);
__sep_pos = 0;
__c = *(++__beg);
}
else
{
__err |= ios_base::failbit;
break;
}
}
else
// Not a valid input item.
break;
}
// Digit grouping is checked. If grouping and found_grouping don't
// match, then get very very upset, and set failbit.
if (__check_grouping && __found_grouping.size())
{
// Add the ending grouping
__found_grouping += static_cast<char>(__sep_pos);
if (!__verify_grouping(__grouping, __found_grouping))
{
__err |= ios_base::failbit;
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
return;
}
}
// Finish up
__xtrc[__pos] = char_type();
if (__beg == __end)
__err |= ios_base::eofbit;
}
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
// NB: This is an unresolved library defect #17
//17. Bad bool parsing //17. Bad bool parsing
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
_InIter _InIter
...@@ -145,7 +354,7 @@ namespace std ...@@ -145,7 +354,7 @@ namespace std
// integral types. // integral types.
char __xtrc[32] = {'\0'}; char __xtrc[32] = {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
...@@ -162,29 +371,30 @@ namespace std ...@@ -162,29 +371,30 @@ namespace std
// Parse bool values as alphanumeric // Parse bool values as alphanumeric
else else
{ {
typedef _Format_cache<char_type> __fcache_type; locale __loc = __io.getloc();
__fcache_type* __fmt = __fcache_type::_S_get(__io); const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__loc);
const char_type* __true = __fmt->_M_truename.c_str(); const char_type* __true = __np.truename().c_str();
const char_type* __false = __fmt->_M_falsename.c_str(); const char_type* __false = __np.falsename().c_str();
const size_t __truelen = __traits_type::length(__true) - 1;
const size_t __falselen = __traits_type::length(__false) - 1; const size_t __truen = __np.truename().size() - 1;
const size_t __falsen = __np.falsename().size() - 1;
for (size_t __pos = 0; __beg != __end; ++__pos)
for (size_t __n = 0; __beg != __end; ++__n)
{ {
char_type __c = *__beg++; char_type __c = *__beg++;
bool __testf = __c == __false[__pos]; bool __testf = __n <= __falsen ? __c == __false[__n] : false;
bool __testt = __c == __true[__pos]; bool __testt = __n <= __truen ? __c == __true[__n] : false;
if (!(__testf || __testt)) if (!(__testf || __testt))
{ {
__err |= ios_base::failbit; __err |= ios_base::failbit;
break; break;
} }
else if (__testf && __pos == __falselen) else if (__testf && __n == __falsen)
{ {
__v = 0; __v = 0;
break; break;
} }
else if (__testt && __pos == __truelen) else if (__testt && __n == __truen)
{ {
__v = 1; __v = 1;
break; break;
...@@ -198,63 +408,6 @@ namespace std ...@@ -198,63 +408,6 @@ namespace std
} }
#endif #endif
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
//XXX. Which number? Presumably same as in locale_facets.h...
template<typename _CharT, typename _InIter>
_InIter
num_get<_CharT, _InIter>::
do_get(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, short& __v) const
{
// Stage 1: extract and determine the conversion specifier.
// Assuming leading zeros eliminated, thus the size of 32 for
// integral types.
char __xtrc[32]= {'\0'};
int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
// Stage 2: convert and store results.
char* __sanity;
errno = 0;
long __l = strtol(__xtrc, &__sanity, __base);
if (!(__err & ios_base::failbit)
&& __sanity != __xtrc && *__sanity == '\0' && errno == 0
&& __l >= SHRT_MIN && __l <= SHRT_MAX)
__v = static_cast<short>(__l);
else
__err |= ios_base::failbit;
return __beg;
}
template<typename _CharT, typename _InIter>
_InIter
num_get<_CharT, _InIter>::
do_get(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, int& __v) const
{
// Stage 1: extract and determine the conversion specifier.
// Assuming leading zeros eliminated, thus the size of 32 for
// integral types.
char __xtrc[32] = {'\0'};
int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
// Stage 2: convert and store results.
char* __sanity;
errno = 0;
long __l = strtol(__xtrc, &__sanity, __base);
if (!(__err & ios_base::failbit)
&& __sanity != __xtrc && *__sanity == '\0' && errno == 0
&& __l >= INT_MIN && __l <= INT_MAX)
__v = static_cast<int>(__l);
else
__err |= ios_base::failbit;
return __beg;
}
#endif
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
_InIter _InIter
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
...@@ -266,7 +419,7 @@ namespace std ...@@ -266,7 +419,7 @@ namespace std
// integral types. // integral types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
...@@ -281,46 +434,45 @@ namespace std ...@@ -281,46 +434,45 @@ namespace std
return __beg; return __beg;
} }
#ifdef _GLIBCPP_USE_LONG_LONG
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
_InIter _InIter
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
do_get(iter_type __beg, iter_type __end, ios_base& __io, do_get(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, long long& __v) const ios_base::iostate& __err, unsigned short& __v) const
{ {
// Stage 1: extract and determine the conversion specifier. // Stage 1: extract and determine the conversion specifier.
// Assuming leading zeros eliminated, thus the size of 32 for // Assuming leading zeros eliminated, thus the size of 32 for
// integral types. // integral types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
errno = 0; errno = 0;
long long __ll = strtoll(__xtrc, &__sanity, __base); unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
if (!(__err & ios_base::failbit) if (!(__err & ios_base::failbit)
&& __sanity != __xtrc && *__sanity == '\0' && errno == 0) && __sanity != __xtrc && *__sanity == '\0' && errno == 0
__v = __ll; && __ul <= USHRT_MAX)
__v = static_cast<unsigned short>(__ul);
else else
__err |= ios_base::failbit; __err |= ios_base::failbit;
return __beg; return __beg;
} }
#endif
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
_InIter _InIter
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
do_get(iter_type __beg, iter_type __end, ios_base& __io, do_get(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, unsigned short& __v) const ios_base::iostate& __err, unsigned int& __v) const
{ {
// Stage 1: extract and determine the conversion specifier. // Stage 1: extract and determine the conversion specifier.
// Assuming leading zeros eliminated, thus the size of 32 for // Assuming leading zeros eliminated, thus the size of 32 for
// integral types. // integral types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
...@@ -328,8 +480,8 @@ namespace std ...@@ -328,8 +480,8 @@ namespace std
unsigned long __ul = strtoul(__xtrc, &__sanity, __base); unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
if (!(__err & ios_base::failbit) if (!(__err & ios_base::failbit)
&& __sanity != __xtrc && *__sanity == '\0' && errno == 0 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
&& __ul <= USHRT_MAX) && __ul <= UINT_MAX)
__v = static_cast<unsigned short>(__ul); __v = static_cast<unsigned int>(__ul);
else else
__err |= ios_base::failbit; __err |= ios_base::failbit;
...@@ -340,56 +492,55 @@ namespace std ...@@ -340,56 +492,55 @@ namespace std
_InIter _InIter
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
do_get(iter_type __beg, iter_type __end, ios_base& __io, do_get(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, unsigned int& __v) const ios_base::iostate& __err, unsigned long& __v) const
{ {
// Stage 1: extract and determine the conversion specifier. // Stage 1: extract and determine the conversion specifier.
// Assuming leading zeros eliminated, thus the size of 32 for // Assuming leading zeros eliminated, thus the size of 32 for
// integral types. // integral types.
char __xtrc[32]= {'\0'}; char __xtrc[32] = {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
errno = 0; errno = 0;
unsigned long __ul = strtoul(__xtrc, &__sanity, __base); unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
if (!(__err & ios_base::failbit) if (!(__err & ios_base::failbit)
&& __sanity != __xtrc && *__sanity == '\0' && errno == 0 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
&& __ul <= UINT_MAX) __v = __ul;
__v = static_cast<unsigned int>(__ul);
else else
__err |= ios_base::failbit; __err |= ios_base::failbit;
return __beg; return __beg;
} }
#ifdef _GLIBCPP_USE_LONG_LONG
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
_InIter _InIter
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
do_get(iter_type __beg, iter_type __end, ios_base& __io, do_get(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, unsigned long& __v) const ios_base::iostate& __err, long long& __v) const
{ {
// Stage 1: extract and determine the conversion specifier. // Stage 1: extract and determine the conversion specifier.
// Assuming leading zeros eliminated, thus the size of 32 for // Assuming leading zeros eliminated, thus the size of 32 for
// integral types. // integral types.
char __xtrc[32] = {'\0'}; char __xtrc[32]= {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
errno = 0; errno = 0;
unsigned long __ul = strtoul(__xtrc, &__sanity, __base); long long __ll = strtoll(__xtrc, &__sanity, __base);
if (!(__err & ios_base::failbit) if (!(__err & ios_base::failbit)
&& __sanity != __xtrc && *__sanity == '\0' && errno == 0) && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
__v = __ul; __v = __ll;
else else
__err |= ios_base::failbit; __err |= ios_base::failbit;
return __beg; return __beg;
} }
#ifdef _GLIBCPP_USE_LONG_LONG
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
_InIter _InIter
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
...@@ -401,7 +552,7 @@ namespace std ...@@ -401,7 +552,7 @@ namespace std
// integral types. // integral types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
...@@ -420,15 +571,14 @@ namespace std ...@@ -420,15 +571,14 @@ namespace std
template<typename _CharT, typename _InIter> template<typename _CharT, typename _InIter>
_InIter _InIter
num_get<_CharT, _InIter>:: num_get<_CharT, _InIter>::
do_get(iter_type __beg, iter_type __end, ios_base& __io, do_get(iter_type __beg, iter_type __end, ios_base& __io,
ios_base::iostate& __err, float& __v) const ios_base::iostate& __err, float& __v) const
{ {
// Stage 1: extract and determine the conversion specifier. // Stage 1: extract and determine the conversion specifier.
// Assuming leading zeros eliminated, thus the size of 256 for // Assuming leading zeros eliminated, thus the size of 256 for
// floating-point types. // floating-point types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; _M_extract_float(__beg, __end, __io, __err, __xtrc);
_M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
...@@ -457,8 +607,7 @@ namespace std ...@@ -457,8 +607,7 @@ namespace std
// Assuming leading zeros eliminated, thus the size of 256 for // Assuming leading zeros eliminated, thus the size of 256 for
// floating-point types. // floating-point types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; _M_extract_float(__beg, __end, __io, __err, __xtrc);
_M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
...@@ -483,8 +632,7 @@ namespace std ...@@ -483,8 +632,7 @@ namespace std
// Assuming leading zeros eliminated, thus the size of 256 for // Assuming leading zeros eliminated, thus the size of 256 for
// floating-point types. // floating-point types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; _M_extract_float(__beg, __end, __io, __err, __xtrc);
_M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
#if defined(_GLIBCPP_USE_C99) && !defined(__hpux) #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
// Stage 2: convert and store results. // Stage 2: convert and store results.
...@@ -539,7 +687,7 @@ namespace std ...@@ -539,7 +687,7 @@ namespace std
// integral types. // integral types.
char __xtrc[32]= {'\0'}; char __xtrc[32]= {'\0'};
int __base; int __base;
_M_extract(__beg, __end, __io, __err, __xtrc, __base, false); _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
// Stage 2: convert and store results. // Stage 2: convert and store results.
char* __sanity; char* __sanity;
...@@ -556,83 +704,138 @@ namespace std ...@@ -556,83 +704,138 @@ namespace std
return __beg; return __beg;
} }
// __pad is specialized for ostreambuf_iterator, random access iterator.
// The following code uses sprintf() to convert floating point
// values for insertion into a stream. An optimization would be to
// replace sprintf() with code that works directly on a wide buffer
// and then use __pad to do the padding. It would be good
// to replace sprintf() anyway to avoid accidental buffer overruns
// and to gain back the efficiency that C++ provides by knowing up
// front the type of the values to insert. This implementation
// follows the C++ standard fairly directly as outlined in 22.2.2.2
// [lib.locale.num.put]
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
inline _OutIter template<typename _ValueT>
__pad(_OutIter __s, _CharT __fill, int __padding); _OutIter
num_put<_CharT, _OutIter>::
_M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
_ValueT __v) const
{
const streamsize __max_prec = numeric_limits<_ValueT>::digits10;
streamsize __prec = __io.precision();
// Protect against sprintf() buffer overflows.
if (__prec > __max_prec)
__prec = __max_prec;
// Long enough for the max format spec.
char __fbuf[16];
char __cs[64];
int __len;
// [22.2.2.2.2] Stage 1, numeric conversion to character.
if (_S_format_float(__io, __fbuf, __mod, __prec))
__len = sprintf(__cs, __fbuf, __prec, __v);
else
__len = sprintf(__cs, __fbuf, __v);
return _M_widen_float(__s, __io, __fill, __cs, __len);
}
template<typename _CharT, typename _RaIter> template<typename _CharT, typename _OutIter>
_RaIter template<typename _ValueT>
__pad(_RaIter __s, _CharT __fill, int __padding, _OutIter
random_access_iterator_tag) num_put<_CharT, _OutIter>::
{ _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
fill_n(__s, __fill); char __modl, _ValueT __v) const
return __s + __padding; {
} // [22.2.2.2.2] Stage 1, numeric conversion to character.
// Leave room for "+/-," "0x," and commas. This size is
// arbitrary, but should work.
char __cs[64];
// Long enough for the max format spec.
char __fbuf[16];
_S_format_int(__io, __fbuf, __mod, __modl);
int __len = sprintf(__cs, __fbuf, __v);
return _M_widen_int(__s, __io, __fill, __cs, __len);
}
template<typename _CharT, typename _OutIter, typename _Tag> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
__pad(_OutIter __s, _CharT __fill, int __padding, _Tag) num_put<_CharT, _OutIter>::
_M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
int __len) const
{ {
while (--__padding >= 0) { *__s = __fill; ++__s; } // [22.2.2.2.2] Stage 2, convert to char_type, using correct
return __s; // 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));
__ctype.widen(__cs, __cs + __len, __ws);
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
// Replace decimal point.
const _CharT* __p;
if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.')))
__ws[__p - __ws] = __np.decimal_point();
return _M_insert(__s, __io, __fill, __ws, __len);
} }
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
inline _OutIter _OutIter
__pad(_OutIter __s, _CharT __fill, int __padding) num_put<_CharT, _OutIter>::
_M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
int __len) const
{ {
return __pad(__s, __fill, __padding, // [22.2.2.2.2] Stage 2, convert to char_type, using correct
typename iterator_traits<_OutIter>::iterator_category()); // 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));
__ctype.widen(__cs, __cs + __len, __ws);
// Add grouping, if necessary.
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
string __grouping = __np.grouping();
ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
bool __dec = __basefield != ios_base::oct
&& __basefield != ios_base::hex;
if (__grouping.size() && __dec)
{
_CharT* __p;
__p = __add_grouping(__ws2, __np.thousands_sep(), __grouping.c_str(),
__grouping.c_str() + __grouping.size(),
__ws, __ws + __len);
__len = __p - __ws2;
// Switch strings.
__ws = __ws2;
}
return _M_insert(__s, __io, __fill, __ws, __len);
} }
// For use by integer and floating-point types after they have been
// converted into a char_type string.
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
__pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/, num_put<_CharT, _OutIter>::
_CharT /*__fill*/, int /*__width*/, _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws,
_CharT const* /*__first*/, _CharT const* /*__middle*/, int __len) const
_CharT const* /*__last*/)
{
// XXX Not currently done: non streambuf_iterator
return __s;
}
// Partial specialization for ostreambuf_iterator.
template<typename _CharT>
ostreambuf_iterator<_CharT>
__pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags,
_CharT __fill, int __width, _CharT const* __first,
_CharT const* __middle, _CharT const* __last)
{ {
typedef ostreambuf_iterator<_CharT> __out_iter; // [22.2.2.2.2] Stage 3.
int __padding = __width - (__last - __first); _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
if (__padding < 0) streamsize __w = __io.width();
__padding = 0; if (__w > static_cast<streamsize>(__len))
ios_base::fmtflags __aflags = __flags & ios_base::adjustfield; {
bool __testfield = __padding == 0 || __aflags == ios_base::left __pad(__io, __fill, __ws2, __ws, __w, __len);
|| __aflags == ios_base::internal; __len = static_cast<int>(__w);
// Switch strings.
// This was needlessly complicated. __ws = __ws2;
if (__first != __middle) }
{ __io.width(0);
if (!__testfield)
{
__pad(__s, __fill, __padding);
__padding = 0;
}
copy(__first, __middle, __s);
}
__out_iter __s2 = __s;
if (__padding && __aflags != ios_base::left) // [22.2.2.2.2] Stage 4.
{ // Write resulting, fully-formatted string to output iterator.
__pad(__s2, __fill, __padding); for (int __j = 0; __j < __len; ++__j, ++__s)
__padding = 0; *__s = __ws[__j];
} return __s;
__out_iter __s3 = copy(__middle, __last, __s2);
if (__padding)
__pad(__s3, __fill, __padding);
return __s3;
} }
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
...@@ -640,278 +843,73 @@ namespace std ...@@ -640,278 +843,73 @@ namespace std
num_put<_CharT, _OutIter>:: num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
{ {
const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
ios_base::fmtflags __flags = __io.flags(); ios_base::fmtflags __flags = __io.flags();
if ((__flags & ios_base::boolalpha) == 0) if ((__flags & ios_base::boolalpha) == 0)
{ {
unsigned long __uv = __v; unsigned long __uv = __v;
return __output_integer(__s, __io, __fill, false, __uv); _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv);
} }
else else
{ {
const char_type* __first; locale __loc = __io.getloc();
const char_type* __last; const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
const char_type* __ws;
int __len;
if (__v) if (__v)
{ {
__first = __fmt->_M_truename.data(); __ws = __np.truename().c_str();
__last = __first + __fmt->_M_truename.size(); __len = __np.truename().size();
} }
else else
{ {
__first = __fmt->_M_falsename.data(); __ws = __np.falsename().c_str();
__last = __first + __fmt->_M_falsename.size(); __len = __np.falsename().size();
} }
streamsize __width = __io.width(0); _M_insert(__s, __io, __fill, __ws, __len);
if (__last - __first >= __width) }
return copy(__first, __last, __s); return __s;
else
{
int __padding = __width - (__last - __first);
ios_base::fmtflags __aflags = __flags & ios_base::adjustfield;
if (__aflags != ios_base::left)
{
__pad(__s, __fill, __padding);
return copy(__first, __last, __s);
}
else
{
copy(__first, __last, __s);
return __pad(__s, __fill, __padding);
}
}
}
}
template<typename _CharT, typename _OutIter, typename _ValueT>
_OutIter
__output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
_ValueT __v)
{
// Leave room for "+/-," "0x," and commas. This size is
// arbitrary, but should work.
const int __n = numeric_limits<_ValueT>::digits10 * 2 + 4;
_CharT* __digits = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
_CharT* __digits_end = __digits + __n;
ios_base::fmtflags __flags = __io.flags();
const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
char const* __table = __fmt->_S_literals + __fmt->_S_digits;
ios_base::fmtflags __basefield = (__flags & __io.basefield);
_CharT* __sign_end = __digits_end;
if (__basefield == ios_base::hex)
{
if (__flags & ios_base::uppercase)
__table += 16; // use ABCDEF
do
*--__digits_end = __table[__v & 15];
while ((__v >>= 4) != 0);
__sign_end = __digits_end;
if (__flags & ios_base::showbase)
{
*--__digits_end = __fmt->_S_literals[__fmt->_S_x +
((__flags & ios_base::uppercase) ? 1 : 0)];
*--__digits_end = __table[0];
}
}
else if (__basefield == ios_base::oct)
{
do
*--__digits_end = __table[__v & 7];
while ((__v >>= 3) != 0);
if (__flags & ios_base::showbase
&& static_cast<char>(*__digits_end) != __table[0])
*--__digits_end = __table[0];
__sign_end = __digits_end;
}
else
{
// NB: This is _lots_ faster than using ldiv.
do
*--__digits_end = __table[__v % 10];
while ((__v /= 10) != 0);
__sign_end = __digits_end;
// NB: ios_base:hex || ios_base::oct assumed to be unsigned.
if (__neg || (__flags & ios_base::showpos))
*--__digits_end = __fmt->_S_literals[__fmt->_S_plus - __neg];
}
// XXX should specialize!
if (!__fmt->_M_use_grouping && !__io.width())
return copy(__digits_end, __digits + __n, __s);
if (!__fmt->_M_use_grouping)
return __pad_numeric(__s, __flags, __fill, __io.width(0),
__digits_end, __sign_end, __digits + __n);
_CharT* __p = __digits;
while (__digits_end < __sign_end)
*__p++ = *__digits_end++;
const char* __gbeg = __fmt->_M_grouping.data();
const char* __gend = __gbeg + __fmt->_M_grouping.size();
__digits_end = __group_digits(__p, __fmt->_M_thousands_sep,
__gbeg, __gend,
__sign_end, __digits + __n);
return __pad_numeric(__s, __flags, __fill, __io.width(0),
__digits, __p, __digits_end);
} }
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
num_put<_CharT, _OutIter>:: num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
{ { return _M_convert_int(__s, __io, __fill, 'd', char_type(), __v); }
unsigned long __uv = __v;
bool __neg = false;
if (__v < 0)
{
__neg = true;
__uv = -__uv;
}
return __output_integer(__s, __io, __fill, __neg, __uv);
}
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
num_put<_CharT, _OutIter>:: num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, do_put(iter_type __s, ios_base& __io, char_type __fill,
unsigned long __v) const unsigned long __v) const
{ return __output_integer(__s, __io, __fill, false, __v); } { return _M_convert_int(__s, __io, __fill, 'u', char_type(), __v); }
#ifdef _GLIBCPP_USE_LONG_LONG #ifdef _GLIBCPP_USE_LONG_LONG
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
num_put<_CharT, _OutIter>:: num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
{ { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
unsigned long long __uv = __v;
bool __neg = false;
if (__v < 0)
{
__neg = true;
__uv = -__uv;
}
return __output_integer(__s, __b, __fill, __neg, __uv);
}
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
num_put<_CharT, _OutIter>:: num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, do_put(iter_type __s, ios_base& __io, char_type __fill,
unsigned long long __v) const unsigned long long __v) const
{ return __output_integer(__s, __io, __fill, false, __v); } { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
#endif #endif
// Generic helper function
template<typename _CharT, typename _Traits, typename _OutIter>
_OutIter
__output_float(_OutIter __s, ios_base& __io, _CharT __fill,
const char* __sptr, size_t __slen)
{
// XXX Not currently done: non-streambuf_iterator
return __s;
}
// Partial specialization for ostreambuf_iterator.
template<typename _CharT, typename _Traits>
ostreambuf_iterator<_CharT, _Traits>
__output_float(ostreambuf_iterator<_CharT, _Traits> __s, ios_base& __io,
_CharT __fill, const char* __sptr, size_t __slen)
{
size_t __padding = __io.width() > streamsize(__slen) ?
__io.width() -__slen : 0;
locale __loc = __io.getloc();
ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield;
const char* const __eptr = __sptr + __slen;
// [22.2.2.2.2.19] Table 61
if (__adjfield == ios_base::internal)
{
// [22.2.2.2.2.14]; widen()
if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
{
__s = __ctype.widen(*__sptr);
++__s;
++__sptr;
}
__s = __pad(__s, __fill, __padding);
__padding = 0;
}
else if (__adjfield != ios_base::left)
{
__s = __pad(__s, __fill, __padding);
__padding = 0;
}
// the "C" locale decimal character
char __decimal_point = *(localeconv()->decimal_point);
const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
for (; __sptr != __eptr; ++__s, ++__sptr)
{
// [22.2.2.2.2.17]; decimal point conversion
if (*__sptr == __decimal_point)
__s = __fmt->_M_decimal_point;
// [22.2.2.2.2.14]; widen()
else
__s = __ctype.widen(*__sptr);
}
// [22.2.2.2.2.19] Table 61
if (__padding)
__pad(__s, __fill, __padding);
__io.width(0);
return __s;
}
bool
__build_float_format(ios_base& __io, char* __fptr, char __modifier,
streamsize __prec);
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
num_put<_CharT, _OutIter>:: num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
{ { return _M_convert_float(__s, __io, __fill, char_type(), __v); }
const streamsize __max_prec = numeric_limits<double>::digits10 + 3;
streamsize __prec = __io.precision();
// Protect against sprintf() buffer overflows.
if (__prec > __max_prec)
__prec = __max_prec;
// The *2 provides for signs, exp, 'E', and pad.
char __sbuf[__max_prec * 2];
size_t __slen;
// Long enough for the max format spec.
char __fbuf[16];
if (__build_float_format(__io, __fbuf, 0, __prec))
__slen = sprintf(__sbuf, __fbuf, __prec, __v);
else
__slen = sprintf(__sbuf, __fbuf, __v);
// [22.2.2.2.2] Stages 2-4.
return __output_float(__s, __io, __fill, __sbuf, __slen);
}
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
num_put<_CharT, _OutIter>:: num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, do_put(iter_type __s, ios_base& __io, char_type __fill,
long double __v) const long double __v) const
{ { return _M_convert_float(__s, __io, __fill, 'L', __v); }
const streamsize __max_prec = numeric_limits<long double>::digits10 + 3;
streamsize __prec = __io.precision();
// Protect against sprintf() buffer overflows.
if (__prec > __max_prec)
__prec = __max_prec;
// The *2 provides for signs, exp, 'E', and pad.
char __sbuf[__max_prec * 2];
size_t __slen;
// Long enough for the max format spec.
char __fbuf[16];
// 'L' as per [22.2.2.2.2] Table 59
if (__build_float_format(__io, __fbuf, 'L', __prec))
__slen = sprintf(__sbuf, __fbuf, __prec, __v);
else
__slen = sprintf(__sbuf, __fbuf, __v);
// [22.2.2.2.2] Stages 2-4
return __output_float(__s, __io, __fill, __sbuf, __slen);
}
template<typename _CharT, typename _OutIter> template<typename _CharT, typename _OutIter>
_OutIter _OutIter
...@@ -919,21 +917,22 @@ namespace std ...@@ -919,21 +917,22 @@ namespace std
do_put(iter_type __s, ios_base& __io, char_type __fill, do_put(iter_type __s, ios_base& __io, char_type __fill,
const void* __v) const const void* __v) const
{ {
typedef ios_base::fmtflags fmtflags; ios_base::fmtflags __flags = __io.flags();
fmtflags __fmt = __io.flags(); ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield | ios_base::uppercase | ios_base::internal);
| ios_base::uppercase | ios_base::internal); __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
__io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); try
try { {
_OutIter __s2 = __output_integer(__s, __io, __fill, false, _M_convert_int(__s, __io, __fill, 'u', char_type(),
reinterpret_cast<unsigned long>(__v)); reinterpret_cast<unsigned long>(__v));
__io.flags(__fmt); __io.flags(__flags);
return __s2; }
} catch (...)
catch (...) { {
__io.flags(__fmt); __io.flags(__flags);
__throw_exception_again; __throw_exception_again;
} }
return __s;
} }
...@@ -1253,13 +1252,13 @@ namespace std ...@@ -1253,13 +1252,13 @@ namespace std
{ {
const char_type __sep = __intl ? __mpt.thousands_sep() const char_type __sep = __intl ? __mpt.thousands_sep()
: __mpf.thousands_sep(); : __mpf.thousands_sep();
const char* __gbeg = __grouping.data(); const char* __gbeg = __grouping.c_str();
const char* __gend = __gbeg + __grouping.size(); const char* __gend = __gbeg + __grouping.size();
const int __n = numeric_limits<long double>::digits10 * 2; const int __n = numeric_limits<long double>::digits10 * 2;
_CharT* __s = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
_CharT* __s_end = __group_digits(__s, __sep, __gbeg, _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg,
__gend, __beg, __end); __gend, __beg, __end);
__value.insert(0, __s, __s_end - __s); __value.insert(0, __ws2, __ws_end - __ws2);
} }
else else
__value.insert(0, string_type(__beg, __end)); __value.insert(0, string_type(__beg, __end));
...@@ -1921,6 +1920,100 @@ namespace std ...@@ -1921,6 +1920,100 @@ namespace std
return static_cast<long>(__val); return static_cast<long>(__val);
} }
// Construct correctly padded string, as per 22.2.2.2.2
// Assumes
// __newlen > __oldlen
// __news is allocated for __newlen size
// Used by both num_put and ostream inserters.
template<typename _CharT, typename _Traits>
void
__pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
const streamsize __newlen, const streamsize __oldlen)
{
typedef _CharT char_type;
typedef _Traits traits_type;
typedef typename traits_type::int_type int_type;
int_type __plen = static_cast<size_t>(__newlen - __oldlen);
char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen));
traits_type::assign(__pads, __plen, __fill);
char_type* __beg;
char_type* __end;
size_t __mod = 0;
size_t __beglen; //either __plen or __oldlen
ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
if (__adjust == ios_base::left)
{
// Padding last.
__beg = const_cast<char_type*>(__olds);
__beglen = __oldlen;
__end = __pads;
}
else if (__adjust == ios_base::internal)
{
// Pad after the sign, if there is one.
// Pad after 0[xX], if there is one.
// Who came up with these rules, anyway? Jeeze.
locale __loc = __io.getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const char_type __minus = __ctype.widen('-');
const char_type __plus = __ctype.widen('+');
bool __testsign = __olds[0] == __minus || __olds[0] == __plus;
bool __testhex = __ctype.widen('0') == __olds[0]
&& (__ctype.widen('x') == __olds[1]
|| __ctype.widen('X') == __olds[1]);
if (__testhex)
{
__news[0] = __olds[0];
__news[1] = __olds[1];
__mod += 2;
__news += 2;
__beg = const_cast<char_type*>(__olds + __mod);
__beglen = __oldlen - __mod;
__end = __pads;
}
else if (__testsign)
{
__news[0] = __olds[0] == __plus ? __plus : __minus;
++__mod;
++__news;
__beg = __pads;
__beglen = __plen;
__end = const_cast<char_type*>(__olds + __mod);
}
else
{
// Padding first.
__beg = __pads;
__beglen = __plen;
__end = const_cast<char_type*>(__olds);
}
}
else
{
// Padding first.
__beg = __pads;
__beglen = __plen;
__end = const_cast<char_type*>(__olds);
}
traits_type::copy(__news, __beg, __beglen);
traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod);
}
// NB: Can't have default argument on non-member template, and
// num_put doesn't have a _Traits template parameter, so this
// forwarding template adds in the default template argument.
template<typename _CharT>
void
__pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
const streamsize __newlen, const streamsize __oldlen)
{
return __pad<_CharT, char_traits<_CharT> >(__io, __fill, __news,
__olds, __newlen, __oldlen);
}
// Used by both numeric and monetary facets. // Used by both numeric and monetary facets.
// Check to make sure that the __grouping_tmp string constructed in // Check to make sure that the __grouping_tmp string constructed in
// money_get or num_get matches the canonical grouping for a given // money_get or num_get matches the canonical grouping for a given
...@@ -1960,102 +2053,23 @@ namespace std ...@@ -1960,102 +2053,23 @@ namespace std
// only with __gbeg != __gend. // only with __gbeg != __gend.
template<typename _CharT> template<typename _CharT>
_CharT* _CharT*
__group_digits(_CharT* __s, _CharT __sep, __add_grouping(_CharT* __s, _CharT __sep,
const char* __gbeg, const char* __gend, const char* __gbeg, const char* __gend,
const _CharT* __first, const _CharT* __last) const _CharT* __first, const _CharT* __last)
{ {
if (__last - __first > *__gbeg) if (__last - __first > *__gbeg)
{ {
__s = __group_digits(__s, __sep, __s = __add_grouping(__s, __sep,
(__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
__gend, __first, __last - *__gbeg); __gend, __first, __last - *__gbeg);
__first = __last - *__gbeg; __first = __last - *__gbeg;
*__s++ = __sep; *__s++ = __sep;
} }
do do
{ *__s++ = *__first++;
*__s++ = *__first++;
}
while (__first != __last); while (__first != __last);
return __s; return __s;
} }
// XXX This stuff needs to be re-examined, heavily modified, or ditched.
template<typename _CharT>
_Format_cache<_CharT>::_Format_cache()
: _M_valid(true), _M_use_grouping(false)
{ }
template<>
_Format_cache<char>::_Format_cache();
template<>
_Format_cache<wchar_t>::_Format_cache();
template<typename _CharT>
void
_Format_cache<_CharT>::_M_populate(ios_base& __io)
{
locale __loc = __io.getloc();
numpunct<_CharT> const& __np = use_facet<numpunct<_CharT> >(__loc);
_M_truename = __np.truename();
_M_falsename = __np.falsename();
_M_thousands_sep = __np.thousands_sep();
_M_decimal_point = __np.decimal_point();
_M_grouping = __np.grouping();
_M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0;
_M_valid = true;
}
// This function is always called via a pointer installed in
// an ios_base by ios_base::register_callback.
template<typename _CharT>
void
_Format_cache<_CharT>::
_S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw()
{
void*& __p = __ios.pword(__ix);
switch (__ev)
{
case ios_base::erase_event:
delete static_cast<_Format_cache<_CharT>*>(__p);
__p = 0;
break;
case ios_base::copyfmt_event:
// If just stored zero, the callback would get registered again.
try
{ __p = new _Format_cache<_CharT>; }
catch(...)
{ }
break;
case ios_base::imbue_event:
static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
break;
}
}
template<typename _CharT>
_Format_cache<_CharT>*
_Format_cache<_CharT>::_S_get(ios_base& __ios)
{
if (!_S_pword_ix)
_S_pword_ix = ios_base::xalloc(); // XXX MT
void*& __p = __ios.pword(_S_pword_ix);
// XXX What if pword fails? must check failbit, throw.
if (__p == 0) // XXX MT? maybe sentry takes care of it
{
auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>);
__ios.register_callback(&_Format_cache<_CharT>::_S_callback,
_S_pword_ix);
__p = __ap.release();
}
_Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p);
if (!__ncp->_M_valid)
__ncp->_M_populate(__ios);
return __ncp;
}
} // namespace std } // namespace std
#endif #endif
...@@ -465,93 +465,6 @@ namespace std ...@@ -465,93 +465,6 @@ namespace std
} }
// 27.6.2.5.4 Character inserters // 27.6.2.5.4 Character inserters
// Construct correctly padded string, as per 22.2.2.2.2
// Similar in theory to __pad_numeric, from num_put, but it doesn't
// use _S_fill: perhaps it should.
// Assumes
// __newlen > __oldlen
// __news is allocated for __newlen size
template<typename _CharT, typename _Traits>
void
__pad_char(basic_ios<_CharT, _Traits>& __ios,
_CharT* __news, const _CharT* __olds,
const streamsize __newlen, const streamsize __oldlen)
{
typedef _CharT char_type;
typedef _Traits traits_type;
typedef typename traits_type::int_type int_type;
int_type __plen = static_cast<size_t>(__newlen - __oldlen);
char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen));
traits_type::assign(__pads, __plen, __ios.fill());
char_type* __beg;
char_type* __end;
size_t __mod = 0;
size_t __beglen; //either __plen or __oldlen
ios_base::fmtflags __adjust = __ios.flags() & ios_base::adjustfield;
if (__adjust == ios_base::left)
{
// Padding last.
__beg = const_cast<char_type*>(__olds);
__beglen = __oldlen;
__end = __pads;
}
else if (__adjust == ios_base::internal)
{
// Pad after the sign, if there is one.
// Pad after 0[xX], if there is one.
// Who came up with these rules, anyway? Jeeze.
typedef _Format_cache<_CharT> __cache_type;
__cache_type const* __fmt = __cache_type::_S_get(__ios);
const char_type* __minus = traits_type::find(__olds, __oldlen,
__fmt->_S_minus);
const char_type* __plus = traits_type::find(__olds, __oldlen,
__fmt->_S_plus);
bool __testsign = __minus || __plus;
bool __testhex = __olds[0] == '0'
&& (__olds[1] == 'x' || __olds[1] == 'X');
if (__testhex)
{
__news[0] = __olds[0];
__news[1] = __olds[1];
__mod += 2;
__beg = const_cast<char_type*>(__olds + __mod);
__beglen = __oldlen - __mod;
__end = __pads;
}
else if (__testsign)
{
__mod += __plen;
const char_type* __sign = __minus ? __minus + 1: __plus + 1;
__beg = const_cast<char_type*>(__olds);
__beglen = __sign - __olds;
__end = const_cast<char_type*>(__sign + __plen);
traits_type::copy(__news + __beglen, __pads, __plen);
}
else
{
// Padding first.
__beg = __pads;
__beglen = __plen;
__end = const_cast<char_type*>(__olds);
}
}
else
{
// Padding first.
__beg = __pads;
__beglen = __plen;
__end = const_cast<char_type*>(__olds);
}
traits_type::copy(__news, __beg, __beglen);
traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod);
}
template<typename _CharT, typename _Traits> template<typename _CharT, typename _Traits>
basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c) operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c)
...@@ -568,7 +481,7 @@ namespace std ...@@ -568,7 +481,7 @@ namespace std
streamsize __len = 1; streamsize __len = 1;
if (__w > __len) if (__w > __len)
{ {
__pad_char(__out, __pads, &__c, __w, __len); __pad(__out, __out.fill(), __pads, &__c, __w, __len);
__len = __w; __len = __w;
} }
__out.write(__pads, __len); __out.write(__pads, __len);
...@@ -603,7 +516,7 @@ namespace std ...@@ -603,7 +516,7 @@ namespace std
streamsize __len = 1; streamsize __len = 1;
if (__w > __len) if (__w > __len)
{ {
__pad_char(__out, __pads, &__c, __w, __len); __pad(__out, __out.fill(), __pads, &__c, __w, __len);
__len = __w; __len = __w;
} }
__out.write(__pads, __len); __out.write(__pads, __len);
...@@ -636,7 +549,7 @@ namespace std ...@@ -636,7 +549,7 @@ namespace std
streamsize __len = static_cast<streamsize>(_Traits::length(__s)); streamsize __len = static_cast<streamsize>(_Traits::length(__s));
if (__w > __len) if (__w > __len)
{ {
__pad_char(__out, __pads, __s, __w, __len); __pad(__out, __out.fill(), __pads, __s, __w, __len);
__s = __pads; __s = __pads;
__len = __w; __len = __w;
} }
...@@ -682,7 +595,7 @@ namespace std ...@@ -682,7 +595,7 @@ namespace std
if (__w > __len) if (__w > __len)
{ {
__pad_char(__out, __pads, __ws, __w, __len); __pad(__out, __out.fill(), __pads, __ws, __w, __len);
__str = __pads; __str = __pads;
__len = __w; __len = __w;
} }
...@@ -717,7 +630,7 @@ namespace std ...@@ -717,7 +630,7 @@ namespace std
streamsize __len = static_cast<streamsize>(_Traits::length(__s)); streamsize __len = static_cast<streamsize>(_Traits::length(__s));
if (__w > __len) if (__w > __len)
{ {
__pad_char(__out, __pads, __s, __w, __len); __pad(__out, __out.fill(), __pads, __s, __w, __len);
__s = __pads; __s = __pads;
__len = __w; __len = __w;
} }
...@@ -755,7 +668,7 @@ namespace std ...@@ -755,7 +668,7 @@ namespace std
#endif #endif
if (__w > __len) if (__w > __len)
{ {
__pad_char(__out, __pads, __s, __w, __len); __pad(__out, __out.fill(), __pads, __s, __w, __len);
__s = __pads; __s = __pads;
__len = __w; __len = __w;
} }
......
...@@ -159,21 +159,21 @@ namespace std ...@@ -159,21 +159,21 @@ namespace std
inline __istream_type& inline __istream_type&
get(char_type* __s, streamsize __n) get(char_type* __s, streamsize __n)
{ return get(__s, __n, this->widen('\n')); } { return this->get(__s, __n, this->widen('\n')); }
__istream_type& __istream_type&
get(__streambuf_type& __sb, char_type __delim); get(__streambuf_type& __sb, char_type __delim);
inline __istream_type& inline __istream_type&
get(__streambuf_type& __sb) get(__streambuf_type& __sb)
{ return get(__sb, this->widen('\n')); } { return this->get(__sb, this->widen('\n')); }
__istream_type& __istream_type&
getline(char_type* __s, streamsize __n, char_type __delim); getline(char_type* __s, streamsize __n, char_type __delim);
inline __istream_type& inline __istream_type&
getline(char_type* __s, streamsize __n) getline(char_type* __s, streamsize __n)
{ return getline(__s, __n, this->widen('\n')); } { return this->getline(__s, __n, this->widen('\n')); }
__istream_type& __istream_type&
ignore(streamsize __n = 1, int_type __delim = traits_type::eof()); ignore(streamsize __n = 1, int_type __delim = traits_type::eof());
...@@ -297,4 +297,3 @@ namespace std ...@@ -297,4 +297,3 @@ namespace std
#endif #endif
#endif /* _CPP_ISTREAM */ #endif /* _CPP_ISTREAM */
...@@ -171,8 +171,7 @@ namespace std ...@@ -171,8 +171,7 @@ namespace std
{ {
int_type __eof = traits_type::eof(); int_type __eof = traits_type::eof();
bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof; bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof;
bool __beof = !__b._M_sbuf bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof;
|| __b._M_sbuf->sgetc() == __eof;
return (__thiseof && __beof || (!__thiseof && !__beof)); return (__thiseof && __beof || (!__thiseof && !__beof));
} }
...@@ -184,8 +183,7 @@ namespace std ...@@ -184,8 +183,7 @@ namespace std
{ {
int_type __eof = traits_type::eof(); int_type __eof = traits_type::eof();
bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof; bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof;
bool __beof = !__b._M_sbuf bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof;
|| __b._M_sbuf->sgetc() == __eof;
return (__thiseof && __beof || (!__thiseof && !__beof)); return (__thiseof && __beof || (!__thiseof && !__beof));
} }
#endif #endif
......
...@@ -284,12 +284,6 @@ namespace std ...@@ -284,12 +284,6 @@ namespace std
{ {
locale __old = _M_ios_locale; locale __old = _M_ios_locale;
_M_ios_locale = __loc; _M_ios_locale = __loc;
// Make sure there's a callback for the format caches so they will be
// marked dirty.
_Format_cache<char>::_S_get(*this);
#ifdef _GLIBCPP_USE_WCHAR_T
_Format_cache<wchar_t>::_S_get(*this);
#endif
_M_call_callbacks(imbue_event); _M_call_callbacks(imbue_event);
return __old; return __old;
} }
......
...@@ -56,7 +56,6 @@ namespace std ...@@ -56,7 +56,6 @@ namespace std
template class moneypunct_byname<char, true>; template class moneypunct_byname<char, true>;
template class money_get<char, ibuf_iterator>; template class money_get<char, ibuf_iterator>;
template class money_put<char, obuf_iterator>; template class money_put<char, obuf_iterator>;
template class _Format_cache<char>;
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
template class moneypunct<wchar_t, false>; template class moneypunct<wchar_t, false>;
...@@ -65,19 +64,91 @@ namespace std ...@@ -65,19 +64,91 @@ namespace std
template class moneypunct_byname<wchar_t, true>; template class moneypunct_byname<wchar_t, true>;
template class money_get<wchar_t, wibuf_iterator>; template class money_get<wchar_t, wibuf_iterator>;
template class money_put<wchar_t, wobuf_iterator>; template class money_put<wchar_t, wobuf_iterator>;
template class _Format_cache<wchar_t>;
#endif #endif
// numpunct, numpunct_byname, num_get, and num_put // numpunct, numpunct_byname, num_get, and num_put
template class numpunct<char>; template class numpunct<char>;
template class numpunct_byname<char>; template class numpunct_byname<char>;
template class num_get<char, ibuf_iterator>; template class num_get<char, ibuf_iterator>;
template class num_put<char, obuf_iterator>; template class num_put<char, obuf_iterator>;
template
obuf_iterator
num_put<char, obuf_iterator>::
_M_convert_int(obuf_iterator, ios_base&, char, char, char, long) const;
template
obuf_iterator
num_put<char, obuf_iterator>::
_M_convert_int(obuf_iterator, ios_base&, char, char, char,
unsigned long) const;
#ifdef _GLIBCPP_USE_LONG_LONG
template
obuf_iterator
num_put<char, obuf_iterator>::
_M_convert_int(obuf_iterator, ios_base&, char, char, char,
long long) const;
template
obuf_iterator
num_put<char, obuf_iterator>::
_M_convert_int(obuf_iterator, ios_base&, char, char, char,
unsigned long long) const;
#endif
template
obuf_iterator
num_put<char, obuf_iterator>::
_M_convert_float(obuf_iterator, ios_base&, char, char, double) const;
template
obuf_iterator
num_put<char, obuf_iterator>::
_M_convert_float(obuf_iterator, ios_base&, char, char,
long double) const;
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
template class numpunct<wchar_t>; template class numpunct<wchar_t>;
template class numpunct_byname<wchar_t>; template class numpunct_byname<wchar_t>;
template class num_get<wchar_t, wibuf_iterator>; template class num_get<wchar_t, wibuf_iterator>;
template class num_put<wchar_t, wobuf_iterator>; template class num_put<wchar_t, wobuf_iterator>;
template
wobuf_iterator
num_put<wchar_t, wobuf_iterator>::
_M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char, long) const;
template
wobuf_iterator
num_put<wchar_t, wobuf_iterator>::
_M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char,
unsigned long) const;
#ifdef _GLIBCPP_USE_LONG_LONG
template
wobuf_iterator
num_put<wchar_t, wobuf_iterator>::
_M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char,
long long) const;
template
wobuf_iterator
num_put<wchar_t, wobuf_iterator>::
_M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char,
unsigned long long) const;
#endif
template
wobuf_iterator
num_put<wchar_t, wobuf_iterator>::
_M_convert_float(wobuf_iterator, ios_base&, wchar_t, char,
double) const;
template
wobuf_iterator
num_put<wchar_t, wobuf_iterator>::
_M_convert_float(wobuf_iterator, ios_base&, wchar_t, char,
long double) const;
#endif #endif
// time_get and time_put // time_get and time_put
...@@ -246,8 +317,8 @@ namespace std ...@@ -246,8 +317,8 @@ namespace std
typedef ostreambuf_iterator<char, char_traits<char> > ostreambuf_iter; typedef ostreambuf_iterator<char, char_traits<char> > ostreambuf_iter;
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
typedef istreambuf_iterator<wchar_t,char_traits<wchar_t> > wistreambuf_iter; typedef istreambuf_iterator<wchar_t, char_traits<wchar_t> > wistreambuf_iter;
typedef ostreambuf_iterator<wchar_t,char_traits<wchar_t> > wostreambuf_iter; typedef ostreambuf_iterator<wchar_t, char_traits<wchar_t> > wostreambuf_iter;
#endif #endif
template template
...@@ -255,36 +326,23 @@ namespace std ...@@ -255,36 +326,23 @@ namespace std
locale::operator()(const string&, const string&) const; locale::operator()(const string&, const string&) const;
template template
ostreambuf_iter
__pad<char, ostreambuf_iter, output_iterator_tag>
(ostreambuf_iter, char, int, output_iterator_tag);
template
ostreambuf_iter
__pad_numeric<char, ostreambuf_iter>
(ostreambuf_iter, ios_base::fmtflags, char, int, char const*, char const*,
char const*);
template
char* char*
__group_digits<char>(char*, char, char const*, char const*, __add_grouping<char>(char*, char, char const*, char const*,
char const*, char const*); char const*, char const*);
template template
bool bool
__verify_grouping<char>(const basic_string<char>&, basic_string<char>&); __verify_grouping<char>(const basic_string<char>&, basic_string<char>&);
template template
ostreambuf_iter void
__output_integer<char, ostreambuf_iter, unsigned long> __pad<char>(ios_base&, char, char*, const char *, streamsize,
(ostreambuf_iter, ios_base &, char, bool, unsigned long); streamsize);
#ifdef _GLIBCPP_USE_LONG_LONG
template template
ostreambuf_iter void
__output_integer<char, ostreambuf_iter, unsigned long long> __pad<char, char_traits<char> >(ios_base&, char, char*,
(ostreambuf_iter, ios_base &, char, bool, unsigned long long); const char *, streamsize, streamsize);
#endif
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
template template
...@@ -294,36 +352,24 @@ namespace std ...@@ -294,36 +352,24 @@ namespace std
typedef ostreambuf_iterator<wchar_t> wostreambuf_iter; typedef ostreambuf_iterator<wchar_t> wostreambuf_iter;
template template
wostreambuf_iter
__pad<wchar_t, wostreambuf_iter, output_iterator_tag>
(wostreambuf_iter, wchar_t, int, output_iterator_tag);
template
wostreambuf_iter
__pad_numeric<wchar_t, wostreambuf_iter>
(wostreambuf_iter, ios_base::fmtflags, wchar_t __fill, int, wchar_t const*,
wchar_t const*, wchar_t const*);
template
wchar_t* wchar_t*
__group_digits<wchar_t>(wchar_t*, wchar_t, char const*, char const*, __add_grouping<wchar_t>(wchar_t*, wchar_t, char const*, char const*,
wchar_t const*, wchar_t const*); wchar_t const*, wchar_t const*);
template template
bool bool
__verify_grouping<wchar_t>(const basic_string<wchar_t>&, __verify_grouping<wchar_t>(const basic_string<wchar_t>&,
basic_string<wchar_t>&); basic_string<wchar_t>&);
template template
wostreambuf_iter void
__output_integer<wchar_t, wostreambuf_iter, unsigned long> __pad<wchar_t>(ios_base&, wchar_t, wchar_t*, const wchar_t*,
(wostreambuf_iter, ios_base &, wchar_t, bool, unsigned long); streamsize, streamsize);
#ifdef _GLIBCPP_USE_LONG_LONG
template template
wostreambuf_iter void
__output_integer<wchar_t, wostreambuf_iter, unsigned long long> __pad<wchar_t, char_traits<wchar_t> >(ios_base&, wchar_t, wchar_t*,
(wostreambuf_iter, ios_base &, wchar_t, bool, unsigned long long); const wchar_t*,
#endif streamsize, streamsize);
#endif // _GLIBCPP_USE_WCHAR_T #endif // _GLIBCPP_USE_WCHAR_T
template template
...@@ -342,4 +388,3 @@ namespace std ...@@ -342,4 +388,3 @@ namespace std
__normal_iterator<locale::facet**, vector<locale::facet*> >, __normal_iterator<locale::facet**, vector<locale::facet*> >,
locale::facet* const&); locale::facet* const&);
} // namespace std } // namespace std
...@@ -74,6 +74,8 @@ namespace std ...@@ -74,6 +74,8 @@ namespace std
// Definitions for static const data members of locale::id // Definitions for static const data members of locale::id
size_t locale::id::_S_highwater; // init'd to 0 by linker size_t locale::id::_S_highwater; // init'd to 0 by linker
const char __num_base::_S_atoms[] = "0123456789eEabcdfxABCDFX";
// Definitions for static const data members of locale::_Impl // Definitions for static const data members of locale::_Impl
const locale::id* const const locale::id* const
locale::_Impl::_S_id_ctype[] = locale::_Impl::_S_id_ctype[] =
...@@ -353,7 +355,7 @@ namespace std ...@@ -353,7 +355,7 @@ namespace std
void void
locale::facet:: locale::facet::
_M_add_reference() throw() _M_add_reference() throw()
{ ++_M_references; } // XXX MT { ++_M_references; } // XXX MT
void void
locale::facet:: locale::facet::
...@@ -458,22 +460,6 @@ namespace std ...@@ -458,22 +460,6 @@ namespace std
money_base::_S_default_pattern = {{symbol, sign, none, value}}; money_base::_S_default_pattern = {{symbol, sign, none, value}};
template<> template<>
_Format_cache<char>::_Format_cache()
: _M_valid(true),
_M_decimal_point('.'), _M_thousands_sep(','),
_M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
{ }
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
_Format_cache<wchar_t>::_Format_cache()
: _M_valid(true),
_M_decimal_point(L'.'), _M_thousands_sep(L','),
_M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false)
{ }
#endif
template<>
const ctype<char>& const ctype<char>&
use_facet<ctype<char> >(const locale& __loc) use_facet<ctype<char> >(const locale& __loc)
{ {
...@@ -493,310 +479,9 @@ namespace std ...@@ -493,310 +479,9 @@ namespace std
} }
#endif #endif
template<>
void
num_get<char, istreambuf_iterator<char> >::
_M_extract(istreambuf_iterator<char> __beg,
istreambuf_iterator<char> __end, ios_base& __io,
ios_base::iostate& __err, char* __xtrc, int& __base,
bool __fp) const
{
typedef _Format_cache<char> __cache_type;
// Prepare for possible failure
__xtrc[0] = '\0';
// Stage 1: determine a conversion specifier.
ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
if (__basefield == ios_base::dec)
__base = 10;
else if (__basefield == ios_base::oct)
__base = 8;
else if (__basefield == ios_base::hex)
__base = 16;
else
__base = 0;
// As far as I can tell, bases other than 10 are not available for
// floating point types
if (__fp)
__base = 10;
// Stage 2: extract characters.
__cache_type const* __fmt = __cache_type::_S_get(__io);
// Fail quickly if !__valid
if (__beg == __end)
{
__err |= (ios_base::eofbit | ios_base::failbit);
return;
}
// Acceptable formats for numbers here are based on 22.2.3.1
string __grp;
int __sep_pos = 0;
int __pos = 0;
const char* __lits = __fmt->_S_literals;
char __c = *__beg;
// Check first for sign
bool __testsign = false;
if ((__c == __lits[__cache_type::_S_minus])
|| (__c == __lits[__cache_type::_S_plus]))
{
__testsign = true;
__xtrc[__pos++] = __c;
++__beg;
__c = * __beg;
// Whitespace may follow a sign
while ((__beg != __end) && (isspace(__c)))
{
++__beg;
__c = *__beg;
}
// There had better be more to come...
if (__beg == __end)
{
__xtrc[__pos] = '\0';
__err |= (ios_base::eofbit | ios_base::failbit);
return;
}
}
// Now check if first character is a zero.
bool __testzero = false;
if (__c == __lits[__cache_type::_S_digits])
{
__testzero = true;
++__beg;
__c = *__beg;
// We have to check for __beg == __end here. If so,
// a plain '0' (possibly with a sign) can be got rid of now
if (__beg == __end)
{
__xtrc[__pos++] = __lits[__cache_type::_S_digits];
__xtrc[__pos] = '\0';
__err |= ios_base::eofbit;
return;
}
// Figure out base for integer types only
// Based on Table 55 of 22.2.2.1.2
if (!__fp && __base != 10 && __base != 8)
{
// Here, __base == 0 or 16
if ((__c == __lits[__cache_type::_S_x])
|| (__c == __lits[__cache_type::_S_X]))
{
++__beg;
__c = *__beg;
__base = 16;
__testzero = false; // "0x" is not a leading zero
}
else if (__base == 0)
__base = 8;
}
// Remove any more leading zeros
while (__beg != __end)
{
if (__c == __lits[__cache_type::_S_digits])
{
++__beg;
__c = *__beg;
__testzero = true;
}
else
break;
}
}
else if (__base == 0) // 1st character is not zero
__base = 10;
// We now seek "units", i.e. digits and thousands separators.
// We may need to know if anything is found here. A leading zero
// (removed by now) would count.
bool __testunits = __testzero;
while (__beg != __end)
{
const char* __p = strchr(__lits, __c);
// NB: strchr returns true for __c == 0x0
if (__p && __c
&&((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits]
&& __p < &__lits[__cache_type::_S_udigits + __base])))
{
// Try first for acceptable digit; record it if found.
__xtrc[__pos++] = __c;
++__sep_pos;
__testunits = true;
++__beg;
__c = *__beg;
}
else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping)
{
// NB: Thousands separator at the beginning of a string
// is a no-no, as is two consecutive thousands
// separators.
if (__sep_pos)
{
__grp += static_cast<char>(__sep_pos);
__sep_pos = 0;
++__beg;
__c = *__beg;
}
else
{
__err |= ios_base::failbit;
break;
}
}
else
// Not a valid input item.
break;
}
// Digit grouping is checked. If _M_groupings() doesn't
// match, then get very very upset, and set failbit.
if (__fmt->_M_use_grouping && !__grp.empty())
{
// Add the ending grouping
__grp += static_cast<char>(__sep_pos);
if (!__verify_grouping(__fmt->_M_grouping, __grp))
{
__err |= ios_base::failbit;
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
return;
}
}
// If there was nothing but zeros, put one in the output string
if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
__xtrc[__pos++] = __lits[__cache_type::_S_digits];
// That's it for integer types. Remaining code is for floating point
if (__fp && __beg != __end)
{
// Check first for decimal point. There MUST be one if
// __testunits is false.
bool __testdec = false; // Is there a decimal point
// with digits following it?
if (__c == __fmt->_M_decimal_point)
{
__xtrc[__pos++] = '.';
++__beg;
__c = *__beg;
// Now we get any digits after the decimal point
// There MUST be some if __testunits is false.
while (__beg != __end)
{
const char* __p = strchr(__lits, __c);
if ((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits]
&& __p < &__lits[__cache_type::_S_udigits + __base]))
{
__xtrc[__pos++] = __c;
++__beg;
__c = *__beg;
__testdec = true;
}
else
break;
}
}
if (!__testunits && !__testdec) // Ill formed
{
__err |= ios_base::failbit;
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
return;
}
// Now we may find an exponent
if (__beg != __end)
{
if ((__c == __lits[__cache_type::_S_ee])
|| (__c == __lits[__cache_type::_S_Ee]))
{
__xtrc[__pos++] = __c;
++__beg;
__c = *__beg;
// Now there may be a sign
if (__beg != __end)
{
if ((__c == __lits[__cache_type::_S_minus])
|| (__c == __lits[__cache_type::_S_plus]))
{
__xtrc[__pos++] = __c;
++__beg;
__c = *__beg;
// whitespace may follow a sign
while ((__beg != __end) && (isspace(__c)))
{
++__beg;
__c = *__beg;
}
}
}
// And now there must be some digits
if (__beg == __end)
{
__xtrc[__pos] = '\0';
__err |= (ios_base::eofbit | ios_base::failbit);
return;
}
while (__beg != __end)
{
const char* __p = strchr(__lits, __c);
if ((__p >= &__lits[__cache_type::_S_digits]
&& __p < &__lits[__cache_type::_S_digits + __base])
|| (__p >= &__lits[__cache_type::_S_udigits]
&& __p < &__lits[__cache_type::_S_udigits + __base]))
{
__xtrc[__pos++] = __c;
++__beg;
__c = *__beg;
}
else
break;
}
}
}
// Finally, that's it for floating point
}
// Finish up
__xtrc[__pos] = '\0';
if (__beg == __end)
__err |= ios_base::eofbit;
}
// The following code uses sprintf() to convert floating point
// values for insertion into a stream. The current implementation
// replicates the code in _S_pad_numeric() (in _S_output_float()) in
// order to prevent having to create a "wide" buffer in addition to
// the "narrow" buffer passed to sprintf(). An optimization would be
// to replace sprintf() with code that works directly on a wide
// buffer and then use _S_pad_numeric() to do the padding. It would
// be good to replace sprintf() anyway to avoid accidental buffer
// overruns and to gain back the efficiency that C++ provides by
// knowing up front the type of the values to insert. This
// implementation follows the C++ standard fairly directly as
// outlined in 22.2.2.2 [lib.locale.num.put]
bool bool
__build_float_format(ios_base& __io, char* __fptr, char __modifier, __num_base::_S_format_float(const ios_base& __io, char* __fptr, char __mod,
streamsize __prec) streamsize __prec)
{ {
bool __incl_prec = false; bool __incl_prec = false;
ios_base::fmtflags __flags = __io.flags(); ios_base::fmtflags __flags = __io.flags();
...@@ -809,12 +494,12 @@ namespace std ...@@ -809,12 +494,12 @@ namespace std
// As per [22.2.2.2.2.11] // As per [22.2.2.2.2.11]
if (__flags & ios_base::fixed || __prec > 0) if (__flags & ios_base::fixed || __prec > 0)
{ {
*__fptr++ = '.'; *__fptr++ = '.';
*__fptr++ = '*'; *__fptr++ = '*';
__incl_prec = true; __incl_prec = true;
} }
if (__modifier) if (__mod)
*__fptr++ = __modifier; *__fptr++ = __mod;
ios_base::fmtflags __fltfield = __flags & ios_base::floatfield; ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
// [22.2.2.2.2] Table 58 // [22.2.2.2.2] Table 58
if (__fltfield == ios_base::fixed) if (__fltfield == ios_base::fixed)
...@@ -826,16 +511,43 @@ namespace std ...@@ -826,16 +511,43 @@ namespace std
*__fptr = '\0'; *__fptr = '\0';
return __incl_prec; return __incl_prec;
} }
void
__num_base::_S_format_int(const ios_base& __io, char* __fptr, char __mod,
char __modl)
{
ios_base::fmtflags __flags = __io.flags();
*__fptr++ = '%';
// [22.2.2.2.2] Table 60
if (__flags & ios_base::showpos)
*__fptr++ = '+';
if (__flags & ios_base::showbase)
*__fptr++ = '#';
*__fptr++ = 'l';
// For long long types.
if (__modl)
*__fptr++ = __modl;
ios_base::fmtflags __bsefield = __flags & ios_base::basefield;
if (__bsefield == ios_base::hex)
*__fptr++ = (__flags & ios_base::uppercase) ? 'X' : 'x';
else if (__bsefield == ios_base::oct)
*__fptr++ = 'o';
else
*__fptr++ = __mod;
*__fptr = '\0';
}
template<> template<>
moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/, moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/,
size_t __refs) size_t __refs)
: moneypunct<char, false>(__refs) { } : moneypunct<char, false>(__refs) { }
template<> template<>
moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/, moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/,
size_t __refs) size_t __refs)
: moneypunct<char, true>(__refs) { } : moneypunct<char, true>(__refs) { }
#ifdef _GLIBCPP_USE_WCHAR_T #ifdef _GLIBCPP_USE_WCHAR_T
ctype<wchar_t>::__wmask_type ctype<wchar_t>::__wmask_type
......
...@@ -242,39 +242,6 @@ namespace std ...@@ -242,39 +242,6 @@ namespace std
string*, __false_type); string*, __false_type);
template template
void
__pad_char(basic_ios<char>&, char*, const char*,
const streamsize, const streamsize);
#ifdef _GLIBCPP_USE_WCHAR_T
template
void
__pad_char(basic_ios<wchar_t>&, wchar_t*, const wchar_t*,
const streamsize, const streamsize);
#endif
template
ostreambuf_iterator<char>
__pad_numeric(ostreambuf_iterator<char>, _Ios_Fmtflags, char, int,
const char*, const char*, const char*);
#ifdef _GLIBCPP_USE_WCHAR_T
template
ostreambuf_iterator<wchar_t>
__pad_numeric(ostreambuf_iterator<wchar_t>, _Ios_Fmtflags, wchar_t, int,
const wchar_t*, const wchar_t*, const wchar_t*);
#endif
template
ostreambuf_iterator<char>
__output_float(ostreambuf_iterator<char>, ios_base&, char,
const char*, size_t);
#ifdef _GLIBCPP_USE_WCHAR_T
template
ostreambuf_iterator<wchar_t>
__output_float(ostreambuf_iterator<wchar_t>, ios_base&, wchar_t,
const char*, size_t);
#endif
template
streamsize streamsize
__copy_streambufs(basic_ios<char>&, basic_streambuf<char>*, __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*,
basic_streambuf<char>*); basic_streambuf<char>*);
......
// 2001-11-21 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2001 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.1 Template class num_get
#include <locale>
void test01()
{
// Check for required base class.
typedef std::num_get<char> test_type;
typedef std::locale::facet base_type;
const test_type& obj = std::use_facet<test_type>(std::locale());
const base_type* base = &obj;
// Check for required typedefs
typedef test_type::char_type char_type;
typedef test_type::iter_type iter_type;
}
// Should be able to instantiate this for other types besides char, wchar_t
class gnu_num_get: public std::num_get<unsigned char>
{ };
void test02()
{
gnu_num_get facet01;
}
int main()
{
test01();
test02();
return 0;
}
// 2001-11-21 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2001 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.1.1 num_get members
#include <locale>
#include <sstream>
#include <testsuite_hooks.h>
// XXX This test is not working for non-glibc locale models.
// { dg-do run { xfail *-*-* } }
void test01()
{
using namespace std;
typedef istreambuf_iterator<char> iterator_type;
bool test = true;
// basic construction
locale loc_c = locale::classic();
locale loc_hk("en_HK");
locale loc_fr("fr_FR@euro");
locale loc_de("de_DE");
VERIFY( loc_c != loc_de );
VERIFY( loc_hk != loc_fr );
VERIFY( loc_hk != loc_de );
VERIFY( loc_de != loc_fr );
// cache the numpunct facets
const numpunct<char>& numpunct_c = use_facet<numpunct<char> >(loc_c);
const numpunct<char>& numpunct_de = use_facet<numpunct<char> >(loc_de);
const numpunct<char>& numpunct_hk = use_facet<numpunct<char> >(loc_hk);
// sanity check the data is correct.
const string empty;
char c;
bool b1 = true;
bool b0 = false;
long l1 = 2147483647;
long l2 = -2147483647;
long l;
unsigned long ul1 = 1294967294;
unsigned long ul2 = 0;
unsigned long ul;
double d1 = 1.02345e+308;
double d2 = 3.15e-308;
double d;
long double ld1 = 6.630025e+4;
long double ld2 = 0.0;
long double ld;
void* v;
const void* cv = &ul2;
// cache the num_get facet
istringstream iss;
iss.imbue(loc_de);
const num_get<char>& ng = use_facet<num_get<char> >(iss.getloc());
const ios_base::iostate goodbit = ios_base::goodbit;
const ios_base::iostate eofbit = ios_base::eofbit;
ios_base::iostate err = ios_base::goodbit;
// bool, simple
iss.str("1");
iterator_type os_it00 = iss.rdbuf();
iterator_type os_it01 = ng.get(os_it00, 0, iss, err, b1);
VERIFY( b1 == true );
VERIFY( err & ios_base::eofbit );
iss.str("0");
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, b0);
VERIFY( b0 == false );
VERIFY( err & eofbit );
// bool, more twisted examples
iss.imbue(loc_c);
iss.str("true ");
iss.clear();
iss.setf(ios_base::boolalpha);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, b0);
VERIFY( b0 == true );
VERIFY( err == goodbit );
iss.str("false ");
iss.clear();
iss.setf(ios_base::boolalpha);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, b1);
VERIFY( b1 == false );
VERIFY( err == goodbit );
// long, in a locale that expects grouping
iss.imbue(loc_hk);
iss.str("2,147,483,647 ");
iss.clear();
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, l);
VERIFY( l == l1 );
VERIFY( err == goodbit );
iss.str("-2,147,483,647++++++");
iss.clear();
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, l);
VERIFY( l == l2 );
VERIFY( err == goodbit );
// unsigned long, in a locale that does not group
iss.imbue(loc_c);
iss.str("1294967294");
iss.clear();
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, ul);
VERIFY( ul == ul1);
VERIFY( err == eofbit );
iss.str("0+++++++++++++++++++");
iss.clear();
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, ul);
VERIFY( ul == ul2);
VERIFY( err == goodbit );
// ... and one that does
iss.imbue(loc_de);
iss.str("1.294.967.294+++++++");
iss.clear();
iss.width(20);
iss.setf(ios_base::left, ios_base::adjustfield);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, ul);
VERIFY( ul == ul1 );
VERIFY( err == goodbit );
// double
iss.imbue(loc_c);
iss.str("1.02345e+308++++++++");
iss.clear();
iss.width(20);
iss.setf(ios_base::left, ios_base::adjustfield);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, d);
VERIFY( d == d1 );
VERIFY( err == goodbit );
iss.str("+3.15e-308");
iss.clear();
iss.width(20);
iss.setf(ios_base::right, ios_base::adjustfield);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, d);
VERIFY( d == d2 );
VERIFY( err == eofbit );
iss.imbue(loc_de);
iss.str("+1,02345e+308");
iss.clear();
iss.width(20);
iss.setf(ios_base::right, ios_base::adjustfield);
iss.setf(ios_base::scientific, ios_base::floatfield);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, d);
VERIFY( d == d1 );
VERIFY( err == eofbit );
iss.str("3,15E-308 ");
iss.clear();
iss.width(20);
iss.precision(10);
iss.setf(ios_base::right, ios_base::adjustfield);
iss.setf(ios_base::scientific, ios_base::floatfield);
iss.setf(ios_base::uppercase);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, d);
VERIFY( d == d2 );
VERIFY( err == goodbit );
// long double
iss.str("6,630025e+4");
iss.clear();
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, ld);
VERIFY( ld == ld1 );
VERIFY( err == eofbit );
iss.str("0 ");
iss.clear();
iss.precision(0);
iss.setf(ios_base::fixed, ios_base::floatfield);
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, ld);
VERIFY( ld == 0 );
VERIFY( err == goodbit );
// const void
iss.str("0xbffff74c.");
iss.clear();
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, v);
VERIFY( &v != &cv );
VERIFY( err == goodbit );
#ifdef _GLIBCPP_USE_LONG_LONG
long long ll1 = 9223372036854775807;
long long ll2 = -9223372036854775807;
long long ll;
iss.str("9.223.372.036.854.775.807");
iss.clear();
err = goodbit;
ng.get(iss.rdbuf(), 0, iss, err, ll);
VERIFY( ll == ll1 );
VERIFY( err == eofbit );
#endif
}
int main()
{
test01();
return 0;
}
// Kathleen Hannah, humanitarian, woman, art-thief
// 2001-11-19 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2001 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 Template class num_put
#include <locale>
void test01()
{
// Check for required base class.
typedef std::num_put<char> test_type;
typedef std::locale::facet base_type;
const test_type& obj = std::use_facet<test_type>(std::locale());
const base_type* base = &obj;
// Check for required typedefs
typedef test_type::char_type char_type;
typedef test_type::iter_type iter_type;
}
// Should be able to instantiate this for other types besides char, wchar_t
class gnu_num_put: public std::num_put<unsigned char>
{ };
void test02()
{
gnu_num_put facet01;
}
int main()
{
test01();
test02();
return 0;
}
// 2001-11-19 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2001 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>
// XXX This test is not working for non-glibc locale models.
// { dg-do run { xfail *-*-* } }
void test01()
{
using namespace std;
typedef ostreambuf_iterator<char> iterator_type;
bool test = true;
// basic construction
locale loc_c = locale::classic();
locale loc_hk("en_HK");
locale loc_fr("fr_FR@euro");
locale loc_de("de_DE");
VERIFY( loc_c != loc_de );
VERIFY( loc_hk != loc_fr );
VERIFY( loc_hk != loc_de );
VERIFY( loc_de != loc_fr );
// cache the numpunct facets
const numpunct<char>& numpunct_c = use_facet<numpunct<char> >(loc_c);
const numpunct<char>& numpunct_de = use_facet<numpunct<char> >(loc_de);
const numpunct<char>& numpunct_hk = use_facet<numpunct<char> >(loc_hk);
// sanity check the data is correct.
const string empty;
string result1;
string result2;
char c;
bool b1 = true;
bool b0 = false;
long l1 = 2147483647;
long l2 = -2147483647;
unsigned long ul1 = 1294967294;
unsigned long ul2 = 0;
double d1 = 1.7976931348623157e+308;
double d2 = 2.2250738585072014e-308;
long double ld1 = 1.7976931348623157e+308;
long double ld2 = 2.2250738585072014e-308;
const void* cv = &ld1;
// cache the num_put facet
ostringstream oss;
oss.imbue(loc_de);
const num_put<char>& np = use_facet<num_put<char> >(oss.getloc());
// bool, simple
iterator_type os_it00 = oss.rdbuf();
iterator_type os_it01 = np.put(os_it00, oss, '+', b1);
result1 = oss.str();
VERIFY( result1 == "1" );
// VERIFY( os_it00 != os_it01 );
oss.str(empty);
np.put(oss.rdbuf(), oss, '+', b0);
result2 = oss.str();
VERIFY( result2 == "0" );
// bool, more twisted examples
oss.imbue(loc_c);
oss.str(empty);
oss.width(20);
oss.setf(ios_base::right, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, '+', b0);
result1 = oss.str();
VERIFY( result1 == "+++++++++++++++++++0" );
oss.str(empty);
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
oss.setf(ios_base::boolalpha);
np.put(oss.rdbuf(), oss, '+', b1);
result2 = oss.str();
VERIFY( result2 == "true++++++++++++++++" );
// long, in a locale that expects grouping
oss.imbue(loc_hk);
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, '+', l1);
result1 = oss.str();
VERIFY( result1 == "2,147,483,647" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, '+', l2);
result1 = oss.str();
VERIFY( result1 == "-2,147,483,647++++++" );
// unsigned long, in a locale that does not group
oss.imbue(loc_c);
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, '+', ul1);
result1 = oss.str();
VERIFY( result1 == "1294967294" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, '+', ul2);
result1 = oss.str();
VERIFY( result1 == "0+++++++++++++++++++" );
// ... and one that does
oss.imbue(loc_de);
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, '+', ul1);
result1 = oss.str();
VERIFY( result1 == "1.294.967.294+++++++" );
// double
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, '+', d1);
result1 = oss.str();
VERIFY( result1 == "1,79769e+308++++++++" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::right, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, '+', d2);
result1 = oss.str();
VERIFY( result1 == "++++++++2,22507e-308" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::right, ios_base::adjustfield);
oss.setf(ios_base::scientific, ios_base::floatfield);
np.put(oss.rdbuf(), oss, '+', d2);
result2 = oss.str();
VERIFY( result2 == "+++++++2,225074e-308" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.precision(10);
oss.setf(ios_base::right, ios_base::adjustfield);
oss.setf(ios_base::scientific, ios_base::floatfield);
oss.setf(ios_base::uppercase);
np.put(oss.rdbuf(), oss, '+', d2);
result1 = oss.str();
VERIFY( result1 == "+++2,2250738585E-308" );
// long double
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, '+', ld1);
result1 = oss.str();
VERIFY( result1 == "1,7976931349E+308" );
oss.str(empty);
oss.clear();
oss.precision(0);
oss.setf(ios_base::fixed, ios_base::floatfield);
np.put(oss.rdbuf(), oss, '+', ld2);
result1 = oss.str();
VERIFY( result1 == "0" );
// const void
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, '+', cv);
result1 = oss.str();
// No grouping characters.
VERIFY( !char_traits<char>::find(result1.c_str(),
numpunct_de.decimal_point(),
result1.size()) );
// Should contain an 'x'.
VERIFY( !char_traits<char>::find(result1.c_str(), 'x', result1.size()) );
#ifdef _GLIBCPP_USE_LONG_LONG
long long ll1 = 9223372036854775807;
long long ll2 = -9223372036854775807;
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, '+', ll1);
result1 = oss.str();
VERIFY( result1 == "9.223.372.036.854.775.807" );
#endif
}
int main()
{
test01();
return 0;
}
// 2001-11-19 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2001 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>
// XXX This test is not working for non-glibc locale models.
// { dg-do run { xfail *-*-* } }
#ifdef _GLIBCPP_USE_WCHAR_T
void test01()
{
using namespace std;
typedef ostreambuf_iterator<wchar_t> iterator_type;
bool test = true;
// basic construction
locale loc_c = locale::classic();
locale loc_hk("en_HK");
locale loc_fr("fr_FR@euro");
locale loc_de("de_DE");
VERIFY( loc_c != loc_de );
VERIFY( loc_hk != loc_fr );
VERIFY( loc_hk != loc_de );
VERIFY( loc_de != loc_fr );
// cache the numpunct facets
const numpunct<wchar_t>& numpunct_c = use_facet<numpunct<wchar_t> >(loc_c);
const numpunct<wchar_t>& numpunct_de = use_facet<numpunct<wchar_t> >(loc_de);
const numpunct<wchar_t>& numpunct_hk = use_facet<numpunct<wchar_t> >(loc_hk);
// sanity check the data is correct.
const wstring empty;
wstring result1;
wstring result2;
wchar_t c;
bool b1 = true;
bool b0 = false;
long l1 = 2147483647;
long l2 = -2147483647;
unsigned long ul1 = 1294967294;
unsigned long ul2 = 0;
double d1 = 1.7976931348623157e+308;
double d2 = 2.2250738585072014e-308;
long double ld1 = 1.7976931348623157e+308;
long double ld2 = 2.2250738585072014e-308;
const void* cv = &ld1;
// cache the num_put facet
wostringstream oss;
oss.imbue(loc_de);
const num_put<wchar_t>& np = use_facet<num_put<wchar_t> >(oss.getloc());
// bool, simple
iterator_type os_it00 = oss.rdbuf();
iterator_type os_it01 = np.put(os_it00, oss, '+', b1);
result1 = oss.str();
VERIFY( result1 == L"1" );
// VERIFY( os_it00 != os_it01 );
oss.str(empty);
np.put(oss.rdbuf(), oss, L'+', b0);
result2 = oss.str();
VERIFY( result2 == L"0" );
// bool, more twisted examples
oss.imbue(loc_c);
oss.str(empty);
oss.width(20);
oss.setf(ios_base::right, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, L'+', b0);
result1 = oss.str();
VERIFY( result1 == L"+++++++++++++++++++0" );
oss.str(empty);
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
oss.setf(ios_base::boolalpha);
np.put(oss.rdbuf(), oss, L'+', b1);
result2 = oss.str();
VERIFY( result2 == L"true++++++++++++++++" );
// long, in a locale that expects grouping
oss.imbue(loc_hk);
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, L'+', l1);
result1 = oss.str();
VERIFY( result1 == L"2,147,483,647" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, L'+', l2);
result1 = oss.str();
VERIFY( result1 == L"-2,147,483,647++++++" );
// unsigned long, in a locale that does not group
oss.imbue(loc_c);
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, L'+', ul1);
result1 = oss.str();
VERIFY( result1 == L"1294967294" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, L'+', ul2);
result1 = oss.str();
VERIFY( result1 == L"0+++++++++++++++++++" );
// ... and one that does
oss.imbue(loc_de);
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, L'+', ul1);
result1 = oss.str();
VERIFY( result1 == L"1.294.967.294+++++++" );
// double
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::left, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, L'+', d1);
result1 = oss.str();
VERIFY( result1 == L"1,79769e+308++++++++" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::right, ios_base::adjustfield);
np.put(oss.rdbuf(), oss, L'+', d2);
result1 = oss.str();
VERIFY( result1 == L"++++++++2,22507e-308" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.setf(ios_base::right, ios_base::adjustfield);
oss.setf(ios_base::scientific, ios_base::floatfield);
np.put(oss.rdbuf(), oss, L'+', d2);
result2 = oss.str();
VERIFY( result2 == L"+++++++2,225074e-308" );
oss.str(empty);
oss.clear();
oss.width(20);
oss.precision(10);
oss.setf(ios_base::right, ios_base::adjustfield);
oss.setf(ios_base::scientific, ios_base::floatfield);
oss.setf(ios_base::uppercase);
np.put(oss.rdbuf(), oss, L'+', d2);
result1 = oss.str();
VERIFY( result1 == L"+++2,2250738585E-308" );
// long double
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, L'+', ld1);
result1 = oss.str();
VERIFY( result1 == L"1,7976931349E+308" );
oss.str(empty);
oss.clear();
oss.precision(0);
oss.setf(ios_base::fixed, ios_base::floatfield);
np.put(oss.rdbuf(), oss, L'+', ld2);
result1 = oss.str();
VERIFY( result1 == L"0" );
// const void
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, L'+', cv);
result1 = oss.str();
// No grouping characters.
VERIFY( !char_traits<wchar_t>::find(result1.c_str(),
numpunct_de.decimal_point(),
result1.size()) );
// Should contain an 'x'.
VERIFY( !char_traits<wchar_t>::find(result1.c_str(), L'x', result1.size()) );
#ifdef _GLIBCPP_USE_LONG_LONG
long long ll1 = 9223372036854775807;
long long ll2 = -9223372036854775807;
oss.str(empty);
oss.clear();
np.put(oss.rdbuf(), oss, '+', ll1);
result1 = oss.str();
VERIFY( result1 == L"9.223.372.036.854.775.807" );
#endif
}
#endif
int main()
{
#ifdef _GLIBCPP_USE_WCHAR_T
test01();
#endif
return 0;
}
// Diana D. Brooks, former chief executive of Sotheby's
// art-thief extraordinaire
...@@ -75,19 +75,12 @@ void test01() ...@@ -75,19 +75,12 @@ void test01()
VERIFY( dp2 != dp3 ); VERIFY( dp2 != dp3 );
VERIFY( th2 != th3 ); VERIFY( th2 != th3 );
#if 0
// XXX isn't actually supported right now.
VERIFY( t2 != t3 );
VERIFY( f2 != f3 );
#endif
VERIFY( dp2 != dp4 ); VERIFY( dp2 != dp4 );
VERIFY( th2 != th4 ); VERIFY( th2 != th4 );
#if 0 // XXX This isn't actually supported right now.
// XXX isn't actually supported right now. // VERIFY( t2 != t3 );
VERIFY( t2 != t3 ); // VERIFY( f2 != f3 );
VERIFY( f2 != f3 );
#endif
} }
int main() int main()
......
// 2001-11-20 Benjamin Kosnik <bkoz@redhat.com>
// Copyright (C) 2001 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.3.1.1 nunpunct members
#include <locale>
#include <testsuite_hooks.h>
// XXX This test is not working for non-glibc locale models.
// { dg-do run { xfail *-*-* } }
void test01()
{
using namespace std;
bool test = true;
// basic construction
locale loc_c = locale::classic();
locale loc_us("en_US");
locale loc_fr("fr_FR");
locale loc_de("de_DE");
VERIFY( loc_c != loc_de );
VERIFY( loc_us != loc_fr );
VERIFY( loc_us != loc_de );
VERIFY( loc_de != loc_fr );
// cache the numpunct facets
const numpunct<wchar_t>& nump_c = use_facet<numpunct<wchar_t> >(loc_c);
const numpunct<wchar_t>& nump_us = use_facet<numpunct<wchar_t> >(loc_us);
const numpunct<wchar_t>& nump_fr = use_facet<numpunct<wchar_t> >(loc_fr);
const numpunct<wchar_t>& nump_de = use_facet<numpunct<wchar_t> >(loc_de);
// sanity check the data is correct.
wchar_t dp1 = nump_c.decimal_point();
wchar_t th1 = nump_c.thousands_sep();
string g1 = nump_c.grouping();
wstring t1 = nump_c.truename();
wstring f1 = nump_c.falsename();
wchar_t dp2 = nump_us.decimal_point();
wchar_t th2 = nump_us.thousands_sep();
string g2 = nump_us.grouping();
wstring t2 = nump_us.truename();
wstring f2 = nump_us.falsename();
wchar_t dp3 = nump_fr.decimal_point();
wchar_t th3 = nump_fr.thousands_sep();
string g3 = nump_fr.grouping();
wstring t3 = nump_fr.truename();
wstring f3 = nump_fr.falsename();
wchar_t dp4 = nump_de.decimal_point();
wchar_t th4 = nump_de.thousands_sep();
string g4 = nump_de.grouping();
wstring t4 = nump_de.truename();
wstring f4 = nump_de.falsename();
VERIFY( dp2 != dp3 );
VERIFY( th2 != th3 );
VERIFY( dp2 != dp4 );
VERIFY( th2 != th4 );
}
int main()
{
test01();
return 0;
}
...@@ -387,7 +387,7 @@ bool test09() ...@@ -387,7 +387,7 @@ bool test09()
} }
bool test10() { bool test10() {
std::string str_01("0 00 000 +0 + 0 - 0"); std::string str_01("0 00 000 +0 +0 -0");
std::stringbuf isbuf_01(str_01); std::stringbuf isbuf_01(str_01);
std::istream is_01(&isbuf_01); std::istream is_01(&isbuf_01);
...@@ -447,7 +447,7 @@ bool test10() { ...@@ -447,7 +447,7 @@ bool test10() {
VERIFY( n == 33 ); VERIFY( n == 33 );
VERIFY( is_03.rdstate() == std::ios_base::eofbit ); VERIFY( is_03.rdstate() == std::ios_base::eofbit );
std::string str_04("3. 4.5E+ 2a5E-3 .6E1"); std::string str_04("3. 4.5E+2a5E-3 .6E1");
std::stringbuf isbuf_04(str_04); std::stringbuf isbuf_04(str_04);
std::istream is_04(&isbuf_04); std::istream is_04(&isbuf_04);
......
...@@ -63,13 +63,13 @@ static bool F=false; ...@@ -63,13 +63,13 @@ static bool F=false;
static _TestCase testcases[] = static _TestCase testcases[] =
{ {
#if _GLIBCPP_USE_WCHAR_T #if _GLIBCPP_USE_WCHAR_T
// standard output (no formatting applied) // standard output (no formatting applied) 1-4
{ 1.2, 6,0,'.',' ', F,F,F,F,F,F,F,F, "1.2",L"1.2" }, { 1.2, 6,0,'.',' ', F,F,F,F,F,F,F,F, "1.2",L"1.2" },
{ 54, 6,0,'.',' ', F,F,F,F,F,F,F,F, "54",L"54" }, { 54, 6,0,'.',' ', F,F,F,F,F,F,F,F, "54",L"54" },
{ -.012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-0.012",L"-0.012" }, { -.012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-0.012",L"-0.012" },
{ -.00000012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-1.2e-07",L"-1.2e-07" }, { -.00000012, 6,0,'.',' ', F,F,F,F,F,F,F,F, "-1.2e-07",L"-1.2e-07" },
// fixed formatting // fixed formatting 5-11
{ 10.2345, 0,0,'.',' ', T,F,F,F,F,F,F,F, "10",L"10" }, { 10.2345, 0,0,'.',' ', T,F,F,F,F,F,F,F, "10",L"10" },
{ 10.2345, 0,0,'.',' ', T,F,F,T,F,F,F,F, "10.",L"10." }, { 10.2345, 0,0,'.',' ', T,F,F,T,F,F,F,F, "10.",L"10." },
{ 10.2345, 1,0,'.',' ', T,F,F,F,F,F,F,F, "10.2",L"10.2" }, { 10.2345, 1,0,'.',' ', T,F,F,F,F,F,F,F, "10.2",L"10.2" },
...@@ -78,7 +78,7 @@ static _TestCase testcases[] = ...@@ -78,7 +78,7 @@ static _TestCase testcases[] =
{ -10.2345, 6,0,'.',' ', T,F,F,F,F,F,F,F, "-10.234500",L"-10.234500" }, { -10.2345, 6,0,'.',' ', T,F,F,F,F,F,F,F, "-10.234500",L"-10.234500" },
{ -10.2345, 6,0,',',' ', T,F,F,F,F,F,F,F, "-10,234500",L"-10,234500" }, { -10.2345, 6,0,',',' ', T,F,F,F,F,F,F,F, "-10,234500",L"-10,234500" },
// fixed formatting with width // fixed formatting with width 12-22
{ 10.2345, 4,5,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" }, { 10.2345, 4,5,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" },
{ 10.2345, 4,6,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" }, { 10.2345, 4,6,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" },
{ 10.2345, 4,7,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" }, { 10.2345, 4,7,'.',' ', T,F,F,F,F,F,F,F, "10.2345",L"10.2345" },
...@@ -91,7 +91,7 @@ static _TestCase testcases[] = ...@@ -91,7 +91,7 @@ static _TestCase testcases[] =
{ -10.2345, 4,10,'.','A', T,F,F,F,F,T,F,F, "-AA10.2345",L"-AA10.2345" }, { -10.2345, 4,10,'.','A', T,F,F,F,F,T,F,F, "-AA10.2345",L"-AA10.2345" },
{ 10.2345, 4,10,'.','#', T,F,T,F,F,T,F,F, "+##10.2345",L"+##10.2345" }, { 10.2345, 4,10,'.','#', T,F,T,F,F,T,F,F, "+##10.2345",L"+##10.2345" },
// scientific formatting // scientific formatting 23-29
{ 1.23e+12, 1,0,'.',' ', F,T,F,F,F,F,F,F, "1.2e+12",L"1.2e+12" }, { 1.23e+12, 1,0,'.',' ', F,T,F,F,F,F,F,F, "1.2e+12",L"1.2e+12" },
{ 1.23e+12, 1,0,'.',' ', F,T,F,F,T,F,F,F, "1.2E+12",L"1.2E+12" }, { 1.23e+12, 1,0,'.',' ', F,T,F,F,T,F,F,F, "1.2E+12",L"1.2E+12" },
{ 1.23e+12, 2,0,'.',' ', F,T,F,F,F,F,F,F, "1.23e+12",L"1.23e+12" }, { 1.23e+12, 2,0,'.',' ', F,T,F,F,F,F,F,F, "1.23e+12",L"1.23e+12" },
...@@ -207,7 +207,7 @@ test01() ...@@ -207,7 +207,7 @@ test01()
apply_formatting(tc, os); apply_formatting(tc, os);
os << tc.val; os << tc.val;
#ifdef TEST_NUMPUT_VERBOSE #ifdef TEST_NUMPUT_VERBOSE
cout << "result: " << os.str() << endl; cout << j << "result 1: " << os.str() << endl;
#endif #endif
VERIFY( os && os.str() == tc.result ); VERIFY( os && os.str() == tc.result );
} }
...@@ -220,7 +220,7 @@ test01() ...@@ -220,7 +220,7 @@ test01()
apply_formatting(tc, os); apply_formatting(tc, os);
os << (long double)tc.val; os << (long double)tc.val;
#ifdef TEST_NUMPUT_VERBOSE #ifdef TEST_NUMPUT_VERBOSE
cout << "result: " << os.str() << endl; cout << j << "result 2: " << os.str() << endl;
#endif #endif
VERIFY( os && os.str() == tc.result ); VERIFY( os && os.str() == tc.result );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment