X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fbits%2Flocale_facets.tcc;h=114d852e2ae39364d285f6b52e63e4a6fa9e5878;hb=2948dd21a7947545dbf6c4a9656a3607242f0966;hp=8bcb035a97e44980042a7c76edef008c811d5ede;hpb=dbccc45ae903778d235be632ea79ef85716e6a45;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 8bcb035a97e..114d852e2ae 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -1,12 +1,13 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +// 2006, 2007, 2008, 2009, 2010 // Free Software Foundation, Inc. // // 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) +// Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, @@ -14,104 +15,28 @@ // 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. +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. -// As a special exception, you may use this file as part of a free software -// library without restriction. Specifically, if other files instantiate -// templates or use macros or inline functions from this file, or you compile -// this file and link it with other files to produce an executable, this -// file does not by itself cause the resulting executable to be covered by -// the GNU General Public License. This exception does not however -// invalidate any other reasons why the executable file might be covered by -// the GNU General Public License. +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . -// Warning: this file is not meant for user inclusion. Use . +/** @file bits/locale_facets.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{locale} + */ #ifndef _LOCALE_FACETS_TCC #define _LOCALE_FACETS_TCC 1 #pragma GCC system_header -#include // For numeric_limits -#include // For bad_cast. -#include - -namespace std +namespace std _GLIBCXX_VISIBILITY(default) { - template - locale - locale::combine(const locale& __other) const - { - _Impl* __tmp = new _Impl(*_M_impl, 1); - try - { - __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); - } - catch(...) - { - __tmp->_M_remove_reference(); - __throw_exception_again; - } - return locale(__tmp); - } - - template - bool - locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, - const basic_string<_CharT, _Traits, _Alloc>& __s2) const - { - typedef std::collate<_CharT> __collate_type; - 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); - } - - /** - * @brief Test for the presence of a facet. - * - * has_facet tests the locale argument for the presence of the facet type - * provided as the template parameter. Facets derived from the facet - * parameter will also return true. - * - * @param Facet The facet type to test the presence of. - * @param locale The locale to test. - * @return true if locale contains a facet of type Facet, else false. - */ - template - inline bool - has_facet(const locale& __loc) throw() - { - const size_t __i = _Facet::id._M_id(); - const locale::facet** __facets = __loc._M_impl->_M_facets; - return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); - } - - /** - * @brief Return a facet. - * - * use_facet looks for and returns a reference to a facet of type Facet - * where Facet is the template parameter. If has_facet(locale) is true, - * there is a suitable facet to return. It throws std::bad_cast if the - * locale doesn't contain a facet of type Facet. - * - * @param Facet The facet type to access. - * @param locale The locale to use. - * @return Reference to facet of type Facet. - * @throw std::bad_cast if locale doesn't contain a facet of type Facet. - */ - template - inline const _Facet& - use_facet(const locale& __loc) - { - const size_t __i = _Facet::id._M_id(); - const locale::facet** __facets = __loc._M_impl->_M_facets; - if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) - __throw_bad_cast(); - return static_cast(*__facets[__i]); - } +_GLIBCXX_BEGIN_NAMESPACE_VERSION // Routine to access a cache for the facet. If the cache didn't // exist before, it gets constructed on the fly. @@ -133,13 +58,13 @@ namespace std const locale::facet** __caches = __loc._M_impl->_M_caches; if (!__caches[__i]) { - __numpunct_cache<_CharT>* __tmp = NULL; - try + __numpunct_cache<_CharT>* __tmp = 0; + __try { __tmp = new __numpunct_cache<_CharT>; __tmp->_M_cache(__loc); } - catch(...) + __catch(...) { delete __tmp; __throw_exception_again; @@ -150,34 +75,6 @@ namespace std } }; - template - struct __use_cache<__moneypunct_cache<_CharT, _Intl> > - { - const __moneypunct_cache<_CharT, _Intl>* - operator() (const locale& __loc) const - { - const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); - const locale::facet** __caches = __loc._M_impl->_M_caches; - if (!__caches[__i]) - { - __moneypunct_cache<_CharT, _Intl>* __tmp = NULL; - try - { - __tmp = new __moneypunct_cache<_CharT, _Intl>; - __tmp->_M_cache(__loc); - } - catch(...) - { - delete __tmp; - __throw_exception_again; - } - __loc._M_impl->_M_install_cache(__tmp, __i); - } - return static_cast< - const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); - } - }; - template void __numpunct_cache<_CharT>::_M_cache(const locale& __loc) @@ -186,75 +83,50 @@ namespace std const numpunct<_CharT>& __np = use_facet >(__loc); - _M_grouping_size = __np.grouping().size(); - char* __grouping = new char[_M_grouping_size]; - __np.grouping().copy(__grouping, _M_grouping_size); - _M_grouping = __grouping; - _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0; - - _M_truename_size = __np.truename().size(); - _CharT* __truename = new _CharT[_M_truename_size]; - __np.truename().copy(__truename, _M_truename_size); - _M_truename = __truename; - - _M_falsename_size = __np.falsename().size(); - _CharT* __falsename = new _CharT[_M_falsename_size]; - __np.falsename().copy(__falsename, _M_falsename_size); - _M_falsename = __falsename; - - _M_decimal_point = __np.decimal_point(); - _M_thousands_sep = __np.thousands_sep(); - - const ctype<_CharT>& __ct = use_facet >(__loc); - __ct.widen(__num_base::_S_atoms_out, - __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out); - __ct.widen(__num_base::_S_atoms_in, - __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in); - } - - template - void - __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) - { - _M_allocated = true; - - const moneypunct<_CharT, _Intl>& __mp = - use_facet >(__loc); - - _M_grouping_size = __mp.grouping().size(); - char* __grouping = new char[_M_grouping_size]; - __mp.grouping().copy(__grouping, _M_grouping_size); - _M_grouping = __grouping; - _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0; - - _M_decimal_point = __mp.decimal_point(); - _M_thousands_sep = __mp.thousands_sep(); - _M_frac_digits = __mp.frac_digits(); - - _M_curr_symbol_size = __mp.curr_symbol().size(); - _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size]; - __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size); - _M_curr_symbol = __curr_symbol; - - _M_positive_sign_size = __mp.positive_sign().size(); - _CharT* __positive_sign = new _CharT[_M_positive_sign_size]; - __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size); - _M_positive_sign = __positive_sign; - - _M_negative_sign_size = __mp.negative_sign().size(); - _CharT* __negative_sign = new _CharT[_M_negative_sign_size]; - __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size); - _M_negative_sign = __negative_sign; - - _M_pos_format = __mp.pos_format(); - _M_neg_format = __mp.neg_format(); - - const ctype<_CharT>& __ct = use_facet >(__loc); - __ct.widen(money_base::_S_atoms, - money_base::_S_atoms + money_base::_S_end, _M_atoms); + char* __grouping = 0; + _CharT* __truename = 0; + _CharT* __falsename = 0; + __try + { + _M_grouping_size = __np.grouping().size(); + __grouping = new char[_M_grouping_size]; + __np.grouping().copy(__grouping, _M_grouping_size); + _M_grouping = __grouping; + _M_use_grouping = (_M_grouping_size + && static_cast(_M_grouping[0]) > 0 + && (_M_grouping[0] + != __gnu_cxx::__numeric_traits::__max)); + + _M_truename_size = __np.truename().size(); + __truename = new _CharT[_M_truename_size]; + __np.truename().copy(__truename, _M_truename_size); + _M_truename = __truename; + + _M_falsename_size = __np.falsename().size(); + __falsename = new _CharT[_M_falsename_size]; + __np.falsename().copy(__falsename, _M_falsename_size); + _M_falsename = __falsename; + + _M_decimal_point = __np.decimal_point(); + _M_thousands_sep = __np.thousands_sep(); + + const ctype<_CharT>& __ct = use_facet >(__loc); + __ct.widen(__num_base::_S_atoms_out, + __num_base::_S_atoms_out + + __num_base::_S_oend, _M_atoms_out); + __ct.widen(__num_base::_S_atoms_in, + __num_base::_S_atoms_in + + __num_base::_S_iend, _M_atoms_in); + } + __catch(...) + { + delete [] __grouping; + delete [] __truename; + delete [] __falsename; + __throw_exception_again; + } } - // 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 @@ -263,9 +135,11 @@ namespace std // 1,222,444 == __grouping_tmp of "\1\3\3" // __grouping is parsed R to L // 1,222,444 == __grouping of "\3" == "\3\3\3" - static bool + _GLIBCXX_PURE bool __verify_grouping(const char* __grouping, size_t __grouping_size, - const string& __grouping_tmp); + const string& __grouping_tmp) throw (); + +_GLIBCXX_BEGIN_NAMESPACE_LDBL template _InIter @@ -274,34 +148,39 @@ namespace std ios_base::iostate& __err, string& __xtrc) const { typedef char_traits<_CharT> __traits_type; - typedef typename numpunct<_CharT>::__cache_type __cache_type; + typedef __numpunct_cache<_CharT> __cache_type; __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); const __cache_type* __lc = __uc(__loc); const _CharT* __lit = __lc->_M_atoms_in; + char_type __c = char_type(); - // True if a mantissa is found. - bool __found_mantissa = false; + // True if __beg becomes equal to __end. + bool __testeof = __beg == __end; // First check for sign. - if (__beg != __end) + if (!__testeof) { - const char_type __c = *__beg; + __c = *__beg; const bool __plus = __c == __lit[__num_base::_S_iplus]; if ((__plus || __c == __lit[__num_base::_S_iminus]) && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) && !(__c == __lc->_M_decimal_point)) { __xtrc += __plus ? '+' : '-'; - ++__beg; + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; } } // Next, look for leading zeros. - while (__beg != __end) + bool __found_mantissa = false; + int __sep_pos = 0; + while (!__testeof) { - const char_type __c = *__beg; - if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep + if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) || __c == __lc->_M_decimal_point) break; else if (__c == __lit[__num_base::_S_izero]) @@ -311,7 +190,12 @@ namespace std __xtrc += '0'; __found_mantissa = true; } - ++__beg; + ++__sep_pos; + + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; } else break; @@ -323,86 +207,146 @@ namespace std string __found_grouping; if (__lc->_M_use_grouping) __found_grouping.reserve(32); - int __sep_pos = 0; const char_type* __lit_zero = __lit + __num_base::_S_izero; - const char_type* __q; - while (__beg != __end) - { - // According to 22.2.2.1.2, p8-9, first look for thousands_sep - // and decimal_point. - const char_type __c = *__beg; - if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) - { - if (!__found_dec && !__found_sci) - { - // 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; - ++__beg; - } - else - { - __err |= ios_base::failbit; - break; - } - } - else - break; - } - else if (__c == __lc->_M_decimal_point) - { - if (!__found_dec && !__found_sci) - { - // If no grouping chars are seen, no grouping check - // is applied. Therefore __found_grouping is adjusted - // only if decimal_point comes after some thousands_sep. - if (__found_grouping.size()) - __found_grouping += static_cast(__sep_pos); - __xtrc += '.'; - __found_dec = true; - ++__beg; - } - else - break; - } - else if (__q = __traits_type::find(__lit_zero, 10, __c)) - { - __xtrc += __num_base::_S_atoms_in[__q - __lit]; - __found_mantissa = true; - ++__sep_pos; - ++__beg; - } - else if ((__c == __lit[__num_base::_S_ie] - || __c == __lit[__num_base::_S_iE]) - && __found_mantissa && !__found_sci) - { - // Scientific notation. - if (__found_grouping.size() && !__found_dec) - __found_grouping += static_cast(__sep_pos); - __xtrc += 'e'; - __found_sci = true; - // Remove optional plus or minus sign, if they exist. - if (++__beg != __end) - { - const bool __plus = *__beg == __lit[__num_base::_S_iplus]; - if ((__plus || *__beg == __lit[__num_base::_S_iminus]) - && !(__lc->_M_use_grouping - && *__beg == __lc->_M_thousands_sep) - && !(*__beg == __lc->_M_decimal_point)) - { + if (!__lc->_M_allocated) + // "C" locale + while (!__testeof) + { + const int __digit = _M_find(__lit_zero, 10, __c); + if (__digit != -1) + { + __xtrc += '0' + __digit; + __found_mantissa = true; + } + else if (__c == __lc->_M_decimal_point + && !__found_dec && !__found_sci) + { + __xtrc += '.'; + __found_dec = true; + } + else if ((__c == __lit[__num_base::_S_ie] + || __c == __lit[__num_base::_S_iE]) + && !__found_sci && __found_mantissa) + { + // Scientific notation. + __xtrc += 'e'; + __found_sci = true; + + // Remove optional plus or minus sign, if they exist. + if (++__beg != __end) + { + __c = *__beg; + const bool __plus = __c == __lit[__num_base::_S_iplus]; + if (__plus || __c == __lit[__num_base::_S_iminus]) __xtrc += __plus ? '+' : '-'; - ++__beg; - } - } - } - else - // Not a valid input item. - break; - } + else + continue; + } + else + { + __testeof = true; + break; + } + } + else + break; + + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } + else + while (!__testeof) + { + // According to 22.2.2.1.2, p8-9, first look for thousands_sep + // and decimal_point. + if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) + { + if (!__found_dec && !__found_sci) + { + // 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; + } + else + { + // NB: __convert_to_v will not assign __v and will + // set the failbit. + __xtrc.clear(); + break; + } + } + else + break; + } + else if (__c == __lc->_M_decimal_point) + { + if (!__found_dec && !__found_sci) + { + // If no grouping chars are seen, no grouping check + // is applied. Therefore __found_grouping is adjusted + // only if decimal_point comes after some thousands_sep. + if (__found_grouping.size()) + __found_grouping += static_cast(__sep_pos); + __xtrc += '.'; + __found_dec = true; + } + else + break; + } + else + { + const char_type* __q = + __traits_type::find(__lit_zero, 10, __c); + if (__q) + { + __xtrc += '0' + (__q - __lit_zero); + __found_mantissa = true; + ++__sep_pos; + } + else if ((__c == __lit[__num_base::_S_ie] + || __c == __lit[__num_base::_S_iE]) + && !__found_sci && __found_mantissa) + { + // Scientific notation. + if (__found_grouping.size() && !__found_dec) + __found_grouping += static_cast(__sep_pos); + __xtrc += 'e'; + __found_sci = true; + + // Remove optional plus or minus sign, if they exist. + if (++__beg != __end) + { + __c = *__beg; + const bool __plus = __c == __lit[__num_base::_S_iplus]; + if ((__plus || __c == __lit[__num_base::_S_iminus]) + && !(__lc->_M_use_grouping + && __c == __lc->_M_thousands_sep) + && !(__c == __lc->_M_decimal_point)) + __xtrc += __plus ? '+' : '-'; + else + continue; + } + else + { + __testeof = true; + break; + } + } + else + break; + } + + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } // Digit grouping is checked. If grouping and found_grouping don't // match, then get very very upset, and set failbit. @@ -415,12 +359,9 @@ namespace std if (!std::__verify_grouping(__lc->_M_grouping, __lc->_M_grouping_size, __found_grouping)) - __err |= ios_base::failbit; + __err = ios_base::failbit; } - // Finish up. - if (__beg == __end) - __err |= ios_base::eofbit; return __beg; } @@ -431,12 +372,15 @@ namespace std _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, ios_base::iostate& __err, _ValueT& __v) const { - typedef char_traits<_CharT> __traits_type; - typedef typename numpunct<_CharT>::__cache_type __cache_type; + typedef char_traits<_CharT> __traits_type; + using __gnu_cxx::__add_unsigned; + typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; + typedef __numpunct_cache<_CharT> __cache_type; __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); const __cache_type* __lc = __uc(__loc); const _CharT* __lit = __lc->_M_atoms_in; + char_type __c = char_type(); // NB: Iff __basefield == 0, __base can change based on contents. const ios_base::fmtflags __basefield = __io.flags() @@ -444,57 +388,72 @@ namespace std const bool __oct = __basefield == ios_base::oct; int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); - // True if numeric digits are found. - bool __found_num = false; + // True if __beg becomes equal to __end. + bool __testeof = __beg == __end; // First check for sign. bool __negative = false; - if (__beg != __end) + if (!__testeof) { - const char_type __c = *__beg; - if (numeric_limits<_ValueT>::is_signed) - __negative = __c == __lit[__num_base::_S_iminus]; + __c = *__beg; + __negative = __c == __lit[__num_base::_S_iminus]; if ((__negative || __c == __lit[__num_base::_S_iplus]) && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) && !(__c == __lc->_M_decimal_point)) - ++__beg; + { + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } } // Next, look for leading zeros and check required digits // for base formats. - while (__beg != __end) + bool __found_zero = false; + int __sep_pos = 0; + while (!__testeof) { - const char_type __c = *__beg; - if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep + if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) || __c == __lc->_M_decimal_point) break; else if (__c == __lit[__num_base::_S_izero] - && (!__found_num || __base == 10)) + && (!__found_zero || __base == 10)) { - __found_num = true; - ++__beg; + __found_zero = true; + ++__sep_pos; + if (__basefield == 0) + __base = 8; + if (__base == 8) + __sep_pos = 0; } - else if (__found_num) + else if (__found_zero + && (__c == __lit[__num_base::_S_ix] + || __c == __lit[__num_base::_S_iX])) { - if (__c == __lit[__num_base::_S_ix] - || __c == __lit[__num_base::_S_iX]) + if (__basefield == 0) + __base = 16; + if (__base == 16) { - if (__basefield == 0) - __base = 16; - if (__base == 16) - { - __found_num = false; - ++__beg; - } + __found_zero = false; + __sep_pos = 0; } - else if (__basefield == 0) - __base = 8; - break; + else + break; } else break; - } + if (++__beg != __end) + { + __c = *__beg; + if (!__found_zero) + break; + } + else + __testeof = true; + } + // At this point, base is determined. If not hex, only allow // base digits as valid input. const size_t __len = (__base == 16 ? __num_base::_S_iend @@ -504,121 +463,123 @@ namespace std string __found_grouping; if (__lc->_M_use_grouping) __found_grouping.reserve(32); - int __sep_pos = 0; - bool __overflow = false; - _ValueT __result = 0; + bool __testfail = false; + bool __testoverflow = false; + const __unsigned_type __max = + (__negative && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) + ? -__gnu_cxx::__numeric_traits<_ValueT>::__min + : __gnu_cxx::__numeric_traits<_ValueT>::__max; + const __unsigned_type __smax = __max / __base; + __unsigned_type __result = 0; + int __digit = 0; const char_type* __lit_zero = __lit + __num_base::_S_izero; - const char_type* __q; - if (__negative) - { - const _ValueT __min = numeric_limits<_ValueT>::min() / __base; - for (; __beg != __end; ++__beg) - { - // According to 22.2.2.1.2, p8-9, first look for thousands_sep - // and decimal_point. - const char_type __c = *__beg; - if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) - { - // 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; - } - else - { - __err |= ios_base::failbit; - break; - } - } - else if (__c == __lc->_M_decimal_point) - break; - else if (__q = __traits_type::find(__lit_zero, __len, __c)) - { - int __digit = __q - __lit_zero; - if (__digit > 15) - __digit -= 6; - if (__result < __min) - __overflow = true; - else - { - const _ValueT __new_result = __result * __base - - __digit; - __overflow |= __new_result > __result; - __result = __new_result; - ++__sep_pos; - __found_num = true; - } - } - else - // Not a valid input item. - break; - } - } - else - { - const _ValueT __max = numeric_limits<_ValueT>::max() / __base; - for (; __beg != __end; ++__beg) - { - const char_type __c = *__beg; - if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) - { - if (__sep_pos) - { - __found_grouping += static_cast(__sep_pos); - __sep_pos = 0; - } - else - { - __err |= ios_base::failbit; - break; - } - } - else if (__c == __lc->_M_decimal_point) - break; - else if (__q = __traits_type::find(__lit_zero, __len, __c)) - { - int __digit = __q - __lit_zero; - if (__digit > 15) - __digit -= 6; - if (__result > __max) - __overflow = true; - else - { - const _ValueT __new_result = __result * __base - + __digit; - __overflow |= __new_result < __result; - __result = __new_result; - ++__sep_pos; - __found_num = true; - } - } - else - break; - } - } - - // Digit grouping is checked. If grouping and found_grouping don't - // match, then get very very upset, and set failbit. - if (__found_grouping.size()) - { - // Add the ending grouping. - __found_grouping += static_cast(__sep_pos); - - if (!std::__verify_grouping(__lc->_M_grouping, - __lc->_M_grouping_size, - __found_grouping)) - __err |= ios_base::failbit; - } - if (!(__err & ios_base::failbit) && !__overflow - && __found_num) - __v = __result; + if (!__lc->_M_allocated) + // "C" locale + while (!__testeof) + { + __digit = _M_find(__lit_zero, __len, __c); + if (__digit == -1) + break; + + if (__result > __smax) + __testoverflow = true; + else + { + __result *= __base; + __testoverflow |= __result > __max - __digit; + __result += __digit; + ++__sep_pos; + } + + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } else - __err |= ios_base::failbit; + while (!__testeof) + { + // According to 22.2.2.1.2, p8-9, first look for thousands_sep + // and decimal_point. + if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) + { + // 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; + } + else + { + __testfail = true; + break; + } + } + else if (__c == __lc->_M_decimal_point) + break; + else + { + const char_type* __q = + __traits_type::find(__lit_zero, __len, __c); + if (!__q) + break; + + __digit = __q - __lit_zero; + if (__digit > 15) + __digit -= 6; + if (__result > __smax) + __testoverflow = true; + else + { + __result *= __base; + __testoverflow |= __result > __max - __digit; + __result += __digit; + ++__sep_pos; + } + } + + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } + + // Digit grouping is checked. If grouping and found_grouping don't + // match, then get very very upset, and set failbit. + if (__found_grouping.size()) + { + // Add the ending grouping. + __found_grouping += static_cast(__sep_pos); - if (__beg == __end) + if (!std::__verify_grouping(__lc->_M_grouping, + __lc->_M_grouping_size, + __found_grouping)) + __err = ios_base::failbit; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 23. Num_get overflow result. + if ((!__sep_pos && !__found_zero && !__found_grouping.size()) + || __testfail) + { + __v = 0; + __err = ios_base::failbit; + } + else if (__testoverflow) + { + if (__negative + && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) + __v = __gnu_cxx::__numeric_traits<_ValueT>::__min; + else + __v = __gnu_cxx::__numeric_traits<_ValueT>::__max; + __err = ios_base::failbit; + } + else + __v = __negative ? -__result : __result; + + if (__testeof) __err |= ios_base::eofbit; return __beg; } @@ -639,121 +600,134 @@ namespace std long __l = -1; __beg = _M_extract_int(__beg, __end, __io, __err, __l); if (__l == 0 || __l == 1) - __v = __l; + __v = bool(__l); else - __err |= ios_base::failbit; + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 23. Num_get overflow result. + __v = true; + __err = ios_base::failbit; + if (__beg == __end) + __err |= ios_base::eofbit; + } } else { // Parse bool values as alphanumeric. - typedef char_traits<_CharT> __traits_type; - typedef typename numpunct<_CharT>::__cache_type __cache_type; + typedef __numpunct_cache<_CharT> __cache_type; __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); const __cache_type* __lc = __uc(__loc); bool __testf = true; bool __testt = true; - size_t __n; - for (__n = 0; __beg != __end; ++__n, ++__beg) - { - if (__testf) - if (__n < __lc->_M_falsename_size) - __testf = *__beg == __lc->_M_falsename[__n]; - else + bool __donef = __lc->_M_falsename_size == 0; + bool __donet = __lc->_M_truename_size == 0; + bool __testeof = false; + size_t __n = 0; + while (!__donef || !__donet) + { + if (__beg == __end) + { + __testeof = true; break; + } - if (__testt) - if (__n < __lc->_M_truename_size) - __testt = *__beg == __lc->_M_truename[__n]; - else - break; + const char_type __c = *__beg; - if (!__testf && !__testt) - break; - } - if (__testf && __n == __lc->_M_falsename_size) - __v = 0; - else if (__testt && __n == __lc->_M_truename_size) - __v = 1; - else - __err |= ios_base::failbit; + if (!__donef) + __testf = __c == __lc->_M_falsename[__n]; - if (__beg == __end) - __err |= ios_base::eofbit; - } - return __beg; - } + if (!__testf && __donet) + break; - template - _InIter - num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, long& __v) const - { return _M_extract_int(__beg, __end, __io, __err, __v); } + if (!__donet) + __testt = __c == __lc->_M_truename[__n]; - 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 - { return _M_extract_int(__beg, __end, __io, __err, __v); } + if (!__testt && __donef) + break; - template - _InIter - num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, unsigned int& __v) const - { return _M_extract_int(__beg, __end, __io, __err, __v); } + if (!__testt && !__testf) + break; - 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 - { return _M_extract_int(__beg, __end, __io, __err, __v); } + ++__n; + ++__beg; -#ifdef _GLIBCXX_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 - { return _M_extract_int(__beg, __end, __io, __err, __v); } + __donef = !__testf || __n >= __lc->_M_falsename_size; + __donet = !__testt || __n >= __lc->_M_truename_size; + } + if (__testf && __n == __lc->_M_falsename_size && __n) + { + __v = false; + if (__testt && __n == __lc->_M_truename_size) + __err = ios_base::failbit; + else + __err = __testeof ? ios_base::eofbit : ios_base::goodbit; + } + else if (__testt && __n == __lc->_M_truename_size && __n) + { + __v = true; + __err = __testeof ? ios_base::eofbit : ios_base::goodbit; + } + else + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 23. Num_get overflow result. + __v = false; + __err = ios_base::failbit; + if (__testeof) + __err |= ios_base::eofbit; + } + } + return __beg; + } template _InIter num_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, unsigned long long& __v) const - { return _M_extract_int(__beg, __end, __io, __err, __v); } -#endif + ios_base::iostate& __err, float& __v) const + { + string __xtrc; + __xtrc.reserve(32); + __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); + std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; + } template _InIter num_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, float& __v) const + ios_base::iostate& __err, double& __v) const { string __xtrc; __xtrc.reserve(32); __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); + if (__beg == __end) + __err |= ios_base::eofbit; return __beg; } +#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ template _InIter num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, double& __v) const + __do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, double& __v) const { string __xtrc; __xtrc.reserve(32); __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); + if (__beg == __end) + __err |= ios_base::eofbit; return __beg; } +#endif template _InIter @@ -765,6 +739,8 @@ namespace std __xtrc.reserve(32); __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); + if (__beg == __end) + __err |= ios_base::eofbit; return __beg; } @@ -777,18 +753,19 @@ namespace std // Prepare for hex formatted input. typedef ios_base::fmtflags fmtflags; const fmtflags __fmt = __io.flags(); - __io.flags(__fmt & ~ios_base::basefield | ios_base::hex); + __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex); + + typedef __gnu_cxx::__conditional_type<(sizeof(void*) + <= sizeof(unsigned long)), + unsigned long, unsigned long long>::__type _UIntPtrType; - unsigned long __ul; + _UIntPtrType __ul; __beg = _M_extract_int(__beg, __end, __io, __err, __ul); // Reset from hex formatted input. __io.flags(__fmt); - if (!(__err & ios_base::failbit)) - __v = reinterpret_cast(__ul); - else - __err |= ios_base::failbit; + __v = reinterpret_cast(__ul); return __beg; } @@ -802,97 +779,38 @@ namespace std { // [22.2.2.2.2] Stage 3. // If necessary, pad. - __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, - __w, __len, true); + __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, + __cs, __w, __len); __len = static_cast(__w); } - // Forwarding functions to peel signed from unsigned integer types. - template - inline int - __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit, - ios_base::fmtflags __flags) - { - unsigned long __ul = static_cast(__v); - bool __neg = false; - if (__v < 0) - { - __ul = -__ul; - __neg = true; - } - return __int_to_char(__bufend, __ul, __lit, __flags, __neg); - } - - template - inline int - __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit, - ios_base::fmtflags __flags) - { - // About showpos, see Table 60 and C99 7.19.6.1, p6 (+). - return __int_to_char(__bufend, __v, __lit, - __flags & ~ios_base::showpos, false); - } - -#ifdef _GLIBCXX_USE_LONG_LONG - template - inline int - __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit, - ios_base::fmtflags __flags) - { - unsigned long long __ull = static_cast(__v); - bool __neg = false; - if (__v < 0) - { - __ull = -__ull; - __neg = true; - } - return __int_to_char(__bufend, __ull, __lit, __flags, __neg); - } - - template - inline int - __int_to_char(_CharT* __bufend, unsigned long long __v, - const _CharT* __lit, ios_base::fmtflags __flags) - { return __int_to_char(__bufend, __v, __lit, - __flags & ~ios_base::showpos, false); } -#endif +_GLIBCXX_END_NAMESPACE_LDBL template int __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, - ios_base::fmtflags __flags, bool __neg) + ios_base::fmtflags __flags, bool __dec) { - // Don't write base if already 0. - const bool __showbase = (__flags & ios_base::showbase) && __v; - const ios_base::fmtflags __basefield = __flags & ios_base::basefield; - _CharT* __buf = __bufend - 1; - - if (__builtin_expect(__basefield != ios_base::oct && - __basefield != ios_base::hex, true)) + _CharT* __buf = __bufend; + if (__builtin_expect(__dec, true)) { // Decimal. do { - *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits]; + *--__buf = __lit[(__v % 10) + __num_base::_S_odigits]; __v /= 10; } while (__v != 0); - if (__neg) - *__buf-- = __lit[__num_base::_S_ominus]; - else if (__flags & ios_base::showpos) - *__buf-- = __lit[__num_base::_S_oplus]; } - else if (__basefield == ios_base::oct) + else if ((__flags & ios_base::basefield) == ios_base::oct) { // Octal. do { - *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits]; + *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits]; __v >>= 3; } while (__v != 0); - if (__showbase) - *__buf-- = __lit[__num_base::_S_odigits]; } else { @@ -902,54 +820,27 @@ namespace std : __num_base::_S_odigits; do { - *__buf-- = __lit[(__v & 0xf) + __case_offset]; + *--__buf = __lit[(__v & 0xf) + __case_offset]; __v >>= 4; } while (__v != 0); - if (__showbase) - { - // 'x' or 'X' - *__buf-- = __lit[__num_base::_S_ox + __uppercase]; - // '0' - *__buf-- = __lit[__num_base::_S_odigits]; - } } - return __bufend - __buf - 1; + return __bufend - __buf; } +_GLIBCXX_BEGIN_NAMESPACE_LDBL + template void num_put<_CharT, _OutIter>:: _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, - ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const + ios_base&, _CharT* __new, _CharT* __cs, int& __len) const { - // By itself __add_grouping cannot deal correctly with __cs when - // ios::showbase is set and ios_base::oct || ios_base::hex. - // Therefore we take care "by hand" of the initial 0, 0x or 0X. - // However, remember that the latter do not occur if the number - // printed is '0' (__len == 1). - streamsize __off = 0; - const ios_base::fmtflags __basefield = __io.flags() - & ios_base::basefield; - if ((__io.flags() & ios_base::showbase) && __len > 1) - if (__basefield == ios_base::oct) - { - __off = 1; - __new[0] = __cs[0]; - } - else if (__basefield == ios_base::hex) - { - __off = 2; - __new[0] = __cs[0]; - __new[1] = __cs[1]; - } - _CharT* __p; - __p = std::__add_grouping(__new + __off, __sep, __grouping, - __grouping_size, __cs + __off, - __cs + __len); + _CharT* __p = std::__add_grouping(__new, __sep, __grouping, + __grouping_size, __cs, __cs + __len); __len = __p - __new; } - + template template _OutIter @@ -957,33 +848,70 @@ namespace std _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, _ValueT __v) const { - typedef typename numpunct<_CharT>::__cache_type __cache_type; + using __gnu_cxx::__add_unsigned; + typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; + typedef __numpunct_cache<_CharT> __cache_type; __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); const __cache_type* __lc = __uc(__loc); const _CharT* __lit = __lc->_M_atoms_out; + const ios_base::fmtflags __flags = __io.flags(); // Long enough to hold hex, dec, and octal representations. - const int __ilen = 4 * sizeof(_ValueT); + const int __ilen = 5 * sizeof(_ValueT); _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __ilen)); // [22.2.2.2.2] Stage 1, numeric conversion to character. // Result is returned right-justified in the buffer. - int __len; - __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags()); + const ios_base::fmtflags __basefield = __flags & ios_base::basefield; + const bool __dec = (__basefield != ios_base::oct + && __basefield != ios_base::hex); + const __unsigned_type __u = ((__v > 0 || !__dec) + ? __unsigned_type(__v) + : -__unsigned_type(__v)); + int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec); __cs += __ilen - __len; // Add grouping, if necessary. if (__lc->_M_use_grouping) { - // Grouping can add (almost) as many separators as the - // number of digits, but no more. + // Grouping can add (almost) as many separators as the number + // of digits + space is reserved for numeric base or sign. _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len * 2)); + * (__len + 1) + * 2)); _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, - __lc->_M_thousands_sep, __io, __cs2, __cs, __len); - __cs = __cs2; + __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len); + __cs = __cs2 + 2; + } + + // Complete Stage 1, prepend numeric base or sign. + if (__builtin_expect(__dec, true)) + { + // Decimal. + if (__v >= 0) + { + if (bool(__flags & ios_base::showpos) + && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) + *--__cs = __lit[__num_base::_S_oplus], ++__len; + } + else + *--__cs = __lit[__num_base::_S_ominus], ++__len; + } + else if (bool(__flags & ios_base::showbase) && __v) + { + if (__basefield == ios_base::oct) + *--__cs = __lit[__num_base::_S_odigits], ++__len; + else + { + // 'x' or 'X' + const bool __uppercase = __flags & ios_base::uppercase; + *--__cs = __lit[__num_base::_S_ox + __uppercase]; + // '0' + *--__cs = __lit[__num_base::_S_odigits]; + __len += 2; + } } // Pad. @@ -1012,10 +940,10 @@ namespace std // _GLIBCXX_RESOLVE_LIB_DEFECTS // 282. What types does numpunct grouping refer to? // Add grouping, if necessary. - _CharT* __p2; const int __declen = __p ? __p - __cs : __len; - __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size, - __cs, __cs + __declen); + _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping, + __grouping_size, + __cs, __cs + __declen); // Tack on decimal part. int __newlen = __p2 - __new; @@ -1027,7 +955,7 @@ namespace std __len = __newlen; } - // The following code uses snprintf (or sprintf(), when + // The following code uses vsnprintf (or vsprintf(), when // _GLIBCXX_USE_C99 is not defined) to convert floating point values // for insertion into a stream. An optimization would be to replace // them with code that works directly on a wide buffer and then use @@ -1044,113 +972,119 @@ namespace std _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, _ValueT __v) const { - typedef typename numpunct<_CharT>::__cache_type __cache_type; + typedef __numpunct_cache<_CharT> __cache_type; __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); const __cache_type* __lc = __uc(__loc); - // Note: digits10 is rounded down: add 1 to ensure the maximum - // available precision. Then, in general, one more 1 needs to - // be added since, when the %{g,G} conversion specifiers are - // chosen inside _S_format_float, the precision field is "the - // maximum number of significant digits", *not* the "number of - // digits to appear after the decimal point", as happens for - // %{e,E,f,F} (C99, 7.19.6.1,4). - const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; - // Use default precision if out of range. - streamsize __prec = __io.precision(); - if (__prec > static_cast(__max_digits)) - __prec = static_cast(__max_digits); - else if (__prec < static_cast(0)) - __prec = static_cast(6); + const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision(); + + const int __max_digits = + __gnu_cxx::__numeric_traits<_ValueT>::__digits10; // [22.2.2.2.2] Stage 1, numeric conversion to character. int __len; // Long enough for the max format spec. char __fbuf[16]; + __num_base::_S_format_float(__io, __fbuf, __mod); #ifdef _GLIBCXX_USE_C99 - // First try a buffer perhaps big enough (for sure sufficient + // First try a buffer perhaps big enough (most probably sufficient // for non-ios_base::fixed outputs) int __cs_size = __max_digits * 3; char* __cs = static_cast(__builtin_alloca(__cs_size)); - - __num_base::_S_format_float(__io, __fbuf, __mod); - __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_get_c_locale(), __prec); + __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, + __fbuf, __prec, __v); // If the buffer was not large enough, try again with the correct size. if (__len >= __cs_size) { __cs_size = __len + 1; __cs = static_cast(__builtin_alloca(__cs_size)); - __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_get_c_locale(), __prec); + __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, + __fbuf, __prec, __v); } #else // Consider the possibility of long ios_base::fixed outputs const bool __fixed = __io.flags() & ios_base::fixed; - const int __max_exp = numeric_limits<_ValueT>::max_exponent10; + const int __max_exp = + __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10; // The size of the output string is computed as follows. - // ios_base::fixed outputs may need up to __max_exp+1 chars - // for the integer part + up to __max_digits chars for the - // fractional part + 3 chars for sign, decimal point, '\0'. On - // the other hand, for non-fixed outputs __max_digits*3 chars - // are largely sufficient. - const int __cs_size = __fixed ? __max_exp + __max_digits + 4 - : __max_digits * 3; + // ios_base::fixed outputs may need up to __max_exp + 1 chars + // for the integer part + __prec chars for the fractional part + // + 3 chars for sign, decimal point, '\0'. On the other hand, + // for non-fixed outputs __max_digits * 2 + __prec chars are + // largely sufficient. + const int __cs_size = __fixed ? __max_exp + __prec + 4 + : __max_digits * 2 + __prec; char* __cs = static_cast(__builtin_alloca(__cs_size)); - - __num_base::_S_format_float(__io, __fbuf, __mod); - __len = std::__convert_from_v(__cs, 0, __fbuf, __v, - _S_get_c_locale(), __prec); + __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, + __prec, __v); #endif - // [22.2.2.2.2] Stage 2, convert to char_type, using correct - // numpunct.decimal_point() values for '.' and adding grouping. - const ctype<_CharT>& __ctype = use_facet >(__loc); - - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len)); - __ctype.widen(__cs, __cs + __len, __ws); - - // Replace decimal point. - const _CharT __cdec = __ctype.widen('.'); - const _CharT __dec = __lc->_M_decimal_point; - const _CharT* __p; - if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) - __ws[__p - __ws] = __dec; - - // Add grouping, if necessary. - if (__lc->_M_use_grouping) - { - // Grouping can add (almost) as many separators as the - // number of digits, but no more. - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len * 2)); - _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, - __lc->_M_thousands_sep, __p, __ws2, __ws, __len); - __ws = __ws2; - } - - // Pad. - const streamsize __w = __io.width(); - if (__w > static_cast(__len)) - { - _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __w)); - _M_pad(__fill, __w, __io, __ws3, __ws, __len); - __ws = __ws3; - } - __io.width(0); + // [22.2.2.2.2] Stage 2, convert to char_type, using correct + // numpunct.decimal_point() values for '.' and adding grouping. + const ctype<_CharT>& __ctype = use_facet >(__loc); + + _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len)); + __ctype.widen(__cs, __cs + __len, __ws); + + // Replace decimal point. + _CharT* __wp = 0; + const char* __p = char_traits::find(__cs, __len, '.'); + if (__p) + { + __wp = __ws + (__p - __cs); + *__wp = __lc->_M_decimal_point; + } + + // Add grouping, if necessary. + // N.B. Make sure to not group things like 2e20, i.e., no decimal + // point, scientific notation. + if (__lc->_M_use_grouping + && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9' + && __cs[1] >= '0' && __cs[2] >= '0'))) + { + // Grouping can add (almost) as many separators as the + // number of digits, but no more. + _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + + streamsize __off = 0; + if (__cs[0] == '-' || __cs[0] == '+') + { + __off = 1; + __ws2[0] = __ws[0]; + __len -= 1; + } + + _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, + __lc->_M_thousands_sep, __wp, __ws2 + __off, + __ws + __off, __len); + __len += __off; + + __ws = __ws2; + } - // [22.2.2.2.2] Stage 4. - // Write resulting, fully-formatted string to output iterator. - return std::__write(__s, __ws, __len); + // Pad. + const streamsize __w = __io.width(); + if (__w > static_cast(__len)) + { + _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); + _M_pad(__fill, __w, __io, __ws3, __ws, __len); + __ws = __ws3; + } + __io.width(0); + + // [22.2.2.2.2] Stage 4. + // Write resulting, fully-formatted string to output iterator. + return std::__write(__s, __ws, __len); } - + template _OutIter num_put<_CharT, _OutIter>:: @@ -1159,12 +1093,12 @@ namespace std const ios_base::fmtflags __flags = __io.flags(); if ((__flags & ios_base::boolalpha) == 0) { - unsigned long __uv = __v; - __s = _M_insert_int(__s, __io, __fill, __uv); + const long __l = __v; + __s = _M_insert_int(__s, __io, __fill, __l); } else { - typedef typename numpunct<_CharT>::__cache_type __cache_type; + typedef __numpunct_cache<_CharT> __cache_type; __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); const __cache_type* __lc = __uc(__loc); @@ -1177,11 +1111,25 @@ namespace std const streamsize __w = __io.width(); if (__w > static_cast(__len)) { - _CharT* __cs + const streamsize __plen = __w - __len; + _CharT* __ps = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __w)); - _M_pad(__fill, __w, __io, __cs, __name, __len); - __name = __cs; + * __plen)); + + char_traits<_CharT>::assign(__ps, __plen, __fill); + __io.width(0); + + if ((__flags & ios_base::adjustfield) == ios_base::left) + { + __s = std::__write(__s, __name, __len); + __s = std::__write(__s, __ps, __plen); + } + else + { + __s = std::__write(__s, __ps, __plen); + __s = std::__write(__s, __name, __len); + } + return __s; } __io.width(0); __s = std::__write(__s, __name, __len); @@ -1192,36 +1140,16 @@ namespace std template _OutIter num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const - { return _M_insert_int(__s, __io, __fill, __v); } - - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, - unsigned long __v) const - { return _M_insert_int(__s, __io, __fill, __v); } - -#ifdef _GLIBCXX_USE_LONG_LONG - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const - { return _M_insert_int(__s, __b, __fill, __v); } - - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, - unsigned long long __v) const - { return _M_insert_int(__s, __io, __fill, __v); } -#endif + do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const + { return _M_insert_float(__s, __io, __fill, char(), __v); } +#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ template _OutIter num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const + __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const { return _M_insert_float(__s, __io, __fill, char(), __v); } +#endif template _OutIter @@ -1237,1156 +1165,26 @@ namespace std const void* __v) const { const ios_base::fmtflags __flags = __io.flags(); - const 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)); + const ios_base::fmtflags __fmt = ~(ios_base::basefield + | ios_base::uppercase); + __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase)); + + typedef __gnu_cxx::__conditional_type<(sizeof(const void*) + <= sizeof(unsigned long)), + unsigned long, unsigned long long>::__type _UIntPtrType; __s = _M_insert_int(__s, __io, __fill, - reinterpret_cast(__v)); + reinterpret_cast<_UIntPtrType>(__v)); __io.flags(__flags); return __s; } - template - template - _InIter - money_get<_CharT, _InIter>:: - _M_extract(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, string& __units) const - { - typedef char_traits<_CharT> __traits_type; - typedef typename string_type::size_type size_type; - typedef money_base::part part; - typedef moneypunct<_CharT, _Intl> __moneypunct_type; - typedef typename __moneypunct_type::__cache_type __cache_type; - - const locale& __loc = __io._M_getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); +_GLIBCXX_END_NAMESPACE_LDBL - __use_cache<__cache_type> __uc; - const __cache_type* __lc = __uc(__loc); - const char_type* __lit = __lc->_M_atoms; - - // Deduced sign. - bool __negative = false; - // Sign size. - size_type __sign_size = 0; - // True if sign is mandatory. - const bool __mandatory_sign = (__lc->_M_positive_sign_size - && __lc->_M_negative_sign_size); - // String of grouping info from thousands_sep plucked from __units. - string __grouping_tmp; - if (__lc->_M_use_grouping) - __grouping_tmp.reserve(32); - // Last position before the decimal point. - int __last_pos = 0; - // Separator positions, then, possibly, fractional digits. - int __n = 0; - // If input iterator is in a valid state. - bool __testvalid = true; - // Flag marking when a decimal point is found. - bool __testdecfound = false; - - // The tentative returned string is stored here. - string __res; - __res.reserve(32); - - const char_type* __lit_zero = __lit + money_base::_S_zero; - const char_type* __q; - const money_base::pattern __p = __lc->_M_neg_format; - for (int __i = 0; __i < 4 && __testvalid; ++__i) - { - const part __which = static_cast(__p.field[__i]); - switch (__which) - { - case money_base::symbol: - // According to 22.2.6.1.2, p2, symbol is required - // if (__io.flags() & ios_base::showbase), otherwise - // is optional and consumed only if other characters - // are needed to complete the format. - if (__io.flags() & ios_base::showbase || __sign_size > 1 - || __i == 0 - || (__i == 1 && (__mandatory_sign - || (static_cast(__p.field[0]) - == money_base::sign) - || (static_cast(__p.field[2]) - == money_base::space))) - || (__i == 2 && ((static_cast(__p.field[3]) - == money_base::value) - || __mandatory_sign - && (static_cast(__p.field[3]) - == money_base::sign)))) - { - const size_type __len = __lc->_M_curr_symbol_size; - size_type __j = 0; - for (; __beg != __end && __j < __len - && *__beg == __lc->_M_curr_symbol[__j]; - ++__beg, ++__j); - if (__j != __len - && (__j || __io.flags() & ios_base::showbase)) - __testvalid = false; - } - break; - case money_base::sign: - // Sign might not exist, or be more than one character long. - if (__lc->_M_positive_sign_size && __beg != __end - && *__beg == __lc->_M_positive_sign[0]) - { - __sign_size = __lc->_M_positive_sign_size; - ++__beg; - } - else if (__lc->_M_negative_sign_size && __beg != __end - && *__beg == __lc->_M_negative_sign[0]) - { - __negative = true; - __sign_size = __lc->_M_negative_sign_size; - ++__beg; - } - else if (__lc->_M_positive_sign_size - && !__lc->_M_negative_sign_size) - // "... if no sign is detected, the result is given the sign - // that corresponds to the source of the empty string" - __negative = true; - else if (__mandatory_sign) - __testvalid = false; - break; - case money_base::value: - // Extract digits, remove and stash away the - // grouping of found thousands separators. - for (; __beg != __end; ++__beg) - if (__q = __traits_type::find(__lit_zero, 10, *__beg)) - { - __res += money_base::_S_atoms[__q - __lit]; - ++__n; - } - else if (*__beg == __lc->_M_decimal_point && !__testdecfound) - { - __last_pos = __n; - __n = 0; - __testdecfound = true; - } - else if (__lc->_M_use_grouping - && *__beg == __lc->_M_thousands_sep - && !__testdecfound) - { - if (__n) - { - // Mark position for later analysis. - __grouping_tmp += static_cast(__n); - __n = 0; - } - else - { - __testvalid = false; - break; - } - } - else - break; - if (__res.empty()) - __testvalid = false; - break; - case money_base::space: - // At least one space is required. - if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) - ++__beg; - else - __testvalid = false; - case money_base::none: - // Only if not at the end of the pattern. - if (__i != 3) - for (; __beg != __end - && __ctype.is(ctype_base::space, *__beg); ++__beg); - break; - } - } - - // Need to get the rest of the sign characters, if they exist. - if (__sign_size > 1 && __testvalid) - { - const char_type* __sign = __negative ? __lc->_M_negative_sign - : __lc->_M_positive_sign; - size_type __i = 1; - for (; __beg != __end && __i < __sign_size - && *__beg == __sign[__i]; ++__beg, ++__i); - - if (__i != __sign_size) - __testvalid = false; - } - - if (__testvalid) - { - // Strip leading zeros. - if (__res.size() > 1) - { - const size_type __first = __res.find_first_not_of('0'); - const bool __only_zeros = __first == string::npos; - if (__first) - __res.erase(0, __only_zeros ? __res.size() - 1 : __first); - } - - // 22.2.6.1.2, p4 - if (__negative && __res[0] != '0') - __res.insert(__res.begin(), '-'); - - // Test for grouping fidelity. - if (__grouping_tmp.size()) - { - // Add the ending grouping. - __grouping_tmp += static_cast(__testdecfound ? __last_pos - : __n); - if (!std::__verify_grouping(__lc->_M_grouping, - __lc->_M_grouping_size, - __grouping_tmp)) - __testvalid = false; - } - - // Iff not enough digits were supplied after the decimal-point. - if (__testdecfound && __lc->_M_frac_digits > 0 - && __n != __lc->_M_frac_digits) - __testvalid = false; - } - - // Iff no more characters are available. - if (__beg == __end) - __err |= ios_base::eofbit; - - // Iff valid sequence is not recognized. - if (!__testvalid) - __err |= ios_base::failbit; - else - __units.swap(__res); - - return __beg; - } - - template - _InIter - money_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, - ios_base::iostate& __err, long double& __units) const - { - string __str; - if (__intl) - __beg = _M_extract(__beg, __end, __io, __err, __str); - else - __beg = _M_extract(__beg, __end, __io, __err, __str); - std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); - return __beg; - } - - template - _InIter - money_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, - ios_base::iostate& __err, string_type& __units) const - { - typedef typename string::size_type size_type; - - const locale& __loc = __io._M_getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - - string __str; - const iter_type __ret = __intl ? _M_extract(__beg, __end, __io, - __err, __str) - : _M_extract(__beg, __end, __io, - __err, __str); - const size_type __len = __str.size(); - if (__len) - { - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len)); - __ctype.widen(__str.data(), __str.data() + __len, __ws); - __units.assign(__ws, __len); - } - - return __ret; - } - - template - template - _OutIter - money_put<_CharT, _OutIter>:: - _M_insert(iter_type __s, ios_base& __io, char_type __fill, - const string_type& __digits) const - { - typedef typename string_type::size_type size_type; - typedef money_base::part part; - typedef moneypunct<_CharT, _Intl> __moneypunct_type; - typedef typename __moneypunct_type::__cache_type __cache_type; - - const locale& __loc = __io._M_getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - - __use_cache<__cache_type> __uc; - const __cache_type* __lc = __uc(__loc); - const char_type* __lit = __lc->_M_atoms; - - // Determine if negative or positive formats are to be used, and - // discard leading negative_sign if it is present. - const char_type* __beg = __digits.data(); - - money_base::pattern __p; - const char_type* __sign; - size_type __sign_size; - if (*__beg != __lit[money_base::_S_minus]) - { - __p = __lc->_M_pos_format; - __sign = __lc->_M_positive_sign; - __sign_size = __lc->_M_positive_sign_size; - } - else - { - __p = __lc->_M_neg_format; - __sign = __lc->_M_negative_sign; - __sign_size = __lc->_M_negative_sign_size; - if (__digits.size()) - ++__beg; - } - - // Look for valid numbers in the ctype facet within input digits. - size_type __len = __ctype.scan_not(ctype_base::digit, __beg, - __beg + __digits.size()) - __beg; - if (__len) - { - // Assume valid input, and attempt to format. - // Break down input numbers into base components, as follows: - // final_value = grouped units + (decimal point) + (digits) - string_type __value; - __value.reserve(2 * __len); - - // Add thousands separators to non-decimal digits, per - // grouping rules. - int __paddec = __len - __lc->_M_frac_digits; - if (__paddec > 0) - { - if (__lc->_M_frac_digits < 0) - __paddec = __len; - if (__lc->_M_grouping_size) - { - _CharT* __ws = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * 2 * __len)); - _CharT* __ws_end = - std::__add_grouping(__ws, __lc->_M_thousands_sep, - __lc->_M_grouping, - __lc->_M_grouping_size, - __beg, __beg + __paddec); - __value.assign(__ws, __ws_end - __ws); - } - else - __value.assign(__beg, __paddec); - } - - // Deal with decimal point, decimal digits. - if (__lc->_M_frac_digits > 0) - { - __value += __lc->_M_decimal_point; - if (__paddec >= 0) - __value.append(__beg + __paddec, __lc->_M_frac_digits); - else - { - // Have to pad zeros in the decimal position. - __value.append(-__paddec, __lit[money_base::_S_zero]); - __value.append(__beg, __len); - } - } - - // Calculate length of resulting string. - const ios_base::fmtflags __f = __io.flags() - & ios_base::adjustfield; - __len = __value.size() + __sign_size; - __len += ((__io.flags() & ios_base::showbase) - ? __lc->_M_curr_symbol_size : 0); - - string_type __res; - __res.reserve(2 * __len); - - const size_type __width = static_cast(__io.width()); - const bool __testipad = (__f == ios_base::internal - && __len < __width); - // Fit formatted digits into the required pattern. - for (int __i = 0; __i < 4; ++__i) - { - const part __which = static_cast(__p.field[__i]); - switch (__which) - { - case money_base::symbol: - if (__io.flags() & ios_base::showbase) - __res.append(__lc->_M_curr_symbol, - __lc->_M_curr_symbol_size); - break; - case money_base::sign: - // Sign might not exist, or be more than one - // charater long. In that case, add in the rest - // below. - if (__sign_size) - __res += __sign[0]; - break; - case money_base::value: - __res += __value; - break; - case money_base::space: - // At least one space is required, but if internal - // formatting is required, an arbitrary number of - // fill spaces will be necessary. - if (__testipad) - __res.append(__width - __len, __fill); - else - __res += __fill; - break; - case money_base::none: - if (__testipad) - __res.append(__width - __len, __fill); - break; - } - } - - // Special case of multi-part sign parts. - if (__sign_size > 1) - __res.append(__sign + 1, __sign_size - 1); - - // Pad, if still necessary. - __len = __res.size(); - if (__width > __len) - { - if (__f == ios_base::left) - // After. - __res.append(__width - __len, __fill); - else - // Before. - __res.insert(0, __width - __len, __fill); - __len = __width; - } - - // Write resulting, fully-formatted string to output iterator. - __s = std::__write(__s, __res.data(), __len); - } - __io.width(0); - return __s; - } - - template - _OutIter - money_put<_CharT, _OutIter>:: - do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, - long double __units) const - { - const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); -#ifdef _GLIBCXX_USE_C99 - // First try a buffer perhaps big enough. - int __cs_size = 64; - char* __cs = static_cast(__builtin_alloca(__cs_size)); - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 328. Bad sprintf format modifier in money_put<>::do_put() - int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units, - _S_get_c_locale()); - // If the buffer was not large enough, try again with the correct size. - if (__len >= __cs_size) - { - __cs_size = __len + 1; - __cs = static_cast(__builtin_alloca(__cs_size)); - __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units, - _S_get_c_locale()); - } -#else - // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. - const int __cs_size = numeric_limits::max_exponent10 + 3; - char* __cs = static_cast(__builtin_alloca(__cs_size)); - int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units, - _S_get_c_locale()); -#endif - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __cs_size)); - __ctype.widen(__cs, __cs + __len, __ws); - const string_type __digits(__ws, __len); - return __intl ? _M_insert(__s, __io, __fill, __digits) - : _M_insert(__s, __io, __fill, __digits); - } - - template - _OutIter - money_put<_CharT, _OutIter>:: - do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, - const string_type& __digits) const - { return __intl ? _M_insert(__s, __io, __fill, __digits) - : _M_insert(__s, __io, __fill, __digits); } - - - // NB: Not especially useful. Without an ios_base object or some - // kind of locale reference, we are left clawing at the air where - // the side of the mountain used to be... - template - time_base::dateorder - time_get<_CharT, _InIter>::do_date_order() const - { return time_base::no_order; } - - // Expand a strftime format string and parse it. E.g., do_get_date() may - // pass %m/%d/%Y => extracted characters. - template - _InIter - time_get<_CharT, _InIter>:: - _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, tm* __tm, - const _CharT* __format) const - { - const locale& __loc = __io._M_getloc(); - const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const size_t __len = char_traits<_CharT>::length(__format); - - for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) - { - if (__ctype.narrow(__format[__i], 0) == '%') - { - // Verify valid formatting code, attempt to extract. - char __c = __ctype.narrow(__format[++__i], 0); - int __mem = 0; - if (__c == 'E' || __c == 'O') - __c = __ctype.narrow(__format[++__i], 0); - switch (__c) - { - const char* __cs; - _CharT __wcs[10]; - case 'a': - // Abbreviated weekday name [tm_wday] - const char_type* __days1[7]; - __tp._M_days_abbreviated(__days1); - __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1, - 7, __io, __err); - break; - case 'A': - // Weekday name [tm_wday]. - const char_type* __days2[7]; - __tp._M_days(__days2); - __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2, - 7, __io, __err); - break; - case 'h': - case 'b': - // Abbreviated month name [tm_mon] - const char_type* __months1[12]; - __tp._M_months_abbreviated(__months1); - __beg = _M_extract_name(__beg, __end, __tm->tm_mon, - __months1, 12, __io, __err); - break; - case 'B': - // Month name [tm_mon]. - const char_type* __months2[12]; - __tp._M_months(__months2); - __beg = _M_extract_name(__beg, __end, __tm->tm_mon, - __months2, 12, __io, __err); - break; - case 'c': - // Default time and date representation. - const char_type* __dt[2]; - __tp._M_date_time_formats(__dt); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __dt[0]); - break; - case 'd': - // Day [01, 31]. [tm_mday] - __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, - __io, __err); - break; - case 'e': - // Day [1, 31], with single digits preceded by - // space. [tm_mday] - if (__ctype.is(ctype_base::space, *__beg)) - __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, - 1, __io, __err); - else - __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, - 2, __io, __err); - break; - case 'D': - // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] - __cs = "%m/%d/%y"; - __ctype.widen(__cs, __cs + 9, __wcs); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __wcs); - break; - case 'H': - // Hour [00, 23]. [tm_hour] - __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, - __io, __err); - break; - case 'I': - // Hour [01, 12]. [tm_hour] - __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, - __io, __err); - break; - case 'm': - // Month [01, 12]. [tm_mon] - __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, - __io, __err); - if (!__err) - __tm->tm_mon = __mem - 1; - break; - case 'M': - // Minute [00, 59]. [tm_min] - __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, - __io, __err); - break; - case 'n': - if (__ctype.narrow(*__beg, 0) == '\n') - ++__beg; - else - __err |= ios_base::failbit; - break; - case 'R': - // Equivalent to (%H:%M). - __cs = "%H:%M"; - __ctype.widen(__cs, __cs + 6, __wcs); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __wcs); - break; - case 'S': - // Seconds. - __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, - __io, __err); - break; - case 't': - if (__ctype.narrow(*__beg, 0) == '\t') - ++__beg; - else - __err |= ios_base::failbit; - break; - case 'T': - // Equivalent to (%H:%M:%S). - __cs = "%H:%M:%S"; - __ctype.widen(__cs, __cs + 9, __wcs); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __wcs); - break; - case 'x': - // Locale's date. - const char_type* __dates[2]; - __tp._M_date_formats(__dates); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __dates[0]); - break; - case 'X': - // Locale's time. - const char_type* __times[2]; - __tp._M_time_formats(__times); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __times[0]); - break; - case 'y': - case 'C': // C99 - // Two digit year. [tm_year] - __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, - __io, __err); - break; - case 'Y': - // Year [1900). [tm_year] - __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, - __io, __err); - if (!__err) - __tm->tm_year = __mem - 1900; - break; - case 'Z': - // Timezone info. - if (__ctype.is(ctype_base::upper, *__beg)) - { - int __tmp; - __beg = _M_extract_name(__beg, __end, __tmp, - __timepunct_cache<_CharT>::_S_timezones, - 14, __io, __err); - - // GMT requires special effort. - if (__beg != __end && !__err && __tmp == 0 - && (*__beg == __ctype.widen('-') - || *__beg == __ctype.widen('+'))) - { - __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, - __io, __err); - __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, - __io, __err); - } - } - else - __err |= ios_base::failbit; - break; - default: - // Not recognized. - __err |= ios_base::failbit; - } - } - else - { - // Verify format and input match, extract and discard. - if (__format[__i] == *__beg) - ++__beg; - else - __err |= ios_base::failbit; - } - } - return __beg; - } - - template - _InIter - time_get<_CharT, _InIter>:: - _M_extract_num(iter_type __beg, iter_type __end, int& __member, - int __min, int __max, size_t __len, - ios_base& __io, ios_base::iostate& __err) const - { - const locale& __loc = __io._M_getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - - // As-is works for __len = 1, 2, 4, the values actually used. - int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); - - ++__min; - size_t __i = 0; - int __value = 0; - for (; __beg != __end && __i < __len; ++__beg, ++__i) - { - const char __c = __ctype.narrow(*__beg, '*'); - if (__c >= '0' && __c <= '9') - { - __value = __value * 10 + (__c - '0'); - const int __valuec = __value * __mult; - if (__valuec > __max || __valuec + __mult < __min) - break; - __mult /= 10; - } - else - break; - } - if (__i == __len) - __member = __value; - else - __err |= ios_base::failbit; - return __beg; - } - - // Assumptions: - // All elements in __names are unique. - template - _InIter - time_get<_CharT, _InIter>:: - _M_extract_name(iter_type __beg, iter_type __end, int& __member, - const _CharT** __names, size_t __indexlen, - ios_base& __io, ios_base::iostate& __err) const - { - typedef char_traits<_CharT> __traits_type; - const locale& __loc = __io._M_getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - - int* __matches = static_cast(__builtin_alloca(sizeof(int) - * __indexlen)); - size_t __nmatches = 0; - size_t __pos = 0; - bool __testvalid = true; - const char_type* __name; - - // Look for initial matches. - // NB: Some of the locale data is in the form of all lowercase - // names, and some is in the form of initially-capitalized - // names. Look for both. - if (__beg != __end) - { - const char_type __c = *__beg; - for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) - if (__c == __names[__i1][0] - || __c == __ctype.toupper(__names[__i1][0])) - __matches[__nmatches++] = __i1; - } - - while (__nmatches > 1) - { - // Find smallest matching string. - size_t __minlen = __traits_type::length(__names[__matches[0]]); - for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) - __minlen = std::min(__minlen, - __traits_type::length(__names[__matches[__i2]])); - ++__pos; - ++__beg; - if (__pos < __minlen && __beg != __end) - for (size_t __i3 = 0; __i3 < __nmatches;) - { - __name = __names[__matches[__i3]]; - if (__name[__pos] != *__beg) - __matches[__i3] = __matches[--__nmatches]; - else - ++__i3; - } - else - break; - } - - if (__nmatches == 1) - { - // Make sure found name is completely extracted. - ++__pos; - ++__beg; - __name = __names[__matches[0]]; - const size_t __len = __traits_type::length(__name); - while (__pos < __len && __beg != __end && __name[__pos] == *__beg) - ++__beg, ++__pos; - - if (__len == __pos) - __member = __matches[0]; - else - __testvalid = false; - } - else - __testvalid = false; - if (!__testvalid) - __err |= ios_base::failbit; - return __beg; - } - - template - _InIter - time_get<_CharT, _InIter>:: - do_get_time(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, tm* __tm) const - { - const locale& __loc = __io._M_getloc(); - const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); - const char_type* __times[2]; - __tp._M_time_formats(__times); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __times[0]); - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } - - template - _InIter - time_get<_CharT, _InIter>:: - do_get_date(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, tm* __tm) const - { - const locale& __loc = __io._M_getloc(); - const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); - const char_type* __dates[2]; - __tp._M_date_formats(__dates); - __beg = _M_extract_via_format(__beg, __end, __io, __err, - __tm, __dates[0]); - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } - - template - _InIter - time_get<_CharT, _InIter>:: - do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, tm* __tm) const - { - typedef char_traits<_CharT> __traits_type; - const locale& __loc = __io._M_getloc(); - const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const char_type* __days[7]; - __tp._M_days_abbreviated(__days); - int __tmpwday; - __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err); - - // Check to see if non-abbreviated name exists, and extract. - // NB: Assumes both _M_days and _M_days_abbreviated organized in - // exact same order, first to last, such that the resulting - // __days array with the same index points to a day, and that - // day's abbreviated form. - // NB: Also assumes that an abbreviated name is a subset of the name. - if (!__err) - { - size_t __pos = __traits_type::length(__days[__tmpwday]); - __tp._M_days(__days); - const char_type* __name = __days[__tmpwday]; - if (__name[__pos] == *__beg) - { - // Extract the rest of it. - const size_t __len = __traits_type::length(__name); - while (__pos < __len && __beg != __end - && __name[__pos] == *__beg) - ++__beg, ++__pos; - if (__len != __pos) - __err |= ios_base::failbit; - } - if (!__err) - __tm->tm_wday = __tmpwday; - } - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } - - template - _InIter - time_get<_CharT, _InIter>:: - do_get_monthname(iter_type __beg, iter_type __end, - ios_base& __io, ios_base::iostate& __err, tm* __tm) const - { - typedef char_traits<_CharT> __traits_type; - const locale& __loc = __io._M_getloc(); - const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const char_type* __months[12]; - __tp._M_months_abbreviated(__months); - int __tmpmon; - __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, - __io, __err); - - // Check to see if non-abbreviated name exists, and extract. - // NB: Assumes both _M_months and _M_months_abbreviated organized in - // exact same order, first to last, such that the resulting - // __months array with the same index points to a month, and that - // month's abbreviated form. - // NB: Also assumes that an abbreviated name is a subset of the name. - if (!__err) - { - size_t __pos = __traits_type::length(__months[__tmpmon]); - __tp._M_months(__months); - const char_type* __name = __months[__tmpmon]; - if (__name[__pos] == *__beg) - { - // Extract the rest of it. - const size_t __len = __traits_type::length(__name); - while (__pos < __len && __beg != __end - && __name[__pos] == *__beg) - ++__beg, ++__pos; - if (__len != __pos) - __err |= ios_base::failbit; - } - if (!__err) - __tm->tm_mon = __tmpmon; - } - - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } - - template - _InIter - time_get<_CharT, _InIter>:: - do_get_year(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, tm* __tm) const - { - const locale& __loc = __io._M_getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - - size_t __i = 0; - int __value = 0; - for (; __beg != __end && __i < 4; ++__beg, ++__i) - { - const char __c = __ctype.narrow(*__beg, '*'); - if (__c >= '0' && __c <= '9') - __value = __value * 10 + (__c - '0'); - else - break; - } - if (__i == 2 || __i == 4) - __tm->tm_year = __i == 2 ? __value : __value - 1900; - else - __err |= ios_base::failbit; - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } - - template - _OutIter - time_put<_CharT, _OutIter>:: - put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, - const _CharT* __beg, const _CharT* __end) const - { - const locale& __loc = __io._M_getloc(); - ctype<_CharT> const& __ctype = use_facet >(__loc); - for (; __beg != __end; ++__beg) - if (__ctype.narrow(*__beg, 0) != '%') - { - *__s = *__beg; - ++__s; - } - else if (++__beg != __end) - { - char __format; - char __mod = 0; - const char __c = __ctype.narrow(*__beg, 0); - if (__c != 'E' && __c != 'O') - __format = __c; - else if (++__beg != __end) - { - __mod = __c; - __format = __ctype.narrow(*__beg, 0); - } - else - break; - __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); - } - else - break; - return __s; - } - - template - _OutIter - time_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, - char __format, char __mod) const - { - const locale& __loc = __io._M_getloc(); - ctype<_CharT> const& __ctype = use_facet >(__loc); - __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); - - // NB: This size is arbitrary. Should this be a data member, - // initialized at construction? - const size_t __maxlen = 64; - char_type* __res = - static_cast(__builtin_alloca(sizeof(char_type) * __maxlen)); - - // NB: In IEE 1003.1-200x, and perhaps other locale models, it - // is possible that the format character will be longer than one - // character. Possibilities include 'E' or 'O' followed by a - // format character: if __mod is not the default argument, assume - // it's a valid modifier. - char_type __fmt[4]; - __fmt[0] = __ctype.widen('%'); - if (!__mod) - { - __fmt[1] = __format; - __fmt[2] = char_type(); - } - else - { - __fmt[1] = __mod; - __fmt[2] = __format; - __fmt[3] = char_type(); - } - - __tp._M_put(__res, __maxlen, __fmt, __tm); - - // Write resulting, fully-formatted string to output iterator. - return std::__write(__s, __res, char_traits::length(__res)); - } - - - // Generic version does nothing. - template - int - collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const - { return 0; } - - // Generic version does nothing. - template - size_t - collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const - { return 0; } - - template - int - collate<_CharT>:: - do_compare(const _CharT* __lo1, const _CharT* __hi1, - const _CharT* __lo2, const _CharT* __hi2) const - { - // strcoll assumes zero-terminated strings so we make a copy - // and then put a zero at the end. - const string_type __one(__lo1, __hi1); - const string_type __two(__lo2, __hi2); - - const _CharT* __p = __one.c_str(); - const _CharT* __pend = __one.data() + __one.length(); - const _CharT* __q = __two.c_str(); - const _CharT* __qend = __two.data() + __two.length(); - - // strcoll stops when it sees a nul character so we break - // the strings into zero-terminated substrings and pass those - // to strcoll. - for (;;) - { - const int __res = _M_compare(__p, __q); - if (__res) - return __res; - - __p += char_traits<_CharT>::length(__p); - __q += char_traits<_CharT>::length(__q); - if (__p == __pend && __q == __qend) - return 0; - else if (__p == __pend) - return -1; - else if (__q == __qend) - return 1; - - __p++; - __q++; - } - } - - template - typename collate<_CharT>::string_type - collate<_CharT>:: - do_transform(const _CharT* __lo, const _CharT* __hi) const - { - // strxfrm assumes zero-terminated strings so we make a copy - string_type __str(__lo, __hi); - - const _CharT* __p = __str.c_str(); - const _CharT* __pend = __str.data() + __str.length(); - - size_t __len = (__hi - __lo) * 2; - - string_type __ret; - - // strxfrm stops when it sees a nul character so we break - // the string into zero-terminated substrings and pass those - // to strxfrm. - for (;;) - { - // First try a buffer perhaps big enough. - _CharT* __c = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); - size_t __res = _M_transform(__c, __p, __len); - // If the buffer was not large enough, try again with the - // correct size. - if (__res >= __len) - { - __len = __res + 1; - __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __len)); - __res = _M_transform(__c, __p, __res + 1); - } - - __ret.append(__c, __res); - __p += char_traits<_CharT>::length(__p); - if (__p == __pend) - return __ret; - - __p++; - __ret.push_back(_CharT()); - } - } - - template - long - collate<_CharT>:: - do_hash(const _CharT* __lo, const _CharT* __hi) const - { - unsigned long __val = 0; - for (; __lo < __hi; ++__lo) - __val = *__lo + ((__val << 7) | - (__val >> (numeric_limits::digits - 7))); - 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: if __num, - // internal-adjusted objects are padded according to the rules below - // concerning 0[xX] and +-, otherwise, exactly as right-adjusted - // ones are. + // Construct correctly padded string, as per 22.2.2.2.2 + // Assumes + // __newlen > __oldlen + // __news is allocated for __newlen size // NB: Of the two parameters, _CharT can be deduced from the // function arguments. The other (_Traits) has to be explicitly specified. @@ -2394,8 +1192,7 @@ namespace std void __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds, - const streamsize __newlen, - const streamsize __oldlen, const bool __num) + streamsize __newlen, streamsize __oldlen) { const size_t __plen = static_cast(__newlen - __oldlen); const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; @@ -2403,13 +1200,13 @@ namespace std // Padding last. if (__adjust == ios_base::left) { - _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen); + _Traits::copy(__news, __olds, __oldlen); _Traits::assign(__news + __oldlen, __plen, __fill); return; } size_t __mod = 0; - if (__adjust == ios_base::internal && __num) + if (__adjust == ios_base::internal) { // Pad after the sign, if there is one. // Pad after 0[xX], if there is one. @@ -2417,72 +1214,63 @@ namespace std const locale& __loc = __io._M_getloc(); const ctype<_CharT>& __ctype = use_facet >(__loc); - const bool __testsign = (__ctype.widen('-') == __olds[0] - || __ctype.widen('+') == __olds[0]); - const bool __testhex = (__ctype.widen('0') == __olds[0] - && __oldlen > 1 - && (__ctype.widen('x') == __olds[1] - || __ctype.widen('X') == __olds[1])); - if (__testhex) + if (__ctype.widen('-') == __olds[0] + || __ctype.widen('+') == __olds[0]) { __news[0] = __olds[0]; - __news[1] = __olds[1]; - __mod = 2; - __news += 2; + __mod = 1; + ++__news; } - else if (__testsign) + else if (__ctype.widen('0') == __olds[0] + && __oldlen > 1 + && (__ctype.widen('x') == __olds[1] + || __ctype.widen('X') == __olds[1])) { __news[0] = __olds[0]; - __mod = 1; - ++__news; + __news[1] = __olds[1]; + __mod = 2; + __news += 2; } // else Padding first. } _Traits::assign(__news, __plen, __fill); - _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod), - __oldlen - __mod); + _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod); } - bool - __verify_grouping(const char* __grouping, size_t __grouping_size, - const string& __grouping_tmp) - { - const size_t __n = __grouping_tmp.size() - 1; - const size_t __min = std::min(__n, size_t(__grouping_size - 1)); - size_t __i = __n; - bool __test = true; - - // Parsed number groupings have to match the - // numpunct::grouping string exactly, starting at the - // right-most point of the parsed sequence of elements ... - for (size_t __j = 0; __j < __min && __test; --__i, ++__j) - __test = __grouping_tmp[__i] == __grouping[__j]; - for (; __i && __test; --__i) - __test = __grouping_tmp[__i] == __grouping[__min]; - // ... but the last parsed grouping can be <= numpunct - // grouping. - __test &= __grouping_tmp[0] <= __grouping[__min]; - return __test; - } - template _CharT* __add_grouping(_CharT* __s, _CharT __sep, const char* __gbeg, size_t __gsize, const _CharT* __first, const _CharT* __last) { - if (__last - __first > *__gbeg) + size_t __idx = 0; + size_t __ctr = 0; + + while (__last - __first > __gbeg[__idx] + && static_cast(__gbeg[__idx]) > 0 + && __gbeg[__idx] != __gnu_cxx::__numeric_traits::__max) { - const bool __bump = __gsize != 1; - __s = std::__add_grouping(__s, __sep, __gbeg + __bump, - __gsize - __bump, __first, - __last - *__gbeg); - __first = __last - *__gbeg; - *__s++ = __sep; + __last -= __gbeg[__idx]; + __idx < __gsize - 1 ? ++__idx : ++__ctr; } - do + + while (__first != __last) *__s++ = *__first++; - while (__first != __last); + + while (__ctr--) + { + *__s++ = __sep; + for (char __i = __gbeg[__idx]; __i > 0; --__i) + *__s++ = *__first++; + } + + while (__idx--) + { + *__s++ = __sep; + for (char __i = __gbeg[__idx]; __i > 0; --__i) + *__s++ = *__first++; + } + return __s; } @@ -2490,35 +1278,15 @@ namespace std // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. #if _GLIBCXX_EXTERN_TEMPLATE - extern template class moneypunct; - extern template class moneypunct; - extern template class moneypunct_byname; - extern template class moneypunct_byname; - extern template class money_get; - extern template class money_put; extern template class numpunct; extern template class numpunct_byname; - extern template class num_get; - extern template class num_put; - extern template class __timepunct; - extern template class time_put; - extern template class time_put_byname; - extern template class time_get; - extern template class time_get_byname; - extern template class messages; - extern template class messages_byname; + extern template class _GLIBCXX_NAMESPACE_LDBL num_get; + extern template class _GLIBCXX_NAMESPACE_LDBL num_put; extern template class ctype_byname; - extern template class codecvt_byname; - extern template class collate; - extern template class collate_byname; extern template - const codecvt& - use_facet >(const locale&); - - extern template - const collate& - use_facet >(const locale&); + const ctype& + use_facet >(const locale&); extern template const numpunct& @@ -2533,51 +1301,11 @@ namespace std use_facet >(const locale&); extern template - const moneypunct& - use_facet >(const locale&); - - extern template - const moneypunct& - use_facet >(const locale&); - - extern template - const money_put& - use_facet >(const locale&); - - extern template - const money_get& - use_facet >(const locale&); - - extern template - const __timepunct& - use_facet<__timepunct >(const locale&); - - extern template - const time_put& - use_facet >(const locale&); - - extern template - const time_get& - use_facet >(const locale&); - - extern template - const messages& - use_facet >(const locale&); - - extern template bool has_facet >(const locale&); extern template bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool has_facet >(const locale&); extern template @@ -2588,64 +1316,16 @@ namespace std bool has_facet >(const locale&); - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet<__timepunct >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - #ifdef _GLIBCXX_USE_WCHAR_T - extern template class moneypunct; - extern template class moneypunct; - extern template class moneypunct_byname; - extern template class moneypunct_byname; - extern template class money_get; - extern template class money_put; extern template class numpunct; extern template class numpunct_byname; - extern template class num_get; - extern template class num_put; - extern template class __timepunct; - extern template class time_put; - extern template class time_put_byname; - extern template class time_get; - extern template class time_get_byname; - extern template class messages; - extern template class messages_byname; + extern template class _GLIBCXX_NAMESPACE_LDBL num_get; + extern template class _GLIBCXX_NAMESPACE_LDBL num_put; extern template class ctype_byname; - extern template class codecvt_byname; - extern template class collate; - extern template class collate_byname; - - extern template - const codecvt& - use_facet >(locale const&); extern template - const collate& - use_facet >(const locale&); + const ctype& + use_facet >(const locale&); extern template const numpunct& @@ -2659,52 +1339,12 @@ namespace std const num_get& use_facet >(const locale&); - extern template - const moneypunct& - use_facet >(const locale&); - - extern template - const moneypunct& - use_facet >(const locale&); - - extern template - const money_put& - use_facet >(const locale&); - - extern template - const money_get& - use_facet >(const locale&); - - extern template - const __timepunct& - use_facet<__timepunct >(const locale&); - - extern template - const time_put& - use_facet >(const locale&); - - extern template - const time_get& - use_facet >(const locale&); - - extern template - const messages& - use_facet >(const locale&); - extern template bool has_facet >(const locale&); extern template bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool has_facet >(const locale&); extern template @@ -2714,36 +1354,10 @@ namespace std extern template bool has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet<__timepunct >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); #endif #endif -} // namespace std + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace #endif