locale_facets.tcc revision 117397
197403Sobrien// Locale support -*- C++ -*- 297403Sobrien 3117397Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 497403Sobrien// Free Software Foundation, Inc. 597403Sobrien// 697403Sobrien// This file is part of the GNU ISO C++ Library. This library is free 797403Sobrien// software; you can redistribute it and/or modify it under the 897403Sobrien// terms of the GNU General Public License as published by the 997403Sobrien// Free Software Foundation; either version 2, or (at your option) 1097403Sobrien// any later version. 1197403Sobrien 1297403Sobrien// This library is distributed in the hope that it will be useful, 1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1597403Sobrien// GNU General Public License for more details. 1697403Sobrien 1797403Sobrien// You should have received a copy of the GNU General Public License along 1897403Sobrien// with this library; see the file COPYING. If not, write to the Free 1997403Sobrien// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 2097403Sobrien// USA. 2197403Sobrien 2297403Sobrien// As a special exception, you may use this file as part of a free software 2397403Sobrien// library without restriction. Specifically, if other files instantiate 2497403Sobrien// templates or use macros or inline functions from this file, or you compile 2597403Sobrien// this file and link it with other files to produce an executable, this 2697403Sobrien// file does not by itself cause the resulting executable to be covered by 2797403Sobrien// the GNU General Public License. This exception does not however 2897403Sobrien// invalidate any other reasons why the executable file might be covered by 2997403Sobrien// the GNU General Public License. 3097403Sobrien 3197403Sobrien// Warning: this file is not meant for user inclusion. Use <locale>. 3297403Sobrien 3397403Sobrien#ifndef _CPP_BITS_LOCFACETS_TCC 3497403Sobrien#define _CPP_BITS_LOCFACETS_TCC 1 3597403Sobrien 3697403Sobrien#pragma GCC system_header 3797403Sobrien 3897403Sobrien#include <cerrno> 39117397Skan#include <clocale> // For localeconv 40117397Skan#include <cstdlib> // For strof, strtold 41117397Skan#include <cmath> // For ceil 42117397Skan#include <cctype> // For isspace 43117397Skan#include <limits> // For numeric_limits 44117397Skan#include <typeinfo> // For bad_cast. 4597403Sobrien#include <bits/streambuf_iterator.h> 4697403Sobrien 4797403Sobriennamespace std 4897403Sobrien{ 4997403Sobrien template<typename _Facet> 5097403Sobrien locale 5197403Sobrien locale::combine(const locale& __other) const 5297403Sobrien { 5397403Sobrien _Impl* __tmp = new _Impl(*_M_impl, 1); 5497403Sobrien __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 5597403Sobrien return locale(__tmp); 5697403Sobrien } 5797403Sobrien 5897403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 5997403Sobrien bool 6097403Sobrien locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 6197403Sobrien const basic_string<_CharT, _Traits, _Alloc>& __s2) const 6297403Sobrien { 6397403Sobrien typedef std::collate<_CharT> __collate_type; 6497403Sobrien const __collate_type& __collate = use_facet<__collate_type>(*this); 6597403Sobrien return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 6697403Sobrien __s2.data(), __s2.data() + __s2.length()) < 0); 6797403Sobrien } 6897403Sobrien 6997403Sobrien template<typename _Facet> 7097403Sobrien const _Facet& 7197403Sobrien use_facet(const locale& __loc) 7297403Sobrien { 7397403Sobrien size_t __i = _Facet::id._M_id(); 7497403Sobrien locale::facet** __facets = __loc._M_impl->_M_facets; 7597403Sobrien if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) 7697403Sobrien __throw_bad_cast(); 7797403Sobrien return static_cast<const _Facet&>(*__facets[__i]); 7897403Sobrien } 7997403Sobrien 8097403Sobrien template<typename _Facet> 8197403Sobrien bool 8297403Sobrien has_facet(const locale& __loc) throw() 8397403Sobrien { 8497403Sobrien size_t __i = _Facet::id._M_id(); 8597403Sobrien locale::facet** __facets = __loc._M_impl->_M_facets; 8697403Sobrien return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); 8797403Sobrien } 8897403Sobrien 89117397Skan // Routine to access a cache for the locale. If the cache didn't 90117397Skan // exist before, it gets constructed on the fly. 91117397Skan template<typename _Facet> 92117397Skan inline const __locale_cache<_Facet>& 93117397Skan __use_cache(const locale& __loc) 94117397Skan { 95117397Skan size_t __i = _Facet::id._M_id(); 96117397Skan if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false)) 97117397Skan __throw_bad_cast(); 98117397Skan __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i); 99117397Skan if (__builtin_expect(!__cache, false)) 100117397Skan { 101117397Skan __cache = new __locale_cache<_Facet>(__loc); 102117397Skan __loc._M_impl->_M_install_cache(__cache, __i); 103117397Skan } 104117397Skan return static_cast<const __locale_cache<_Facet>&>(*__cache); 105117397Skan } 10697403Sobrien 10797403Sobrien // Stage 1: Determine a conversion specifier. 10897403Sobrien template<typename _CharT, typename _InIter> 10997403Sobrien _InIter 11097403Sobrien num_get<_CharT, _InIter>:: 11197403Sobrien _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 11297403Sobrien ios_base::iostate& __err, string& __xtrc) const 11397403Sobrien { 114102782Skan typedef char_traits<_CharT> __traits_type; 11597403Sobrien const locale __loc = __io.getloc(); 11697403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 11797403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 11897403Sobrien 11997403Sobrien // First check for sign. 12097403Sobrien const char_type __plus = __ctype.widen('+'); 12197403Sobrien const char_type __minus = __ctype.widen('-'); 12297403Sobrien int __pos = 0; 12397403Sobrien char_type __c = *__beg; 124102782Skan if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 125102782Skan && __beg != __end) 12697403Sobrien { 12797403Sobrien __xtrc += __ctype.narrow(__c, char()); 12897403Sobrien ++__pos; 12997403Sobrien __c = *(++__beg); 13097403Sobrien } 13197403Sobrien 13297403Sobrien // Next, strip leading zeros. 133117397Skan const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); 13497403Sobrien bool __found_zero = false; 135102782Skan while (__traits_type::eq(__c, __zero) && __beg != __end) 13697403Sobrien { 13797403Sobrien __c = *(++__beg); 13897403Sobrien __found_zero = true; 13997403Sobrien } 14097403Sobrien if (__found_zero) 14197403Sobrien { 142117397Skan __xtrc += _S_atoms_in[_M_zero]; 14397403Sobrien ++__pos; 14497403Sobrien } 14597403Sobrien 14697403Sobrien // Only need acceptable digits for floating point numbers. 14797403Sobrien const size_t __len = _M_E - _M_zero + 1; 14897403Sobrien char_type __watoms[__len]; 149117397Skan __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); 15097403Sobrien bool __found_dec = false; 15197403Sobrien bool __found_sci = false; 15297403Sobrien const char_type __dec = __np.decimal_point(); 15397403Sobrien 15497403Sobrien string __found_grouping; 15597403Sobrien const string __grouping = __np.grouping(); 15697403Sobrien bool __check_grouping = __grouping.size(); 15797403Sobrien int __sep_pos = 0; 15897403Sobrien const char_type __sep = __np.thousands_sep(); 15997403Sobrien 16097403Sobrien while (__beg != __end) 16197403Sobrien { 16297403Sobrien // Only look in digits. 16397403Sobrien const char_type* __p = __traits_type::find(__watoms, 10, __c); 16497403Sobrien 16597403Sobrien // NB: strchr returns true for __c == 0x0 166102782Skan if (__p && !__traits_type::eq(__c, char_type())) 16797403Sobrien { 16897403Sobrien // Try first for acceptable digit; record it if found. 16997403Sobrien ++__pos; 170117397Skan __xtrc += _S_atoms_in[__p - __watoms]; 17197403Sobrien ++__sep_pos; 17297403Sobrien __c = *(++__beg); 17397403Sobrien } 174102782Skan else if (__traits_type::eq(__c, __sep) 175102782Skan && __check_grouping && !__found_dec) 17697403Sobrien { 17797403Sobrien // NB: Thousands separator at the beginning of a string 17897403Sobrien // is a no-no, as is two consecutive thousands separators. 17997403Sobrien if (__sep_pos) 18097403Sobrien { 18197403Sobrien __found_grouping += static_cast<char>(__sep_pos); 18297403Sobrien __sep_pos = 0; 18397403Sobrien __c = *(++__beg); 18497403Sobrien } 18597403Sobrien else 18697403Sobrien { 18797403Sobrien __err |= ios_base::failbit; 18897403Sobrien break; 18997403Sobrien } 19097403Sobrien } 191102782Skan else if (__traits_type::eq(__c, __dec) && !__found_dec) 19297403Sobrien { 19397403Sobrien // According to the standard, if no grouping chars are seen, 19497403Sobrien // no grouping check is applied. Therefore __found_grouping 19597403Sobrien // must be adjusted only if __dec comes after some __sep. 19697403Sobrien if (__found_grouping.size()) 19797403Sobrien __found_grouping += static_cast<char>(__sep_pos); 19897403Sobrien ++__pos; 19997403Sobrien __xtrc += '.'; 20097403Sobrien __c = *(++__beg); 20197403Sobrien __found_dec = true; 20297403Sobrien } 203102782Skan else if ((__traits_type::eq(__c, __watoms[_M_e]) 204102782Skan || __traits_type::eq(__c, __watoms[_M_E])) 20597403Sobrien && !__found_sci && __pos) 20697403Sobrien { 20797403Sobrien // Scientific notation. 20897403Sobrien ++__pos; 20997403Sobrien __xtrc += __ctype.narrow(__c, char()); 21097403Sobrien __c = *(++__beg); 21197403Sobrien 21297403Sobrien // Remove optional plus or minus sign, if they exist. 213102782Skan if (__traits_type::eq(__c, __plus) 214102782Skan || __traits_type::eq(__c, __minus)) 21597403Sobrien { 21697403Sobrien ++__pos; 21797403Sobrien __xtrc += __ctype.narrow(__c, char()); 21897403Sobrien __c = *(++__beg); 21997403Sobrien } 22097403Sobrien __found_sci = true; 22197403Sobrien } 22297403Sobrien else 22397403Sobrien // Not a valid input item. 22497403Sobrien break; 22597403Sobrien } 22697403Sobrien 22797403Sobrien // Digit grouping is checked. If grouping and found_grouping don't 22897403Sobrien // match, then get very very upset, and set failbit. 22997403Sobrien if (__check_grouping && __found_grouping.size()) 23097403Sobrien { 23197403Sobrien // Add the ending grouping if a decimal wasn't found. 23297403Sobrien if (!__found_dec) 23397403Sobrien __found_grouping += static_cast<char>(__sep_pos); 23497403Sobrien if (!__verify_grouping(__grouping, __found_grouping)) 23597403Sobrien __err |= ios_base::failbit; 23697403Sobrien } 23797403Sobrien 23897403Sobrien // Finish up 23997403Sobrien __xtrc += char(); 24097403Sobrien if (__beg == __end) 24197403Sobrien __err |= ios_base::eofbit; 24297403Sobrien return __beg; 24397403Sobrien } 24497403Sobrien 24597403Sobrien // Stage 1: Determine a conversion specifier. 24697403Sobrien template<typename _CharT, typename _InIter> 24797403Sobrien _InIter 24897403Sobrien num_get<_CharT, _InIter>:: 24997403Sobrien _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 25097403Sobrien ios_base::iostate& __err, string& __xtrc, int& __base) const 25197403Sobrien { 252102782Skan typedef char_traits<_CharT> __traits_type; 25397403Sobrien const locale __loc = __io.getloc(); 25497403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 25597403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 25697403Sobrien 25797403Sobrien // NB: Iff __basefield == 0, this can change based on contents. 25897403Sobrien ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 25997403Sobrien if (__basefield == ios_base::oct) 26097403Sobrien __base = 8; 26197403Sobrien else if (__basefield == ios_base::hex) 26297403Sobrien __base = 16; 26397403Sobrien else 26497403Sobrien __base = 10; 26597403Sobrien 266102782Skan // First check for sign. 26797403Sobrien int __pos = 0; 26897403Sobrien char_type __c = *__beg; 269102782Skan const char_type __plus = __ctype.widen('+'); 270102782Skan const char_type __minus = __ctype.widen('-'); 271102782Skan 272102782Skan if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 27397403Sobrien && __beg != __end) 27497403Sobrien { 27597403Sobrien __xtrc += __ctype.narrow(__c, char()); 27697403Sobrien ++__pos; 27797403Sobrien __c = *(++__beg); 27897403Sobrien } 27997403Sobrien 28097403Sobrien // Next, strip leading zeros and check required digits for base formats. 281117397Skan const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); 28297403Sobrien const char_type __x = __ctype.widen('x'); 28397403Sobrien const char_type __X = __ctype.widen('X'); 28497403Sobrien if (__base == 10) 28597403Sobrien { 28697403Sobrien bool __found_zero = false; 287102782Skan while (__traits_type::eq(__c, __zero) && __beg != __end) 28897403Sobrien { 28997403Sobrien __c = *(++__beg); 29097403Sobrien __found_zero = true; 29197403Sobrien } 29297403Sobrien if (__found_zero) 29397403Sobrien { 294117397Skan __xtrc += _S_atoms_in[_M_zero]; 29597403Sobrien ++__pos; 29697403Sobrien if (__basefield == 0) 29797403Sobrien { 298102782Skan if ((__traits_type::eq(__c, __x) 299102782Skan || __traits_type::eq(__c, __X)) 300102782Skan && __beg != __end) 30197403Sobrien { 30297403Sobrien __xtrc += __ctype.narrow(__c, char()); 30397403Sobrien ++__pos; 30497403Sobrien __c = *(++__beg); 30597403Sobrien __base = 16; 30697403Sobrien } 30797403Sobrien else 30897403Sobrien __base = 8; 30997403Sobrien } 31097403Sobrien } 31197403Sobrien } 31297403Sobrien else if (__base == 16) 31397403Sobrien { 314102782Skan if (__traits_type::eq(__c, __zero) && __beg != __end) 31597403Sobrien { 316117397Skan __xtrc += _S_atoms_in[_M_zero]; 31797403Sobrien ++__pos; 31897403Sobrien __c = *(++__beg); 319102782Skan if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) 320102782Skan && __beg != __end) 32197403Sobrien { 32297403Sobrien __xtrc += __ctype.narrow(__c, char()); 32397403Sobrien ++__pos; 32497403Sobrien __c = *(++__beg); 32597403Sobrien } 32697403Sobrien } 32797403Sobrien } 32897403Sobrien 32997403Sobrien // At this point, base is determined. If not hex, only allow 33097403Sobrien // base digits as valid input. 33197403Sobrien size_t __len; 33297403Sobrien if (__base == 16) 33397403Sobrien __len = _M_size; 33497403Sobrien else 33597403Sobrien __len = __base; 33697403Sobrien 33797403Sobrien // Extract. 33897403Sobrien char_type __watoms[_M_size]; 339117397Skan __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); 34097403Sobrien string __found_grouping; 34197403Sobrien const string __grouping = __np.grouping(); 34297403Sobrien bool __check_grouping = __grouping.size(); 34397403Sobrien int __sep_pos = 0; 34497403Sobrien const char_type __sep = __np.thousands_sep(); 34597403Sobrien while (__beg != __end) 34697403Sobrien { 34797403Sobrien const char_type* __p = __traits_type::find(__watoms, __len, __c); 34897403Sobrien 34997403Sobrien // NB: strchr returns true for __c == 0x0 350102782Skan if (__p && !__traits_type::eq(__c, char_type())) 35197403Sobrien { 35297403Sobrien // Try first for acceptable digit; record it if found. 353117397Skan __xtrc += _S_atoms_in[__p - __watoms]; 35497403Sobrien ++__pos; 35597403Sobrien ++__sep_pos; 35697403Sobrien __c = *(++__beg); 35797403Sobrien } 358102782Skan else if (__traits_type::eq(__c, __sep) && __check_grouping) 35997403Sobrien { 36097403Sobrien // NB: Thousands separator at the beginning of a string 36197403Sobrien // is a no-no, as is two consecutive thousands separators. 36297403Sobrien if (__sep_pos) 36397403Sobrien { 36497403Sobrien __found_grouping += static_cast<char>(__sep_pos); 36597403Sobrien __sep_pos = 0; 36697403Sobrien __c = *(++__beg); 36797403Sobrien } 36897403Sobrien else 36997403Sobrien { 37097403Sobrien __err |= ios_base::failbit; 37197403Sobrien break; 37297403Sobrien } 37397403Sobrien } 37497403Sobrien else 37597403Sobrien // Not a valid input item. 37697403Sobrien break; 37797403Sobrien } 37897403Sobrien 37997403Sobrien // Digit grouping is checked. If grouping and found_grouping don't 38097403Sobrien // match, then get very very upset, and set failbit. 38197403Sobrien if (__check_grouping && __found_grouping.size()) 38297403Sobrien { 38397403Sobrien // Add the ending grouping. 38497403Sobrien __found_grouping += static_cast<char>(__sep_pos); 38597403Sobrien if (!__verify_grouping(__grouping, __found_grouping)) 38697403Sobrien __err |= ios_base::failbit; 38797403Sobrien } 38897403Sobrien 38997403Sobrien // Finish up. 39097403Sobrien __xtrc += char(); 39197403Sobrien if (__beg == __end) 39297403Sobrien __err |= ios_base::eofbit; 39397403Sobrien return __beg; 39497403Sobrien } 39597403Sobrien 39697403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 39797403Sobrien //17. Bad bool parsing 39897403Sobrien template<typename _CharT, typename _InIter> 39997403Sobrien _InIter 40097403Sobrien num_get<_CharT, _InIter>:: 40197403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 40297403Sobrien ios_base::iostate& __err, bool& __v) const 40397403Sobrien { 40497403Sobrien // Parse bool values as unsigned long 40597403Sobrien if (!(__io.flags() & ios_base::boolalpha)) 40697403Sobrien { 40797403Sobrien // NB: We can't just call do_get(long) here, as it might 40897403Sobrien // refer to a derived class. 40997403Sobrien string __xtrc; 41097403Sobrien int __base; 41197403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 41297403Sobrien 41397403Sobrien unsigned long __ul; 41497403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 41597403Sobrien if (!(__err & ios_base::failbit) && __ul <= 1) 41697403Sobrien __v = __ul; 41797403Sobrien else 41897403Sobrien __err |= ios_base::failbit; 41997403Sobrien } 42097403Sobrien 42197403Sobrien // Parse bool values as alphanumeric 42297403Sobrien else 42397403Sobrien { 424102782Skan typedef char_traits<_CharT> __traits_type; 425102782Skan typedef basic_string<_CharT> __string_type; 426102782Skan 42797403Sobrien locale __loc = __io.getloc(); 42897403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 42997403Sobrien const __string_type __true = __np.truename(); 43097403Sobrien const __string_type __false = __np.falsename(); 43197403Sobrien const char_type* __trues = __true.c_str(); 43297403Sobrien const char_type* __falses = __false.c_str(); 43397403Sobrien const size_t __truen = __true.size() - 1; 43497403Sobrien const size_t __falsen = __false.size() - 1; 43597403Sobrien 43697403Sobrien for (size_t __n = 0; __beg != __end; ++__n) 43797403Sobrien { 43897403Sobrien char_type __c = *__beg++; 439102782Skan bool __testf = __n <= __falsen 440102782Skan ? __traits_type::eq(__c, __falses[__n]) : false; 441102782Skan bool __testt = __n <= __truen 442102782Skan ? __traits_type::eq(__c, __trues[__n]) : false; 44397403Sobrien if (!(__testf || __testt)) 44497403Sobrien { 44597403Sobrien __err |= ios_base::failbit; 44697403Sobrien break; 44797403Sobrien } 44897403Sobrien else if (__testf && __n == __falsen) 44997403Sobrien { 45097403Sobrien __v = 0; 45197403Sobrien break; 45297403Sobrien } 45397403Sobrien else if (__testt && __n == __truen) 45497403Sobrien { 45597403Sobrien __v = 1; 45697403Sobrien break; 45797403Sobrien } 45897403Sobrien } 45997403Sobrien if (__beg == __end) 46097403Sobrien __err |= ios_base::eofbit; 46197403Sobrien } 46297403Sobrien return __beg; 46397403Sobrien } 46497403Sobrien#endif 46597403Sobrien 46697403Sobrien template<typename _CharT, typename _InIter> 46797403Sobrien _InIter 46897403Sobrien num_get<_CharT, _InIter>:: 46997403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 47097403Sobrien ios_base::iostate& __err, long& __v) const 47197403Sobrien { 47297403Sobrien string __xtrc; 47397403Sobrien int __base; 47497403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 47597403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 47697403Sobrien return __beg; 47797403Sobrien } 47897403Sobrien 47997403Sobrien template<typename _CharT, typename _InIter> 48097403Sobrien _InIter 48197403Sobrien num_get<_CharT, _InIter>:: 48297403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 48397403Sobrien ios_base::iostate& __err, unsigned short& __v) const 48497403Sobrien { 48597403Sobrien string __xtrc; 48697403Sobrien int __base; 48797403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 48897403Sobrien unsigned long __ul; 48997403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 49097403Sobrien if (!(__err & ios_base::failbit) 49197403Sobrien && __ul <= numeric_limits<unsigned short>::max()) 49297403Sobrien __v = static_cast<unsigned short>(__ul); 49397403Sobrien else 49497403Sobrien __err |= ios_base::failbit; 49597403Sobrien return __beg; 49697403Sobrien } 49797403Sobrien 49897403Sobrien template<typename _CharT, typename _InIter> 49997403Sobrien _InIter 50097403Sobrien num_get<_CharT, _InIter>:: 50197403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 50297403Sobrien ios_base::iostate& __err, unsigned int& __v) const 50397403Sobrien { 50497403Sobrien string __xtrc; 50597403Sobrien int __base; 50697403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 50797403Sobrien unsigned long __ul; 50897403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 50997403Sobrien if (!(__err & ios_base::failbit) 51097403Sobrien && __ul <= numeric_limits<unsigned int>::max()) 51197403Sobrien __v = static_cast<unsigned int>(__ul); 51297403Sobrien else 51397403Sobrien __err |= ios_base::failbit; 51497403Sobrien return __beg; 51597403Sobrien } 51697403Sobrien 51797403Sobrien template<typename _CharT, typename _InIter> 51897403Sobrien _InIter 51997403Sobrien num_get<_CharT, _InIter>:: 52097403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 52197403Sobrien ios_base::iostate& __err, unsigned long& __v) const 52297403Sobrien { 52397403Sobrien string __xtrc; 52497403Sobrien int __base; 52597403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 52697403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 52797403Sobrien return __beg; 52897403Sobrien } 52997403Sobrien 53097403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG 53197403Sobrien template<typename _CharT, typename _InIter> 53297403Sobrien _InIter 53397403Sobrien num_get<_CharT, _InIter>:: 53497403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 53597403Sobrien ios_base::iostate& __err, long long& __v) const 53697403Sobrien { 53797403Sobrien string __xtrc; 53897403Sobrien int __base; 53997403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 54097403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 54197403Sobrien return __beg; 54297403Sobrien } 54397403Sobrien 54497403Sobrien template<typename _CharT, typename _InIter> 54597403Sobrien _InIter 54697403Sobrien num_get<_CharT, _InIter>:: 54797403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 54897403Sobrien ios_base::iostate& __err, unsigned long long& __v) const 54997403Sobrien { 55097403Sobrien string __xtrc; 55197403Sobrien int __base; 55297403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 55397403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 55497403Sobrien return __beg; 55597403Sobrien } 55697403Sobrien#endif 55797403Sobrien 55897403Sobrien template<typename _CharT, typename _InIter> 55997403Sobrien _InIter 56097403Sobrien num_get<_CharT, _InIter>:: 56197403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 56297403Sobrien ios_base::iostate& __err, float& __v) const 56397403Sobrien { 56497403Sobrien string __xtrc; 56597403Sobrien __xtrc.reserve(32); 56697403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 56797403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 56897403Sobrien return __beg; 56997403Sobrien } 57097403Sobrien 57197403Sobrien template<typename _CharT, typename _InIter> 57297403Sobrien _InIter 57397403Sobrien num_get<_CharT, _InIter>:: 57497403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 57597403Sobrien ios_base::iostate& __err, double& __v) const 57697403Sobrien { 57797403Sobrien string __xtrc; 57897403Sobrien __xtrc.reserve(32); 57997403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 58097403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 58197403Sobrien return __beg; 58297403Sobrien } 58397403Sobrien 58497403Sobrien template<typename _CharT, typename _InIter> 58597403Sobrien _InIter 58697403Sobrien num_get<_CharT, _InIter>:: 58797403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 58897403Sobrien ios_base::iostate& __err, long double& __v) const 58997403Sobrien { 59097403Sobrien string __xtrc; 59197403Sobrien __xtrc.reserve(32); 59297403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 59397403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 59497403Sobrien return __beg; 59597403Sobrien } 59697403Sobrien 59797403Sobrien template<typename _CharT, typename _InIter> 59897403Sobrien _InIter 59997403Sobrien num_get<_CharT, _InIter>:: 60097403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 60197403Sobrien ios_base::iostate& __err, void*& __v) const 60297403Sobrien { 60397403Sobrien // Prepare for hex formatted input 60497403Sobrien typedef ios_base::fmtflags fmtflags; 60597403Sobrien fmtflags __fmt = __io.flags(); 60697403Sobrien fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield 60797403Sobrien | ios_base::uppercase | ios_base::internal); 60897403Sobrien __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); 60997403Sobrien 61097403Sobrien string __xtrc; 61197403Sobrien int __base; 61297403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 61397403Sobrien 61497403Sobrien // Reset from hex formatted input 61597403Sobrien __io.flags(__fmt); 61697403Sobrien 61797403Sobrien unsigned long __ul; 61897403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 61997403Sobrien if (!(__err & ios_base::failbit)) 62097403Sobrien __v = reinterpret_cast<void*>(__ul); 62197403Sobrien else 62297403Sobrien __err |= ios_base::failbit; 62397403Sobrien return __beg; 62497403Sobrien } 62597403Sobrien 626117397Skan // For use by integer and floating-point types after they have been 627117397Skan // converted into a char_type string. 628117397Skan template<typename _CharT, typename _OutIter> 629117397Skan void 630117397Skan num_put<_CharT, _OutIter>:: 631117397Skan _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 632117397Skan _CharT* __new, const _CharT* __cs, int& __len) const 633117397Skan { 634117397Skan // [22.2.2.2.2] Stage 3. 635117397Skan // If necessary, pad. 636117397Skan __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 637117397Skan __w, __len, true); 638117397Skan __len = static_cast<int>(__w); 639117397Skan } 640117397Skan 641117397Skan // Forwarding functions to peel signed from unsigned integer types. 642117397Skan template<typename _CharT> 643117397Skan inline int 644117397Skan __int_to_char(_CharT* __out, const int __size, long __v, 645117397Skan const _CharT* __lit, ios_base::fmtflags __flags) 646117397Skan { 647117397Skan unsigned long __ul = static_cast<unsigned long>(__v); 648117397Skan bool __neg = false; 649117397Skan if (__v < 0) 650117397Skan { 651117397Skan __ul = -__ul; 652117397Skan __neg = true; 653117397Skan } 654117397Skan return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); 655117397Skan } 656117397Skan 657117397Skan template<typename _CharT> 658117397Skan inline int 659117397Skan __int_to_char(_CharT* __out, const int __size, unsigned long __v, 660117397Skan const _CharT* __lit, ios_base::fmtflags __flags) 661117397Skan { return __int_to_char(__out, __size, __v, __lit, __flags, false); } 662117397Skan 663117397Skan#ifdef _GLIBCPP_USE_LONG_LONG 664117397Skan template<typename _CharT> 665117397Skan inline int 666117397Skan __int_to_char(_CharT* __out, const int __size, long long __v, 667117397Skan const _CharT* __lit, ios_base::fmtflags __flags) 668117397Skan { 669117397Skan unsigned long long __ull = static_cast<unsigned long long>(__v); 670117397Skan bool __neg = false; 671117397Skan if (__v < 0) 672117397Skan { 673117397Skan __ull = -__ull; 674117397Skan __neg = true; 675117397Skan } 676117397Skan return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); 677117397Skan } 678117397Skan 679117397Skan template<typename _CharT> 680117397Skan inline int 681117397Skan __int_to_char(_CharT* __out, const int __size, unsigned long long __v, 682117397Skan const _CharT* __lit, ios_base::fmtflags __flags) 683117397Skan { return __int_to_char(__out, __size, __v, __lit, __flags, false); } 684117397Skan#endif 685117397Skan 686117397Skan template<typename _CharT, typename _ValueT> 687117397Skan int 688117397Skan __int_to_char(_CharT* __out, const int __size, _ValueT __v, 689117397Skan const _CharT* __lit, ios_base::fmtflags __flags, bool __neg) 690117397Skan { 691117397Skan // Don't write base if already 0. 692117397Skan const bool __showbase = (__flags & ios_base::showbase) && __v; 693117397Skan const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 694117397Skan _CharT* __buf = __out + __size - 1; 695117397Skan _CharT* __bufend = __out + __size; 696117397Skan 697117397Skan if (__builtin_expect(__basefield != ios_base::oct && 698117397Skan __basefield != ios_base::hex, true)) 699117397Skan { 700117397Skan // Decimal. 701117397Skan do 702117397Skan { 703117397Skan *__buf-- = __lit[(__v % 10) + __num_base::_S_digits]; 704117397Skan __v /= 10; 705117397Skan } 706117397Skan while (__v != 0); 707117397Skan if (__neg) 708117397Skan *__buf-- = __lit[__num_base::_S_minus]; 709117397Skan else if (__flags & ios_base::showpos) 710117397Skan *__buf-- = __lit[__num_base::_S_plus]; 711117397Skan } 712117397Skan else if (__basefield == ios_base::oct) 713117397Skan { 714117397Skan // Octal. 715117397Skan do 716117397Skan { 717117397Skan *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits]; 718117397Skan __v >>= 3; 719117397Skan } 720117397Skan while (__v != 0); 721117397Skan if (__showbase) 722117397Skan *__buf-- = __lit[__num_base::_S_digits]; 723117397Skan } 724117397Skan else 725117397Skan { 726117397Skan // Hex. 727117397Skan const bool __uppercase = __flags & ios_base::uppercase; 728117397Skan int __case_offset = __uppercase 729117397Skan ? __num_base::_S_udigits : __num_base::_S_digits; 730117397Skan do 731117397Skan { 732117397Skan *__buf-- = __lit[(__v & 0xf) + __case_offset]; 733117397Skan __v >>= 4; 734117397Skan } 735117397Skan while (__v != 0); 736117397Skan if (__showbase) 737117397Skan { 738117397Skan // 'x' or 'X' 739117397Skan *__buf-- = __lit[__num_base::_S_x + __uppercase]; 740117397Skan // '0' 741117397Skan *__buf-- = __lit[__num_base::_S_digits]; 742117397Skan } 743117397Skan } 744117397Skan int __ret = __bufend - __buf - 1; 745117397Skan return __ret; 746117397Skan } 747117397Skan 748117397Skan template<typename _CharT, typename _OutIter> 749117397Skan void 750117397Skan num_put<_CharT, _OutIter>:: 751117397Skan _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 752117397Skan _CharT* __new, _CharT* __cs, int& __len) const 753117397Skan { 754117397Skan // By itself __add_grouping cannot deal correctly with __ws when 755117397Skan // ios::showbase is set and ios_base::oct || ios_base::hex. 756117397Skan // Therefore we take care "by hand" of the initial 0, 0x or 0X. 757117397Skan // However, remember that the latter do not occur if the number 758117397Skan // printed is '0' (__len == 1). 759117397Skan streamsize __off = 0; 760117397Skan const ios_base::fmtflags __basefield = __io.flags() 761117397Skan & ios_base::basefield; 762117397Skan if ((__io.flags() & ios_base::showbase) && __len > 1) 763117397Skan if (__basefield == ios_base::oct) 764117397Skan { 765117397Skan __off = 1; 766117397Skan *__new = *__cs; 767117397Skan } 768117397Skan else if (__basefield == ios_base::hex) 769117397Skan { 770117397Skan __off = 2; 771117397Skan *__new = *__cs; 772117397Skan *(__new + 1) = *(__cs + 1); 773117397Skan } 774117397Skan _CharT* __p; 775117397Skan __p = __add_grouping(__new + __off, __sep, 776117397Skan __grouping.c_str(), 777117397Skan __grouping.c_str() + __grouping.size(), 778117397Skan __cs + __off, __cs + __len); 779117397Skan __len = __p - __new; 780117397Skan } 781117397Skan 782117397Skan template<typename _CharT, typename _OutIter> 783117397Skan template<typename _ValueT> 784117397Skan _OutIter 785117397Skan num_put<_CharT, _OutIter>:: 786117397Skan _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 787117397Skan _ValueT __v) const 788117397Skan { 789117397Skan typedef numpunct<_CharT> __facet_type; 790117397Skan typedef __locale_cache<numpunct<_CharT> > __cache_type; 791117397Skan const locale& __loc = __io._M_getloc(); 792117397Skan const __cache_type& __lc = __use_cache<__facet_type>(__loc); 793117397Skan const _CharT* __lit = __lc._M_atoms_out; 794117397Skan 795117397Skan // Long enough to hold hex, dec, and octal representations. 796117397Skan int __ilen = 4 * sizeof(_ValueT); 797117397Skan _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 798117397Skan * __ilen)); 799117397Skan // [22.2.2.2.2] Stage 1, numeric conversion to character. 800117397Skan // Result is returned right-justified in the buffer. 801117397Skan int __len; 802117397Skan __len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags()); 803117397Skan __cs = __cs + __ilen - __len; 804117397Skan 805117397Skan // Add grouping, if necessary. 806117397Skan _CharT* __cs2; 807117397Skan if (__lc._M_use_grouping) 808117397Skan { 809117397Skan // Grouping can add (almost) as many separators as the 810117397Skan // number of digits, but no more. 811117397Skan __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 812117397Skan * __len * 2)); 813117397Skan _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, 814117397Skan __cs2, __cs, __len); 815117397Skan __cs = __cs2; 816117397Skan } 817117397Skan 818117397Skan // Pad. 819117397Skan _CharT* __cs3; 820117397Skan streamsize __w = __io.width(); 821117397Skan if (__w > static_cast<streamsize>(__len)) 822117397Skan { 823117397Skan __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 824117397Skan * __w)); 825117397Skan _M_pad(__fill, __w, __io, __cs3, __cs, __len); 826117397Skan __cs = __cs3; 827117397Skan } 828117397Skan __io.width(0); 829117397Skan 830117397Skan // [22.2.2.2.2] Stage 4. 831117397Skan // Write resulting, fully-formatted string to output iterator. 832117397Skan return __write(__s, __cs, __len); 833117397Skan } 834117397Skan 835117397Skan template<typename _CharT, typename _OutIter> 836117397Skan void 837117397Skan num_put<_CharT, _OutIter>:: 838117397Skan _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 839117397Skan _CharT* __new, _CharT* __cs, int& __len) const 840117397Skan { 841117397Skan#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 842117397Skan //282. What types does numpunct grouping refer to? 843117397Skan // Add grouping, if necessary. 844117397Skan _CharT* __p2; 845117397Skan int __declen = __p ? __p - __cs : __len; 846117397Skan __p2 = __add_grouping(__new, __sep, 847117397Skan __grouping.c_str(), 848117397Skan __grouping.c_str() + __grouping.size(), 849117397Skan __cs, __cs + __declen); 850117397Skan 851117397Skan // Tack on decimal part. 852117397Skan int __newlen = __p2 - __new; 853117397Skan if (__p) 854117397Skan { 855117397Skan char_traits<_CharT>::copy(__p2, __p, __len - __declen); 856117397Skan __newlen += __len - __declen; 857117397Skan } 858117397Skan __len = __newlen; 859117397Skan#endif 860117397Skan } 861117397Skan 862117397Skan // The following code uses snprintf (or sprintf(), when 863117397Skan // _GLIBCPP_USE_C99 is not defined) to convert floating point values 864117397Skan // for insertion into a stream. An optimization would be to replace 865117397Skan // them with code that works directly on a wide buffer and then use 866117397Skan // __pad to do the padding. It would be good to replace them anyway 867117397Skan // to gain back the efficiency that C++ provides by knowing up front 868117397Skan // the type of the values to insert. Also, sprintf is dangerous 869117397Skan // since may lead to accidental buffer overruns. This 870117397Skan // implementation follows the C++ standard fairly directly as 87197403Sobrien // outlined in 22.2.2.2 [lib.locale.num.put] 87297403Sobrien template<typename _CharT, typename _OutIter> 87397403Sobrien template<typename _ValueT> 87497403Sobrien _OutIter 87597403Sobrien num_put<_CharT, _OutIter>:: 87697403Sobrien _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 87797403Sobrien _ValueT __v) const 87897403Sobrien { 879117397Skan // Note: digits10 is rounded down: add 1 to ensure the maximum 880117397Skan // available precision. Then, in general, one more 1 needs to 881117397Skan // be added since, when the %{g,G} conversion specifiers are 882117397Skan // chosen inside _S_format_float, the precision field is "the 883117397Skan // maximum number of significant digits", *not* the "number of 884117397Skan // digits to appear after the decimal point", as happens for 885117397Skan // %{e,E,f,F} (C99, 7.19.6.1,4). 886110614Skan const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; 887117397Skan 888117397Skan // Use default precision if out of range. 88997403Sobrien streamsize __prec = __io.precision(); 89097403Sobrien if (__prec > static_cast<streamsize>(__max_digits)) 89197403Sobrien __prec = static_cast<streamsize>(__max_digits); 892117397Skan else if (__prec < static_cast<streamsize>(0)) 893117397Skan __prec = static_cast<streamsize>(6); 89497403Sobrien 895117397Skan typedef numpunct<_CharT> __facet_type; 896117397Skan typedef __locale_cache<numpunct<_CharT> > __cache_type; 897117397Skan const locale __loc = __io._M_getloc(); 898117397Skan const __cache_type& __lc = __use_cache<__facet_type>(__loc); 899117397Skan 900117397Skan // [22.2.2.2.2] Stage 1, numeric conversion to character. 901117397Skan int __len; 90297403Sobrien // Long enough for the max format spec. 90397403Sobrien char __fbuf[16]; 90497403Sobrien 90597403Sobrien#ifdef _GLIBCPP_USE_C99 906117397Skan // First try a buffer perhaps big enough (for sure sufficient 907117397Skan // for non-ios_base::fixed outputs) 90897403Sobrien int __cs_size = __max_digits * 3; 90997403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 91097403Sobrien 911117397Skan _S_format_float(__io, __fbuf, __mod, __prec); 912117397Skan __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 913117397Skan _S_c_locale, __prec); 91497403Sobrien 91597403Sobrien // If the buffer was not large enough, try again with the correct size. 91697403Sobrien if (__len >= __cs_size) 91797403Sobrien { 91897403Sobrien __cs_size = __len + 1; 91997403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 920117397Skan __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 921117397Skan _S_c_locale, __prec); 92297403Sobrien } 92397403Sobrien#else 92497403Sobrien // Consider the possibility of long ios_base::fixed outputs 92597403Sobrien const bool __fixed = __io.flags() & ios_base::fixed; 92697403Sobrien const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 927117397Skan 92897403Sobrien // ios_base::fixed outputs may need up to __max_exp+1 chars 92997403Sobrien // for the integer part + up to __max_digits chars for the 93097403Sobrien // fractional part + 3 chars for sign, decimal point, '\0'. On 93197403Sobrien // the other hand, for non-fixed outputs __max_digits*3 chars 93297403Sobrien // are largely sufficient. 93397403Sobrien const int __cs_size = __fixed ? __max_exp + __max_digits + 4 93497403Sobrien : __max_digits * 3; 93597403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 93697403Sobrien 937117397Skan _S_format_float(__io, __fbuf, __mod, __prec); 938117397Skan __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); 93997403Sobrien#endif 94097403Sobrien 94197403Sobrien // [22.2.2.2.2] Stage 2, convert to char_type, using correct 94297403Sobrien // numpunct.decimal_point() values for '.' and adding grouping. 94397403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 944117397Skan 94597403Sobrien _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 94697403Sobrien * __len)); 94797403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 94897403Sobrien 94997403Sobrien // Replace decimal point. 950117397Skan const _CharT __cdec = __ctype.widen('.'); 951117397Skan const _CharT __dec = __lc._M_decimal_point; 95297403Sobrien const _CharT* __p; 953117397Skan if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) 954117397Skan __ws[__p - __ws] = __dec; 95597403Sobrien 95697403Sobrien // Add grouping, if necessary. 957117397Skan _CharT* __ws2; 958117397Skan if (__lc._M_use_grouping) 95997403Sobrien { 960117397Skan // Grouping can add (almost) as many separators as the 961117397Skan // number of digits, but no more. 962117397Skan __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 963117397Skan * __len * 2)); 964117397Skan _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p, 965117397Skan __ws2, __ws, __len); 966117397Skan __ws = __ws2; 96797403Sobrien } 96897403Sobrien 969117397Skan // Pad. 970117397Skan _CharT* __ws3; 97197403Sobrien streamsize __w = __io.width(); 97297403Sobrien if (__w > static_cast<streamsize>(__len)) 97397403Sobrien { 974117397Skan __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); 975117397Skan _M_pad(__fill, __w, __io, __ws3, __ws, __len); 976117397Skan __ws = __ws3; 97797403Sobrien } 97897403Sobrien __io.width(0); 979117397Skan 98097403Sobrien // [22.2.2.2.2] Stage 4. 98197403Sobrien // Write resulting, fully-formatted string to output iterator. 982117397Skan return __write(__s, __ws, __len); 983117397Skan } 98497403Sobrien 98597403Sobrien template<typename _CharT, typename _OutIter> 98697403Sobrien _OutIter 98797403Sobrien num_put<_CharT, _OutIter>:: 98897403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 98997403Sobrien { 99097403Sobrien ios_base::fmtflags __flags = __io.flags(); 99197403Sobrien if ((__flags & ios_base::boolalpha) == 0) 99297403Sobrien { 99397403Sobrien unsigned long __uv = __v; 994117397Skan __s = _M_convert_int(__s, __io, __fill, __uv); 99597403Sobrien } 99697403Sobrien else 99797403Sobrien { 998117397Skan typedef numpunct<_CharT> __facet_type; 999117397Skan typedef __locale_cache<numpunct<_CharT> > __cache_type; 1000117397Skan const locale __loc = __io._M_getloc(); 1001117397Skan const __cache_type& __lc = __use_cache<__facet_type>(__loc); 1002117397Skan 1003117397Skan typedef basic_string<_CharT> __string_type; 100497403Sobrien __string_type __name; 100597403Sobrien if (__v) 1006117397Skan __name = __lc._M_truename; 100797403Sobrien else 1008117397Skan __name = __lc._M_falsename; 1009117397Skan 1010117397Skan const _CharT* __cs = __name.c_str(); 1011117397Skan int __len = __name.size(); 1012117397Skan _CharT* __cs3; 1013117397Skan streamsize __w = __io.width(); 1014117397Skan if (__w > static_cast<streamsize>(__len)) 1015117397Skan { 1016117397Skan __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1017117397Skan * __w)); 1018117397Skan _M_pad(__fill, __w, __io, __cs3, __cs, __len); 1019117397Skan __cs = __cs3; 1020117397Skan } 1021117397Skan __io.width(0); 1022117397Skan __s = __write(__s, __cs, __len); 102397403Sobrien } 102497403Sobrien return __s; 102597403Sobrien } 102697403Sobrien 102797403Sobrien template<typename _CharT, typename _OutIter> 102897403Sobrien _OutIter 102997403Sobrien num_put<_CharT, _OutIter>:: 103097403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 1031117397Skan { return _M_convert_int(__s, __io, __fill, __v); } 103297403Sobrien 103397403Sobrien template<typename _CharT, typename _OutIter> 103497403Sobrien _OutIter 103597403Sobrien num_put<_CharT, _OutIter>:: 103697403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 103797403Sobrien unsigned long __v) const 1038117397Skan { return _M_convert_int(__s, __io, __fill, __v); } 103997403Sobrien 104097403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG 104197403Sobrien template<typename _CharT, typename _OutIter> 104297403Sobrien _OutIter 104397403Sobrien num_put<_CharT, _OutIter>:: 104497403Sobrien do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 1045117397Skan { return _M_convert_int(__s, __b, __fill, __v); } 104697403Sobrien 104797403Sobrien template<typename _CharT, typename _OutIter> 104897403Sobrien _OutIter 104997403Sobrien num_put<_CharT, _OutIter>:: 105097403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 105197403Sobrien unsigned long long __v) const 1052117397Skan { return _M_convert_int(__s, __io, __fill, __v); } 105397403Sobrien#endif 105497403Sobrien 105597403Sobrien template<typename _CharT, typename _OutIter> 105697403Sobrien _OutIter 105797403Sobrien num_put<_CharT, _OutIter>:: 105897403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 1059102782Skan { return _M_convert_float(__s, __io, __fill, char(), __v); } 106097403Sobrien 106197403Sobrien template<typename _CharT, typename _OutIter> 106297403Sobrien _OutIter 106397403Sobrien num_put<_CharT, _OutIter>:: 106497403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 106597403Sobrien long double __v) const 106697403Sobrien { return _M_convert_float(__s, __io, __fill, 'L', __v); } 106797403Sobrien 106897403Sobrien template<typename _CharT, typename _OutIter> 106997403Sobrien _OutIter 107097403Sobrien num_put<_CharT, _OutIter>:: 107197403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 107297403Sobrien const void* __v) const 107397403Sobrien { 107497403Sobrien ios_base::fmtflags __flags = __io.flags(); 107597403Sobrien ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield 107697403Sobrien | ios_base::uppercase | ios_base::internal); 107797403Sobrien __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 107897403Sobrien try 107997403Sobrien { 1080117397Skan __s = _M_convert_int(__s, __io, __fill, 108197403Sobrien reinterpret_cast<unsigned long>(__v)); 108297403Sobrien __io.flags(__flags); 108397403Sobrien } 108497403Sobrien catch (...) 108597403Sobrien { 108697403Sobrien __io.flags(__flags); 108797403Sobrien __throw_exception_again; 108897403Sobrien } 108997403Sobrien return __s; 109097403Sobrien } 109197403Sobrien 109297403Sobrien 109397403Sobrien template<typename _CharT, typename _InIter> 109497403Sobrien _InIter 109597403Sobrien money_get<_CharT, _InIter>:: 109697403Sobrien do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 109797403Sobrien ios_base::iostate& __err, long double& __units) const 109897403Sobrien { 109997403Sobrien string_type __str; 110097403Sobrien __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 110197403Sobrien 110297403Sobrien const int __n = numeric_limits<long double>::digits10; 110397403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__n)); 110497403Sobrien const locale __loc = __io.getloc(); 110597403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 110697403Sobrien const _CharT* __wcs = __str.c_str(); 110797403Sobrien __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); 110897403Sobrien __convert_to_v(__cs, __units, __err, _S_c_locale); 110997403Sobrien return __beg; 111097403Sobrien } 111197403Sobrien 111297403Sobrien template<typename _CharT, typename _InIter> 111397403Sobrien _InIter 111497403Sobrien money_get<_CharT, _InIter>:: 111597403Sobrien do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 111697403Sobrien ios_base::iostate& __err, string_type& __units) const 111797403Sobrien { 111897403Sobrien // These contortions are quite unfortunate. 111997403Sobrien typedef moneypunct<_CharT, true> __money_true; 112097403Sobrien typedef moneypunct<_CharT, false> __money_false; 112197403Sobrien typedef money_base::part part; 112297403Sobrien typedef typename string_type::size_type size_type; 112397403Sobrien 112497403Sobrien const locale __loc = __io.getloc(); 112597403Sobrien const __money_true& __mpt = use_facet<__money_true>(__loc); 112697403Sobrien const __money_false& __mpf = use_facet<__money_false>(__loc); 112797403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 112897403Sobrien 112997403Sobrien const money_base::pattern __p = __intl ? __mpt.neg_format() 113097403Sobrien : __mpf.neg_format(); 113197403Sobrien 113297403Sobrien const string_type __pos_sign =__intl ? __mpt.positive_sign() 113397403Sobrien : __mpf.positive_sign(); 113497403Sobrien const string_type __neg_sign =__intl ? __mpt.negative_sign() 113597403Sobrien : __mpf.negative_sign(); 113697403Sobrien const char_type __d = __intl ? __mpt.decimal_point() 113797403Sobrien : __mpf.decimal_point(); 113897403Sobrien const char_type __sep = __intl ? __mpt.thousands_sep() 113997403Sobrien : __mpf.thousands_sep(); 114097403Sobrien 114197403Sobrien const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); 114297403Sobrien 114397403Sobrien // Set to deduced positive or negative sign, depending. 114497403Sobrien string_type __sign; 114597403Sobrien // String of grouping info from thousands_sep plucked from __units. 114697403Sobrien string __grouping_tmp; 114797403Sobrien // Marker for thousands_sep position. 114897403Sobrien int __sep_pos = 0; 114997403Sobrien // If input iterator is in a valid state. 115097403Sobrien bool __testvalid = true; 115197403Sobrien // Flag marking when a decimal point is found. 115297403Sobrien bool __testdecfound = false; 115397403Sobrien 115497403Sobrien // The tentative returned string is stored here. 115597403Sobrien string_type __temp_units; 115697403Sobrien 115797403Sobrien char_type __c = *__beg; 115897403Sobrien char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); 115997403Sobrien for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) 116097403Sobrien { 116197403Sobrien part __which = static_cast<part>(__p.field[__i]); 116297403Sobrien switch (__which) 116397403Sobrien { 116497403Sobrien case money_base::symbol: 116597403Sobrien if (__io.flags() & ios_base::showbase 116697403Sobrien || __i < 2 || __sign.size() > 1 116797403Sobrien || ((static_cast<part>(__p.field[3]) != money_base::none) 116897403Sobrien && __i == 2)) 116997403Sobrien { 117097403Sobrien // According to 22.2.6.1.2.2, symbol is required 117197403Sobrien // if (__io.flags() & ios_base::showbase), 117297403Sobrien // otherwise is optional and consumed only if 117397403Sobrien // other characters are needed to complete the 117497403Sobrien // format. 117597403Sobrien const string_type __symbol = __intl ? __mpt.curr_symbol() 117697403Sobrien : __mpf.curr_symbol(); 117797403Sobrien size_type __len = __symbol.size(); 117897403Sobrien size_type __j = 0; 117997403Sobrien while (__beg != __end 118097403Sobrien && __j < __len && __symbol[__j] == __c) 118197403Sobrien { 118297403Sobrien __c = *(++__beg); 118397403Sobrien ++__j; 118497403Sobrien } 118597403Sobrien // When (__io.flags() & ios_base::showbase) 118697403Sobrien // symbol is required. 118797403Sobrien if (__j != __len && (__io.flags() & ios_base::showbase)) 118897403Sobrien __testvalid = false; 118997403Sobrien } 119097403Sobrien break; 119197403Sobrien case money_base::sign: 119297403Sobrien // Sign might not exist, or be more than one character long. 119397403Sobrien if (__pos_sign.size() && __neg_sign.size()) 119497403Sobrien { 119597403Sobrien // Sign is mandatory. 119697403Sobrien if (__c == __pos_sign[0]) 119797403Sobrien { 119897403Sobrien __sign = __pos_sign; 119997403Sobrien __c = *(++__beg); 120097403Sobrien } 120197403Sobrien else if (__c == __neg_sign[0]) 120297403Sobrien { 120397403Sobrien __sign = __neg_sign; 120497403Sobrien __c = *(++__beg); 120597403Sobrien } 120697403Sobrien else 120797403Sobrien __testvalid = false; 120897403Sobrien } 120997403Sobrien else if (__pos_sign.size() && __c == __pos_sign[0]) 121097403Sobrien { 121197403Sobrien __sign = __pos_sign; 121297403Sobrien __c = *(++__beg); 121397403Sobrien } 121497403Sobrien else if (__neg_sign.size() && __c == __neg_sign[0]) 121597403Sobrien { 121697403Sobrien __sign = __neg_sign; 121797403Sobrien __c = *(++__beg); 121897403Sobrien } 121997403Sobrien break; 122097403Sobrien case money_base::value: 122197403Sobrien // Extract digits, remove and stash away the 122297403Sobrien // grouping of found thousands separators. 122397403Sobrien while (__beg != __end 122497403Sobrien && (__ctype.is(ctype_base::digit, __c) 122597403Sobrien || (__c == __d && !__testdecfound) 122697403Sobrien || __c == __sep)) 122797403Sobrien { 122897403Sobrien if (__c == __d) 122997403Sobrien { 123097403Sobrien __grouping_tmp += static_cast<char>(__sep_pos); 123197403Sobrien __sep_pos = 0; 123297403Sobrien __testdecfound = true; 123397403Sobrien } 123497403Sobrien else if (__c == __sep) 123597403Sobrien { 123697403Sobrien if (__grouping.size()) 123797403Sobrien { 123897403Sobrien // Mark position for later analysis. 123997403Sobrien __grouping_tmp += static_cast<char>(__sep_pos); 124097403Sobrien __sep_pos = 0; 124197403Sobrien } 124297403Sobrien else 124397403Sobrien { 124497403Sobrien __testvalid = false; 124597403Sobrien break; 124697403Sobrien } 124797403Sobrien } 124897403Sobrien else 124997403Sobrien { 125097403Sobrien __temp_units += __c; 125197403Sobrien ++__sep_pos; 125297403Sobrien } 125397403Sobrien __c = *(++__beg); 125497403Sobrien } 125597403Sobrien break; 125697403Sobrien case money_base::space: 125797403Sobrien case money_base::none: 125897403Sobrien // Only if not at the end of the pattern. 125997403Sobrien if (__i != 3) 126097403Sobrien while (__beg != __end 126197403Sobrien && __ctype.is(ctype_base::space, __c)) 126297403Sobrien __c = *(++__beg); 126397403Sobrien break; 126497403Sobrien } 126597403Sobrien } 126697403Sobrien 126797403Sobrien // Need to get the rest of the sign characters, if they exist. 126897403Sobrien if (__sign.size() > 1) 126997403Sobrien { 127097403Sobrien size_type __len = __sign.size(); 127197403Sobrien size_type __i = 1; 127297403Sobrien for (; __c != __eof && __i < __len; ++__i) 127397403Sobrien while (__beg != __end && __c != __sign[__i]) 127497403Sobrien __c = *(++__beg); 127597403Sobrien 127697403Sobrien if (__i != __len) 127797403Sobrien __testvalid = false; 127897403Sobrien } 127997403Sobrien 128097403Sobrien // Strip leading zeros. 128197403Sobrien while (__temp_units[0] == __ctype.widen('0')) 128297403Sobrien __temp_units.erase(__temp_units.begin()); 128397403Sobrien 128497403Sobrien if (__sign.size() && __sign == __neg_sign) 128597403Sobrien __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); 128697403Sobrien 128797403Sobrien // Test for grouping fidelity. 128897403Sobrien if (__grouping.size() && __grouping_tmp.size()) 128997403Sobrien { 129097403Sobrien if (!__verify_grouping(__grouping, __grouping_tmp)) 129197403Sobrien __testvalid = false; 129297403Sobrien } 129397403Sobrien 129497403Sobrien // Iff no more characters are available. 129597403Sobrien if (__c == __eof) 129697403Sobrien __err |= ios_base::eofbit; 129797403Sobrien 129897403Sobrien // Iff valid sequence is not recognized. 129997403Sobrien if (!__testvalid || !__temp_units.size()) 130097403Sobrien __err |= ios_base::failbit; 130197403Sobrien else 130297403Sobrien // Use the "swap trick" to copy __temp_units into __units. 130397403Sobrien __temp_units.swap(__units); 130497403Sobrien 130597403Sobrien return __beg; 130697403Sobrien } 130797403Sobrien 130897403Sobrien template<typename _CharT, typename _OutIter> 130997403Sobrien _OutIter 131097403Sobrien money_put<_CharT, _OutIter>:: 131197403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 131297403Sobrien long double __units) const 131397403Sobrien { 131497403Sobrien const locale __loc = __io.getloc(); 131597403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 131697403Sobrien#ifdef _GLIBCPP_USE_C99 131797403Sobrien // First try a buffer perhaps big enough. 131897403Sobrien int __cs_size = 64; 131997403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 132097403Sobrien int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 132197403Sobrien _S_c_locale); 132297403Sobrien // If the buffer was not large enough, try again with the correct size. 132397403Sobrien if (__len >= __cs_size) 132497403Sobrien { 132597403Sobrien __cs_size = __len + 1; 132697403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 132797403Sobrien __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 132897403Sobrien _S_c_locale); 132997403Sobrien } 133097403Sobrien#else 133197403Sobrien // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, 133297403Sobrien // decimal digit, '\0'. 133397403Sobrien const int __cs_size = numeric_limits<long double>::max_exponent10 + 5; 133497403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 133597403Sobrien int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); 133697403Sobrien#endif 1337117397Skan _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1338117397Skan * __cs_size)); 133997403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 134097403Sobrien string_type __digits(__ws); 134197403Sobrien return this->do_put(__s, __intl, __io, __fill, __digits); 134297403Sobrien } 134397403Sobrien 134497403Sobrien template<typename _CharT, typename _OutIter> 134597403Sobrien _OutIter 134697403Sobrien money_put<_CharT, _OutIter>:: 134797403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 134897403Sobrien const string_type& __digits) const 134997403Sobrien { 135097403Sobrien typedef typename string_type::size_type size_type; 135197403Sobrien typedef money_base::part part; 135297403Sobrien 135397403Sobrien const locale __loc = __io.getloc(); 135497403Sobrien const size_type __width = static_cast<size_type>(__io.width()); 135597403Sobrien 135697403Sobrien // These contortions are quite unfortunate. 135797403Sobrien typedef moneypunct<_CharT, true> __money_true; 135897403Sobrien typedef moneypunct<_CharT, false> __money_false; 135997403Sobrien const __money_true& __mpt = use_facet<__money_true>(__loc); 136097403Sobrien const __money_false& __mpf = use_facet<__money_false>(__loc); 136197403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 136297403Sobrien 136397403Sobrien // Determine if negative or positive formats are to be used, and 136497403Sobrien // discard leading negative_sign if it is present. 136597403Sobrien const char_type* __beg = __digits.data(); 136697403Sobrien const char_type* __end = __beg + __digits.size(); 136797403Sobrien money_base::pattern __p; 136897403Sobrien string_type __sign; 136997403Sobrien if (*__beg != __ctype.widen('-')) 137097403Sobrien { 137197403Sobrien __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); 137297403Sobrien __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); 137397403Sobrien } 137497403Sobrien else 137597403Sobrien { 137697403Sobrien __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); 137797403Sobrien __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); 137897403Sobrien ++__beg; 137997403Sobrien } 138097403Sobrien 138197403Sobrien // Look for valid numbers in the current ctype facet within input digits. 138297403Sobrien __end = __ctype.scan_not(ctype_base::digit, __beg, __end); 138397403Sobrien if (__beg != __end) 138497403Sobrien { 138597403Sobrien // Assume valid input, and attempt to format. 138697403Sobrien // Break down input numbers into base components, as follows: 138797403Sobrien // final_value = grouped units + (decimal point) + (digits) 138897403Sobrien string_type __res; 138997403Sobrien string_type __value; 139097403Sobrien const string_type __symbol = __intl ? __mpt.curr_symbol() 139197403Sobrien : __mpf.curr_symbol(); 139297403Sobrien 139397403Sobrien // Deal with decimal point, decimal digits. 139497403Sobrien const int __frac = __intl ? __mpt.frac_digits() 139597403Sobrien : __mpf.frac_digits(); 139697403Sobrien if (__frac > 0) 139797403Sobrien { 139897403Sobrien const char_type __d = __intl ? __mpt.decimal_point() 139997403Sobrien : __mpf.decimal_point(); 140097403Sobrien if (__end - __beg >= __frac) 140197403Sobrien { 140297403Sobrien __value = string_type(__end - __frac, __end); 140397403Sobrien __value.insert(__value.begin(), __d); 140497403Sobrien __end -= __frac; 140597403Sobrien } 140697403Sobrien else 140797403Sobrien { 140897403Sobrien // Have to pad zeros in the decimal position. 140997403Sobrien __value = string_type(__beg, __end); 141097403Sobrien int __paddec = __frac - (__end - __beg); 141197403Sobrien char_type __zero = __ctype.widen('0'); 141297403Sobrien __value.insert(__value.begin(), __paddec, __zero); 141397403Sobrien __value.insert(__value.begin(), __d); 141497403Sobrien __beg = __end; 141597403Sobrien } 141697403Sobrien } 141797403Sobrien 141897403Sobrien // Add thousands separators to non-decimal digits, per 141997403Sobrien // grouping rules. 142097403Sobrien if (__beg != __end) 142197403Sobrien { 142297403Sobrien const string __grouping = __intl ? __mpt.grouping() 142397403Sobrien : __mpf.grouping(); 142497403Sobrien if (__grouping.size()) 142597403Sobrien { 142697403Sobrien const char_type __sep = __intl ? __mpt.thousands_sep() 142797403Sobrien : __mpf.thousands_sep(); 142897403Sobrien const char* __gbeg = __grouping.c_str(); 142997403Sobrien const char* __gend = __gbeg + __grouping.size(); 143097403Sobrien const int __n = (__end - __beg) * 2; 143197403Sobrien _CharT* __ws2 = 1432117397Skan static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); 143397403Sobrien _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 143497403Sobrien __gend, __beg, __end); 143597403Sobrien __value.insert(0, __ws2, __ws_end - __ws2); 143697403Sobrien } 143797403Sobrien else 143897403Sobrien __value.insert(0, string_type(__beg, __end)); 143997403Sobrien } 144097403Sobrien 144197403Sobrien // Calculate length of resulting string. 144297403Sobrien ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; 144397403Sobrien size_type __len = __value.size() + __sign.size(); 144497403Sobrien __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; 144597403Sobrien bool __testipad = __f == ios_base::internal && __len < __width; 144697403Sobrien 144797403Sobrien // Fit formatted digits into the required pattern. 144897403Sobrien for (int __i = 0; __i < 4; ++__i) 144997403Sobrien { 145097403Sobrien part __which = static_cast<part>(__p.field[__i]); 145197403Sobrien switch (__which) 145297403Sobrien { 145397403Sobrien case money_base::symbol: 145497403Sobrien if (__io.flags() & ios_base::showbase) 145597403Sobrien __res += __symbol; 145697403Sobrien break; 145797403Sobrien case money_base::sign: 145897403Sobrien // Sign might not exist, or be more than one 145997403Sobrien // charater long. In that case, add in the rest 146097403Sobrien // below. 146197403Sobrien if (__sign.size()) 146297403Sobrien __res += __sign[0]; 146397403Sobrien break; 146497403Sobrien case money_base::value: 146597403Sobrien __res += __value; 146697403Sobrien break; 146797403Sobrien case money_base::space: 146897403Sobrien // At least one space is required, but if internal 146997403Sobrien // formatting is required, an arbitrary number of 147097403Sobrien // fill spaces will be necessary. 147197403Sobrien if (__testipad) 147297403Sobrien __res += string_type(__width - __len, __fill); 147397403Sobrien else 147497403Sobrien __res += __ctype.widen(__fill); 147597403Sobrien break; 147697403Sobrien case money_base::none: 147797403Sobrien if (__testipad) 147897403Sobrien __res += string_type(__width - __len, __fill); 147997403Sobrien break; 148097403Sobrien } 148197403Sobrien } 148297403Sobrien 148397403Sobrien // Special case of multi-part sign parts. 148497403Sobrien if (__sign.size() > 1) 148597403Sobrien __res += string_type(__sign.begin() + 1, __sign.end()); 148697403Sobrien 148797403Sobrien // Pad, if still necessary. 148897403Sobrien __len = __res.size(); 148997403Sobrien if (__width > __len) 149097403Sobrien { 149197403Sobrien if (__f == ios_base::left) 149297403Sobrien // After. 149397403Sobrien __res.append(__width - __len, __fill); 149497403Sobrien else 149597403Sobrien // Before. 149697403Sobrien __res.insert(0, string_type(__width - __len, __fill)); 149797403Sobrien __len = __width; 149897403Sobrien } 149997403Sobrien 150097403Sobrien // Write resulting, fully-formatted string to output iterator. 1501117397Skan __s = __write(__s, __res.c_str(), __len); 150297403Sobrien } 150397403Sobrien __io.width(0); 150497403Sobrien return __s; 150597403Sobrien } 150697403Sobrien 150797403Sobrien 150897403Sobrien // NB: Not especially useful. Without an ios_base object or some 150997403Sobrien // kind of locale reference, we are left clawing at the air where 151097403Sobrien // the side of the mountain used to be... 151197403Sobrien template<typename _CharT, typename _InIter> 151297403Sobrien time_base::dateorder 151397403Sobrien time_get<_CharT, _InIter>::do_date_order() const 151497403Sobrien { return time_base::no_order; } 151597403Sobrien 151697403Sobrien template<typename _CharT, typename _InIter> 151797403Sobrien void 151897403Sobrien time_get<_CharT, _InIter>:: 151997403Sobrien _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, 152097403Sobrien ios_base::iostate& __err, tm* __tm, 152197403Sobrien const _CharT* __format) const 152297403Sobrien { 152397403Sobrien locale __loc = __io.getloc(); 152497403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 152597403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 152697403Sobrien size_t __len = char_traits<_CharT>::length(__format); 152797403Sobrien 152897403Sobrien for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 152997403Sobrien { 153097403Sobrien char __c = __format[__i]; 153197403Sobrien if (__c == '%') 153297403Sobrien { 153397403Sobrien // Verify valid formatting code, attempt to extract. 153497403Sobrien __c = __format[++__i]; 153597403Sobrien char __mod = 0; 153697403Sobrien int __mem = 0; 153797403Sobrien if (__c == 'E' || __c == 'O') 153897403Sobrien { 153997403Sobrien __mod = __c; 154097403Sobrien __c = __format[++__i]; 154197403Sobrien } 154297403Sobrien switch (__c) 154397403Sobrien { 154497403Sobrien const char* __cs; 154597403Sobrien _CharT __wcs[10]; 154697403Sobrien case 'a': 154797403Sobrien // Abbreviated weekday name [tm_wday] 154897403Sobrien const char_type* __days1[7]; 154997403Sobrien __tp._M_days_abbreviated(__days1); 155097403Sobrien _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 155197403Sobrien __err); 155297403Sobrien break; 155397403Sobrien case 'A': 155497403Sobrien // Weekday name [tm_wday]. 155597403Sobrien const char_type* __days2[7]; 155697403Sobrien __tp._M_days(__days2); 155797403Sobrien _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 155897403Sobrien __err); 155997403Sobrien break; 156097403Sobrien case 'h': 156197403Sobrien case 'b': 156297403Sobrien // Abbreviated month name [tm_mon] 156397403Sobrien const char_type* __months1[12]; 156497403Sobrien __tp._M_months_abbreviated(__months1); 156597403Sobrien _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 156697403Sobrien __err); 156797403Sobrien break; 156897403Sobrien case 'B': 156997403Sobrien // Month name [tm_mon]. 157097403Sobrien const char_type* __months2[12]; 157197403Sobrien __tp._M_months(__months2); 157297403Sobrien _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 157397403Sobrien __err); 157497403Sobrien break; 157597403Sobrien case 'c': 157697403Sobrien // Default time and date representation. 157797403Sobrien const char_type* __dt[2]; 157897403Sobrien __tp._M_date_time_formats(__dt); 157997403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 158097403Sobrien __dt[0]); 158197403Sobrien break; 158297403Sobrien case 'd': 158397403Sobrien // Day [01, 31]. [tm_mday] 158497403Sobrien _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 158597403Sobrien __ctype, __err); 158697403Sobrien break; 158797403Sobrien case 'D': 158897403Sobrien // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 158997403Sobrien __cs = "%m/%d/%y"; 159097403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 159197403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 159297403Sobrien __wcs); 159397403Sobrien break; 159497403Sobrien case 'H': 159597403Sobrien // Hour [00, 23]. [tm_hour] 159697403Sobrien _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 159797403Sobrien __ctype, __err); 159897403Sobrien break; 159997403Sobrien case 'I': 160097403Sobrien // Hour [01, 12]. [tm_hour] 160197403Sobrien _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 160297403Sobrien __ctype, __err); 160397403Sobrien break; 160497403Sobrien case 'm': 160597403Sobrien // Month [01, 12]. [tm_mon] 160697403Sobrien _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 160797403Sobrien __err); 160897403Sobrien if (!__err) 160997403Sobrien __tm->tm_mon = __mem - 1; 161097403Sobrien break; 161197403Sobrien case 'M': 161297403Sobrien // Minute [00, 59]. [tm_min] 161397403Sobrien _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 161497403Sobrien __ctype, __err); 161597403Sobrien break; 161697403Sobrien case 'n': 161797403Sobrien if (__ctype.narrow(*__beg, 0) == '\n') 161897403Sobrien ++__beg; 161997403Sobrien else 162097403Sobrien __err |= ios_base::failbit; 162197403Sobrien break; 162297403Sobrien case 'R': 162397403Sobrien // Equivalent to (%H:%M). 162497403Sobrien __cs = "%H:%M"; 162597403Sobrien __ctype.widen(__cs, __cs + 6, __wcs); 162697403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 162797403Sobrien __wcs); 162897403Sobrien break; 162997403Sobrien case 'S': 163097403Sobrien // Seconds. 163197403Sobrien _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 163297403Sobrien __ctype, __err); 163397403Sobrien break; 163497403Sobrien case 't': 163597403Sobrien if (__ctype.narrow(*__beg, 0) == '\t') 163697403Sobrien ++__beg; 163797403Sobrien else 163897403Sobrien __err |= ios_base::failbit; 163997403Sobrien break; 164097403Sobrien case 'T': 164197403Sobrien // Equivalent to (%H:%M:%S). 164297403Sobrien __cs = "%H:%M:%S"; 164397403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 164497403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 164597403Sobrien __wcs); 164697403Sobrien break; 164797403Sobrien case 'x': 164897403Sobrien // Locale's date. 164997403Sobrien const char_type* __dates[2]; 165097403Sobrien __tp._M_date_formats(__dates); 165197403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 165297403Sobrien __dates[0]); 165397403Sobrien break; 165497403Sobrien case 'X': 165597403Sobrien // Locale's time. 165697403Sobrien const char_type* __times[2]; 165797403Sobrien __tp._M_time_formats(__times); 165897403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 165997403Sobrien __times[0]); 166097403Sobrien break; 166197403Sobrien case 'y': 166297403Sobrien // Two digit year. [tm_year] 166397403Sobrien _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 166497403Sobrien __ctype, __err); 166597403Sobrien break; 166697403Sobrien case 'Y': 166797403Sobrien // Year [1900). [tm_year] 166897403Sobrien _M_extract_num(__beg, __end, __mem, 0, 166997403Sobrien numeric_limits<int>::max(), 4, 167097403Sobrien __ctype, __err); 167197403Sobrien if (!__err) 167297403Sobrien __tm->tm_year = __mem - 1900; 167397403Sobrien break; 167497403Sobrien case 'Z': 167597403Sobrien // Timezone info. 167697403Sobrien if (__ctype.is(ctype_base::upper, *__beg)) 167797403Sobrien { 167897403Sobrien int __tmp; 167997403Sobrien _M_extract_name(__beg, __end, __tmp, 168097403Sobrien __timepunct<_CharT>::_S_timezones, 168197403Sobrien 14, __err); 168297403Sobrien 168397403Sobrien // GMT requires special effort. 168497403Sobrien char_type __c = *__beg; 168597403Sobrien if (!__err && __tmp == 0 168697403Sobrien && (__c == __ctype.widen('-') 168797403Sobrien || __c == __ctype.widen('+'))) 168897403Sobrien { 168997403Sobrien _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 169097403Sobrien __ctype, __err); 169197403Sobrien _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 169297403Sobrien __ctype, __err); 169397403Sobrien } 169497403Sobrien } 169597403Sobrien else 169697403Sobrien __err |= ios_base::failbit; 169797403Sobrien break; 169897403Sobrien default: 169997403Sobrien // Not recognized. 170097403Sobrien __err |= ios_base::failbit; 170197403Sobrien } 170297403Sobrien } 170397403Sobrien else 170497403Sobrien { 170597403Sobrien // Verify format and input match, extract and discard. 170697403Sobrien if (__c == __ctype.narrow(*__beg, 0)) 170797403Sobrien ++__beg; 170897403Sobrien else 170997403Sobrien __err |= ios_base::failbit; 171097403Sobrien } 171197403Sobrien } 171297403Sobrien } 171397403Sobrien 171497403Sobrien template<typename _CharT, typename _InIter> 171597403Sobrien void 171697403Sobrien time_get<_CharT, _InIter>:: 171797403Sobrien _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, 171897403Sobrien int __min, int __max, size_t __len, 171997403Sobrien const ctype<_CharT>& __ctype, 172097403Sobrien ios_base::iostate& __err) const 172197403Sobrien { 172297403Sobrien size_t __i = 0; 172397403Sobrien string __digits; 172497403Sobrien bool __testvalid = true; 172597403Sobrien char_type __c = *__beg; 172697403Sobrien while (__beg != __end && __i < __len 172797403Sobrien && __ctype.is(ctype_base::digit, __c)) 172897403Sobrien { 172997403Sobrien __digits += __ctype.narrow(__c, 0); 173097403Sobrien __c = *(++__beg); 173197403Sobrien ++__i; 173297403Sobrien } 173397403Sobrien if (__i == __len) 173497403Sobrien { 173597403Sobrien int __value = atoi(__digits.c_str()); 173697403Sobrien if (__min <= __value && __value <= __max) 173797403Sobrien __member = __value; 173897403Sobrien else 173997403Sobrien __testvalid = false; 174097403Sobrien } 174197403Sobrien else 174297403Sobrien __testvalid = false; 174397403Sobrien if (!__testvalid) 174497403Sobrien __err |= ios_base::failbit; 174597403Sobrien } 174697403Sobrien 174797403Sobrien // Assumptions: 174897403Sobrien // All elements in __names are unique. 174997403Sobrien template<typename _CharT, typename _InIter> 175097403Sobrien void 175197403Sobrien time_get<_CharT, _InIter>:: 175297403Sobrien _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, 175397403Sobrien const _CharT** __names, size_t __indexlen, 175497403Sobrien ios_base::iostate& __err) const 175597403Sobrien { 1756102782Skan typedef char_traits<_CharT> __traits_type; 1757117397Skan int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 1758117397Skan * __indexlen)); 175997403Sobrien size_t __nmatches = 0; 176097403Sobrien size_t __pos = 0; 176197403Sobrien bool __testvalid = true; 176297403Sobrien const char_type* __name; 176397403Sobrien 176497403Sobrien char_type __c = *__beg; 176597403Sobrien // Look for initial matches. 176697403Sobrien for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 176797403Sobrien if (__c == __names[__i1][0]) 176897403Sobrien __matches[__nmatches++] = __i1; 176997403Sobrien 1770117397Skan while (__nmatches > 1) 177197403Sobrien { 177297403Sobrien // Find smallest matching string. 177397403Sobrien size_t __minlen = 10; 177497403Sobrien for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 1775110614Skan __minlen = min(__minlen, 177697403Sobrien __traits_type::length(__names[__matches[__i2]])); 177797403Sobrien 177897403Sobrien if (__pos < __minlen && __beg != __end) 177997403Sobrien { 178097403Sobrien ++__pos; 178197403Sobrien __c = *(++__beg); 178297403Sobrien for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 178397403Sobrien { 178497403Sobrien __name = __names[__matches[__i3]]; 178597403Sobrien if (__name[__pos] != __c) 178697403Sobrien __matches[__i3] = __matches[--__nmatches]; 178797403Sobrien } 178897403Sobrien } 178997403Sobrien else 179097403Sobrien break; 179197403Sobrien } 179297403Sobrien 179397403Sobrien if (__nmatches == 1) 179497403Sobrien { 179597403Sobrien // Make sure found name is completely extracted. 179697403Sobrien __name = __names[__matches[0]]; 179797403Sobrien const size_t __len = __traits_type::length(__name); 179897403Sobrien while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 179997403Sobrien ++__beg, ++__pos; 180097403Sobrien 180197403Sobrien if (__len == __pos) 180297403Sobrien __member = __matches[0]; 180397403Sobrien else 180497403Sobrien __testvalid = false; 180597403Sobrien } 180697403Sobrien else 180797403Sobrien __testvalid = false; 180897403Sobrien if (!__testvalid) 180997403Sobrien __err |= ios_base::failbit; 181097403Sobrien } 181197403Sobrien 181297403Sobrien template<typename _CharT, typename _InIter> 181397403Sobrien _InIter 181497403Sobrien time_get<_CharT, _InIter>:: 181597403Sobrien do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 181697403Sobrien ios_base::iostate& __err, tm* __tm) const 181797403Sobrien { 181897403Sobrien _CharT __wcs[3]; 181997403Sobrien const char* __cs = "%X"; 182097403Sobrien locale __loc = __io.getloc(); 182197403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 182297403Sobrien __ctype.widen(__cs, __cs + 3, __wcs); 182397403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 182497403Sobrien if (__beg == __end) 182597403Sobrien __err |= ios_base::eofbit; 182697403Sobrien return __beg; 182797403Sobrien } 182897403Sobrien 182997403Sobrien template<typename _CharT, typename _InIter> 183097403Sobrien _InIter 183197403Sobrien time_get<_CharT, _InIter>:: 183297403Sobrien do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 183397403Sobrien ios_base::iostate& __err, tm* __tm) const 183497403Sobrien { 183597403Sobrien _CharT __wcs[3]; 183697403Sobrien const char* __cs = "%x"; 183797403Sobrien locale __loc = __io.getloc(); 183897403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 183997403Sobrien __ctype.widen(__cs, __cs + 3, __wcs); 184097403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 184197403Sobrien if (__beg == __end) 184297403Sobrien __err |= ios_base::eofbit; 184397403Sobrien return __beg; 184497403Sobrien } 184597403Sobrien 184697403Sobrien template<typename _CharT, typename _InIter> 184797403Sobrien _InIter 184897403Sobrien time_get<_CharT, _InIter>:: 184997403Sobrien do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 185097403Sobrien ios_base::iostate& __err, tm* __tm) const 185197403Sobrien { 1852102782Skan typedef char_traits<_CharT> __traits_type; 185397403Sobrien locale __loc = __io.getloc(); 185497403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 185597403Sobrien const char_type* __days[7]; 185697403Sobrien __tp._M_days_abbreviated(__days); 185797403Sobrien int __tmpwday; 185897403Sobrien _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); 185997403Sobrien 186097403Sobrien // Check to see if non-abbreviated name exists, and extract. 186197403Sobrien // NB: Assumes both _M_days and _M_days_abbreviated organized in 186297403Sobrien // exact same order, first to last, such that the resulting 186397403Sobrien // __days array with the same index points to a day, and that 186497403Sobrien // day's abbreviated form. 186597403Sobrien // NB: Also assumes that an abbreviated name is a subset of the name. 186697403Sobrien if (!__err) 186797403Sobrien { 186897403Sobrien size_t __pos = __traits_type::length(__days[__tmpwday]); 186997403Sobrien __tp._M_days(__days); 187097403Sobrien const char_type* __name = __days[__tmpwday]; 187197403Sobrien if (__name[__pos] == *__beg) 187297403Sobrien { 187397403Sobrien // Extract the rest of it. 187497403Sobrien const size_t __len = __traits_type::length(__name); 187597403Sobrien while (__pos < __len && __beg != __end 187697403Sobrien && __name[__pos] == *__beg) 187797403Sobrien ++__beg, ++__pos; 187897403Sobrien if (__len != __pos) 187997403Sobrien __err |= ios_base::failbit; 188097403Sobrien } 188197403Sobrien if (!__err) 188297403Sobrien __tm->tm_wday = __tmpwday; 188397403Sobrien } 188497403Sobrien if (__beg == __end) 188597403Sobrien __err |= ios_base::eofbit; 188697403Sobrien return __beg; 188797403Sobrien } 188897403Sobrien 188997403Sobrien template<typename _CharT, typename _InIter> 189097403Sobrien _InIter 189197403Sobrien time_get<_CharT, _InIter>:: 189297403Sobrien do_get_monthname(iter_type __beg, iter_type __end, 189397403Sobrien ios_base& __io, ios_base::iostate& __err, tm* __tm) const 189497403Sobrien { 1895102782Skan typedef char_traits<_CharT> __traits_type; 189697403Sobrien locale __loc = __io.getloc(); 189797403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 189897403Sobrien const char_type* __months[12]; 189997403Sobrien __tp._M_months_abbreviated(__months); 190097403Sobrien int __tmpmon; 190197403Sobrien _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); 190297403Sobrien 190397403Sobrien // Check to see if non-abbreviated name exists, and extract. 190497403Sobrien // NB: Assumes both _M_months and _M_months_abbreviated organized in 190597403Sobrien // exact same order, first to last, such that the resulting 190697403Sobrien // __months array with the same index points to a month, and that 190797403Sobrien // month's abbreviated form. 190897403Sobrien // NB: Also assumes that an abbreviated name is a subset of the name. 190997403Sobrien if (!__err) 191097403Sobrien { 191197403Sobrien size_t __pos = __traits_type::length(__months[__tmpmon]); 191297403Sobrien __tp._M_months(__months); 191397403Sobrien const char_type* __name = __months[__tmpmon]; 191497403Sobrien if (__name[__pos] == *__beg) 191597403Sobrien { 191697403Sobrien // Extract the rest of it. 191797403Sobrien const size_t __len = __traits_type::length(__name); 191897403Sobrien while (__pos < __len && __beg != __end 191997403Sobrien && __name[__pos] == *__beg) 192097403Sobrien ++__beg, ++__pos; 192197403Sobrien if (__len != __pos) 192297403Sobrien __err |= ios_base::failbit; 192397403Sobrien } 192497403Sobrien if (!__err) 192597403Sobrien __tm->tm_mon = __tmpmon; 192697403Sobrien } 192797403Sobrien 192897403Sobrien if (__beg == __end) 192997403Sobrien __err |= ios_base::eofbit; 193097403Sobrien return __beg; 193197403Sobrien } 193297403Sobrien 193397403Sobrien template<typename _CharT, typename _InIter> 193497403Sobrien _InIter 193597403Sobrien time_get<_CharT, _InIter>:: 193697403Sobrien do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 193797403Sobrien ios_base::iostate& __err, tm* __tm) const 193897403Sobrien { 193997403Sobrien locale __loc = __io.getloc(); 194097403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 194197403Sobrien 194297403Sobrien char_type __c = *__beg; 194397403Sobrien size_t __i = 0; 194497403Sobrien string __digits; 194597403Sobrien while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) 194697403Sobrien { 194797403Sobrien __digits += __ctype.narrow(__c, 0); 194897403Sobrien __c = *(++__beg); 194997403Sobrien ++__i; 195097403Sobrien } 195197403Sobrien if (__i == 2 || __i == 4) 195297403Sobrien { 195397403Sobrien long __l; 195497403Sobrien __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); 195597403Sobrien if (!(__err & ios_base::failbit) && __l <= INT_MAX) 195697403Sobrien { 195797403Sobrien __l = __i == 2 ? __l : __l - 1900; 195897403Sobrien __tm->tm_year = static_cast<int>(__l); 195997403Sobrien } 196097403Sobrien } 196197403Sobrien else 196297403Sobrien __err |= ios_base::failbit; 196397403Sobrien if (__beg == __end) 196497403Sobrien __err |= ios_base::eofbit; 196597403Sobrien return __beg; 196697403Sobrien } 196797403Sobrien 196897403Sobrien template<typename _CharT, typename _OutIter> 196997403Sobrien _OutIter 197097403Sobrien time_put<_CharT, _OutIter>:: 197197403Sobrien put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 197297403Sobrien const _CharT* __beg, const _CharT* __end) const 197397403Sobrien { 197497403Sobrien locale __loc = __io.getloc(); 197597403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 197697403Sobrien while (__beg != __end) 197797403Sobrien { 197897403Sobrien char __c = __ctype.narrow(*__beg, 0); 197997403Sobrien ++__beg; 198097403Sobrien if (__c == '%') 198197403Sobrien { 198297403Sobrien char __format; 198397403Sobrien char __mod = 0; 198497403Sobrien size_t __len = 1; 198597403Sobrien __c = __ctype.narrow(*__beg, 0); 198697403Sobrien ++__beg; 198797403Sobrien if (__c == 'E' || __c == 'O') 198897403Sobrien { 198997403Sobrien __mod = __c; 199097403Sobrien __format = __ctype.narrow(*__beg, 0); 199197403Sobrien ++__beg; 199297403Sobrien } 199397403Sobrien else 199497403Sobrien __format = __c; 1995117397Skan __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod); 199697403Sobrien } 199797403Sobrien else 199897403Sobrien { 199997403Sobrien *__s = __c; 200097403Sobrien ++__s; 200197403Sobrien } 200297403Sobrien } 200397403Sobrien return __s; 200497403Sobrien } 200597403Sobrien 200697403Sobrien template<typename _CharT, typename _OutIter> 200797403Sobrien _OutIter 200897403Sobrien time_put<_CharT, _OutIter>:: 200997403Sobrien do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 201097403Sobrien char __format, char __mod) const 201197403Sobrien { 201297403Sobrien locale __loc = __io.getloc(); 201397403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 201497403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 201597403Sobrien 201697403Sobrien // NB: This size is arbitrary. Should this be a data member, 201797403Sobrien // initialized at construction? 201897403Sobrien const size_t __maxlen = 64; 2019117397Skan char_type* __res = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 202097403Sobrien 202197403Sobrien // NB: In IEE 1003.1-200x, and perhaps other locale models, it 202297403Sobrien // is possible that the format character will be longer than one 202397403Sobrien // character. Possibilities include 'E' or 'O' followed by a 202497403Sobrien // format character: if __mod is not the default argument, assume 202597403Sobrien // it's a valid modifier. 202697403Sobrien char_type __fmt[4]; 202797403Sobrien __fmt[0] = __ctype.widen('%'); 202897403Sobrien if (!__mod) 202997403Sobrien { 203097403Sobrien __fmt[1] = __format; 203197403Sobrien __fmt[2] = char_type(); 203297403Sobrien } 203397403Sobrien else 203497403Sobrien { 203597403Sobrien __fmt[1] = __mod; 203697403Sobrien __fmt[2] = __format; 203797403Sobrien __fmt[3] = char_type(); 203897403Sobrien } 203997403Sobrien 204097403Sobrien __tp._M_put(__res, __maxlen, __fmt, __tm); 204197403Sobrien 204297403Sobrien // Write resulting, fully-formatted string to output iterator. 2043117397Skan return __write(__s, __res, char_traits<char_type>::length(__res)); 204497403Sobrien } 204597403Sobrien 204697403Sobrien 204797403Sobrien // Generic version does nothing. 204897403Sobrien template<typename _CharT> 204997403Sobrien int 205097403Sobrien collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 205197403Sobrien { return 0; } 205297403Sobrien 205397403Sobrien // Generic version does nothing. 205497403Sobrien template<typename _CharT> 205597403Sobrien size_t 205697403Sobrien collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 205797403Sobrien { return 0; } 205897403Sobrien 205997403Sobrien template<typename _CharT> 206097403Sobrien int 206197403Sobrien collate<_CharT>:: 206297403Sobrien do_compare(const _CharT* __lo1, const _CharT* __hi1, 206397403Sobrien const _CharT* __lo2, const _CharT* __hi2) const 206497403Sobrien { 2065117397Skan // strcoll assumes zero-terminated strings so we make a copy 2066117397Skan // and then put a zero at the end. 206797403Sobrien const string_type __one(__lo1, __hi1); 206897403Sobrien const string_type __two(__lo2, __hi2); 2069117397Skan 2070117397Skan const _CharT* __p = __one.c_str(); 2071117397Skan const _CharT* __pend = __one.c_str() + __one.length(); 2072117397Skan const _CharT* __q = __two.c_str(); 2073117397Skan const _CharT* __qend = __two.c_str() + __two.length(); 2074117397Skan 2075117397Skan // strcoll stops when it sees a nul character so we break 2076117397Skan // the strings into zero-terminated substrings and pass those 2077117397Skan // to strcoll. 2078117397Skan for (;;) 2079117397Skan { 2080117397Skan int __res = _M_compare(__p, __q); 2081117397Skan if (__res) 2082117397Skan return __res; 2083117397Skan 2084117397Skan __p += char_traits<_CharT>::length(__p); 2085117397Skan __q += char_traits<_CharT>::length(__q); 2086117397Skan if (__p == __pend && __q == __qend) 2087117397Skan return 0; 2088117397Skan else if (__p == __pend) 2089117397Skan return -1; 2090117397Skan else if (__q == __qend) 2091117397Skan return 1; 2092117397Skan 2093117397Skan __p++; 2094117397Skan __q++; 2095117397Skan } 209697403Sobrien } 209797403Sobrien 209897403Sobrien template<typename _CharT> 209997403Sobrien typename collate<_CharT>::string_type 210097403Sobrien collate<_CharT>:: 210197403Sobrien do_transform(const _CharT* __lo, const _CharT* __hi) const 210297403Sobrien { 2103117397Skan // strxfrm assumes zero-terminated strings so we make a copy 2104117397Skan string_type __str(__lo, __hi); 2105117397Skan 2106117397Skan const _CharT* __p = __str.c_str(); 2107117397Skan const _CharT* __pend = __str.c_str() + __str.length(); 2108117397Skan 210997403Sobrien size_t __len = (__hi - __lo) * 2; 2110117397Skan 2111117397Skan string_type __ret; 2112117397Skan 2113117397Skan // strxfrm stops when it sees a nul character so we break 2114117397Skan // the string into zero-terminated substrings and pass those 2115117397Skan // to strxfrm. 2116117397Skan for (;;) 211797403Sobrien { 2118117397Skan // First try a buffer perhaps big enough. 2119117397Skan _CharT* __c = 2120117397Skan static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 2121117397Skan size_t __res = _M_transform(__c, __p, __len); 2122117397Skan // If the buffer was not large enough, try again with the 2123117397Skan // correct size. 2124117397Skan if (__res >= __len) 2125117397Skan { 2126117397Skan __len = __res + 1; 2127117397Skan __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2128117397Skan * __len)); 2129117397Skan __res = _M_transform(__c, __p, __res + 1); 2130117397Skan } 2131117397Skan 2132117397Skan __ret.append(__c, __res); 2133117397Skan __p += char_traits<_CharT>::length(__p); 2134117397Skan if (__p == __pend) 2135117397Skan return __ret; 2136117397Skan 2137117397Skan __p++; 2138117397Skan __ret.push_back(_CharT()); 213997403Sobrien } 214097403Sobrien } 214197403Sobrien 214297403Sobrien template<typename _CharT> 214397403Sobrien long 214497403Sobrien collate<_CharT>:: 214597403Sobrien do_hash(const _CharT* __lo, const _CharT* __hi) const 214697403Sobrien { 214797403Sobrien unsigned long __val = 0; 214897403Sobrien for (; __lo < __hi; ++__lo) 214997403Sobrien __val = *__lo + ((__val << 7) | 215097403Sobrien (__val >> (numeric_limits<unsigned long>::digits - 7))); 215197403Sobrien return static_cast<long>(__val); 215297403Sobrien } 215397403Sobrien 215497403Sobrien // Construct correctly padded string, as per 22.2.2.2.2 215597403Sobrien // Assumes 215697403Sobrien // __newlen > __oldlen 215797403Sobrien // __news is allocated for __newlen size 215897403Sobrien // Used by both num_put and ostream inserters: if __num, 215997403Sobrien // internal-adjusted objects are padded according to the rules below 216097403Sobrien // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 216197403Sobrien // ones are. 2162102782Skan 2163102782Skan // NB: Of the two parameters, _CharT can be deduced from the 2164102782Skan // function arguments. The other (_Traits) has to be explicitly specified. 216597403Sobrien template<typename _CharT, typename _Traits> 2166102782Skan void 2167102782Skan __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2168102782Skan _CharT* __news, const _CharT* __olds, 2169102782Skan const streamsize __newlen, 2170102782Skan const streamsize __oldlen, const bool __num) 2171102782Skan { 2172102782Skan size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2173117397Skan _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2174117397Skan * __plen)); 2175102782Skan _Traits::assign(__pads, __plen, __fill); 2176102782Skan 2177102782Skan _CharT* __beg; 2178102782Skan _CharT* __end; 217997403Sobrien size_t __mod = 0; 218097403Sobrien size_t __beglen; //either __plen or __oldlen 218197403Sobrien ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 218297403Sobrien 218397403Sobrien if (__adjust == ios_base::left) 218497403Sobrien { 218597403Sobrien // Padding last. 2186102782Skan __beg = const_cast<_CharT*>(__olds); 218797403Sobrien __beglen = __oldlen; 218897403Sobrien __end = __pads; 218997403Sobrien } 219097403Sobrien else if (__adjust == ios_base::internal && __num) 219197403Sobrien { 219297403Sobrien // Pad after the sign, if there is one. 219397403Sobrien // Pad after 0[xX], if there is one. 219497403Sobrien // Who came up with these rules, anyway? Jeeze. 219597403Sobrien locale __loc = __io.getloc(); 219697403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2197102782Skan const _CharT __minus = __ctype.widen('-'); 2198102782Skan const _CharT __plus = __ctype.widen('+'); 2199102782Skan bool __testsign = _Traits::eq(__olds[0], __minus) 2200102782Skan || _Traits::eq(__olds[0], __plus); 2201102782Skan 2202102782Skan bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 2203102782Skan && (_Traits::eq(__ctype.widen('x'), __olds[1]) 2204102782Skan || _Traits::eq(__ctype.widen('X'), __olds[1])); 220597403Sobrien if (__testhex) 220697403Sobrien { 220797403Sobrien __news[0] = __olds[0]; 220897403Sobrien __news[1] = __olds[1]; 220997403Sobrien __mod += 2; 221097403Sobrien __news += 2; 221197403Sobrien __beg = __pads; 221297403Sobrien __beglen = __plen; 2213102782Skan __end = const_cast<_CharT*>(__olds + __mod); 221497403Sobrien } 221597403Sobrien else if (__testsign) 221697403Sobrien { 2217102782Skan _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; 221897403Sobrien ++__mod; 221997403Sobrien ++__news; 222097403Sobrien __beg = __pads; 222197403Sobrien __beglen = __plen; 2222102782Skan __end = const_cast<_CharT*>(__olds + __mod); 222397403Sobrien } 222497403Sobrien else 222597403Sobrien { 222697403Sobrien // Padding first. 222797403Sobrien __beg = __pads; 222897403Sobrien __beglen = __plen; 2229102782Skan __end = const_cast<_CharT*>(__olds); 223097403Sobrien } 223197403Sobrien } 223297403Sobrien else 223397403Sobrien { 223497403Sobrien // Padding first. 223597403Sobrien __beg = __pads; 223697403Sobrien __beglen = __plen; 2237102782Skan __end = const_cast<_CharT*>(__olds); 223897403Sobrien } 2239102782Skan _Traits::copy(__news, __beg, __beglen); 2240102782Skan _Traits::copy(__news + __beglen, __end, 2241102782Skan __newlen - __beglen - __mod); 224297403Sobrien } 224397403Sobrien 224497403Sobrien template<typename _CharT> 224597403Sobrien bool 224697403Sobrien __verify_grouping(const basic_string<_CharT>& __grouping, 224797403Sobrien basic_string<_CharT>& __grouping_tmp) 224897403Sobrien { 224997403Sobrien int __i = 0; 225097403Sobrien int __j = 0; 225197403Sobrien const int __len = __grouping.size(); 225297403Sobrien const int __n = __grouping_tmp.size(); 225397403Sobrien bool __test = true; 225497403Sobrien 225597403Sobrien // Parsed number groupings have to match the 225697403Sobrien // numpunct::grouping string exactly, starting at the 225797403Sobrien // right-most point of the parsed sequence of elements ... 225897403Sobrien while (__test && __i < __n - 1) 225997403Sobrien for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) 226097403Sobrien __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; 226197403Sobrien // ... but the last parsed grouping can be <= numpunct 226297403Sobrien // grouping. 226397403Sobrien __j == __len ? __j = 0 : __j; 226497403Sobrien __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; 226597403Sobrien return __test; 226697403Sobrien } 226797403Sobrien 226897403Sobrien template<typename _CharT> 226997403Sobrien _CharT* 227097403Sobrien __add_grouping(_CharT* __s, _CharT __sep, 227197403Sobrien const char* __gbeg, const char* __gend, 227297403Sobrien const _CharT* __first, const _CharT* __last) 227397403Sobrien { 227497403Sobrien if (__last - __first > *__gbeg) 227597403Sobrien { 227697403Sobrien __s = __add_grouping(__s, __sep, 227797403Sobrien (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), 227897403Sobrien __gend, __first, __last - *__gbeg); 227997403Sobrien __first = __last - *__gbeg; 228097403Sobrien *__s++ = __sep; 228197403Sobrien } 228297403Sobrien do 228397403Sobrien *__s++ = *__first++; 228497403Sobrien while (__first != __last); 228597403Sobrien return __s; 228697403Sobrien } 228797403Sobrien 2288117397Skan#if 1 2289117397Skan // XXX GLIBCXX_ABI Deprecated, compatibility only. 2290117397Skan template<typename _CharT, typename _OutIter> 2291117397Skan template<typename _ValueT> 2292117397Skan _OutIter 2293117397Skan num_put<_CharT, _OutIter>:: 2294117397Skan _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 2295117397Skan char __modl, _ValueT __v) const 2296117397Skan { 2297117397Skan // [22.2.2.2.2] Stage 1, numeric conversion to character. 2298117397Skan 2299117397Skan // Long enough for the max format spec. 2300117397Skan char __fbuf[16]; 2301117397Skan _S_format_int(__io, __fbuf, __mod, __modl); 2302117397Skan#ifdef _GLIBCPP_USE_C99 2303117397Skan // First try a buffer perhaps big enough. 2304117397Skan int __cs_size = 64; 2305117397Skan char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 2306117397Skan int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 2307117397Skan _S_c_locale); 2308117397Skan // If the buffer was not large enough, try again with the correct size. 2309117397Skan if (__len >= __cs_size) 2310117397Skan { 2311117397Skan __cs_size = __len + 1; 2312117397Skan __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 2313117397Skan __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 2314117397Skan _S_c_locale); 2315117397Skan } 2316117397Skan#else 2317117397Skan // Leave room for "+/-," "0x," and commas. This size is 2318117397Skan // arbitrary, but should be largely sufficient. 2319117397Skan char __cs[128]; 2320117397Skan int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 2321117397Skan#endif 2322117397Skan return _M_widen_int(__s, __io, __fill, __cs, __len); 2323117397Skan } 2324117397Skan 2325117397Skan template<typename _CharT, typename _OutIter> 2326117397Skan _OutIter 2327117397Skan num_put<_CharT, _OutIter>:: 2328117397Skan _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 2329117397Skan int __len) const 2330117397Skan { 2331117397Skan typedef char_traits<_CharT> __traits_type; 2332117397Skan // [22.2.2.2.2] Stage 2, convert to char_type, using correct 2333117397Skan // numpunct.decimal_point() values for '.' and adding grouping. 2334117397Skan const locale __loc = __io.getloc(); 2335117397Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2336117397Skan _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2337117397Skan * __len)); 2338117397Skan // Grouping can add (almost) as many separators as the number of 2339117397Skan // digits, but no more. 2340117397Skan _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2341117397Skan * __len * 2)); 2342117397Skan __ctype.widen(__cs, __cs + __len, __ws); 2343117397Skan 2344117397Skan // Replace decimal point. 2345117397Skan const _CharT* __p; 2346117397Skan const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2347117397Skan if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) 2348117397Skan __ws[__p - __ws] = __np.decimal_point(); 2349117397Skan 2350117397Skan#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 2351117397Skan//282. What types does numpunct grouping refer to? 2352117397Skan // Add grouping, if necessary. 2353117397Skan const string __grouping = __np.grouping(); 2354117397Skan if (__grouping.size()) 2355117397Skan { 2356117397Skan _CharT* __p2; 2357117397Skan int __declen = __p ? __p - __ws : __len; 2358117397Skan __p2 = __add_grouping(__ws2, __np.thousands_sep(), 2359117397Skan __grouping.c_str(), 2360117397Skan __grouping.c_str() + __grouping.size(), 2361117397Skan __ws, __ws + __declen); 2362117397Skan int __newlen = __p2 - __ws2; 2363117397Skan 2364117397Skan // Tack on decimal part. 2365117397Skan if (__p) 2366117397Skan { 2367117397Skan __traits_type::copy(__p2, __p, __len - __declen); 2368117397Skan __newlen += __len - __declen; 2369117397Skan } 2370117397Skan 2371117397Skan // Switch strings, establish correct new length. 2372117397Skan __ws = __ws2; 2373117397Skan __len = __newlen; 2374117397Skan } 2375117397Skan#endif 2376117397Skan return _M_insert(__s, __io, __fill, __ws, __len); 2377117397Skan } 2378117397Skan 2379117397Skan template<typename _CharT, typename _OutIter> 2380117397Skan _OutIter 2381117397Skan num_put<_CharT, _OutIter>:: 2382117397Skan _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 2383117397Skan int __len) const 2384117397Skan { 2385117397Skan // [22.2.2.2.2] Stage 2, convert to char_type, using correct 2386117397Skan // numpunct.decimal_point() values for '.' and adding grouping. 2387117397Skan const locale __loc = __io.getloc(); 2388117397Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2389117397Skan _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2390117397Skan * __len)); 2391117397Skan // Grouping can add (almost) as many separators as the number of 2392117397Skan // digits, but no more. 2393117397Skan _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2394117397Skan * __len * 2)); 2395117397Skan __ctype.widen(__cs, __cs + __len, __ws); 2396117397Skan 2397117397Skan // Add grouping, if necessary. 2398117397Skan const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2399117397Skan const string __grouping = __np.grouping(); 2400117397Skan if (__grouping.size()) 2401117397Skan { 2402117397Skan // By itself __add_grouping cannot deal correctly with __ws when 2403117397Skan // ios::showbase is set and ios_base::oct || ios_base::hex. 2404117397Skan // Therefore we take care "by hand" of the initial 0, 0x or 0X. 2405117397Skan // However, remember that the latter do not occur if the number 2406117397Skan // printed is '0' (__len == 1). 2407117397Skan streamsize __off = 0; 2408117397Skan const ios_base::fmtflags __basefield = __io.flags() 2409117397Skan & ios_base::basefield; 2410117397Skan if ((__io.flags() & ios_base::showbase) && __len > 1) 2411117397Skan if (__basefield == ios_base::oct) 2412117397Skan { 2413117397Skan __off = 1; 2414117397Skan *__ws2 = *__ws; 2415117397Skan } 2416117397Skan else if (__basefield == ios_base::hex) 2417117397Skan { 2418117397Skan __off = 2; 2419117397Skan *__ws2 = *__ws; 2420117397Skan *(__ws2 + 1) = *(__ws + 1); 2421117397Skan } 2422117397Skan _CharT* __p; 2423117397Skan __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 2424117397Skan __grouping.c_str(), 2425117397Skan __grouping.c_str() + __grouping.size(), 2426117397Skan __ws + __off, __ws + __len); 2427117397Skan __len = __p - __ws2; 2428117397Skan // Switch strings. 2429117397Skan __ws = __ws2; 2430117397Skan } 2431117397Skan return _M_insert(__s, __io, __fill, __ws, __len); 2432117397Skan } 2433117397Skan 2434117397Skan // For use by integer and floating-point types after they have been 2435117397Skan // converted into a char_type string. 2436117397Skan template<typename _CharT, typename _OutIter> 2437117397Skan _OutIter 2438117397Skan num_put<_CharT, _OutIter>:: 2439117397Skan _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 2440117397Skan int __len) const 2441117397Skan { 2442117397Skan typedef char_traits<_CharT> __traits_type; 2443117397Skan // [22.2.2.2.2] Stage 3. 2444117397Skan // If necessary, pad. 2445117397Skan streamsize __w = __io.width(); 2446117397Skan _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2447117397Skan * __w)); 2448117397Skan if (__w > static_cast<streamsize>(__len)) 2449117397Skan { 2450117397Skan __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 2451117397Skan __w, __len, true); 2452117397Skan __len = static_cast<int>(__w); 2453117397Skan // Switch strings. 2454117397Skan __ws = __ws2; 2455117397Skan } 2456117397Skan __io.width(0); 2457117397Skan 2458117397Skan // [22.2.2.2.2] Stage 4. 2459117397Skan // Write resulting, fully-formatted string to output iterator. 2460117397Skan return __write(__s, __ws, __len); 2461117397Skan } 2462117397Skan#endif 2463117397Skan 2464117397Skan template<typename _CharT> 2465117397Skan __locale_cache<numpunct<_CharT> >::__locale_cache(const locale& __loc) 2466117397Skan : _M_truename(0), _M_falsename(0), _M_use_grouping(false), 2467117397Skan _M_grouping(0) 2468117397Skan { 2469117397Skan if (has_facet<numpunct<_CharT> >(__loc)) 2470117397Skan { 2471117397Skan const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2472117397Skan _M_decimal_point = __np.decimal_point(); 2473117397Skan _M_thousands_sep = __np.thousands_sep(); 2474117397Skan 2475117397Skan string_type __false = __np.falsename(); 2476117397Skan _CharT* __falsename = new _CharT[__false.length() + 1]; 2477117397Skan __false.copy(__falsename, __false.length()); 2478117397Skan __falsename[__false.length()] = _CharT(); 2479117397Skan _M_falsename = __falsename; 2480117397Skan 2481117397Skan string_type __true = __np.truename(); 2482117397Skan _CharT* __truename = new _CharT[__true.length() + 1]; 2483117397Skan __true.copy(__truename, __true.length()); 2484117397Skan __truename[__true.length()] = _CharT(); 2485117397Skan _M_truename = __truename; 2486117397Skan 2487117397Skan string __grouping = __np.grouping(); 2488117397Skan char* __group = new char[__grouping.length() + 1]; 2489117397Skan __grouping.copy(__group, __grouping.length()); 2490117397Skan __group[__grouping.length()] = 0; 2491117397Skan _M_grouping = __group; 2492117397Skan 2493117397Skan _M_use_grouping = __grouping.length() != 0 2494117397Skan && __grouping.data()[0] != 0; 2495117397Skan } 2496117397Skan 2497117397Skan if (has_facet<ctype<_CharT> >(__loc)) 2498117397Skan { 2499117397Skan const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 2500117397Skan __ct.widen(__num_base::_S_atoms_out, 2501117397Skan __num_base::_S_atoms_out + __num_base::_S_end, 2502117397Skan _M_atoms_out); 2503117397Skan } 2504117397Skan } 2505117397Skan 2506117397Skan // Static locale cache initialization. Only instantiated with char 2507117397Skan // and wchar_t, so no need to check has_facet. 2508117397Skan template<typename _CharT> 2509117397Skan __locale_cache<numpunct<_CharT> >:: 2510117397Skan __locale_cache(const locale& __loc, bool) 2511117397Skan { 2512117397Skan // Grab pointers to numpunct static strings 2513117397Skan const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2514117397Skan _M_thousands_sep = __np._M_thousands_sep; 2515117397Skan _M_decimal_point = __np._M_decimal_point; 2516117397Skan _M_falsename = __np._M_falsename; 2517117397Skan _M_truename = __np._M_truename; 2518117397Skan _M_grouping = __np._M_grouping; 2519117397Skan _M_use_grouping = false; 2520117397Skan 2521117397Skan const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 2522117397Skan __ct.widen(__num_base::_S_atoms_out, 2523117397Skan __num_base::_S_atoms_out + __num_base::_S_end, 2524117397Skan _M_atoms_out); 2525117397Skan } 2526117397Skan 252797403Sobrien // Inhibit implicit instantiations for required instantiations, 252897403Sobrien // which are defined via explicit instantiations elsewhere. 252997403Sobrien // NB: This syntax is a GNU extension. 2530117397Skan#if _GLIBCPP_EXTERN_TEMPLATE 253197403Sobrien extern template class moneypunct<char, false>; 253297403Sobrien extern template class moneypunct<char, true>; 253397403Sobrien extern template class moneypunct_byname<char, false>; 253497403Sobrien extern template class moneypunct_byname<char, true>; 253597403Sobrien extern template class money_get<char>; 253697403Sobrien extern template class money_put<char>; 253797403Sobrien extern template class numpunct<char>; 253897403Sobrien extern template class numpunct_byname<char>; 253997403Sobrien extern template class num_get<char>; 254097403Sobrien extern template class num_put<char>; 254197403Sobrien extern template class __timepunct<char>; 254297403Sobrien extern template class time_put<char>; 254397403Sobrien extern template class time_put_byname<char>; 254497403Sobrien extern template class time_get<char>; 254597403Sobrien extern template class time_get_byname<char>; 254697403Sobrien extern template class messages<char>; 254797403Sobrien extern template class messages_byname<char>; 254897403Sobrien extern template class ctype_byname<char>; 254997403Sobrien extern template class codecvt_byname<char, char, mbstate_t>; 255097403Sobrien extern template class collate<char>; 255197403Sobrien extern template class collate_byname<char>; 255297403Sobrien 255397403Sobrien extern template 255497403Sobrien const codecvt<char, char, mbstate_t>& 255597403Sobrien use_facet<codecvt<char, char, mbstate_t> >(const locale&); 255697403Sobrien 255797403Sobrien extern template 255897403Sobrien const collate<char>& 255997403Sobrien use_facet<collate<char> >(const locale&); 256097403Sobrien 256197403Sobrien extern template 256297403Sobrien const numpunct<char>& 256397403Sobrien use_facet<numpunct<char> >(const locale&); 256497403Sobrien 256597403Sobrien extern template 256697403Sobrien const num_put<char>& 256797403Sobrien use_facet<num_put<char> >(const locale&); 256897403Sobrien 256997403Sobrien extern template 257097403Sobrien const num_get<char>& 257197403Sobrien use_facet<num_get<char> >(const locale&); 257297403Sobrien 257397403Sobrien extern template 257497403Sobrien const moneypunct<char, true>& 257597403Sobrien use_facet<moneypunct<char, true> >(const locale&); 257697403Sobrien 257797403Sobrien extern template 257897403Sobrien const moneypunct<char, false>& 257997403Sobrien use_facet<moneypunct<char, false> >(const locale&); 258097403Sobrien 258197403Sobrien extern template 258297403Sobrien const money_put<char>& 258397403Sobrien use_facet<money_put<char> >(const locale&); 258497403Sobrien 258597403Sobrien extern template 258697403Sobrien const money_get<char>& 258797403Sobrien use_facet<money_get<char> >(const locale&); 258897403Sobrien 258997403Sobrien extern template 259097403Sobrien const __timepunct<char>& 259197403Sobrien use_facet<__timepunct<char> >(const locale&); 259297403Sobrien 259397403Sobrien extern template 259497403Sobrien const time_put<char>& 259597403Sobrien use_facet<time_put<char> >(const locale&); 259697403Sobrien 259797403Sobrien extern template 259897403Sobrien const time_get<char>& 259997403Sobrien use_facet<time_get<char> >(const locale&); 260097403Sobrien 260197403Sobrien extern template 260297403Sobrien const messages<char>& 260397403Sobrien use_facet<messages<char> >(const locale&); 260497403Sobrien 2605107606Sobrien extern template 2606107606Sobrien bool 2607107606Sobrien has_facet<ctype<char> >(const locale&); 2608107606Sobrien 2609107606Sobrien extern template 2610107606Sobrien bool 2611107606Sobrien has_facet<codecvt<char, char, mbstate_t> >(const locale&); 2612107606Sobrien 2613107606Sobrien extern template 2614107606Sobrien bool 2615107606Sobrien has_facet<collate<char> >(const locale&); 2616107606Sobrien 2617107606Sobrien extern template 2618107606Sobrien bool 2619107606Sobrien has_facet<numpunct<char> >(const locale&); 2620107606Sobrien 2621107606Sobrien extern template 2622107606Sobrien bool 2623107606Sobrien has_facet<num_put<char> >(const locale&); 2624107606Sobrien 2625107606Sobrien extern template 2626107606Sobrien bool 2627107606Sobrien has_facet<num_get<char> >(const locale&); 2628107606Sobrien 2629107606Sobrien extern template 2630107606Sobrien bool 2631107606Sobrien has_facet<moneypunct<char> >(const locale&); 2632107606Sobrien 2633107606Sobrien extern template 2634107606Sobrien bool 2635107606Sobrien has_facet<money_put<char> >(const locale&); 2636107606Sobrien 2637107606Sobrien extern template 2638107606Sobrien bool 2639107606Sobrien has_facet<money_get<char> >(const locale&); 2640107606Sobrien 2641107606Sobrien extern template 2642107606Sobrien bool 2643107606Sobrien has_facet<__timepunct<char> >(const locale&); 2644107606Sobrien 2645107606Sobrien extern template 2646107606Sobrien bool 2647107606Sobrien has_facet<time_put<char> >(const locale&); 2648107606Sobrien 2649107606Sobrien extern template 2650107606Sobrien bool 2651107606Sobrien has_facet<time_get<char> >(const locale&); 2652107606Sobrien 2653107606Sobrien extern template 2654107606Sobrien bool 2655107606Sobrien has_facet<messages<char> >(const locale&); 2656107606Sobrien 2657107606Sobrien#ifdef _GLIBCPP_USE_WCHAR_T 2658107606Sobrien extern template class moneypunct<wchar_t, false>; 2659107606Sobrien extern template class moneypunct<wchar_t, true>; 2660107606Sobrien extern template class moneypunct_byname<wchar_t, false>; 2661107606Sobrien extern template class moneypunct_byname<wchar_t, true>; 2662107606Sobrien extern template class money_get<wchar_t>; 2663107606Sobrien extern template class money_put<wchar_t>; 2664107606Sobrien extern template class numpunct<wchar_t>; 2665107606Sobrien extern template class numpunct_byname<wchar_t>; 2666107606Sobrien extern template class num_get<wchar_t>; 2667107606Sobrien extern template class num_put<wchar_t>; 2668107606Sobrien extern template class __timepunct<wchar_t>; 2669107606Sobrien extern template class time_put<wchar_t>; 2670107606Sobrien extern template class time_put_byname<wchar_t>; 2671107606Sobrien extern template class time_get<wchar_t>; 2672107606Sobrien extern template class time_get_byname<wchar_t>; 2673107606Sobrien extern template class messages<wchar_t>; 2674107606Sobrien extern template class messages_byname<wchar_t>; 2675107606Sobrien extern template class ctype_byname<wchar_t>; 2676107606Sobrien extern template class codecvt_byname<wchar_t, char, mbstate_t>; 2677107606Sobrien extern template class collate<wchar_t>; 2678107606Sobrien extern template class collate_byname<wchar_t>; 2679107606Sobrien 268097403Sobrien extern template 268197403Sobrien const codecvt<wchar_t, char, mbstate_t>& 268297403Sobrien use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 268397403Sobrien 268497403Sobrien extern template 268597403Sobrien const collate<wchar_t>& 268697403Sobrien use_facet<collate<wchar_t> >(const locale&); 268797403Sobrien 268897403Sobrien extern template 268997403Sobrien const numpunct<wchar_t>& 269097403Sobrien use_facet<numpunct<wchar_t> >(const locale&); 269197403Sobrien 269297403Sobrien extern template 269397403Sobrien const num_put<wchar_t>& 269497403Sobrien use_facet<num_put<wchar_t> >(const locale&); 269597403Sobrien 269697403Sobrien extern template 269797403Sobrien const num_get<wchar_t>& 269897403Sobrien use_facet<num_get<wchar_t> >(const locale&); 269997403Sobrien 270097403Sobrien extern template 270197403Sobrien const moneypunct<wchar_t, true>& 270297403Sobrien use_facet<moneypunct<wchar_t, true> >(const locale&); 270397403Sobrien 270497403Sobrien extern template 270597403Sobrien const moneypunct<wchar_t, false>& 270697403Sobrien use_facet<moneypunct<wchar_t, false> >(const locale&); 270797403Sobrien 270897403Sobrien extern template 270997403Sobrien const money_put<wchar_t>& 271097403Sobrien use_facet<money_put<wchar_t> >(const locale&); 271197403Sobrien 271297403Sobrien extern template 271397403Sobrien const money_get<wchar_t>& 271497403Sobrien use_facet<money_get<wchar_t> >(const locale&); 271597403Sobrien 271697403Sobrien extern template 271797403Sobrien const __timepunct<wchar_t>& 271897403Sobrien use_facet<__timepunct<wchar_t> >(const locale&); 271997403Sobrien 272097403Sobrien extern template 272197403Sobrien const time_put<wchar_t>& 272297403Sobrien use_facet<time_put<wchar_t> >(const locale&); 272397403Sobrien 272497403Sobrien extern template 272597403Sobrien const time_get<wchar_t>& 272697403Sobrien use_facet<time_get<wchar_t> >(const locale&); 272797403Sobrien 272897403Sobrien extern template 272997403Sobrien const messages<wchar_t>& 273097403Sobrien use_facet<messages<wchar_t> >(const locale&); 273197403Sobrien 273297403Sobrien extern template 273397403Sobrien bool 273497403Sobrien has_facet<ctype<wchar_t> >(const locale&); 273597403Sobrien 273697403Sobrien extern template 273797403Sobrien bool 273897403Sobrien has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 273997403Sobrien 274097403Sobrien extern template 274197403Sobrien bool 274297403Sobrien has_facet<collate<wchar_t> >(const locale&); 274397403Sobrien 274497403Sobrien extern template 274597403Sobrien bool 274697403Sobrien has_facet<numpunct<wchar_t> >(const locale&); 274797403Sobrien 274897403Sobrien extern template 274997403Sobrien bool 275097403Sobrien has_facet<num_put<wchar_t> >(const locale&); 275197403Sobrien 275297403Sobrien extern template 275397403Sobrien bool 275497403Sobrien has_facet<num_get<wchar_t> >(const locale&); 275597403Sobrien 275697403Sobrien extern template 275797403Sobrien bool 275897403Sobrien has_facet<moneypunct<wchar_t> >(const locale&); 275997403Sobrien 276097403Sobrien extern template 276197403Sobrien bool 276297403Sobrien has_facet<money_put<wchar_t> >(const locale&); 276397403Sobrien 276497403Sobrien extern template 276597403Sobrien bool 276697403Sobrien has_facet<money_get<wchar_t> >(const locale&); 276797403Sobrien 276897403Sobrien extern template 276997403Sobrien bool 277097403Sobrien has_facet<__timepunct<wchar_t> >(const locale&); 277197403Sobrien 277297403Sobrien extern template 277397403Sobrien bool 277497403Sobrien has_facet<time_put<wchar_t> >(const locale&); 277597403Sobrien 277697403Sobrien extern template 277797403Sobrien bool 277897403Sobrien has_facet<time_get<wchar_t> >(const locale&); 277997403Sobrien 278097403Sobrien extern template 278197403Sobrien bool 278297403Sobrien has_facet<messages<wchar_t> >(const locale&); 2783107606Sobrien#endif 2784117397Skan#endif 278597403Sobrien} // namespace std 278697403Sobrien 278797403Sobrien#endif 2788