X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fbits%2Flocale_facets.tcc;h=cb6dccd19e674df28d2248bea1058070d7f62fc5;hb=8c726f8b0ccd895f08cb2b1e53c5ab6b13cf5e09;hp=3a404dd7ec154f2f2dfbe9e04785952593f8f96a;hpb=4ee92eb6c43a8c101f8fd3762cf84de570f78a0e;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 3a404dd7ec1..cb6dccd19e6 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -1,6 +1,7 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 +// 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 @@ -27,30 +28,31 @@ // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. -// Warning: this file is not meant for user inclusion. Use . +// Warning: this file is not meant for user inclusion. Use . #ifndef _CPP_BITS_LOCFACETS_TCC #define _CPP_BITS_LOCFACETS_TCC 1 -#include -#include // For localeconv -#include // For strof, strtold -#include // For numeric_limits -#include // For auto_ptr -#include // For streambuf_iterators -#include // For isspace -#include +#pragma GCC system_header + +#include +#include // For localeconv +#include // For strof, strtold +#include // For ceil +#include // For isspace +#include // For numeric_limits +#include // For bad_cast. +#include namespace std { template locale - locale::combine(const locale& __other) + locale::combine(const locale& __other) const { - locale __copy(*this); - __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id); - __copy._M_impl->_M_has_name = false; - return __copy; + _Impl* __tmp = new _Impl(*_M_impl, 1); + __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); + return locale(__tmp); } template @@ -58,291 +60,380 @@ namespace std locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, const basic_string<_CharT, _Traits, _Alloc>& __s2) const { - // XXX should not need to qualify here. - // typedef collate<_CharT> __collate_type; typedef std::collate<_CharT> __collate_type; - const __collate_type* __fcoll = &use_facet<__collate_type>(*this); - return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(), - __s2.data(), __s2.data() + __s2.length()) < 0); + const __collate_type& __collate = use_facet<__collate_type>(*this); + return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), + __s2.data(), __s2.data() + __s2.length()) < 0); } template const _Facet& use_facet(const locale& __loc) { - typedef locale::_Impl::__vec_facet __vec_facet; - locale::id& __id = _Facet::id; // check member id - size_t __i = __id._M_index; - __vec_facet* __facet = __loc._M_impl->_M_facets; - const locale::facet* __fp = (*__facet)[__i]; // check derivation - if (__i >= __facet->size() || __fp == 0) - return _Use_facet_failure_handler<_Facet>(__loc); - return static_cast(*__fp); + size_t __i = _Facet::id._M_id(); + const locale::facet** __facets = __loc._M_impl->_M_facets; + if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) + __throw_bad_cast(); + return static_cast(*__facets[__i]); } template bool has_facet(const locale& __loc) throw() { - typedef locale::_Impl::__vec_facet __vec_facet; - locale::id& __id = _Facet::id; // check member id - size_t __i = __id._M_index; - __vec_facet* __facet = __loc._M_impl->_M_facets; - return (__i < __facet->size() && (*__facet)[__i] != 0); + size_t __i = _Facet::id._M_id(); + const locale::facet** __facets = __loc._M_impl->_M_facets; + return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); } - // __match_parallel - // matches input __s against a set of __ntargs strings in __targets, - // placing in __matches a vector of indices into __targets which - // match, and in __remain the number of such matches. If it hits - // end of sequence before it minimizes the set, sets __eof. - // Empty strings are never matched. - template + + // Stage 1: Determine a conversion specifier. + template _InIter - __match_parallel(_InIter __s, _InIter __end, int __ntargs, - const basic_string<_CharT>* __targets, - int* __matches, int& __remain, bool& __eof) + num_get<_CharT, _InIter>:: + _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, + ios_base::iostate& __err, string& __xtrc) const { - typedef basic_string<_CharT> __string_type; - __eof = false; - for (int __ti = 0; __ti < __ntargs; ++__ti) - __matches[__ti] = __ti; - __remain = __ntargs; - size_t __pos = 0; - do + 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); + + // 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) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + } + + // Next, strip leading zeros. + const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); + bool __found_zero = false; + while (__traits_type::eq(__c, __zero) && __beg != __end) + { + __c = *(++__beg); + __found_zero = true; + } + if (__found_zero) + { + __xtrc += _S_atoms_in[_M_zero]; + ++__pos; + } + + // 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_in, _S_atoms_in + __len, __watoms); + bool __found_dec = false; + bool __found_sci = false; + const char_type __dec = __np.decimal_point(); + + string __found_grouping; + const string __grouping = __np.grouping(); + bool __check_grouping = __grouping.size(); + int __sep_pos = 0; + const char_type __sep = __np.thousands_sep(); + + while (__beg != __end) { - { - int __ti = 0; - for (;__ti < __remain && - __pos == __targets[__matches[__ti]].size(); ++__ti) - { } - if (__ti == __remain) - { - if (__pos == 0) __remain = 0; - return __s; - } - } - if (__s == __end) - __eof = true; - bool __matched = false; - for (int __ti = 0; __ti < __remain; ) - { - const __string_type& __target = __targets[__matches[__ti]]; - if (__pos < __target.size()) + // Only look in digits. + const char_type* __p = __traits_type::find(__watoms, 10, __c); + + // 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_in[__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) { - if (__eof || __target[__pos] != *__s) - { - __matches[__ti] = __matches[--__remain]; - continue; - } - __matched = true; + __found_grouping += static_cast(__sep_pos); + __sep_pos = 0; + __c = *(++__beg); } - ++__ti; - } - if (__matched) - { - ++__s; - ++__pos; - } - for (int __ti = 0; __ti < __remain;) - { - if (__pos > __targets[__matches[__ti]].size()) - { - __matches[__ti] = __matches[--__remain]; - continue; - } - ++__ti; + else + { + __err |= ios_base::failbit; + 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; } - while (__remain); - return __s; - } - - template - locale::id ctype<_CharT>::id; - - template - int _Format_cache<_CharT>::_S_pword_ix; - - template - const char _Format_cache<_CharT>:: - _S_literals[] = "-+xX0123456789abcdef0123456789ABCDEF"; - template - _Format_cache<_CharT>::_Format_cache() - : _M_valid(true), _M_use_grouping(false) - { } - - template<> - _Format_cache::_Format_cache(); - - template<> - _Format_cache::_Format_cache(); + // Digit grouping is checked. If grouping and found_grouping don't + // match, then get very very upset, and set failbit. + if (__check_grouping && __found_grouping.size()) + { + // Add the ending grouping if a decimal wasn't found. + if (!__found_dec) + __found_grouping += static_cast(__sep_pos); + if (!__verify_grouping(__grouping, __found_grouping)) + __err |= ios_base::failbit; + } - template - void - _Format_cache<_CharT>::_M_populate(ios_base& __io) - { - locale __loc = __io.getloc (); - numpunct<_CharT> const& __np = use_facet >(__loc); - _M_truename = __np.truename(); - _M_falsename = __np.falsename(); - _M_thousands_sep = __np.thousands_sep(); - _M_decimal_point = __np.decimal_point(); - _M_grouping = __np.grouping(); - _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0; - _M_valid = true; + // Finish up + __xtrc += char(); + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; } - // This function is always called via a pointer installed in - // an ios_base by ios_base::register_callback. - template - void - _Format_cache<_CharT>:: - _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw() + // 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 { - void*& __p = __ios.pword(__ix); - switch (__ev) + 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('-'); + + if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) + && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + } + + // Next, strip leading zeros and check required digits for base formats. + const char_type __zero = __ctype.widen(_S_atoms_in[_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) + { + __c = *(++__beg); + __found_zero = true; + } + if (__found_zero) + { + __xtrc += _S_atoms_in[_M_zero]; + ++__pos; + if (__basefield == 0) + { + if ((__traits_type::eq(__c, __x) + || __traits_type::eq(__c, __X)) + && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + __base = 16; + } + else + __base = 8; + } + } + } + else if (__base == 16) + { + if (__traits_type::eq(__c, __zero) && __beg != __end) + { + __xtrc += _S_atoms_in[_M_zero]; + ++__pos; + __c = *(++__beg); + if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) + && __beg != __end) + { + __xtrc += __ctype.narrow(__c, char()); + ++__pos; + __c = *(++__beg); + } + } + } + + // 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_in, _S_atoms_in + __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) { - case ios_base::erase_event: - delete static_cast<_Format_cache<_CharT>*> (__p); __p = 0; - break; - case ios_base::copyfmt_event: - // If just stored zero, the callback would get registered again. - try { - __p = new _Format_cache<_CharT>; - } - catch(...) { - } - break; - case ios_base::imbue_event: - static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false; - break; + const char_type* __p = __traits_type::find(__watoms, __len, __c); + + // 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_in[__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; } - } - template - _Format_cache<_CharT>* - _Format_cache<_CharT>::_S_get(ios_base& __ios) - { - if (!_S_pword_ix) - _S_pword_ix = ios_base::xalloc(); // XXX MT - void*& __p = __ios.pword(_S_pword_ix); - - // XXX What if pword fails? must check failbit, throw. - if (__p == 0) // XXX MT? maybe sentry takes care of it + // 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()) { - auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>); - __ios.register_callback(&_Format_cache<_CharT>::_S_callback, - _S_pword_ix); - __p = __ap.release(); + // Add the ending grouping. + __found_grouping += static_cast(__sep_pos); + if (!__verify_grouping(__grouping, __found_grouping)) + __err |= ios_base::failbit; } - _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p); - if (!__ncp->_M_valid) - __ncp->_M_populate(__ios); - - return __ncp; - } - template - locale::id num_get<_CharT, _InIter>::id; - - // This member function takes an (w)istreambuf_iterator object and - // parses it into a generic char array suitable for parsing with - // strto[l,ll,f,d]. The thought was to encapsulate the conversion - // into this one function, and thus the num_get::do_get member - // functions can just adjust for the type of the overloaded - // argument and process the char array returned from _M_extract. - // Other things were also considered, including a fused - // multiply-add loop that would obviate the need for any call to - // strto... at all: however, it would b e a bit of a pain, because - // you'd have to be able to return either floating or integral - // types, etc etc. The current approach seems to be smack dab in - // the middle between an unoptimized approach using sscanf, and - // some kind of hyper-optimized approach alluded to above. - - // XXX - // Need to do partial specialization to account for differences - // between character sets. For char, this is pretty - // straightforward, but for wchar_t, the conversion to a plain-jane - // char type is a bit more involved. - template - void - num_get<_CharT, _InIter>:: - _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/, - ios_base::iostate& /*__err*/, char* /*__xtrc*/, - int& /*__base*/, bool /*__fp*/) const - { - // XXX Not currently done: need to expand upon char version below. + // Finish up. + __xtrc += char(); + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; } - template<> - void - num_get >:: - _M_extract(istreambuf_iterator __beg, - istreambuf_iterator __end, ios_base& __io, - ios_base::iostate& __err, char* __xtrc, int& __base, - bool __fp) const; - #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS - // NB: This is an unresolved library defect #17 + //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 long + // Parse bool values as unsigned long if (!(__io.flags() & ios_base::boolalpha)) { // NB: We can't just call do_get(long) here, as it might // refer to a derived class. - - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32] = {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long __l = strtol(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __l <= 1 - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __l; - else + __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; } // Parse bool values as alphanumeric else { - typedef _Format_cache __fcache_type; - __fcache_type* __fmt = __fcache_type::_S_get(__io); - const char_type* __true = __fmt->_M_truename.c_str(); - const char_type* __false = __fmt->_M_falsename.c_str(); - const size_t __truelen = __traits_type::length(__true) - 1; - const size_t __falselen = __traits_type::length(__false) - 1; - - for (size_t __pos = 0; __beg != __end; ++__pos) + 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 = __c == __false[__pos]; - bool __testt = __c == __true[__pos]; + 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 && __pos == __falselen) + else if (__testf && __n == __falsen) { __v = 0; break; } - else if (__testt && __pos == __truelen) + else if (__testt && __n == __truen) { __v = 1; break; @@ -351,63 +442,6 @@ namespace std if (__beg == __end) __err |= ios_base::eofbit; } - - return __beg; - } -#endif - -#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS - template - _InIter - num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, short& __v) const - { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long __l = strtol(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __l >= SHRT_MIN && __l <= SHRT_MAX) - __v = static_cast(__l); - else - __err |= ios_base::failbit; - - return __beg; - } - - template - _InIter - num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, int& __v) const - { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32] = {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long __l = strtol(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __l >= INT_MIN && __l <= INT_MAX) - __v = static_cast(__l); - else - __err |= ios_base::failbit; - return __beg; } #endif @@ -418,78 +452,29 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long __l = strtol(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __l; - else - __err |= ios_base::failbit; - + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 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 - { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long long __ll = strtoll(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ll; - else - __err |= ios_base::failbit; - - return __beg; - } -#endif - template _InIter num_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, unsigned short& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long __ul = strtoul(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __ul <= USHRT_MAX) - __v = static_cast(__ul); - else - __err |= ios_base::failbit; - + __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; return __beg; } @@ -499,24 +484,16 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, unsigned int& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long __ul = strtoul(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0 - && __ul <= UINT_MAX) - __v = static_cast(__ul); - else - __err |= ios_base::failbit; - + __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; return __beg; } @@ -526,23 +503,10 @@ namespace std do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, unsigned long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32] = {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long __ul = strtoul(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ul; - else - __err |= ios_base::failbit; - + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); + __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); return __beg; } @@ -551,147 +515,67 @@ namespace std _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 + ios_base::iostate& __err, long long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - unsigned long long __ull = strtoull(__xtrc, &__sanity, __base); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ull; - else - __err |= ios_base::failbit; - + __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 template _InIter num_get<_CharT, _InIter>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, float& __v) const + ios_base::iostate& __err, unsigned long long& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 256 for - // floating-point types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; -#ifdef _GLIBCPP_HAVE_STRTOF - float __f = strtof(__xtrc, &__sanity); -#else - float __f = static_cast(strtod(__xtrc, &__sanity)); -#endif - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __f; - else - __err |= ios_base::failbit; - + __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 template _InIter num_get<_CharT, _InIter>:: - do_get(iter_type __beg, iter_type __end, ios_base& __io, - ios_base::iostate& __err, double& __v) const + do_get(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, float& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 256 for - // floating-point types. - char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - double __d = strtod(__xtrc, &__sanity); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __d; - else - __err |= ios_base::failbit; - + 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; } -#if defined(_GLIBCPP_HAVE_STRTOLD) && !defined(__hpux) 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 + ios_base::iostate& __err, double& __v) const { - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 256 for - // floating-point types. - char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - long double __ld = strtold(__xtrc, &__sanity); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __ld; - else - __err |= ios_base::failbit; - + 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; } -#else + 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 { - // Stage 1: extract - char __xtrc[32]= {'\0'}; - int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); - - // Stage 2: determine a conversion specifier. - ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; - const char* __conv; - if (__basefield == ios_base::oct) - __conv = "%Lo"; - else if (__basefield == ios_base::hex) - __conv = "%LX"; - else if (__basefield == 0) - __conv = "%Li"; - else - __conv = "%Lg"; - - // Stage 3: store results. - long double __ld; - int __p = sscanf(__xtrc, __conv, &__ld); - if (__p - && static_cast<__traits_type::int_type>(__p) != __traits_type::eof()) - __v = __ld; - else - __err |= ios_base::failbit; - + 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; } -#endif template _InIter @@ -706,573 +590,1908 @@ namespace std | ios_base::uppercase | ios_base::internal); __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); - // Stage 1: extract and determine the conversion specifier. - // Assuming leading zeros eliminated, thus the size of 32 for - // integral types. - char __xtrc[32]= {'\0'}; + string __xtrc; int __base; - _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); - - // Stage 2: convert and store results. - char* __sanity; - errno = 0; - void* __vp = reinterpret_cast(strtoul(__xtrc, &__sanity, __base)); - if (!(__err & ios_base::failbit) - && __sanity != __xtrc && *__sanity == '\0' && errno == 0) - __v = __vp; - else - __err |= ios_base::failbit; + __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); // 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; return __beg; } - template - locale::id num_put<_CharT, _OutIter>::id; - - // _S_fill is specialized for ostreambuf_iterator, random access iterator. - template - inline _OutIter - _S_fill(_OutIter __s, _CharT __fill, int __padding); - - template - _RaIter - _S_fill(_RaIter __s, _CharT __fill, int __padding, - random_access_iterator_tag) + // For use by integer and floating-point types after they have been + // converted into a char_type string. + template + void + num_put<_CharT, _OutIter>:: + _M_pad(_CharT __fill, streamsize __w, ios_base& __io, + _CharT* __new, const _CharT* __cs, int& __len) const { - fill_n(__s, __fill); - return __s + __padding; + // [22.2.2.2.2] Stage 3. + // If necessary, pad. + __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, + __w, __len, true); + __len = static_cast(__w); } - template - _OutIter - _S_fill(_OutIter __s, _CharT __fill, int __padding, _Tag) + // Forwarding functions to peel signed from unsigned integer types. + template + inline int + __int_to_char(_CharT* __out, const int __size, long __v, + const _CharT* __lit, ios_base::fmtflags __flags) { - while (--__padding >= 0) { *__s = __fill; ++__s; } - return __s; + unsigned long __ul = static_cast(__v); + bool __neg = false; + if (__v < 0) + { + __ul = -__ul; + __neg = true; + } + return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); } - template - inline _OutIter - _S_fill(_OutIter __s, _CharT __fill, int __padding) - { - return _S_fill(__s, __fill, __padding, - iterator_traits<_OutIter>::iterator_category()); + template + inline int + __int_to_char(_CharT* __out, const int __size, unsigned long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { return __int_to_char(__out, __size, __v, __lit, __flags, false); } + +#ifdef _GLIBCPP_USE_LONG_LONG + template + inline int + __int_to_char(_CharT* __out, const int __size, long long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { + unsigned long long __ull = static_cast(__v); + bool __neg = false; + if (__v < 0) + { + __ull = -__ull; + __neg = true; + } + return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); } - template - _OutIter - _S_pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/, - _CharT /*__fill*/, int /*__width*/, - _CharT const* /*__first*/, _CharT const* /*__middle*/, - _CharT const* /*__last*/) + template + inline int + __int_to_char(_CharT* __out, const int __size, unsigned long long __v, + const _CharT* __lit, ios_base::fmtflags __flags) + { return __int_to_char(__out, __size, __v, __lit, __flags, false); } +#endif + + template + int + __int_to_char(_CharT* __out, const int __size, _ValueT __v, + const _CharT* __lit, ios_base::fmtflags __flags, bool __neg) { - // XXX Not currently done: non streambuf_iterator - return __s; + // Don't write base if already 0. + const bool __showbase = (__flags & ios_base::showbase) && __v; + const ios_base::fmtflags __basefield = __flags & ios_base::basefield; + _CharT* __buf = __out + __size - 1; + _CharT* __bufend = __out + __size; + + if (__builtin_expect(__basefield == ios_base::oct, false)) + { + // Octal. + do + { + *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits]; + __v >>= 3; + } + while (__v != 0); + if (__showbase) + *__buf-- = __lit[__num_base::_S_digits]; + } + else if (__builtin_expect(__basefield == ios_base::hex, false)) + { + // Hex. + const bool __uppercase = __flags & ios_base::uppercase; + int __case_offset = __uppercase + ? __num_base::_S_udigits : __num_base::_S_digits; + do + { + *__buf-- = __lit[(__v & 0xf) + __case_offset]; + __v >>= 4; + } + while (__v != 0); + if (__showbase) + { + // 'x' or 'X' + *__buf-- = __lit[__num_base::_S_x + __uppercase]; + // '0' + *__buf-- = __lit[__num_base::_S_digits]; + } + } + else + { + // Decimal. + do + { + *__buf-- = __lit[(__v % 10) + __num_base::_S_digits]; + __v /= 10; + } + while (__v != 0); + if (__neg) + *__buf-- = __lit[__num_base::_S_minus]; + else if (__flags & ios_base::showpos) + *__buf-- = __lit[__num_base::_S_plus]; + } + int __ret = __bufend - __buf - 1; + return __ret; } - // Partial specialization for ostreambuf_iterator. - template - ostreambuf_iterator<_CharT> - _S_pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags, - _CharT __fill, int __width, _CharT const* __first, - _CharT const* __middle, _CharT const* __last) + template + void + num_put<_CharT, _OutIter>:: + _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, + _CharT* __new, _CharT* __cs, int& __len) const { - typedef ostreambuf_iterator<_CharT> __out_iter; - int __padding = __width - (__last - __first); - if (__padding < 0) - __padding = 0; - ios_base::fmtflags __aflags = __flags & ios_base::adjustfield; - bool __testfield = __padding == 0 || __aflags == ios_base::left - || __aflags == ios_base::internal; - - // This was needlessly complicated. - if (__first != __middle) - { - if (!__testfield) - { - _S_fill(__s, __fill, __padding); - __padding = 0; - } - copy(__first, __middle, __s); - } - __out_iter __s2 = __s; + // 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; + const ios_base::fmtflags __basefield = __io.flags() + & ios_base::basefield; + if ((__io.flags() & ios_base::showbase) && __len > 1) + if (__basefield == ios_base::oct) + { + __off = 1; + *__new = *__cs; + } + else if (__basefield == ios_base::hex) + { + __off = 2; + *__new = *__cs; + *(__new + 1) = *(__cs + 1); + } + _CharT* __p; + __p = __add_grouping(__new + __off, __sep, + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __cs + __off, __cs + __len); + __len = __p - __new; + } - if (__padding && __aflags != ios_base::left) - { - _S_fill(__s2, __fill, __padding); - __padding = 0; - } - __out_iter __s3 = copy(__middle, __last, __s2); - if (__padding) - _S_fill(__s3, __fill, __padding); - return __s3; + template + template + _OutIter + num_put<_CharT, _OutIter>:: + _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, + _ValueT __v) const + { + typedef __locale_cache<_CharT> __cache_type; + __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); + _CharT* __lit = __lc._M_literals; + + // Long enough to hold hex, dec, and octal representations. + int __ilen = 4 * sizeof(_ValueT); + _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __ilen)); + // [22.2.2.2.2] Stage 1, numeric conversion to character. + // Result is returned right-justified in the buffer. + int __len; + __len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags()); + __cs = __cs + __ilen - __len; + + // Add grouping, if necessary. + _CharT* __cs2; + if (__lc._M_use_grouping) + { + // Grouping can add (almost) as many separators as the + // number of digits, but no more. + __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, + __cs2, __cs, __len); + __cs = __cs2; + } + + // Pad. + _CharT* __cs3; + streamsize __w = __io.width(); + if (__w > static_cast(__len)) + { + __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); + _M_pad(__fill, __w, __io, __cs3, __cs, __len); + __cs = __cs3; + } + __io.width(0); + + // [22.2.2.2.2] Stage 4. + // Write resulting, fully-formatted string to output iterator. + return __write(__s, __cs, __len); + } + + template + void + num_put<_CharT, _OutIter>:: + _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, + _CharT* __new, _CharT* __cs, int& __len) const + { +#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS + //282. What types does numpunct grouping refer to? + // Add grouping, if necessary. + _CharT* __p2; + int __declen = __p ? __p - __cs : __len; + __p2 = __add_grouping(__new, __sep, + __grouping.c_str(), + __grouping.c_str() + __grouping.size(), + __cs, __cs + __declen); + + // Tack on decimal part. + int __newlen = __p2 - __new; + if (__p) + { + char_traits<_CharT>::copy(__p2, __p, __len - __declen); + __newlen += __len - __declen; + } + __len = __newlen; +#endif } - template + // 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: add 1 to ensure the maximum + // available precision. Then, in general, one more 1 needs to + // be added since, when the %{g,G} conversion specifiers are + // chosen inside _S_format_float, the precision field is "the + // maximum number of significant digits", *not* the "number of + // digits to appear after the decimal point", as happens for + // %{e,E,f,F} (C99, 7.19.6.1,4). + const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; + + // Use default precision if out of range. + streamsize __prec = __io.precision(); + if (__prec > static_cast(__max_digits)) + __prec = static_cast(__max_digits); + else if (__prec < static_cast(0)) + __prec = static_cast(6); + + typedef __locale_cache<_CharT> __cache_type; + __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); + + // [22.2.2.2.2] Stage 1, numeric conversion to character. + int __len; + // Long enough for the max format spec. + char __fbuf[16]; + +#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)); + + _S_format_float(__io, __fbuf, __mod); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); + + // If the buffer was not large enough, try again with the correct size. + if (__len >= __cs_size) + { + __cs_size = __len + 1; + __cs = static_cast(__builtin_alloca(__cs_size)); + __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, + _S_c_locale, __prec); + } +#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)); + + _S_format_float(__io, __fbuf, __mod); + __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); +#endif + + // [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)); + __ctype.widen(__cs, __cs + __len, __ws); + + // Replace decimal point. + const _CharT __cdec = __ctype.widen('.'); + const _CharT __dec = __lc._M_decimal_point; + const _CharT* __p; + if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) + __ws[__p - __ws] = __dec; + + // Add grouping, if necessary. + _CharT* __ws2; + if (__lc._M_use_grouping) + { + // Grouping can add (almost) as many separators as the + // number of digits, but no more. + __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __len * 2)); + _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p, + __ws2, __ws, __len); + __ws = __ws2; + } + + // Pad. + _CharT* __ws3; + streamsize __w = __io.width(); + if (__w > static_cast(__len)) + { + __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 __write(__s, __ws, __len); + } + + template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const { - const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); ios_base::fmtflags __flags = __io.flags(); - if ((__flags & ios_base::boolalpha) == 0) { unsigned long __uv = __v; - return _S_format(__s, __io, __fill, false, __uv); + __s = _M_convert_int(__s, __io, __fill, __uv); } else { - const char_type* __first; - const char_type* __last; + locale __loc = __io.getloc(); + const numpunct<_CharT>& __np = use_facet >(__loc); + typedef basic_string<_CharT> __string_type; + __string_type __name; if (__v) - { - __first = __fmt->_M_truename.data(); - __last = __first + __fmt->_M_truename.size(); - } + __name = __np.truename(); else - { - __first = __fmt->_M_falsename.data(); - __last = __first + __fmt->_M_falsename.size(); - } - copy(__first, __last, __s); - } - return __s; - } - - // _S_group_digits 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 __grouping != __grend. - template - _CharT* - _S_group_digits(_CharT* __s, _CharT __grsep, char const* __grouping, - char const* __grend, _CharT const* __first, - _CharT const* __last) - { - if (__last - __first > *__grouping) - { - __s = _S_group_digits(__s, __grsep, - (__grouping + 1 == __grend ? __grouping : __grouping + 1), - __grend, __first, __last - *__grouping); - __first = __last - *__grouping; - *__s++ = __grsep; - } - do - { - *__s++ = *__first++; - } - while (__first != __last); + __name = __np.falsename(); + + const _CharT* __cs = __name.c_str(); + int __len = __name.size(); + _CharT* __cs3; + streamsize __w = __io.width(); + if (__w > static_cast(__len)) + { + __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __w)); + _M_pad(__fill, __w, __io, __cs3, __cs, __len); + __cs = __cs3; + } + __io.width(0); + __s = __write(__s, __cs, __len); + } return __s; } - template - _OutIter - _S_format(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg, - _ValueT __v) - { - // Leave room for "+/-," "0x," and commas. - const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4; - _CharT __digits[_M_room]; - _CharT* __front = __digits + _M_room; - ios_base::fmtflags __flags = __io.flags(); - const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); - char const* __table = __fmt->_S_literals + __fmt->_S_digits; - - ios_base::fmtflags __basefield = (__flags & __io.basefield); - _CharT* __sign_end = __front; - if (__basefield == ios_base::hex) - { - if (__flags & ios_base::uppercase) - __table += 16; // use ABCDEF - do - *--__front = __table[__v & 15]; - while ((__v >>= 4) != 0); - __sign_end = __front; - if (__flags & ios_base::showbase) - { - *--__front = __fmt->_S_literals[__fmt->_S_x + - ((__flags & ios_base::uppercase) ? 1 : 0)]; - *--__front = __table[0]; - } - } - else if (__basefield == ios_base::oct) - { - do - *--__front = __table[__v & 7]; - while ((__v >>= 3) != 0); - if (__flags & ios_base::showbase - && static_cast(*__front) != __table[0]) - *--__front = __table[0]; - __sign_end = __front; - } - else - { - // NB: This is _lots_ faster than using ldiv. - do - *--__front = __table[__v % 10]; - while ((__v /= 10) != 0); - __sign_end = __front; - // NB: ios_base:hex || ios_base::oct assumed to be unsigned. - if (__neg || (__flags & ios_base::showpos)) - *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg]; - } - - // XXX should specialize! - if (!__fmt->_M_use_grouping && !__io.width()) - return copy(__front, __digits + _M_room, __s); - - if (!__fmt->_M_use_grouping) - return _S_pad_numeric(__s, __flags, __fill, __io.width(0), - __front, __sign_end, __digits + _M_room); - - _CharT* __p = __digits; - while (__front < __sign_end) - *__p++ = *__front++; - const char* __gr = __fmt->_M_grouping.data(); - __front = _S_group_digits(__p, __fmt->_M_thousands_sep, __gr, - __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room); - return _S_pad_numeric(__s, __flags, __fill, __io.width(0), - __digits, __p, __front); - } - - template + template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const - { - unsigned long __uv = __v; - bool __neg = false; - if (__v < 0) - { - __neg = true; - __uv = -__uv; - } - return _S_format(__s, __io, __fill, __neg, __uv); - } + { return _M_convert_int(__s, __io, __fill, __v); } - template + template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, unsigned long __v) const - { return _S_format(__s, __io, __fill, false, __v); } + { return _M_convert_int(__s, __io, __fill, __v); } #ifdef _GLIBCPP_USE_LONG_LONG - template + template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const - { - unsigned long long __uv = __v; - bool __neg = false; - if (__v < 0) - { - __neg = true; - __uv = -__uv; - } - return _S_format(__s, __b, __fill, __neg, __uv); - } + { return _M_convert_int(__s, __b, __fill, __v); } - template + template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, unsigned long long __v) const - { return _S_format(__s, __io, __fill, false, __v); } + { return _M_convert_int(__s, __io, __fill, __v); } #endif - // Generic helper function template - static _OutIter - _S_output_float(_OutIter __s, ios_base& __io, _CharT __fill, - const char* __sptr, size_t __slen) - { - // XXX Not currently done: non streambuf_iterator - return __s; - } - - // Partial specialization for ostreambuf_iterator. - template - static ostreambuf_iterator<_CharT> - _S_output_float(ostreambuf_iterator<_CharT> __s, ios_base& __io, - _CharT __fill, const char* __sptr, size_t __slen) - { - size_t __padding = __io.width() > streamsize(__slen) ? - __io.width() -__slen : 0; - locale __loc = __io.getloc(); - ctype<_CharT> const& __ct = use_facet >(__loc); - ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield; - const char* const __eptr = __sptr + __slen; - // [22.2.2.2.2.19] Table 61 - if (__adjfield == ios_base::internal) - { - // [22.2.2.2.2.14]; widen() - if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-')) - { - __s = __ct.widen(*__sptr); - ++__s; - ++__sptr; - } - __s = _S_fill(__s, __fill, __padding); - __padding = 0; - } - else if (__adjfield != ios_base::left) - { - __s = _S_fill(__s, __fill, __padding); - __padding = 0; - } - // the "C" locale decimal character - char __decimal_point = *(localeconv()->decimal_point); - const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); - for (; __sptr != __eptr; ++__s, ++__sptr) - { - // [22.2.2.2.2.17]; decimal point conversion - if (*__sptr == __decimal_point) - __s = __fmt->_M_decimal_point; - // [22.2.2.2.2.14]; widen() - else - __s = __ct.widen(*__sptr); - } - // [22.2.2.2.2.19] Table 61 - if (__padding) - _S_fill(__s, __fill, __padding); - __io.width(0); - return __s; - } - - bool - _S_build_float_format(ios_base& __io, char* __fptr, char __modifier, - streamsize __prec); - - template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const - { - const streamsize __max_prec = numeric_limits::digits10 + 3; - streamsize __prec = __io.precision(); - // Protect against sprintf() buffer overflows. - if (__prec > __max_prec) - __prec = __max_prec; - // The *2 provides for signs, exp, 'E', and pad. - char __sbuf[__max_prec*2]; - size_t __slen; - // Long enough for the max format spec. - char __fbuf[16]; - if (_S_build_float_format(__io, __fbuf, 0, __prec)) - __slen = sprintf(__sbuf, __fbuf, __prec, __v); - else - __slen = sprintf(__sbuf, __fbuf, __v); - // [22.2.2.2.2] Stages 2-4. - return _S_output_float(__s, __io, __fill, __sbuf, __slen); - } + { return _M_convert_float(__s, __io, __fill, char(), __v); } - template + template _OutIter num_put<_CharT, _OutIter>:: - do_put(iter_type __s, ios_base& __io, char_type __fill, - long double __v) const - { - const streamsize __max_prec = numeric_limits::digits10 + 3; - streamsize __prec = __io.precision(); - // Protect against sprintf() buffer overflows. - if (__prec > __max_prec) - __prec = __max_prec; - // The *2 provides for signs, exp, 'E', and pad. - char __sbuf[__max_prec*2]; - size_t __slen; - // Long enough for the max format spec. - char __fbuf[16]; - // 'L' as per [22.2.2.2.2] Table 59 - if ( _S_build_float_format(__io, __fbuf, 'L', __prec)) - __slen = sprintf(__sbuf, __fbuf, __prec, __v); - else - __slen = sprintf(__sbuf, __fbuf, __v); - // [22.2.2.2.2] Stages 2-4 - return _S_output_float(__s, __io, __fill, __sbuf, __slen); - } + do_put(iter_type __s, ios_base& __io, char_type __fill, + long double __v) const + { return _M_convert_float(__s, __io, __fill, 'L', __v); } - template + template _OutIter num_put<_CharT, _OutIter>:: do_put(iter_type __s, ios_base& __io, char_type __fill, const void* __v) const { - typedef ios_base::fmtflags fmtflags; - fmtflags __fmt = __io.flags(); - fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield - | ios_base::uppercase | ios_base::internal); - __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); - try { - _OutIter __s2 = _S_format(__s, __io, __fill, false, - reinterpret_cast(__v)); - __io.flags(__fmt); - return __s2; - } - catch (...) { - __io.flags(__fmt); - throw; - } + 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 + { + __s = _M_convert_int(__s, __io, __fill, + reinterpret_cast(__v)); + __io.flags(__flags); + } + catch (...) + { + __io.flags(__flags); + __throw_exception_again; + } + return __s; } - template - locale::id numpunct<_CharT>::id; - template - locale::id collate<_CharT>::id; - - // Support for time_get: - // Note that these partial specializations could, and maybe should, - // be changed to full specializations (by eliminating the _Dummy - // argument) and moved to a .cc file. - template - struct _Weekdaynames; - - template - struct _Weekdaynames - { static const char* const _S_names[14]; }; - - template - const char* const - _Weekdaynames::_S_names[14] = - { - "Sun", "Sunday", - "Mon", "Monday", "Tue", "Tuesday", "Wed", "Wednesday", - "Thu", "Thursday", "Fri", "Friday", "Sat", "Saturday" - }; + 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; + } -#ifdef _GLIBCPP_USE_WCHAR_T - template - struct _Weekdaynames - { static const wchar_t* const _S_names[14]; }; + 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); - template - const wchar_t* const - _Weekdaynames::_S_names[14] = - { - L"Sun", L"Sunday", - L"Mon", L"Monday", L"Tue", L"Tuesday", L"Wed", L"Wednesday", - L"Thu", L"Thursday", L"Fri", L"Friday", L"Sat", L"Saturday" - }; + 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) + { + if (__f == ios_base::left) + // After. + __res.append(__width - __len, __fill); + else + // Before. + __res.insert(0, string_type(__width - __len, __fill)); + __len = __width; + } + + // Write resulting, fully-formatted string to output iterator. + __s = __write(__s, __res.c_str(), __len); + } + __io.width(0); + return __s; + } - template - struct _Monthnames; - template - struct _Monthnames - { static const char* const _S_names[24]; }; + // 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) + { + char __c = __format[__i]; + if (__c == '%') + { + // 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 - const char* const - _Monthnames::_S_names[24] = + 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 { - "Jan", "January", "Feb", "February", "Mar", "March", - "Apr", "April", "May", "May", "Jun", "June", - "Jul", "July", "Aug", "August", "Sep", "September", - "Oct", "October", "Nov", "November", "Dec", "December" - }; + 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; + } + else + __testvalid = false; + if (!__testvalid) + __err |= ios_base::failbit; + } -#ifdef _GLIBCPP_USE_WCHAR_T - template - struct _Monthnames - { static const wchar_t* const _S_names[24]; }; + // 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) + { + ++__pos; + __c = *(++__beg); + for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) + { + __name = __names[__matches[__i3]]; + if (__name[__pos] != __c) + __matches[__i3] = __matches[--__nmatches]; + } + } + 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; + } + else + __testvalid = false; + if (!__testvalid) + __err |= ios_base::failbit; + } - template - const wchar_t* const - _Monthnames::_S_names[24] = + 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 { - L"Jan", L"January", L"Feb", L"February", L"Mar", L"March", - L"Apr", L"April", L"May", L"May", L"Jun", L"June", - L"Jul", L"July", L"Aug", L"August", L"Sep", L"September", - L"Oct", L"October", L"Nov", L"November", L"Dec", L"December" - }; -#endif + _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; + } template - locale::id time_get<_CharT, _InIter>::id; + _InIter + time_get<_CharT, _InIter>:: + do_get_date(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; + } template _InIter time_get<_CharT, _InIter>:: - do_get_weekday(iter_type __s, iter_type __end, - ios_base& __io, ios_base::iostate& __err, tm* __t) const + do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const { - if (!_M_daynames) - { - _M_daynames = new basic_string<_CharT>[14]; - for (int __i = 0; __i < 14; ++__i) - _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i]; - } - bool __at_eof = false; - int __remain = 0; - int __matches[14]; - iter_type __out = __match_parallel(__s, __end, 14, _M_daynames, - __matches, __remain, __at_eof); - __err = ios_base::iostate(0); - if (__at_eof) __err |= __io.eofbit; - if (__remain == 1 || - __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1)) - __t->tm_wday = (__matches[0]>>1); - else - __err |= __io.failbit; - return __out; + 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; + } + + template + _InIter + time_get<_CharT, _InIter>:: + do_get_monthname(iter_type __beg, iter_type __end, + ios_base& __io, ios_base::iostate& __err, tm* __tm) const + { + typedef char_traits<_CharT> __traits_type; + 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) + { + size_t __pos = __traits_type::length(__months[__tmpmon]); + __tp._M_months(__months); + const char_type* __name = __months[__tmpmon]; + if (__name[__pos] == *__beg) + { + // Extract the rest of it. + const size_t __len = __traits_type::length(__name); + while (__pos < __len && __beg != __end + && __name[__pos] == *__beg) + ++__beg, ++__pos; + if (__len != __pos) + __err |= ios_base::failbit; + } + if (!__err) + __tm->tm_mon = __tmpmon; + } + + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; } template _InIter time_get<_CharT, _InIter>:: - do_get_monthname(iter_type __s, iter_type __end, - ios_base& __io, ios_base::iostate& __err, tm* __t) const + do_get_year(iter_type __beg, iter_type __end, ios_base& __io, + ios_base::iostate& __err, tm* __tm) const { - if (!_M_monthnames) - { - _M_monthnames = new basic_string<_CharT>[24]; - for (int __i = 0; __i < 24; ++__i) - _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i]; - } - bool __at_eof = false; - int __remain = 0; - int __matches[24]; - iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames, - __matches, __remain, __at_eof); - __err = ios_base::iostate(0); - if (__at_eof) __err |= __io.eofbit; - if (__remain == 1 || - __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1)) - __t->tm_mon = (__matches[0]>>1); + locale __loc = __io.getloc(); + const ctype<_CharT>& __ctype = use_facet >(__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 |= __io.failbit; - return __out; + __err |= ios_base::failbit; + if (__beg == __end) + __err |= ios_base::eofbit; + return __beg; } template - locale::id time_put<_CharT, _OutIter>::id; - - template - locale::id money_get<_CharT, _InIter>::id; + _OutIter + time_put<_CharT, _OutIter>:: + put(iter_type __s, ios_base& __io, char_type, const tm* __tm, + const _CharT* __beg, const _CharT* __end) const + { + locale __loc = __io.getloc(); + ctype<_CharT> const& __ctype = use_facet >(__loc); + while (__beg != __end) + { + char __c = __ctype.narrow(*__beg, 0); + ++__beg; + if (__c == '%') + { + char __format; + char __mod = 0; + size_t __len = 1; + __c = __ctype.narrow(*__beg, 0); + ++__beg; + if (__c == 'E' || __c == 'O') + { + __mod = __c; + __format = __ctype.narrow(*__beg, 0); + ++__beg; + } + else + __format = __c; + __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod); + } + else + { + *__s = __c; + ++__s; + } + } + return __s; + } template - locale::id money_put<_CharT, _OutIter>::id; + _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); - template - locale::id moneypunct<_CharT, _Intl>::id; + // Write resulting, fully-formatted string to output iterator. + return __write(__s, __res, char_traits::length(__res)); + } - template - const bool moneypunct<_CharT, _Intl>::intl; - template - const bool moneypunct_byname<_CharT, _Intl>::intl; + // Generic version does nothing. + template + int + collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const + { return 0; } + // Generic version does nothing. template - locale::id messages<_CharT>::id; -} // std:: + size_t + collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const + { return 0; } -#endif /* _CPP_BITS_LOCFACETS_TCC */ + 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 + typename collate<_CharT>::string_type + collate<_CharT>:: + do_transform(const _CharT* __lo, const _CharT* __hi) 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); + } + + // Construct correctly padded string, as per 22.2.2.2.2 + // Assumes + // __newlen > __oldlen + // __news is allocated for __newlen size + // Used by both num_put and ostream inserters: if __num, + // internal-adjusted objects are padded according to the rules below + // concerning 0[xX] and +-, otherwise, exactly as right-adjusted + // ones are. + + // NB: Of the two parameters, _CharT can be deduced from the + // function arguments. The other (_Traits) has to be explicitly specified. + 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) + { + 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; + + if (__adjust == ios_base::left) + { + // Padding last. + __beg = const_cast<_CharT*>(__olds); + __beglen = __oldlen; + __end = __pads; + } + else if (__adjust == ios_base::internal && __num) + { + // 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) + { + _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; + ++__mod; + ++__news; + __beg = __pads; + __beglen = __plen; + __end = const_cast<_CharT*>(__olds + __mod); + } + else + { + // Padding first. + __beg = __pads; + __beglen = __plen; + __end = const_cast<_CharT*>(__olds); + } + } + 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); + } + + 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; + } + + template + _CharT* + __add_grouping(_CharT* __s, _CharT __sep, + const char* __gbeg, const char* __gend, + 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 + *__s++ = *__first++; + while (__first != __last); + return __s; + } + + // Generic definition, locale cache initialization. + template + void + __locale_cache<_CharT>::_M_init(const locale& __loc) + { + if (__builtin_expect(has_facet >(__loc), true)) + { + const numpunct<_CharT>& __np = use_facet >(__loc); + _M_falsename = __np.falsename(); + _M_truename = __np.truename(); + _M_thousands_sep = __np.thousands_sep(); + _M_decimal_point = __np.decimal_point(); + _M_grouping = __np.grouping(); + _M_use_grouping = _M_grouping.size() != 0 + && _M_grouping.data()[0] != 0; + } + if (__builtin_expect(has_facet >(__loc), true)) + { + const ctype<_CharT>& __ct = use_facet< ctype<_CharT> >(__loc); + __ct.widen(__num_base::_S_atoms_out, + __num_base::_S_atoms_out + __num_base::_S_end, + _M_literals); + } + } + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. +#if _GLIBCPP_EXTERN_TEMPLATE + extern template class moneypunct; + extern template class moneypunct; + extern template class moneypunct_byname; + extern template class moneypunct_byname; + extern template class money_get; + extern template class money_put; + extern template class numpunct; + extern template class numpunct_byname; + extern template class num_get; + extern template class num_put; + extern template class __timepunct; + extern template class time_put; + extern template class time_put_byname; + extern template class time_get; + extern template class time_get_byname; + extern template class messages; + extern template class messages_byname; + extern template class 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&); + + extern template + 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&); + + 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&); -// Local Variables: -// mode:c++ -// End: + 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 >(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; + 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 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&); + + extern template + 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&); + + extern template + const __timepunct& + use_facet<__timepunct >(const locale&); + + extern template + const time_put& + use_facet >(const locale&); + + extern template + const time_get& + use_facet >(const locale&); + + extern template + const messages& + use_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + 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 >(const locale&); + + extern template + bool + has_facet<__timepunct >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); + + extern template + bool + has_facet >(const locale&); +#endif +#endif +} // namespace std + +#endif