X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fbits%2Flocale_facets.tcc;h=ba8f3988fd65a816c786993964a72a20737cd171;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=1bf3d7ce796270c2c848821612dd032bc865a38c;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 1bf3d7ce..ba8f3988 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 +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +// 2006, 2007, 2008, 2009 // 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,448 +15,668 @@ // 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 locale_facets.tcc + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. + */ -#ifndef _CPP_BITS_LOCFACETS_TCC -#define _CPP_BITS_LOCFACETS_TCC 1 +#ifndef _LOCALE_FACETS_TCC +#define _LOCALE_FACETS_TCC 1 #pragma GCC system_header -#include -#include // For localeconv -#include // For strof, strtold -#include // For ceil -#include // For isspace -#include // For numeric_limits -#include -#include // For bad_cast. - -namespace std -{ +_GLIBCXX_BEGIN_NAMESPACE(std) + + // Routine to access a cache for the facet. If the cache didn't + // exist before, it gets constructed on the fly. template - locale - locale::combine(const locale& __other) const + struct __use_cache { - _Impl* __tmp = new _Impl(*_M_impl, 1); - __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); - return locale(__tmp); - } + const _Facet* + operator() (const locale& __loc) const; + }; - template - bool - locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, - const basic_string<_CharT, _Traits, _Alloc>& __s2) const + // Specializations. + template + struct __use_cache<__numpunct_cache<_CharT> > { - 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); - } + const __numpunct_cache<_CharT>* + operator() (const locale& __loc) const + { + const size_t __i = numpunct<_CharT>::id._M_id(); + const locale::facet** __caches = __loc._M_impl->_M_caches; + if (!__caches[__i]) + { + __numpunct_cache<_CharT>* __tmp = NULL; + __try + { + __tmp = new __numpunct_cache<_CharT>; + __tmp->_M_cache(__loc); + } + __catch(...) + { + delete __tmp; + __throw_exception_again; + } + __loc._M_impl->_M_install_cache(__tmp, __i); + } + return static_cast*>(__caches[__i]); + } + }; - template - const _Facet& - use_facet(const locale& __loc) + template + void + __numpunct_cache<_CharT>::_M_cache(const locale& __loc) { - size_t __i = _Facet::id._M_id(); - 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]); - } + _M_allocated = true; - template - bool - has_facet(const locale& __loc) throw() - { - size_t __i = _Facet::id._M_id(); - locale::facet** __facets = __loc._M_impl->_M_facets; - return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); + 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 + && static_cast(_M_grouping[0]) > 0 + && (_M_grouping[0] + != __gnu_cxx::__numeric_traits::__max)); + + _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); } + // 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 + // locale. + // __grouping_tmp is parsed L to R + // 1,222,444 == __grouping_tmp of "\1\3\3" + // __grouping is parsed R to L + // 1,222,444 == __grouping of "\3" == "\3\3\3" + bool + __verify_grouping(const char* __grouping, size_t __grouping_size, + const string& __grouping_tmp); + +_GLIBCXX_BEGIN_LDBL_NAMESPACE - // Stage 1: Determine a conversion specifier. template _InIter num_get<_CharT, _InIter>:: _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, ios_base::iostate& __err, string& __xtrc) const { - typedef char_traits<_CharT> __traits_type; - const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const numpunct<_CharT>& __np = use_facet >(__loc); + typedef char_traits<_CharT> __traits_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 __beg becomes equal to __end. + bool __testeof = __beg == __end; // First check for sign. - const char_type __plus = __ctype.widen('+'); - const char_type __minus = __ctype.widen('-'); - int __pos = 0; - char_type __c = *__beg; - if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) - && __beg != __end) + if (!__testeof) { - __xtrc += __ctype.narrow(__c, char()); - ++__pos; - __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 ? '+' : '-'; + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } } - // Next, strip leading zeros. - const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); - bool __found_zero = false; - while (__traits_type::eq(__c, __zero) && __beg != __end) - { - __c = *(++__beg); - __found_zero = true; - } - if (__found_zero) + // Next, look for leading zeros. + bool __found_mantissa = false; + int __sep_pos = 0; + while (!__testeof) { - __xtrc += _S_atoms[_M_zero]; - ++__pos; + if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) + || __c == __lc->_M_decimal_point) + break; + else if (__c == __lit[__num_base::_S_izero]) + { + if (!__found_mantissa) + { + __xtrc += '0'; + __found_mantissa = true; + } + ++__sep_pos; + + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } + else + break; } // 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(); + if (__lc->_M_use_grouping) + __found_grouping.reserve(32); + const char_type* __lit_zero = __lit + __num_base::_S_izero; - while (__beg != __end) - { - // Only look in digits. - const char_type* __p = __traits_type::find(__watoms, 10, __c); + 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 ? '+' : '-'; + else + continue; + } + else + { + __testeof = true; + break; + } + } + else + break; - // NB: strchr returns true for __c == 0x0 - if (__p && !__traits_type::eq(__c, char_type())) - { - // Try first for acceptable digit; record it if found. - ++__pos; - __xtrc += _S_atoms[__p - __watoms]; - ++__sep_pos; - __c = *(++__beg); - } - else if (__traits_type::eq(__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; + 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 (__traits_type::eq(__c, __dec) && !__found_dec) - { - // According to the standard, if no grouping chars are seen, - // no grouping check is applied. Therefore __found_grouping - // must be adjusted only if __dec comes after some __sep. - if (__found_grouping.size()) - __found_grouping += static_cast(__sep_pos); - ++__pos; - __xtrc += '.'; - __c = *(++__beg); - __found_dec = true; - } - else if ((__traits_type::eq(__c, __watoms[_M_e]) - || __traits_type::eq(__c, __watoms[_M_E])) - && !__found_sci && __pos) - { - // Scientific notation. - ++__pos; - __xtrc += __ctype.narrow(__c, char()); - __c = *(++__beg); - - // Remove optional plus or minus sign, if they exist. - if (__traits_type::eq(__c, __plus) - || __traits_type::eq(__c, __minus)) - { - ++__pos; - __xtrc += __ctype.narrow(__c, char()); - __c = *(++__beg); - } - __found_sci = true; - } - else - // Not a valid input item. - 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. - if (__check_grouping && __found_grouping.size()) + if (__found_grouping.size()) { - // Add the ending grouping if a decimal wasn't found. - if (!__found_dec) + // Add the ending grouping if a decimal or 'e'/'E' wasn't found. + if (!__found_dec && !__found_sci) __found_grouping += static_cast(__sep_pos); - if (!__verify_grouping(__grouping, __found_grouping)) - __err |= ios_base::failbit; + + if (!std::__verify_grouping(__lc->_M_grouping, + __lc->_M_grouping_size, + __found_grouping)) + __err = ios_base::failbit; } - // Finish up - __xtrc += char(); - if (__beg == __end) - __err |= ios_base::eofbit; return __beg; } - // Stage 1: Determine a conversion specifier. template - _InIter - num_get<_CharT, _InIter>:: - _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, - ios_base::iostate& __err, string& __xtrc, int& __base) const - { - typedef char_traits<_CharT> __traits_type; - const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const numpunct<_CharT>& __np = use_facet >(__loc); - - // NB: Iff __basefield == 0, this can change based on contents. - 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; - - // First check for sign. - int __pos = 0; - char_type __c = *__beg; - const char_type __plus = __ctype.widen('+'); - const char_type __minus = __ctype.widen('-'); + template + _InIter + num_get<_CharT, _InIter>:: + _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, + ios_base::iostate& __err, _ValueT& __v) const + { + 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() + & ios_base::basefield; + const bool __oct = __basefield == ios_base::oct; + int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); + + // True if __beg becomes equal to __end. + bool __testeof = __beg == __end; + + // First check for sign. + bool __negative = false; + if (!__testeof) + { + __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)) + { + if (++__beg != __end) + __c = *__beg; + else + __testeof = true; + } + } - if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) - && __beg != __end) - { - __xtrc += __ctype.narrow(__c, char()); - ++__pos; - __c = *(++__beg); - } + // Next, look for leading zeros and check required digits + // for base formats. + bool __found_zero = false; + int __sep_pos = 0; + while (!__testeof) + { + 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_zero || __base == 10)) + { + __found_zero = true; + ++__sep_pos; + if (__basefield == 0) + __base = 8; + if (__base == 8) + __sep_pos = 0; + } + else if (__found_zero + && (__c == __lit[__num_base::_S_ix] + || __c == __lit[__num_base::_S_iX])) + { + if (__basefield == 0) + __base = 16; + if (__base == 16) + { + __found_zero = false; + __sep_pos = 0; + } + else + break; + } + else + break; - // Next, strip leading zeros and check required digits for base formats. - const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); - const char_type __x = __ctype.widen('x'); - const char_type __X = __ctype.widen('X'); - if (__base == 10) - { - bool __found_zero = false; - while (__traits_type::eq(__c, __zero) && __beg != __end) + 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 + - __num_base::_S_izero : __base); + + // Extract. + string __found_grouping; + if (__lc->_M_use_grouping) + __found_grouping.reserve(32); + 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; + + if (!__lc->_M_allocated) + // "C" locale + while (!__testeof) { - __c = *(++__beg); - __found_zero = true; + __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; } - if (__found_zero) + else + while (!__testeof) { - __xtrc += _S_atoms[_M_zero]; - ++__pos; - if (__basefield == 0) - { - if ((__traits_type::eq(__c, __x) - || __traits_type::eq(__c, __X)) - && __beg != __end) + // 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) { - __xtrc += __ctype.narrow(__c, char()); - ++__pos; - __c = *(++__beg); - __base = 16; + __found_grouping += static_cast(__sep_pos); + __sep_pos = 0; + } + else + { + __testfail = true; + break; } - else - __base = 8; } - } - } - else if (__base == 16) - { - if (__traits_type::eq(__c, __zero) && __beg != __end) - { - __xtrc += _S_atoms[_M_zero]; - ++__pos; - __c = *(++__beg); - if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) - && __beg != __end) + else if (__c == __lc->_M_decimal_point) + break; + else { - __xtrc += __ctype.narrow(__c, char()); - ++__pos; - __c = *(++__beg); + 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; } - } - - // 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; - - // Extract. - 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(); - int __sep_pos = 0; - const char_type __sep = __np.thousands_sep(); - while (__beg != __end) - { - const char_type* __p = __traits_type::find(__watoms, __len, __c); + + // 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); - // NB: strchr returns true for __c == 0x0 - if (__p && !__traits_type::eq(__c, char_type())) - { - // Try first for acceptable digit; record it if found. - __xtrc += _S_atoms[__p - __watoms]; - ++__pos; - ++__sep_pos; - __c = *(++__beg); - } - else if (__traits_type::eq(__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; - } + if (!std::__verify_grouping(__lc->_M_grouping, + __lc->_M_grouping_size, + __found_grouping)) + __err = ios_base::failbit; + } - // 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; - } + // _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; - // Finish up. - __xtrc += char(); - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } + if (__testeof) + __err |= ios_base::eofbit; + return __beg; + } -#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS - //17. Bad bool parsing + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 17. Bad bool parsing template _InIter num_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, bool& __v) const { - // Parse bool values as unsigned long if (!(__io.flags() & ios_base::boolalpha)) { + // Parse bool values as long. // NB: We can't just call do_get(long) here, as it might // refer to a derived class. - string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - unsigned long __ul; - __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); - if (!(__err & ios_base::failbit) && __ul <= 1) - __v = __ul; - else - __err |= ios_base::failbit; + long __l = -1; + __beg = _M_extract_int(__beg, __end, __io, __err, __l); + if (__l == 0 || __l == 1) + __v = bool(__l); + else + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 23. Num_get overflow result. + __v = true; + __err = ios_base::failbit; + if (__beg == __end) + __err |= ios_base::eofbit; + } } - - // Parse bool values as alphanumeric else { - typedef char_traits<_CharT> __traits_type; - typedef basic_string<_CharT> __string_type; - - locale __loc = __io.getloc(); - const numpunct<_CharT>& __np = use_facet >(__loc); - const __string_type __true = __np.truename(); - const __string_type __false = __np.falsename(); - const char_type* __trues = __true.c_str(); - const char_type* __falses = __false.c_str(); - const size_t __truen = __true.size() - 1; - const size_t __falsen = __false.size() - 1; - - for (size_t __n = 0; __beg != __end; ++__n) - { - char_type __c = *__beg++; - bool __testf = __n <= __falsen - ? __traits_type::eq(__c, __falses[__n]) : false; - bool __testt = __n <= __truen - ? __traits_type::eq(__c, __trues[__n]) : false; - if (!(__testf || __testt)) - { - __err |= ios_base::failbit; - break; - } - else if (__testf && __n == __falsen) - { - __v = 0; - break; - } - else if (__testt && __n == __truen) - { - __v = 1; - break; - } - } - if (__beg == __end) - __err |= ios_base::eofbit; - } + // Parse bool values as alphanumeric. + 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; + 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; + } + + const char_type __c = *__beg; + + if (!__donef) + __testf = __c == __lc->_M_falsename[__n]; + + if (!__testf && __donet) + break; + + if (!__donet) + __testt = __c == __lc->_M_truename[__n]; + + if (!__testt && __donef) + break; + + if (!__testt && !__testf) + break; + + ++__n; + ++__beg; + + __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; } -#endif template _InIter num_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, long& __v) const + ios_base::iostate& __err, float& __v) const { string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); + __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; } @@ -463,1935 +684,662 @@ namespace std _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, double& __v) const { string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - unsigned long __ul; - __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); - if (!(__err & ios_base::failbit) - && __ul <= numeric_limits::max()) - __v = static_cast(__ul); - else - __err |= ios_base::failbit; + __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, unsigned int& __v) const + __do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, double& __v) const { string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - unsigned long __ul; - __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); - if (!(__err & ios_base::failbit) - && __ul <= numeric_limits::max()) - __v = static_cast(__ul); - else - __err |= ios_base::failbit; + __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 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 double& __v) const { string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); + __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; } -#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, void*& __v) const { - string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); - return __beg; - } + // Prepare for hex formatted input. + typedef ios_base::fmtflags fmtflags; + const fmtflags __fmt = __io.flags(); + __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex); - 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 - { - string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); - return __beg; - } -#endif + typedef __gnu_cxx::__conditional_type<(sizeof(void*) + <= sizeof(unsigned long)), + unsigned long, unsigned long long>::__type _UIntPtrType; - template - _InIter - num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, float& __v) const - { - string __xtrc; - __xtrc.reserve(32); - __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); - __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); - return __beg; - } + _UIntPtrType __ul; + __beg = _M_extract_int(__beg, __end, __io, __err, __ul); - template - _InIter - num_get<_CharT, _InIter>:: - 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); - __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); - return __beg; - } - - template - _InIter - num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, long double& __v) const - { - string __xtrc; - __xtrc.reserve(32); - __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); - __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); - return __beg; - } - - template - _InIter - num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, void*& __v) const - { - // Prepare for hex formatted input - 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)); - - string __xtrc; - int __base; - __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); - - // Reset from hex formatted input + // Reset from hex formatted input. __io.flags(__fmt); - unsigned long __ul; - __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); - if (!(__err & ios_base::failbit)) - __v = reinterpret_cast(__ul); - else - __err |= ios_base::failbit; + __v = reinterpret_cast(__ul); return __beg; } - // The following code uses snprintf (or sprintf(), when _GLIBCPP_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 __pad to do the padding. - // It would be good to replace them anyway to gain back the efficiency - // that C++ provides by knowing up front the type of the values to insert. - // Also, sprintf is dangerous since may lead to accidental buffer overruns. - // This implementation follows the C++ standard fairly directly as - // outlined in 22.2.2.2 [lib.locale.num.put] - template - template - _OutIter - num_put<_CharT, _OutIter>:: - _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, - _ValueT __v) const - { - // Note: digits10 is rounded down: we need to add 1 to ensure - // we get the full 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; - streamsize __prec = __io.precision(); - - if (__prec > static_cast(__max_digits)) - __prec = static_cast(__max_digits); - - // Long enough for the max format spec. - char __fbuf[16]; - - // [22.2.2.2.2] Stage 1, numeric conversion to character. - int __len; -#ifdef _GLIBCPP_USE_C99 - // First try a buffer perhaps big enough (for sure sufficient for - // non-ios_base::fixed outputs) - int __cs_size = __max_digits * 3; - char* __cs = static_cast(__builtin_alloca(__cs_size)); - - const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); - if (__fp) - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); - - // If the buffer was not large enough, try again with the correct size. - if (__len >= __cs_size) - { - __cs_size = __len + 1; - __cs = static_cast(__builtin_alloca(__cs_size)); - if (__fp) - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale); - } -#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; - // 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; - char* __cs = static_cast(__builtin_alloca(__cs_size)); - - if (_S_format_float(__io, __fbuf, __mod, __prec)) - __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); - else - __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); -#endif - return _M_widen_float(__s, __io, __fill, __cs, __len); - } - - 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. - - // Long enough for the max format spec. - char __fbuf[16]; - _S_format_int(__io, __fbuf, __mod, __modl); -#ifdef _GLIBCPP_USE_C99 - // First try a buffer perhaps big enough. - int __cs_size = 64; - char* __cs = static_cast(__builtin_alloca(__cs_size)); - int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_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 = __convert_from_v(__cs, __cs_size, __fbuf, __v, - _S_c_locale); - } -#else - // Leave room for "+/-," "0x," and commas. This size is - // arbitrary, but should be largely sufficient. - char __cs[128]; - int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); -#endif - return _M_widen_int(__s, __io, __fill, __cs, __len); - } - - template - _OutIter - num_put<_CharT, _OutIter>:: - _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, - int __len) const - { - typedef char_traits<_CharT> __traits_type; - // [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) - * __len)); - // 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)); - __ctype.widen(__cs, __cs + __len, __ws); - - // Replace decimal point. - const _CharT* __p; - const numpunct<_CharT>& __np = use_facet >(__loc); - if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) - __ws[__p - __ws] = __np.decimal_point(); - -#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS -//282. What types does numpunct grouping refer to? - // Add grouping, if necessary. - const string __grouping = __np.grouping(); - ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - if (__grouping.size()) - { - _CharT* __p2; - int __declen = __p ? __p - __ws : __len; - __p2 = __add_grouping(__ws2, __np.thousands_sep(), - __grouping.c_str(), - __grouping.c_str() + __grouping.size(), - __ws, __ws + __declen); - int __newlen = __p2 - __ws2; - - // Tack on decimal part. - if (__p) - { - __traits_type::copy(__p2, __p, __len - __declen); - __newlen += __len - __declen; - } - - // Switch strings, establish correct new length. - __ws = __ws2; - __len = __newlen; - } -#endif - return _M_insert(__s, __io, __fill, __ws, __len); - } - - template - _OutIter - num_put<_CharT, _OutIter>:: - _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, - int __len) const - { - // [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) - * __len)); - // 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)); - __ctype.widen(__cs, __cs + __len, __ws); - - // Add grouping, if necessary. - const numpunct<_CharT>& __np = use_facet >(__loc); - const string __grouping = __np.grouping(); - const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - if (__grouping.size()) - { - // By itself __add_grouping cannot deal correctly with __ws 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; - if ((__io.flags() & ios_base::showbase) && __len > 1) - if (__basefield == ios_base::oct) - { - __off = 1; - *__ws2 = *__ws; - } - else if (__basefield == ios_base::hex) - { - __off = 2; - *__ws2 = *__ws; - *(__ws2 + 1) = *(__ws + 1); - } - _CharT* __p; - __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), - __grouping.c_str(), - __grouping.c_str() + __grouping.size(), - __ws + __off, __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 + void num_put<_CharT, _OutIter>:: - _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, - int __len) const + _M_pad(_CharT __fill, streamsize __w, ios_base& __io, + _CharT* __new, const _CharT* __cs, int& __len) const { - typedef char_traits<_CharT> __traits_type; // [22.2.2.2.2] Stage 3. - streamsize __w = __io.width(); - _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) - * __w)); - if (__w > static_cast(__len)) - { - __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, - __w, __len, true); - __len = static_cast(__w); - // Switch strings. - __ws = __ws2; - } - __io.width(0); - - // [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 - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const - { - ios_base::fmtflags __flags = __io.flags(); - if ((__flags & ios_base::boolalpha) == 0) - { - unsigned long __uv = __v; - __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv); - } - else - { - typedef basic_string<_CharT> __string_type; - locale __loc = __io.getloc(); - const numpunct<_CharT>& __np = use_facet >(__loc); - __string_type __name; - if (__v) - __name = __np.truename(); - else - __name = __np.falsename(); - __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); - } - return __s; + // If necessary, pad. + __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, + __cs, __w, __len); + __len = static_cast(__w); } - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const - { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); } - - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, - unsigned long __v) const - { return _M_convert_int(__s, __io, __fill, 'u', char(), __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 - { 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 _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } -#endif - - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const - { return _M_convert_float(__s, __io, __fill, char(), __v); } - - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, - long double __v) const - { return _M_convert_float(__s, __io, __fill, 'L', __v); } +_GLIBCXX_END_LDBL_NAMESPACE - template - _OutIter - num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, - const void* __v) const + template + int + __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, + ios_base::fmtflags __flags, bool __dec) { - 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 + _CharT* __buf = __bufend; + if (__builtin_expect(__dec, true)) { - __s = _M_convert_int(__s, __io, __fill, 'u', char(), - reinterpret_cast(__v)); - __io.flags(__flags); - } - catch (...) - { - __io.flags(__flags); - __throw_exception_again; - } - return __s; - } - - - 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_type __str; - __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); - - const int __n = numeric_limits::digits10; - char* __cs = static_cast(__builtin_alloca(__n)); - const locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); - const _CharT* __wcs = __str.c_str(); - __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); - __convert_to_v(__cs, __units, __err, _S_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 - { - // These contortions are quite unfortunate. - typedef moneypunct<_CharT, true> __money_true; - typedef moneypunct<_CharT, false> __money_false; - typedef money_base::part part; - typedef typename string_type::size_type size_type; - - const locale __loc = __io.getloc(); - const __money_true& __mpt = use_facet<__money_true>(__loc); - const __money_false& __mpf = use_facet<__money_false>(__loc); - const ctype<_CharT>& __ctype = use_facet >(__loc); - - const money_base::pattern __p = __intl ? __mpt.neg_format() - : __mpf.neg_format(); - - const string_type __pos_sign =__intl ? __mpt.positive_sign() - : __mpf.positive_sign(); - const string_type __neg_sign =__intl ? __mpt.negative_sign() - : __mpf.negative_sign(); - const char_type __d = __intl ? __mpt.decimal_point() - : __mpf.decimal_point(); - const char_type __sep = __intl ? __mpt.thousands_sep() - : __mpf.thousands_sep(); - - const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); - - // Set to deduced positive or negative sign, depending. - string_type __sign; - // String of grouping info from thousands_sep plucked from __units. - string __grouping_tmp; - // Marker for thousands_sep position. - int __sep_pos = 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_type __temp_units; - - char_type __c = *__beg; - char_type __eof = static_cast(char_traits::eof()); - for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) - { - part __which = static_cast(__p.field[__i]); - switch (__which) - { - case money_base::symbol: - if (__io.flags() & ios_base::showbase - || __i < 2 || __sign.size() > 1 - || ((static_cast(__p.field[3]) != money_base::none) - && __i == 2)) - { - // According to 22.2.6.1.2.2, symbol is required - // if (__io.flags() & ios_base::showbase), - // otherwise is optional and consumed only if - // other characters are needed to complete the - // format. - const string_type __symbol = __intl ? __mpt.curr_symbol() - : __mpf.curr_symbol(); - size_type __len = __symbol.size(); - size_type __j = 0; - while (__beg != __end - && __j < __len && __symbol[__j] == __c) - { - __c = *(++__beg); - ++__j; - } - // When (__io.flags() & ios_base::showbase) - // symbol is required. - if (__j != __len && (__io.flags() & ios_base::showbase)) - __testvalid = false; - } - break; - case money_base::sign: - // Sign might not exist, or be more than one character long. - if (__pos_sign.size() && __neg_sign.size()) - { - // Sign is mandatory. - if (__c == __pos_sign[0]) - { - __sign = __pos_sign; - __c = *(++__beg); - } - else if (__c == __neg_sign[0]) - { - __sign = __neg_sign; - __c = *(++__beg); - } - else - __testvalid = false; - } - else if (__pos_sign.size() && __c == __pos_sign[0]) - { - __sign = __pos_sign; - __c = *(++__beg); - } - else if (__neg_sign.size() && __c == __neg_sign[0]) - { - __sign = __neg_sign; - __c = *(++__beg); - } - break; - case money_base::value: - // Extract digits, remove and stash away the - // grouping of found thousands separators. - while (__beg != __end - && (__ctype.is(ctype_base::digit, __c) - || (__c == __d && !__testdecfound) - || __c == __sep)) - { - if (__c == __d) - { - __grouping_tmp += static_cast(__sep_pos); - __sep_pos = 0; - __testdecfound = true; - } - else if (__c == __sep) - { - if (__grouping.size()) - { - // Mark position for later analysis. - __grouping_tmp += static_cast(__sep_pos); - __sep_pos = 0; - } - else - { - __testvalid = false; - break; - } - } - else - { - __temp_units += __c; - ++__sep_pos; - } - __c = *(++__beg); - } - break; - case money_base::space: - case money_base::none: - // Only if not at the end of the pattern. - if (__i != 3) - while (__beg != __end - && __ctype.is(ctype_base::space, __c)) - __c = *(++__beg); - break; - } - } - - // Need to get the rest of the sign characters, if they exist. - if (__sign.size() > 1) - { - size_type __len = __sign.size(); - size_type __i = 1; - for (; __c != __eof && __i < __len; ++__i) - while (__beg != __end && __c != __sign[__i]) - __c = *(++__beg); - - if (__i != __len) - __testvalid = false; - } - - // Strip leading zeros. - while (__temp_units[0] == __ctype.widen('0')) - __temp_units.erase(__temp_units.begin()); - - if (__sign.size() && __sign == __neg_sign) - __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); - - // Test for grouping fidelity. - if (__grouping.size() && __grouping_tmp.size()) - { - if (!__verify_grouping(__grouping, __grouping_tmp)) - __testvalid = false; - } - - // Iff no more characters are available. - if (__c == __eof) - __err |= ios_base::eofbit; - - // Iff valid sequence is not recognized. - if (!__testvalid || !__temp_units.size()) - __err |= ios_base::failbit; - else - // Use the "swap trick" to copy __temp_units into __units. - __temp_units.swap(__units); - - return __beg; - } - - 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 _GLIBCPP_USE_C99 - // First try a buffer perhaps big enough. - int __cs_size = 64; - char* __cs = static_cast(__builtin_alloca(__cs_size)); - int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, - _S_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 = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, - _S_c_locale); - } -#else - // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, - // decimal digit, '\0'. - const int __cs_size = numeric_limits::max_exponent10 + 5; - char* __cs = static_cast(__builtin_alloca(__cs_size)); - int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); -#endif - _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); - __ctype.widen(__cs, __cs + __len, __ws); - string_type __digits(__ws); - return this->do_put(__s, __intl, __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 - { - typedef typename string_type::size_type size_type; - typedef money_base::part part; - - const locale __loc = __io.getloc(); - const size_type __width = static_cast(__io.width()); - - // These contortions are quite unfortunate. - typedef moneypunct<_CharT, true> __money_true; - typedef moneypunct<_CharT, false> __money_false; - const __money_true& __mpt = use_facet<__money_true>(__loc); - const __money_false& __mpf = use_facet<__money_false>(__loc); - const ctype<_CharT>& __ctype = use_facet >(__loc); - - // 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(); - const char_type* __end = __beg + __digits.size(); - money_base::pattern __p; - string_type __sign; - if (*__beg != __ctype.widen('-')) - { - __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); - __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); - } - else - { - __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); - __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); - ++__beg; - } - - // Look for valid numbers in the current ctype facet within input digits. - __end = __ctype.scan_not(ctype_base::digit, __beg, __end); - if (__beg != __end) - { - // 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 __res; - string_type __value; - const string_type __symbol = __intl ? __mpt.curr_symbol() - : __mpf.curr_symbol(); - - // Deal with decimal point, decimal digits. - const int __frac = __intl ? __mpt.frac_digits() - : __mpf.frac_digits(); - if (__frac > 0) - { - const char_type __d = __intl ? __mpt.decimal_point() - : __mpf.decimal_point(); - if (__end - __beg >= __frac) - { - __value = string_type(__end - __frac, __end); - __value.insert(__value.begin(), __d); - __end -= __frac; - } - else - { - // Have to pad zeros in the decimal position. - __value = string_type(__beg, __end); - int __paddec = __frac - (__end - __beg); - char_type __zero = __ctype.widen('0'); - __value.insert(__value.begin(), __paddec, __zero); - __value.insert(__value.begin(), __d); - __beg = __end; - } - } - - // Add thousands separators to non-decimal digits, per - // grouping rules. - if (__beg != __end) - { - const string __grouping = __intl ? __mpt.grouping() - : __mpf.grouping(); - if (__grouping.size()) - { - const char_type __sep = __intl ? __mpt.thousands_sep() - : __mpf.thousands_sep(); - const char* __gbeg = __grouping.c_str(); - const char* __gend = __gbeg + __grouping.size(); - const int __n = (__end - __beg) * 2; - _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)); - } - - // Calculate length of resulting string. - ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; - size_type __len = __value.size() + __sign.size(); - __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; - bool __testipad = __f == ios_base::internal && __len < __width; - - // Fit formatted digits into the required pattern. - for (int __i = 0; __i < 4; ++__i) - { - part __which = static_cast(__p.field[__i]); - switch (__which) - { - case money_base::symbol: - if (__io.flags() & ios_base::showbase) - __res += __symbol; - 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 += string_type(__width - __len, __fill); - else - __res += __ctype.widen(__fill); - break; - case money_base::none: - if (__testipad) - __res += string_type(__width - __len, __fill); - break; - } - } - - // Special case of multi-part sign parts. - if (__sign.size() > 1) - __res += string_type(__sign.begin() + 1, __sign.end()); - - // Pad, if still necessary. - __len = __res.size(); - if (__width > __len) + // Decimal. + do { - if (__f == ios_base::left) - // After. - __res.append(__width - __len, __fill); - else - // Before. - __res.insert(0, string_type(__width - __len, __fill)); - __len = __width; + *--__buf = __lit[(__v % 10) + __num_base::_S_odigits]; + __v /= 10; } - - // Write resulting, fully-formatted string to output iterator. - for (size_type __j = 0; __j < __len; ++__j, ++__s) - *__s = __res[__j]; + while (__v != 0); } - __io.width(0); - return __s; - } - - - // 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; } - - template - void - 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 - { - locale __loc = __io.getloc(); - __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); - const ctype<_CharT>& __ctype = use_facet >(__loc); - size_t __len = char_traits<_CharT>::length(__format); - - for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) + else if ((__flags & ios_base::basefield) == ios_base::oct) { - char __c = __format[__i]; - if (__c == '%') + // Octal. + do { - // Verify valid formatting code, attempt to extract. - __c = __format[++__i]; - char __mod = 0; - int __mem = 0; - if (__c == 'E' || __c == 'O') - { - __mod = __c; - __c = __format[++__i]; - } - 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); - _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, - __err); - break; - case 'A': - // Weekday name [tm_wday]. - const char_type* __days2[7]; - __tp._M_days(__days2); - _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, - __err); - break; - case 'h': - case 'b': - // Abbreviated month name [tm_mon] - const char_type* __months1[12]; - __tp._M_months_abbreviated(__months1); - _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, - __err); - break; - case 'B': - // Month name [tm_mon]. - const char_type* __months2[12]; - __tp._M_months(__months2); - _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, - __err); - break; - case 'c': - // Default time and date representation. - const char_type* __dt[2]; - __tp._M_date_time_formats(__dt); - _M_extract_via_format(__beg, __end, __io, __err, __tm, - __dt[0]); - break; - case 'd': - // Day [01, 31]. [tm_mday] - _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, - __ctype, __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); - _M_extract_via_format(__beg, __end, __io, __err, __tm, - __wcs); - break; - case 'H': - // Hour [00, 23]. [tm_hour] - _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, - __ctype, __err); - break; - case 'I': - // Hour [01, 12]. [tm_hour] - _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, - __ctype, __err); - break; - case 'm': - // Month [01, 12]. [tm_mon] - _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, - __err); - if (!__err) - __tm->tm_mon = __mem - 1; - break; - case 'M': - // Minute [00, 59]. [tm_min] - _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, - __ctype, __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); - _M_extract_via_format(__beg, __end, __io, __err, __tm, - __wcs); - break; - case 'S': - // Seconds. - _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, - __ctype, __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); - _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); - _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); - _M_extract_via_format(__beg, __end, __io, __err, __tm, - __times[0]); - break; - case 'y': - // Two digit year. [tm_year] - _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, - __ctype, __err); - break; - case 'Y': - // Year [1900). [tm_year] - _M_extract_num(__beg, __end, __mem, 0, - numeric_limits::max(), 4, - __ctype, __err); - if (!__err) - __tm->tm_year = __mem - 1900; - break; - case 'Z': - // Timezone info. - if (__ctype.is(ctype_base::upper, *__beg)) - { - int __tmp; - _M_extract_name(__beg, __end, __tmp, - __timepunct<_CharT>::_S_timezones, - 14, __err); - - // GMT requires special effort. - char_type __c = *__beg; - if (!__err && __tmp == 0 - && (__c == __ctype.widen('-') - || __c == __ctype.widen('+'))) - { - _M_extract_num(__beg, __end, __tmp, 0, 23, 2, - __ctype, __err); - _M_extract_num(__beg, __end, __tmp, 0, 59, 2, - __ctype, __err); - } - } - else - __err |= ios_base::failbit; - break; - default: - // Not recognized. - __err |= ios_base::failbit; - } - } - else - { - // Verify format and input match, extract and discard. - if (__c == __ctype.narrow(*__beg, 0)) - ++__beg; - else - __err |= ios_base::failbit; - } - } - } - - template - void - time_get<_CharT, _InIter>:: - _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, - int __min, int __max, size_t __len, - const ctype<_CharT>& __ctype, - ios_base::iostate& __err) const - { - size_t __i = 0; - string __digits; - bool __testvalid = true; - char_type __c = *__beg; - while (__beg != __end && __i < __len - && __ctype.is(ctype_base::digit, __c)) - { - __digits += __ctype.narrow(__c, 0); - __c = *(++__beg); - ++__i; - } - if (__i == __len) - { - int __value = atoi(__digits.c_str()); - if (__min <= __value && __value <= __max) - __member = __value; - else - __testvalid = false; + *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits]; + __v >>= 3; + } + while (__v != 0); } else - __testvalid = false; - if (!__testvalid) - __err |= ios_base::failbit; - } - - // Assumptions: - // All elements in __names are unique. - template - void - time_get<_CharT, _InIter>:: - _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, - const _CharT** __names, size_t __indexlen, - ios_base::iostate& __err) const - { - typedef char_traits<_CharT> __traits_type; - int* __matches = static_cast(__builtin_alloca(sizeof(int) * __indexlen)); - size_t __nmatches = 0; - size_t __pos = 0; - bool __testvalid = true; - const char_type* __name; - - char_type __c = *__beg; - // Look for initial matches. - for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) - if (__c == __names[__i1][0]) - __matches[__nmatches++] = __i1; - - while(__nmatches > 1) { - // Find smallest matching string. - size_t __minlen = 10; - for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) - __minlen = min(__minlen, - __traits_type::length(__names[__matches[__i2]])); - - if (__pos < __minlen && __beg != __end) + // Hex. + const bool __uppercase = __flags & ios_base::uppercase; + const int __case_offset = __uppercase ? __num_base::_S_oudigits + : __num_base::_S_odigits; + do { - ++__pos; - __c = *(++__beg); - for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) - { - __name = __names[__matches[__i3]]; - if (__name[__pos] != __c) - __matches[__i3] = __matches[--__nmatches]; - } + *--__buf = __lit[(__v & 0xf) + __case_offset]; + __v >>= 4; } - else - break; - } - - if (__nmatches == 1) - { - // Make sure found name is completely extracted. - __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; + while (__v != 0); } - else - __testvalid = false; - if (!__testvalid) - __err |= ios_base::failbit; + return __bufend - __buf; } - 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 - { - _CharT __wcs[3]; - const char* __cs = "%X"; - locale __loc = __io.getloc(); - ctype<_CharT> const& __ctype = use_facet >(__loc); - __ctype.widen(__cs, __cs + 3, __wcs); - _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } +_GLIBCXX_BEGIN_LDBL_NAMESPACE - 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 + template + void + num_put<_CharT, _OutIter>:: + _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, + ios_base&, _CharT* __new, _CharT* __cs, int& __len) const { - _CharT __wcs[3]; - const char* __cs = "%x"; - locale __loc = __io.getloc(); - ctype<_CharT> const& __ctype = use_facet >(__loc); - __ctype.widen(__cs, __cs + 3, __wcs); - _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; + _CharT* __p = std::__add_grouping(__new, __sep, __grouping, + __grouping_size, __cs, __cs + __len); + __len = __p - __new; } + + template + template + _OutIter + num_put<_CharT, _OutIter>:: + _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, + _ValueT __v) const + { + 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 = 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. + 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 + space is reserved for numeric base or sign. + _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * (__len + 1) + * 2)); + _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, + __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; + } + } - 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; - locale __loc = __io.getloc(); - __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); - const char_type* __days[7]; - __tp._M_days_abbreviated(__days); - int __tmpwday; - _M_extract_name(__beg, __end, __tmpwday, __days, 7, __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; - } + // Pad. + const streamsize __w = __io.width(); + if (__w > static_cast(__len)) + { + _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); + _M_pad(__fill, __w, __io, __cs3, __cs, __len); + __cs = __cs3; + } + __io.width(0); - 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 + // [22.2.2.2.2] Stage 4. + // Write resulting, fully-formatted string to output iterator. + return std::__write(__s, __cs, __len); + } + + template + void + num_put<_CharT, _OutIter>:: + _M_group_float(const char* __grouping, size_t __grouping_size, + _CharT __sep, const _CharT* __p, _CharT* __new, + _CharT* __cs, int& __len) const { - typedef char_traits<_CharT> __traits_type; - locale __loc = __io.getloc(); - __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); - const char_type* __months[12]; - __tp._M_months_abbreviated(__months); - int __tmpmon; - _M_extract_name(__beg, __end, __tmpmon, __months, 12, __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) + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 282. What types does numpunct grouping refer to? + // Add grouping, if necessary. + const int __declen = __p ? __p - __cs : __len; + _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping, + __grouping_size, + __cs, __cs + __declen); + + // Tack on decimal part. + int __newlen = __p2 - __new; + if (__p) { - 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; + char_traits<_CharT>::copy(__p2, __p, __len - __declen); + __newlen += __len - __declen; } - - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; + __len = __newlen; } - 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 - { - locale __loc = __io.getloc(); - const ctype<_CharT>& __ctype = use_facet >(__loc); + // 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 + // __pad to do the padding. It would be good to replace them anyway + // to gain back the efficiency that C++ provides by knowing up front + // the type of the values to insert. Also, sprintf is dangerous + // since may lead to accidental buffer overruns. This + // implementation follows the C++ standard fairly directly as + // outlined in 22.2.2.2 [lib.locale.num.put] + template + template + _OutIter + num_put<_CharT, _OutIter>:: + _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, + _ValueT __v) const + { + typedef __numpunct_cache<_CharT> __cache_type; + __use_cache<__cache_type> __uc; + const locale& __loc = __io._M_getloc(); + const __cache_type* __lc = __uc(__loc); - char_type __c = *__beg; - size_t __i = 0; - string __digits; - while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) - { - __digits += __ctype.narrow(__c, 0); - __c = *(++__beg); - ++__i; - } - if (__i == 2 || __i == 4) - { - long __l; - __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); - if (!(__err & ios_base::failbit) && __l <= INT_MAX) - { - __l = __i == 2 ? __l : __l - 1900; - __tm->tm_year = static_cast(__l); - } - } - else - __err |= ios_base::failbit; - if (__beg == __end) - __err |= ios_base::eofbit; - return __beg; - } + // Use default precision if out of range. + 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 (most probably sufficient + // for non-ios_base::fixed outputs) + int __cs_size = __max_digits * 3; + char* __cs = static_cast(__builtin_alloca(__cs_size)); + __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(_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 = + __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 + __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)); + __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. + _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; + } + // 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 - time_put<_CharT, _OutIter>:: - put(iter_type __s, ios_base& __io, char_type, const tm* __tm, - const _CharT* __beg, const _CharT* __end) const + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const { - locale __loc = __io.getloc(); - ctype<_CharT> const& __ctype = use_facet >(__loc); - while (__beg != __end) - { - char __c = __ctype.narrow(*__beg, 0); - ++__beg; - if (__c == '%') + const ios_base::fmtflags __flags = __io.flags(); + if ((__flags & ios_base::boolalpha) == 0) + { + const long __l = __v; + __s = _M_insert_int(__s, __io, __fill, __l); + } + else + { + 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* __name = __v ? __lc->_M_truename + : __lc->_M_falsename; + int __len = __v ? __lc->_M_truename_size + : __lc->_M_falsename_size; + + const streamsize __w = __io.width(); + if (__w > static_cast(__len)) { - char __format; - char __mod = 0; - size_t __len = 1; - __c = __ctype.narrow(*__beg, 0); - ++__beg; - if (__c == 'E' || __c == 'O') + const streamsize __plen = __w - __len; + _CharT* __ps + = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __plen)); + + char_traits<_CharT>::assign(__ps, __plen, __fill); + __io.width(0); + + if ((__flags & ios_base::adjustfield) == ios_base::left) { - __mod = __c; - __format = __ctype.narrow(*__beg, 0); - ++__beg; + __s = std::__write(__s, __name, __len); + __s = std::__write(__s, __ps, __plen); } else - __format = __c; - __s = this->do_put(__s, __io, char_type(), __tm, __format, - __mod); - } - else - { - *__s = __c; - ++__s; + { + __s = std::__write(__s, __ps, __plen); + __s = std::__write(__s, __name, __len); + } + return __s; } + __io.width(0); + __s = std::__write(__s, __name, __len); } 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 - { - locale __loc = __io.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. - size_t __len = char_traits::length(__res); - for (size_t __i = 0; __i < __len; ++__i, ++__s) - *__s = __res[__i]; - return __s; - } - - - // Generic version does nothing. - template - int - collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const - { return 0; } + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const + { return _M_insert_float(__s, __io, __fill, char(), __v); } - // Generic version does nothing. - template - size_t - collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const - { return 0; } +#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 + { return _M_insert_float(__s, __io, __fill, char(), __v); } +#endif - template - int - collate<_CharT>:: - do_compare(const _CharT* __lo1, const _CharT* __hi1, - const _CharT* __lo2, const _CharT* __hi2) const - { - const string_type __one(__lo1, __hi1); - const string_type __two(__lo2, __hi2); - return _M_compare(__one.c_str(), __two.c_str()); - } + template + _OutIter + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, + long double __v) const + { return _M_insert_float(__s, __io, __fill, 'L', __v); } - template - typename collate<_CharT>::string_type - collate<_CharT>:: - do_transform(const _CharT* __lo, const _CharT* __hi) const + template + _OutIter + num_put<_CharT, _OutIter>:: + do_put(iter_type __s, ios_base& __io, char_type __fill, + const void* __v) const { - size_t __len = (__hi - __lo) * 2; - // First try a buffer perhaps big enough. - _CharT* __c = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); - size_t __res = _M_transform(__c, __lo, __len); - // If the buffer was not large enough, try again with the correct size. - if (__res >= __len) - { - __c = - static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); - _M_transform(__c, __lo, __res + 1); - } - return string_type(__c); - } - - 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); + const ios_base::fmtflags __flags = __io.flags(); + 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<_UIntPtrType>(__v)); + __io.flags(__flags); + return __s; } - // Convert string to numeric value of type _Tv and store results. - // NB: This is specialized for all required types, there is no - // generic definition. - template - void - __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, - const __c_locale& __cloc, int __base = 10); - - // Convert numeric value of type _Tv to string and return length of string. - // If snprintf is available use it, otherwise fall back to the unsafe sprintf - // which, in general, can be dangerous and should be avoided. - template - int - __convert_from_v(char* __out, const int __size, const char* __fmt, - _Tv __v, const __c_locale&, int __prec = -1); +_GLIBCXX_END_LDBL_NAMESPACE // Construct correctly padded string, as per 22.2.2.2.2 - // Assumes + // 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. // NB: Of the two parameters, _CharT can be deduced from the // function arguments. The other (_Traits) has to be explicitly specified. template - struct __pad - { - static void - _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, - const _CharT* __olds, const streamsize __newlen, - const streamsize __oldlen, const bool __num); - }; - - template - 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) + void + __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, + _CharT* __news, const _CharT* __olds, + streamsize __newlen, streamsize __oldlen) { - size_t __plen = static_cast(__newlen - __oldlen); - _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen)); - _Traits::assign(__pads, __plen, __fill); - - _CharT* __beg; - _CharT* __end; - size_t __mod = 0; - size_t __beglen; //either __plen or __oldlen - ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; + const size_t __plen = static_cast(__newlen - __oldlen); + const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; + // Padding last. if (__adjust == ios_base::left) { - // Padding last. - __beg = const_cast<_CharT*>(__olds); - __beglen = __oldlen; - __end = __pads; + _Traits::copy(__news, __olds, __oldlen); + _Traits::assign(__news + __oldlen, __plen, __fill); + return; } - else if (__adjust == ios_base::internal && __num) + + size_t __mod = 0; + 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 _CharT __minus = __ctype.widen('-'); - const _CharT __plus = __ctype.widen('+'); - bool __testsign = _Traits::eq(__olds[0], __minus) - || _Traits::eq(__olds[0], __plus); - - bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) - && (_Traits::eq(__ctype.widen('x'), __olds[1]) - || _Traits::eq(__ctype.widen('X'), __olds[1])); - if (__testhex) - { - __news[0] = __olds[0]; - __news[1] = __olds[1]; - __mod += 2; - __news += 2; - __beg = __pads; - __beglen = __plen; - __end = const_cast<_CharT*>(__olds + __mod); - } - else if (__testsign) + const locale& __loc = __io._M_getloc(); + const ctype<_CharT>& __ctype = use_facet >(__loc); + + if (__ctype.widen('-') == __olds[0] + || __ctype.widen('+') == __olds[0]) { - _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; - ++__mod; + __news[0] = __olds[0]; + __mod = 1; ++__news; - __beg = __pads; - __beglen = __plen; - __end = const_cast<_CharT*>(__olds + __mod); } - else + else if (__ctype.widen('0') == __olds[0] + && __oldlen > 1 + && (__ctype.widen('x') == __olds[1] + || __ctype.widen('X') == __olds[1])) { - // Padding first. - __beg = __pads; - __beglen = __plen; - __end = const_cast<_CharT*>(__olds); + __news[0] = __olds[0]; + __news[1] = __olds[1]; + __mod = 2; + __news += 2; } + // else Padding first. } - else - { - // Padding first. - __beg = __pads; - __beglen = __plen; - __end = const_cast<_CharT*>(__olds); - } - _Traits::copy(__news, __beg, __beglen); - _Traits::copy(__news + __beglen, __end, - __newlen - __beglen - __mod); - } - - // 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 - // locale. - // __grouping_tmp is parsed L to R - // 1,222,444 == __grouping_tmp of "/1/3/3" - // __grouping is parsed R to L - // 1,222,444 == __grouping of "/3" == "/3/3/3" - template - bool - __verify_grouping(const basic_string<_CharT>& __grouping, - basic_string<_CharT>& __grouping_tmp) - { - int __i = 0; - int __j = 0; - const int __len = __grouping.size(); - const int __n = __grouping_tmp.size(); - 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 ... - while (__test && __i < __n - 1) - for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) - __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; - // ... but the last parsed grouping can be <= numpunct - // grouping. - __j == __len ? __j = 0 : __j; - __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; - return __test; + _Traits::assign(__news, __plen, __fill); + _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod); } - // Used by both numeric and monetary facets. - // Inserts "group separator" characters into an array of characters. - // It's recursive, one iteration per group. It moves the characters - // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this - // only with __gbeg != __gend. template _CharT* - __add_grouping(_CharT* __s, _CharT __sep, - const char* __gbeg, const char* __gend, + __add_grouping(_CharT* __s, _CharT __sep, + const char* __gbeg, size_t __gsize, const _CharT* __first, const _CharT* __last) { - if (__last - __first > *__gbeg) - { - __s = __add_grouping(__s, __sep, - (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), - __gend, __first, __last - *__gbeg); - __first = __last - *__gbeg; - *__s++ = __sep; - } - do + 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) + { + __last -= __gbeg[__idx]; + __idx < __gsize - 1 ? ++__idx : ++__ctr; + } + + 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; } // Inhibit implicit instantiations for required instantiations, - // which are defined via explicit instantiations elsewhere. + // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. - 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; +#if _GLIBCXX_EXTERN_TEMPLATE 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_LDBL_NAMESPACE num_get; + extern template class _GLIBCXX_LDBL_NAMESPACE 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& + const numpunct& use_facet >(const locale&); - extern template - const num_put& - use_facet >(const locale&); - - extern template - const num_get& - use_facet >(const locale&); - extern template - const moneypunct& - use_facet >(const locale&); + const num_put& + 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&); + const num_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 + extern template bool has_facet >(const locale&); - extern template + extern template bool has_facet >(const locale&); - extern template + 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&); - -#ifdef _GLIBCPP_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; +#ifdef _GLIBCXX_USE_WCHAR_T 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_LDBL_NAMESPACE num_get; + extern template class _GLIBCXX_LDBL_NAMESPACE 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& + const numpunct& use_facet >(const locale&); - extern template - const num_put& - use_facet >(const locale&); - - extern template - 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&); + const num_put& + 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&); + const num_get& + use_facet >(const locale&); - extern template + extern template bool has_facet >(const locale&); - extern template - bool - has_facet >(const locale&); - - extern template - bool - has_facet >(const locale&); - - extern template + extern template bool has_facet >(const locale&); - extern template + extern template bool has_facet >(const locale&); - extern template + 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 -} // namespace std +#endif + +_GLIBCXX_END_NAMESPACE #endif