From 86ade44cb2ce7df746d88f6491de469cc6a62c14 Mon Sep 17 00:00:00 2001 From: Benjamin Kosnik Date: Wed, 28 Nov 2001 04:07:11 +0000 Subject: [PATCH] Numeric facets cleanup. 2001-11-27 Benjamin Kosnik 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 --- libstdc++-v3/ChangeLog | 71 ++ libstdc++-v3/include/bits/istream.tcc | 25 +- libstdc++-v3/include/bits/locale_facets.h | 538 +++------ libstdc++-v3/include/bits/locale_facets.tcc | 1074 +++++++++-------- libstdc++-v3/include/bits/ostream.tcc | 99 +- libstdc++-v3/include/bits/std_istream.h | 7 +- .../include/bits/streambuf_iterator.h | 6 +- libstdc++-v3/src/ios.cc | 6 - libstdc++-v3/src/locale-inst.cc | 141 ++- libstdc++-v3/src/locale.cc | 374 +----- libstdc++-v3/src/misc-inst.cc | 33 - libstdc++-v3/testsuite/22_locale/num_get.cc | 52 + .../22_locale/num_get_members_char.cc | 246 ++++ libstdc++-v3/testsuite/22_locale/num_put.cc | 52 + .../22_locale/num_put_members_char.cc | 230 ++++ .../22_locale/num_put_members_wchar_t.cc | 234 ++++ .../22_locale/numpunct_members_char.cc | 13 +- .../22_locale/numpunct_members_wchar_t.cc | 88 ++ .../27_io/istream_extractor_arith.cc | 4 +- .../testsuite/27_io/ostream_inserter_arith.cc | 12 +- 20 files changed, 1892 insertions(+), 1413 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/num_get.cc create mode 100644 libstdc++-v3/testsuite/22_locale/num_get_members_char.cc create mode 100644 libstdc++-v3/testsuite/22_locale/num_put.cc create mode 100644 libstdc++-v3/testsuite/22_locale/num_put_members_char.cc create mode 100644 libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc create mode 100644 libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0f58b3cf82b..b86bf98c08a 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,74 @@ +2001-11-27 Benjamin Kosnik + + 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 * docs/html/explanations.html: New section, empty for now. diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index 47b01f6bae2..43ea6a5a37e 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -134,8 +134,18 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + long __l; 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::min() <= __l + && __l <= numeric_limits::max())) + __n = __l; + else + __err |= ios_base::failbit; +#endif this->setstate(__err); } catch(exception& __fail) @@ -188,8 +198,18 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); + long __l; 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::min() <= __l + && __l <= numeric_limits::max())) + __n = __l; + else + __err |= ios_base::failbit; +#endif this->setstate(__err); } catch(exception& __fail) @@ -1252,4 +1272,3 @@ namespace std // Local Variables: // mode:C++ // End: - diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index 8ea0ed547ef..878f8b28cab 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -415,162 +415,157 @@ namespace std // 22.2.1.5 Template class codecvt #include - template - class _Numeric_get; // forward - // _Format_cache holds the information extracted from the numpunct<> - // and moneypunct<> facets in a form optimized for parsing and - // formatting. It is stored via a void* pointer in the pword() - // array of an iosbase object passed to the _get and _put facets. - // NB: contains no user-serviceable parts. + class __num_base + { + public: + // String literal of acceptable (narrow) input, for num_get. + // "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 - class _Format_cache + class numpunct : public locale::facet { - public: + public: // Types: - typedef _CharT char_type; - typedef char_traits<_CharT> traits_type; - typedef basic_string<_CharT> string_type; - typedef typename string_type::size_type size_type; - - // Forward decls and Friends: - friend class locale; - template - 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>; + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; - // Data Members: + static locale::id id; - // ios_base::pword() reserved cell - static int _S_pword_ix; - - // True iff data members are consistent with the current locale, - // ie imbue sets this to false. - bool _M_valid; - - // 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); + private: + char_type _M_decimal_point; + char_type _M_thousands_sep; + string _M_grouping; + string_type _M_truename; + string_type _M_falsename; - void - _M_populate(ios_base&); + 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; } - static void - _S_callback(ios_base::event __event, ios_base& __ios, int __ix) throw(); + 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 - int _Format_cache<_CharT>::_S_pword_ix; + locale::id numpunct<_CharT>::id; + // NB: Cannot be made generic. template - const char _Format_cache<_CharT>:: - _S_literals[] = "-+xX0123456789abcdef0123456789ABCDEF"; + void + numpunct<_CharT>::_M_initialize_numpunct(__c_locale) + { } - template<> _Format_cache::_Format_cache(); + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc); #ifdef _GLIBCPP_USE_WCHAR_T - template<> _Format_cache::_Format_cache(); + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc); #endif - // _Numeric_get is used by num_get, money_get, and time_get to help - // in parsing out numbers. - template - class _Numeric_get + template + class numpunct_byname : public numpunct<_CharT> { + // Data Member. + __c_locale _M_c_locale_numpunct; + public: - // Types: - typedef _CharT char_type; - typedef _InIter iter_type; - - // Forward decls and Friends: - template - friend class num_get; - template - friend class time_get; - template - friend class money_get; - template - friend class num_put; - template - friend class time_put; - template - friend class money_put; + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; - private: 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 - ~_Numeric_get() { } - - iter_type - _M_get_digits(iter_type __in, iter_type __end) const; + ~numpunct_byname() + { _S_destroy_c_locale(_M_c_locale_numpunct); } }; template - class num_get : public locale::facet + class num_get : public locale::facet, public __num_base { public: // Types: typedef _CharT char_type; typedef _InIter iter_type; - typedef char_traits<_CharT> __traits_type; static locale::id id; @@ -580,118 +575,99 @@ namespace std iter_type get(iter_type __in, iter_type __end, ios_base& __io, ios_base::iostate& __err, bool& __v) const - { return 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 + { 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, long& __v) const - { return 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 + { 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 short& __v) const - { return do_get(__in, __end, __io, __err, __v); } + { 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 int& __v) const - { return do_get(__in, __end, __io, __err, __v); } + { 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& __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 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 - { return do_get(__in, __end, __io, __err, __v); } + { return this->do_get(__in, __end, __io, __err, __v); } #endif iter_type get(iter_type __in, iter_type __end, ios_base& __io, 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 get(iter_type __in, iter_type __end, ios_base& __io, 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 get(iter_type __in, iter_type __end, ios_base& __io, 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 get(iter_type __in, iter_type __end, ios_base& __io, 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: 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 - _M_extract(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, char* __xtrc, - int& __base, bool __fp = true) const; + _M_extract_float(iter_type, iter_type, ios_base&, ios_base::iostate&, + char* __xtrc) const; + + void + _M_extract_int(iter_type, iter_type, ios_base&, ios_base::iostate&, + char* __xtrc, int& __base) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, bool&) const; -#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS - //XXX. What number? 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 - do_get(iter_type, iter_type, ios_base&, ios_base::iostate&, int&) const; -#endif + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + unsigned short&) 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&, long&) const; + 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, long long&) const; -#endif + virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, - unsigned short&) 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; + unsigned long long&) const; #endif + virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, float&) const; @@ -701,8 +677,8 @@ namespace std double&) const; virtual iter_type - do_get(iter_type, iter_type, ios_base&, - ios_base::iostate& __err, long double&) const; + do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, + long double&) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& __err, @@ -712,38 +688,13 @@ namespace std template locale::id num_get<_CharT, _InIter>::id; - // Declare specialized extraction member function. - template<> - void - num_get >:: - _M_extract(istreambuf_iterator __beg, - istreambuf_iterator __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 - class _Numeric_put - { - public: - typedef _CharT char_type; - typedef _OutIter iter_type; - protected: - explicit - _Numeric_put() { } - - virtual - ~_Numeric_put() { } - }; - - template - class num_put : public locale::facet + class num_put : public locale::facet, public __num_base { public: // Types: - typedef _CharT char_type; - typedef _OutIter iter_type; + typedef _CharT char_type; + typedef _OutIter iter_type; static locale::id id; @@ -752,43 +703,65 @@ namespace std iter_type 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 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 put(iter_type __s, ios_base& __f, char_type __fill, unsigned long __v) const - { return do_put(__s, __f, __fill, __v); } + { return this->do_put(__s, __f, __fill, __v); } #ifdef _GLIBCPP_USE_LONG_LONG iter_type 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 put(iter_type __s, ios_base& __f, char_type __fill, unsigned long long __v) const - { return do_put(__s, __f, __fill, __v); } + { return this->do_put(__s, __f, __fill, __v); } #endif iter_type 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 put(iter_type __s, ios_base& __f, char_type __fill, long double __v) const - { return do_put(__s, __f, __fill, __v); } + { return this->do_put(__s, __f, __fill, __v); } iter_type put(iter_type __s, ios_base& __f, char_type __fill, const void* __v) const - { return do_put(__s, __f, __fill, __v); } + { return this->do_put(__s, __f, __fill, __v); } protected: + template + iter_type + _M_convert_float(iter_type, ios_base& __io, char_type __fill, + char __mod, _ValueT __v) const; + + template + 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 ~num_put() { }; @@ -798,15 +771,13 @@ namespace std virtual iter_type do_put(iter_type, ios_base&, char_type __fill, long __v) const; -#ifdef _GLIBCPP_USE_LONG_LONG virtual iter_type - do_put(iter_type, ios_base&, char_type __fill, long long __v) const; -#endif + do_put(iter_type, ios_base&, char_type __fill, unsigned long) const; +#ifdef _GLIBCPP_USE_LONG_LONG 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 do_put(iter_type, ios_base&, char_type __fill, unsigned long long) const; #endif @@ -825,126 +796,6 @@ namespace std locale::id num_put<_CharT, _OutIter>::id; - template - 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 - locale::id numpunct<_CharT>::id; - - // NB: Cannot be made generic. - template - void - numpunct<_CharT>::_M_initialize_numpunct(__c_locale) - { } - - template<> - void - numpunct::_M_initialize_numpunct(__c_locale __cloc); - -#ifdef _GLIBCPP_USE_WCHAR_T - template<> - void - numpunct::_M_initialize_numpunct(__c_locale __cloc); -#endif - - - template - 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 class collate : public locale::facet { @@ -1466,8 +1317,9 @@ namespace std }; - struct money_base + class money_base { + public: enum part { none, space, symbol, sign, value }; struct pattern { char field[4]; }; diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index b4c7f7c69e7..3b9148e565c 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -59,18 +59,17 @@ namespace std const basic_string<_CharT, _Traits, _Alloc>& __s2) const { typedef std::collate<_CharT> __collate_type; - const __collate_type* __fcoll = &use_facet<__collate_type>(*this); - return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(), - __s2.data(), __s2.data() + __s2.length()) < 0); + const __collate_type& __collate = use_facet<__collate_type>(*this); + return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), + __s2.data(), __s2.data() + __s2.length()) < 0); } template const _Facet& use_facet(const locale& __loc) { - typedef locale::_Impl::__vec_facet __vec_facet; 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]; if (__fp == 0 || __i >= __facet->size()) __throw_bad_cast(); @@ -81,52 +80,262 @@ namespace std bool has_facet(const locale& __loc) throw() { - typedef locale::_Impl::__vec_facet __vec_facet; 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); } - // 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 void num_get<_CharT, _InIter>:: - _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/, - ios_base::iostate& /*__err*/, char* /*__xtrc*/, - int& /*__base*/, bool /*__fp*/) const + _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, + ios_base::iostate& __err, char* __xtrc) const { - // XXX Not currently done: need to expand upon char version below. + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet >(__loc); + const numpunct<_CharT>& __np = use_facet >(__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(__sep_pos); + __sep_pos = 0; + __c = *(++__beg); + } + else + { + __err |= ios_base::failbit; + break; + } + } + else if (__c == __dec && !__found_dec) + { + __found_grouping += static_cast(__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(__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 void - num_get >:: - _M_extract(istreambuf_iterator __beg, - istreambuf_iterator __end, ios_base& __io, - ios_base::iostate& __err, char* __xtrc, int& __base, - bool __fp) const; + num_get<_CharT, _InIter>:: + _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, + ios_base::iostate& __err, char* __xtrc, int& __base) 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 >(__loc); + const numpunct<_CharT>& __np = use_facet >(__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(__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(__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 - // NB: This is an unresolved library defect #17 //17. Bad bool parsing template _InIter @@ -145,7 +354,7 @@ namespace std // integral types. char __xtrc[32] = {'\0'}; 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. char* __sanity; @@ -162,29 +371,30 @@ namespace std // Parse bool values as alphanumeric else { - typedef _Format_cache __fcache_type; - __fcache_type* __fmt = __fcache_type::_S_get(__io); - const char_type* __true = __fmt->_M_truename.c_str(); - const char_type* __false = __fmt->_M_falsename.c_str(); - const size_t __truelen = __traits_type::length(__true) - 1; - const size_t __falselen = __traits_type::length(__false) - 1; - - for (size_t __pos = 0; __beg != __end; ++__pos) + locale __loc = __io.getloc(); + const numpunct& __np = use_facet >(__loc); + const char_type* __true = __np.truename().c_str(); + const char_type* __false = __np.falsename().c_str(); + + const size_t __truen = __np.truename().size() - 1; + const size_t __falsen = __np.falsename().size() - 1; + + for (size_t __n = 0; __beg != __end; ++__n) { char_type __c = *__beg++; - bool __testf = __c == __false[__pos]; - bool __testt = __c == __true[__pos]; + bool __testf = __n <= __falsen ? __c == __false[__n] : false; + bool __testt = __n <= __truen ? __c == __true[__n] : false; if (!(__testf || __testt)) { __err |= ios_base::failbit; break; } - else if (__testf && __pos == __falselen) + else if (__testf && __n == __falsen) { __v = 0; break; } - else if (__testt && __pos == __truelen) + else if (__testt && __n == __truen) { __v = 1; break; @@ -198,63 +408,6 @@ namespace std } #endif -#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS - //XXX. Which number? Presumably same as in locale_facets.h... - template - _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(__l); - else - __err |= ios_base::failbit; - - return __beg; - } - - template - _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(__l); - else - __err |= ios_base::failbit; - - return __beg; - } -#endif - template _InIter num_get<_CharT, _InIter>:: @@ -266,7 +419,7 @@ namespace std // integral types. char __xtrc[32]= {'\0'}; 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. char* __sanity; @@ -281,46 +434,45 @@ namespace std return __beg; } -#ifdef _GLIBCPP_USE_LONG_LONG template _InIter num_get<_CharT, _InIter>:: 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. // 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); + _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); // Stage 2: convert and store results. char* __sanity; errno = 0; - long long __ll = strtoll(__xtrc, &__sanity, __base); + unsigned long __ul = strtoul(__xtrc, &__sanity, __base); if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ll; + && __sanity != __xtrc && *__sanity == '\0' && errno == 0 + && __ul <= USHRT_MAX) + __v = static_cast(__ul); else __err |= ios_base::failbit; return __beg; } -#endif template _InIter num_get<_CharT, _InIter>:: 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. // 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); + _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); // Stage 2: convert and store results. char* __sanity; @@ -328,8 +480,8 @@ namespace std unsigned long __ul = strtoul(__xtrc, &__sanity, __base); if (!(__err & ios_base::failbit) && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __ul <= USHRT_MAX) - __v = static_cast(__ul); + && __ul <= UINT_MAX) + __v = static_cast(__ul); else __err |= ios_base::failbit; @@ -340,56 +492,55 @@ namespace std _InIter num_get<_CharT, _InIter>:: 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. // Assuming leading zeros eliminated, thus the size of 32 for // integral types. - char __xtrc[32]= {'\0'}; + char __xtrc[32] = {'\0'}; 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. char* __sanity; errno = 0; unsigned long __ul = strtoul(__xtrc, &__sanity, __base); if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __ul <= UINT_MAX) - __v = static_cast(__ul); + && __sanity != __xtrc && *__sanity == '\0' && errno == 0) + __v = __ul; else __err |= ios_base::failbit; return __beg; } +#ifdef _GLIBCPP_USE_LONG_LONG template _InIter num_get<_CharT, _InIter>:: 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. // Assuming leading zeros eliminated, thus the size of 32 for // integral types. - char __xtrc[32] = {'\0'}; + char __xtrc[32]= {'\0'}; 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. char* __sanity; errno = 0; - unsigned long __ul = strtoul(__xtrc, &__sanity, __base); + long long __ll = strtoll(__xtrc, &__sanity, __base); if (!(__err & ios_base::failbit) && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ul; + __v = __ll; else __err |= ios_base::failbit; return __beg; } -#ifdef _GLIBCPP_USE_LONG_LONG template _InIter num_get<_CharT, _InIter>:: @@ -401,7 +552,7 @@ namespace std // integral types. char __xtrc[32]= {'\0'}; 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. char* __sanity; @@ -420,15 +571,14 @@ namespace std template _InIter num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, float& __v) const + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, float& __v) const { // Stage 1: extract and determine the conversion specifier. // Assuming leading zeros eliminated, thus the size of 256 for // floating-point types. char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); + _M_extract_float(__beg, __end, __io, __err, __xtrc); // Stage 2: convert and store results. char* __sanity; @@ -457,8 +607,7 @@ namespace std // Assuming leading zeros eliminated, thus the size of 256 for // floating-point types. char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); + _M_extract_float(__beg, __end, __io, __err, __xtrc); // Stage 2: convert and store results. char* __sanity; @@ -483,8 +632,7 @@ namespace std // Assuming leading zeros eliminated, thus the size of 256 for // floating-point types. char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); + _M_extract_float(__beg, __end, __io, __err, __xtrc); #if defined(_GLIBCPP_USE_C99) && !defined(__hpux) // Stage 2: convert and store results. @@ -539,7 +687,7 @@ namespace std // integral types. char __xtrc[32]= {'\0'}; 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. char* __sanity; @@ -556,83 +704,138 @@ namespace std 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 - inline _OutIter - __pad(_OutIter __s, _CharT __fill, int __padding); + template + _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 - _RaIter - __pad(_RaIter __s, _CharT __fill, int __padding, - random_access_iterator_tag) - { - fill_n(__s, __fill); - return __s + __padding; - } + template + template + _OutIter + num_put<_CharT, _OutIter>:: + _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, + char __modl, _ValueT __v) const + { + // [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 + template _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; } - return __s; + // [22.2.2.2.2] Stage 2, convert to char_type, using correct + // numpunct.decimal_point() values for '.' and adding grouping. + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet >(__loc); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); + __ctype.widen(__cs, __cs + __len, __ws); + + const numpunct<_CharT>& __np = use_facet >(__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 - inline _OutIter - __pad(_OutIter __s, _CharT __fill, int __padding) + _OutIter + num_put<_CharT, _OutIter>:: + _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, + int __len) const { - return __pad(__s, __fill, __padding, - typename iterator_traits<_OutIter>::iterator_category()); + // [22.2.2.2.2] Stage 2, convert to char_type, using correct + // numpunct.decimal_point() values for '.' and adding grouping. + const locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet >(__loc); + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); + __ctype.widen(__cs, __cs + __len, __ws); + + // Add grouping, if necessary. + const numpunct<_CharT>& __np = use_facet >(__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 _OutIter - __pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/, - _CharT /*__fill*/, int /*__width*/, - _CharT const* /*__first*/, _CharT const* /*__middle*/, - _CharT const* /*__last*/) - { - // XXX Not currently done: non streambuf_iterator - return __s; - } - - // Partial specialization for ostreambuf_iterator. - template - 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) + num_put<_CharT, _OutIter>:: + _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, + int __len) const { - typedef ostreambuf_iterator<_CharT> __out_iter; - int __padding = __width - (__last - __first); - if (__padding < 0) - __padding = 0; - ios_base::fmtflags __aflags = __flags & ios_base::adjustfield; - bool __testfield = __padding == 0 || __aflags == ios_base::left - || __aflags == ios_base::internal; - - // This was needlessly complicated. - if (__first != __middle) - { - if (!__testfield) - { - __pad(__s, __fill, __padding); - __padding = 0; - } - copy(__first, __middle, __s); - } - __out_iter __s2 = __s; + // [22.2.2.2.2] Stage 3. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64)); + streamsize __w = __io.width(); + if (__w > static_cast(__len)) + { + __pad(__io, __fill, __ws2, __ws, __w, __len); + __len = static_cast(__w); + // Switch strings. + __ws = __ws2; + } + __io.width(0); - if (__padding && __aflags != ios_base::left) - { - __pad(__s2, __fill, __padding); - __padding = 0; - } - __out_iter __s3 = copy(__middle, __last, __s2); - if (__padding) - __pad(__s3, __fill, __padding); - return __s3; + // [22.2.2.2.2] Stage 4. + // Write resulting, fully-formatted string to output iterator. + for (int __j = 0; __j < __len; ++__j, ++__s) + *__s = __ws[__j]; + return __s; } template @@ -640,278 +843,73 @@ namespace std num_put<_CharT, _OutIter>:: 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(); - if ((__flags & ios_base::boolalpha) == 0) { unsigned long __uv = __v; - return __output_integer(__s, __io, __fill, false, __uv); + _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv); } else { - const char_type* __first; - const char_type* __last; + locale __loc = __io.getloc(); + const numpunct<_CharT>& __np = use_facet >(__loc); + const char_type* __ws; + int __len; if (__v) { - __first = __fmt->_M_truename.data(); - __last = __first + __fmt->_M_truename.size(); + __ws = __np.truename().c_str(); + __len = __np.truename().size(); } else { - __first = __fmt->_M_falsename.data(); - __last = __first + __fmt->_M_falsename.size(); + __ws = __np.falsename().c_str(); + __len = __np.falsename().size(); } - streamsize __width = __io.width(0); - if (__last - __first >= __width) - return copy(__first, __last, __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 - _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(*__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); + _M_insert(__s, __io, __fill, __ws, __len); + } + return __s; } template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const - { - unsigned long __uv = __v; - bool __neg = false; - if (__v < 0) - { - __neg = true; - __uv = -__uv; - } - return __output_integer(__s, __io, __fill, __neg, __uv); - } + { return _M_convert_int(__s, __io, __fill, 'd', char_type(), __v); } template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, 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 template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const - { - unsigned long long __uv = __v; - bool __neg = false; - if (__v < 0) - { - __neg = true; - __uv = -__uv; - } - return __output_integer(__s, __b, __fill, __neg, __uv); - } + { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); } template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, unsigned long long __v) const - { return __output_integer(__s, __io, __fill, false, __v); } + { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } #endif - // Generic helper function - template - _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 - 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 >(__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 _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const - { - const streamsize __max_prec = numeric_limits::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); - } + { return _M_convert_float(__s, __io, __fill, char_type(), __v); } template _OutIter num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, - long double __v) const - { - const streamsize __max_prec = numeric_limits::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); - } + do_put(iter_type __s, ios_base& __io, char_type __fill, + long double __v) const + { return _M_convert_float(__s, __io, __fill, 'L', __v); } template _OutIter @@ -919,21 +917,22 @@ namespace std do_put(iter_type __s, ios_base& __io, char_type __fill, const void* __v) const { - typedef ios_base::fmtflags fmtflags; - fmtflags __fmt = __io.flags(); - fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield - | ios_base::uppercase | ios_base::internal); - __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); - try { - _OutIter __s2 = __output_integer(__s, __io, __fill, false, - reinterpret_cast(__v)); - __io.flags(__fmt); - return __s2; - } - catch (...) { - __io.flags(__fmt); - __throw_exception_again; - } + ios_base::fmtflags __flags = __io.flags(); + ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield + | ios_base::uppercase | ios_base::internal); + __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); + try + { + _M_convert_int(__s, __io, __fill, 'u', char_type(), + reinterpret_cast(__v)); + __io.flags(__flags); + } + catch (...) + { + __io.flags(__flags); + __throw_exception_again; + } + return __s; } @@ -1253,13 +1252,13 @@ namespace std { const char_type __sep = __intl ? __mpt.thousands_sep() : __mpf.thousands_sep(); - const char* __gbeg = __grouping.data(); + const char* __gbeg = __grouping.c_str(); const char* __gend = __gbeg + __grouping.size(); const int __n = numeric_limits::digits10 * 2; - _CharT* __s = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); - _CharT* __s_end = __group_digits(__s, __sep, __gbeg, - __gend, __beg, __end); - __value.insert(0, __s, __s_end - __s); + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); + _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, + __gend, __beg, __end); + __value.insert(0, __ws2, __ws_end - __ws2); } else __value.insert(0, string_type(__beg, __end)); @@ -1921,6 +1920,100 @@ namespace std return static_cast(__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 + 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(__newlen - __oldlen); + char_type* __pads = static_cast(__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(__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 >(__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(__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(__olds + __mod); + } + else + { + // Padding first. + __beg = __pads; + __beglen = __plen; + __end = const_cast(__olds); + } + } + else + { + // Padding first. + __beg = __pads; + __beglen = __plen; + __end = const_cast(__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 + 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. // Check to make sure that the __grouping_tmp string constructed in // money_get or num_get matches the canonical grouping for a given @@ -1960,102 +2053,23 @@ namespace std // only with __gbeg != __gend. template _CharT* - __group_digits(_CharT* __s, _CharT __sep, + __add_grouping(_CharT* __s, _CharT __sep, const char* __gbeg, const char* __gend, const _CharT* __first, const _CharT* __last) { if (__last - __first > *__gbeg) { - __s = __group_digits(__s, __sep, + __s = __add_grouping(__s, __sep, (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), __gend, __first, __last - *__gbeg); __first = __last - *__gbeg; *__s++ = __sep; } do - { - *__s++ = *__first++; - } + *__s++ = *__first++; while (__first != __last); return __s; } - - // XXX This stuff needs to be re-examined, heavily modified, or ditched. - template - _Format_cache<_CharT>::_Format_cache() - : _M_valid(true), _M_use_grouping(false) - { } - - template<> - _Format_cache::_Format_cache(); - - template<> - _Format_cache::_Format_cache(); - - template - void - _Format_cache<_CharT>::_M_populate(ios_base& __io) - { - locale __loc = __io.getloc(); - numpunct<_CharT> const& __np = use_facet >(__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 - 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 - _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 #endif diff --git a/libstdc++-v3/include/bits/ostream.tcc b/libstdc++-v3/include/bits/ostream.tcc index ff9283dc70b..8ecd01998c2 100644 --- a/libstdc++-v3/include/bits/ostream.tcc +++ b/libstdc++-v3/include/bits/ostream.tcc @@ -465,93 +465,6 @@ namespace std } // 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 - 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(__newlen - __oldlen); - char_type* __pads = static_cast(__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(__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(__olds + __mod); - __beglen = __oldlen - __mod; - __end = __pads; - } - else if (__testsign) - { - __mod += __plen; - const char_type* __sign = __minus ? __minus + 1: __plus + 1; - __beg = const_cast(__olds); - __beglen = __sign - __olds; - __end = const_cast(__sign + __plen); - traits_type::copy(__news + __beglen, __pads, __plen); - } - else - { - // Padding first. - __beg = __pads; - __beglen = __plen; - __end = const_cast(__olds); - } - } - else - { - // Padding first. - __beg = __pads; - __beglen = __plen; - __end = const_cast(__olds); - } - - traits_type::copy(__news, __beg, __beglen); - traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod); - } - template basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c) @@ -568,7 +481,7 @@ namespace std streamsize __len = 1; if (__w > __len) { - __pad_char(__out, __pads, &__c, __w, __len); + __pad(__out, __out.fill(), __pads, &__c, __w, __len); __len = __w; } __out.write(__pads, __len); @@ -603,7 +516,7 @@ namespace std streamsize __len = 1; if (__w > __len) { - __pad_char(__out, __pads, &__c, __w, __len); + __pad(__out, __out.fill(), __pads, &__c, __w, __len); __len = __w; } __out.write(__pads, __len); @@ -636,7 +549,7 @@ namespace std streamsize __len = static_cast(_Traits::length(__s)); if (__w > __len) { - __pad_char(__out, __pads, __s, __w, __len); + __pad(__out, __out.fill(), __pads, __s, __w, __len); __s = __pads; __len = __w; } @@ -682,7 +595,7 @@ namespace std if (__w > __len) { - __pad_char(__out, __pads, __ws, __w, __len); + __pad(__out, __out.fill(), __pads, __ws, __w, __len); __str = __pads; __len = __w; } @@ -717,7 +630,7 @@ namespace std streamsize __len = static_cast(_Traits::length(__s)); if (__w > __len) { - __pad_char(__out, __pads, __s, __w, __len); + __pad(__out, __out.fill(), __pads, __s, __w, __len); __s = __pads; __len = __w; } @@ -755,7 +668,7 @@ namespace std #endif if (__w > __len) { - __pad_char(__out, __pads, __s, __w, __len); + __pad(__out, __out.fill(), __pads, __s, __w, __len); __s = __pads; __len = __w; } diff --git a/libstdc++-v3/include/bits/std_istream.h b/libstdc++-v3/include/bits/std_istream.h index 3f690d7870e..4afbbc0528d 100644 --- a/libstdc++-v3/include/bits/std_istream.h +++ b/libstdc++-v3/include/bits/std_istream.h @@ -159,21 +159,21 @@ namespace std inline __istream_type& get(char_type* __s, streamsize __n) - { return get(__s, __n, this->widen('\n')); } + { return this->get(__s, __n, this->widen('\n')); } __istream_type& get(__streambuf_type& __sb, char_type __delim); inline __istream_type& get(__streambuf_type& __sb) - { return get(__sb, this->widen('\n')); } + { return this->get(__sb, this->widen('\n')); } __istream_type& getline(char_type* __s, streamsize __n, char_type __delim); inline __istream_type& getline(char_type* __s, streamsize __n) - { return getline(__s, __n, this->widen('\n')); } + { return this->getline(__s, __n, this->widen('\n')); } __istream_type& ignore(streamsize __n = 1, int_type __delim = traits_type::eof()); @@ -297,4 +297,3 @@ namespace std #endif #endif /* _CPP_ISTREAM */ - diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index 2f8b4b44070..3061fcc4cc7 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -171,8 +171,7 @@ namespace std { int_type __eof = traits_type::eof(); bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof; - bool __beof = !__b._M_sbuf - || __b._M_sbuf->sgetc() == __eof; + bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof; return (__thiseof && __beof || (!__thiseof && !__beof)); } @@ -184,8 +183,7 @@ namespace std { int_type __eof = traits_type::eof(); bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof; - bool __beof = !__b._M_sbuf - || __b._M_sbuf->sgetc() == __eof; + bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof; return (__thiseof && __beof || (!__thiseof && !__beof)); } #endif diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc index faa11fbeea1..90379fb8845 100644 --- a/libstdc++-v3/src/ios.cc +++ b/libstdc++-v3/src/ios.cc @@ -284,12 +284,6 @@ namespace std { locale __old = _M_ios_locale; _M_ios_locale = __loc; - // Make sure there's a callback for the format caches so they will be - // marked dirty. - _Format_cache::_S_get(*this); -#ifdef _GLIBCPP_USE_WCHAR_T - _Format_cache::_S_get(*this); -#endif _M_call_callbacks(imbue_event); return __old; } diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc index ac072151f3f..5107a2963d4 100644 --- a/libstdc++-v3/src/locale-inst.cc +++ b/libstdc++-v3/src/locale-inst.cc @@ -56,7 +56,6 @@ namespace std template class moneypunct_byname; template class money_get; template class money_put; - template class _Format_cache; #ifdef _GLIBCPP_USE_WCHAR_T template class moneypunct; @@ -65,19 +64,91 @@ namespace std template class moneypunct_byname; template class money_get; template class money_put; - template class _Format_cache; #endif // numpunct, numpunct_byname, num_get, and num_put template class numpunct; template class numpunct_byname; template class num_get; - template class num_put; + template class num_put; + template + obuf_iterator + num_put:: + _M_convert_int(obuf_iterator, ios_base&, char, char, char, long) const; + + template + obuf_iterator + num_put:: + _M_convert_int(obuf_iterator, ios_base&, char, char, char, + unsigned long) const; + +#ifdef _GLIBCPP_USE_LONG_LONG + template + obuf_iterator + num_put:: + _M_convert_int(obuf_iterator, ios_base&, char, char, char, + long long) const; + + template + obuf_iterator + num_put:: + _M_convert_int(obuf_iterator, ios_base&, char, char, char, + unsigned long long) const; +#endif + + template + obuf_iterator + num_put:: + _M_convert_float(obuf_iterator, ios_base&, char, char, double) const; + + template + obuf_iterator + num_put:: + _M_convert_float(obuf_iterator, ios_base&, char, char, + long double) const; + #ifdef _GLIBCPP_USE_WCHAR_T template class numpunct; template class numpunct_byname; template class num_get; template class num_put; + + template + wobuf_iterator + num_put:: + _M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char, long) const; + + template + wobuf_iterator + num_put:: + _M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char, + unsigned long) const; + +#ifdef _GLIBCPP_USE_LONG_LONG + template + wobuf_iterator + num_put:: + _M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char, + long long) const; + + template + wobuf_iterator + num_put:: + _M_convert_int(wobuf_iterator, ios_base&, wchar_t, char, char, + unsigned long long) const; +#endif + + template + wobuf_iterator + num_put:: + _M_convert_float(wobuf_iterator, ios_base&, wchar_t, char, + double) const; + + template + wobuf_iterator + num_put:: + _M_convert_float(wobuf_iterator, ios_base&, wchar_t, char, + long double) const; #endif // time_get and time_put @@ -246,45 +317,32 @@ namespace std typedef ostreambuf_iterator > ostreambuf_iter; #ifdef _GLIBCPP_USE_WCHAR_T - typedef istreambuf_iterator > wistreambuf_iter; - typedef ostreambuf_iterator > wostreambuf_iter; + typedef istreambuf_iterator > wistreambuf_iter; + typedef ostreambuf_iterator > wostreambuf_iter; #endif template bool locale::operator()(const string&, const string&) const; - template - ostreambuf_iter - __pad - (ostreambuf_iter, char, int, output_iterator_tag); - - template - ostreambuf_iter - __pad_numeric - (ostreambuf_iter, ios_base::fmtflags, char, int, char const*, char const*, - char const*); - template char* - __group_digits(char*, char, char const*, char const*, + __add_grouping(char*, char, char const*, char const*, char const*, char const*); template bool __verify_grouping(const basic_string&, basic_string&); - template - ostreambuf_iter - __output_integer - (ostreambuf_iter, ios_base &, char, bool, unsigned long); + template + void + __pad(ios_base&, char, char*, const char *, streamsize, + streamsize); -#ifdef _GLIBCPP_USE_LONG_LONG template - ostreambuf_iter - __output_integer - (ostreambuf_iter, ios_base &, char, bool, unsigned long long); -#endif + void + __pad >(ios_base&, char, char*, + const char *, streamsize, streamsize); #ifdef _GLIBCPP_USE_WCHAR_T template @@ -293,37 +351,25 @@ namespace std typedef ostreambuf_iterator wostreambuf_iter; - template - wostreambuf_iter - __pad - (wostreambuf_iter, wchar_t, int, output_iterator_tag); - - template - wostreambuf_iter - __pad_numeric - (wostreambuf_iter, ios_base::fmtflags, wchar_t __fill, int, wchar_t const*, - wchar_t const*, wchar_t const*); - template wchar_t* - __group_digits(wchar_t*, wchar_t, char const*, char const*, + __add_grouping(wchar_t*, wchar_t, char const*, char const*, wchar_t const*, wchar_t const*); template bool __verify_grouping(const basic_string&, basic_string&); - template - wostreambuf_iter - __output_integer - (wostreambuf_iter, ios_base &, wchar_t, bool, unsigned long); + template + void + __pad(ios_base&, wchar_t, wchar_t*, const wchar_t*, + streamsize, streamsize); -#ifdef _GLIBCPP_USE_LONG_LONG template - wostreambuf_iter - __output_integer - (wostreambuf_iter, ios_base &, wchar_t, bool, unsigned long long); -#endif + void + __pad >(ios_base&, wchar_t, wchar_t*, + const wchar_t*, + streamsize, streamsize); #endif // _GLIBCPP_USE_WCHAR_T template @@ -342,4 +388,3 @@ namespace std __normal_iterator >, locale::facet* const&); } // namespace std - diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 02297d1d9ea..c3572c40b15 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -74,6 +74,8 @@ namespace std // Definitions for static const data members of locale::id 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 const locale::id* const locale::_Impl::_S_id_ctype[] = @@ -353,7 +355,7 @@ namespace std void locale::facet:: _M_add_reference() throw() - { ++_M_references; } // XXX MT + { ++_M_references; } // XXX MT void locale::facet:: @@ -457,22 +459,6 @@ namespace std const money_base::pattern money_base::_S_default_pattern = {{symbol, sign, none, value}}; - template<> - _Format_cache::_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::_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& use_facet >(const locale& __loc) @@ -493,310 +479,9 @@ namespace std } #endif - template<> - void - num_get >:: - _M_extract(istreambuf_iterator __beg, - istreambuf_iterator __end, ios_base& __io, - ios_base::iostate& __err, char* __xtrc, int& __base, - bool __fp) const - { - typedef _Format_cache __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(__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(__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 - __build_float_format(ios_base& __io, char* __fptr, char __modifier, - streamsize __prec) + __num_base::_S_format_float(const ios_base& __io, char* __fptr, char __mod, + streamsize __prec) { bool __incl_prec = false; ios_base::fmtflags __flags = __io.flags(); @@ -809,12 +494,12 @@ namespace std // As per [22.2.2.2.2.11] if (__flags & ios_base::fixed || __prec > 0) { - *__fptr++ = '.'; - *__fptr++ = '*'; - __incl_prec = true; + *__fptr++ = '.'; + *__fptr++ = '*'; + __incl_prec = true; } - if (__modifier) - *__fptr++ = __modifier; + if (__mod) + *__fptr++ = __mod; ios_base::fmtflags __fltfield = __flags & ios_base::floatfield; // [22.2.2.2.2] Table 58 if (__fltfield == ios_base::fixed) @@ -826,16 +511,43 @@ namespace std *__fptr = '\0'; 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<> - moneypunct_byname::moneypunct_byname(const char* /*__s*/, - size_t __refs) - : moneypunct(__refs) { } + moneypunct_byname::moneypunct_byname(const char* /*__s*/, + size_t __refs) + : moneypunct(__refs) { } template<> - moneypunct_byname::moneypunct_byname(const char* /*__s*/, - size_t __refs) - : moneypunct(__refs) { } + moneypunct_byname::moneypunct_byname(const char* /*__s*/, + size_t __refs) + : moneypunct(__refs) { } #ifdef _GLIBCPP_USE_WCHAR_T ctype::__wmask_type diff --git a/libstdc++-v3/src/misc-inst.cc b/libstdc++-v3/src/misc-inst.cc index 45cd0bcd697..484a551c44d 100644 --- a/libstdc++-v3/src/misc-inst.cc +++ b/libstdc++-v3/src/misc-inst.cc @@ -241,39 +241,6 @@ namespace std (vector::const_iterator, vector::const_iterator, string*, __false_type); - template - void - __pad_char(basic_ios&, char*, const char*, - const streamsize, const streamsize); -#ifdef _GLIBCPP_USE_WCHAR_T - template - void - __pad_char(basic_ios&, wchar_t*, const wchar_t*, - const streamsize, const streamsize); -#endif - - template - ostreambuf_iterator - __pad_numeric(ostreambuf_iterator, _Ios_Fmtflags, char, int, - const char*, const char*, const char*); -#ifdef _GLIBCPP_USE_WCHAR_T - template - ostreambuf_iterator - __pad_numeric(ostreambuf_iterator, _Ios_Fmtflags, wchar_t, int, - const wchar_t*, const wchar_t*, const wchar_t*); -#endif - - template - ostreambuf_iterator - __output_float(ostreambuf_iterator, ios_base&, char, - const char*, size_t); -#ifdef _GLIBCPP_USE_WCHAR_T - template - ostreambuf_iterator - __output_float(ostreambuf_iterator, ios_base&, wchar_t, - const char*, size_t); -#endif - template streamsize __copy_streambufs(basic_ios&, basic_streambuf*, diff --git a/libstdc++-v3/testsuite/22_locale/num_get.cc b/libstdc++-v3/testsuite/22_locale/num_get.cc new file mode 100644 index 00000000000..fae184d6cdb --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_get.cc @@ -0,0 +1,52 @@ +// 2001-11-21 Benjamin Kosnik + +// 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 + +void test01() +{ + // Check for required base class. + typedef std::num_get test_type; + typedef std::locale::facet base_type; + const test_type& obj = std::use_facet(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 +{ }; + +void test02() +{ + gnu_num_get facet01; +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/num_get_members_char.cc b/libstdc++-v3/testsuite/22_locale/num_get_members_char.cc new file mode 100644 index 00000000000..3ab623645fc --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_get_members_char.cc @@ -0,0 +1,246 @@ +// 2001-11-21 Benjamin Kosnik + +// 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 +#include +#include + +// XXX This test is not working for non-glibc locale models. +// { dg-do run { xfail *-*-* } } + +void test01() +{ + using namespace std; + typedef istreambuf_iterator 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& numpunct_c = use_facet >(loc_c); + const numpunct& numpunct_de = use_facet >(loc_de); + const numpunct& numpunct_hk = use_facet >(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& ng = use_facet >(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 diff --git a/libstdc++-v3/testsuite/22_locale/num_put.cc b/libstdc++-v3/testsuite/22_locale/num_put.cc new file mode 100644 index 00000000000..1715231e999 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_put.cc @@ -0,0 +1,52 @@ +// 2001-11-19 Benjamin Kosnik + +// 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 + +void test01() +{ + // Check for required base class. + typedef std::num_put test_type; + typedef std::locale::facet base_type; + const test_type& obj = std::use_facet(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 +{ }; + +void test02() +{ + gnu_num_put facet01; +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/num_put_members_char.cc b/libstdc++-v3/testsuite/22_locale/num_put_members_char.cc new file mode 100644 index 00000000000..9bc5dce9d6e --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_put_members_char.cc @@ -0,0 +1,230 @@ +// 2001-11-19 Benjamin Kosnik + +// 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 +#include +#include + +// XXX This test is not working for non-glibc locale models. +// { dg-do run { xfail *-*-* } } + +void test01() +{ + using namespace std; + typedef ostreambuf_iterator 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& numpunct_c = use_facet >(loc_c); + const numpunct& numpunct_de = use_facet >(loc_de); + const numpunct& numpunct_hk = use_facet >(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& np = use_facet >(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::find(result1.c_str(), + numpunct_de.decimal_point(), + result1.size()) ); + // Should contain an 'x'. + VERIFY( !char_traits::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; +} + + + diff --git a/libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc new file mode 100644 index 00000000000..885df82d246 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc @@ -0,0 +1,234 @@ +// 2001-11-19 Benjamin Kosnik + +// 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 +#include +#include + +// 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 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& numpunct_c = use_facet >(loc_c); + const numpunct& numpunct_de = use_facet >(loc_de); + const numpunct& numpunct_hk = use_facet >(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& np = use_facet >(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::find(result1.c_str(), + numpunct_de.decimal_point(), + result1.size()) ); + // Should contain an 'x'. + VERIFY( !char_traits::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 diff --git a/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc b/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc index 0527c99e1cf..901de4c1f61 100644 --- a/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc +++ b/libstdc++-v3/testsuite/22_locale/numpunct_members_char.cc @@ -75,19 +75,12 @@ void test01() VERIFY( dp2 != dp3 ); VERIFY( th2 != th3 ); -#if 0 - // XXX isn't actually supported right now. - VERIFY( t2 != t3 ); - VERIFY( f2 != f3 ); -#endif VERIFY( dp2 != dp4 ); VERIFY( th2 != th4 ); -#if 0 - // XXX isn't actually supported right now. - VERIFY( t2 != t3 ); - VERIFY( f2 != f3 ); -#endif + // XXX This isn't actually supported right now. + // VERIFY( t2 != t3 ); + // VERIFY( f2 != f3 ); } int main() diff --git a/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc new file mode 100644 index 00000000000..afb7eb9fbd0 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc @@ -0,0 +1,88 @@ +// 2001-11-20 Benjamin Kosnik + +// 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 +#include + +// 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& nump_c = use_facet >(loc_c); + const numpunct& nump_us = use_facet >(loc_us); + const numpunct& nump_fr = use_facet >(loc_fr); + const numpunct& nump_de = use_facet >(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; +} diff --git a/libstdc++-v3/testsuite/27_io/istream_extractor_arith.cc b/libstdc++-v3/testsuite/27_io/istream_extractor_arith.cc index e6bb415d2ef..0cb5ae0ed02 100644 --- a/libstdc++-v3/testsuite/27_io/istream_extractor_arith.cc +++ b/libstdc++-v3/testsuite/27_io/istream_extractor_arith.cc @@ -387,7 +387,7 @@ bool test09() } 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::istream is_01(&isbuf_01); @@ -447,7 +447,7 @@ bool test10() { VERIFY( n == 33 ); 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::istream is_04(&isbuf_04); diff --git a/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc b/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc index af45aaafaf5..bd49ebf7f76 100644 --- a/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc +++ b/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc @@ -63,13 +63,13 @@ static bool F=false; static _TestCase testcases[] = { #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" }, { 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" }, { -.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,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" }, @@ -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" }, - // 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,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" }, @@ -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,'.','#', 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,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" }, @@ -207,7 +207,7 @@ test01() apply_formatting(tc, os); os << tc.val; #ifdef TEST_NUMPUT_VERBOSE - cout << "result: " << os.str() << endl; + cout << j << "result 1: " << os.str() << endl; #endif VERIFY( os && os.str() == tc.result ); } @@ -220,7 +220,7 @@ test01() apply_formatting(tc, os); os << (long double)tc.val; #ifdef TEST_NUMPUT_VERBOSE - cout << "result: " << os.str() << endl; + cout << j << "result 2: " << os.str() << endl; #endif VERIFY( os && os.str() == tc.result ); } -- 2.30.2