locale_facets.tcc revision 102782
197403Sobrien// Locale support -*- C++ -*- 297403Sobrien 397403Sobrien// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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> 3997403Sobrien#include <clocale> // For localeconv 4097403Sobrien#include <cstdlib> // For strof, strtold 4197403Sobrien#include <cmath> // For ceil 4297403Sobrien#include <cctype> // For isspace 4397403Sobrien#include <limits> // For numeric_limits 4497403Sobrien#include <bits/streambuf_iterator.h> 4597403Sobrien#include <typeinfo> // For bad_cast. 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 8997403Sobrien 9097403Sobrien // Stage 1: Determine a conversion specifier. 9197403Sobrien template<typename _CharT, typename _InIter> 9297403Sobrien _InIter 9397403Sobrien num_get<_CharT, _InIter>:: 9497403Sobrien _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 9597403Sobrien ios_base::iostate& __err, string& __xtrc) const 9697403Sobrien { 97102782Skan typedef char_traits<_CharT> __traits_type; 9897403Sobrien const locale __loc = __io.getloc(); 9997403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 10097403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 10197403Sobrien 10297403Sobrien // First check for sign. 10397403Sobrien const char_type __plus = __ctype.widen('+'); 10497403Sobrien const char_type __minus = __ctype.widen('-'); 10597403Sobrien int __pos = 0; 10697403Sobrien char_type __c = *__beg; 107102782Skan if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 108102782Skan && __beg != __end) 10997403Sobrien { 11097403Sobrien __xtrc += __ctype.narrow(__c, char()); 11197403Sobrien ++__pos; 11297403Sobrien __c = *(++__beg); 11397403Sobrien } 11497403Sobrien 11597403Sobrien // Next, strip leading zeros. 11697403Sobrien const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); 11797403Sobrien bool __found_zero = false; 118102782Skan while (__traits_type::eq(__c, __zero) && __beg != __end) 11997403Sobrien { 12097403Sobrien __c = *(++__beg); 12197403Sobrien __found_zero = true; 12297403Sobrien } 12397403Sobrien if (__found_zero) 12497403Sobrien { 12597403Sobrien __xtrc += _S_atoms[_M_zero]; 12697403Sobrien ++__pos; 12797403Sobrien } 12897403Sobrien 12997403Sobrien // Only need acceptable digits for floating point numbers. 13097403Sobrien const size_t __len = _M_E - _M_zero + 1; 13197403Sobrien char_type __watoms[__len]; 13297403Sobrien __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); 13397403Sobrien bool __found_dec = false; 13497403Sobrien bool __found_sci = false; 13597403Sobrien const char_type __dec = __np.decimal_point(); 13697403Sobrien 13797403Sobrien string __found_grouping; 13897403Sobrien const string __grouping = __np.grouping(); 13997403Sobrien bool __check_grouping = __grouping.size(); 14097403Sobrien int __sep_pos = 0; 14197403Sobrien const char_type __sep = __np.thousands_sep(); 14297403Sobrien 14397403Sobrien while (__beg != __end) 14497403Sobrien { 14597403Sobrien // Only look in digits. 14697403Sobrien const char_type* __p = __traits_type::find(__watoms, 10, __c); 14797403Sobrien 14897403Sobrien // NB: strchr returns true for __c == 0x0 149102782Skan if (__p && !__traits_type::eq(__c, char_type())) 15097403Sobrien { 15197403Sobrien // Try first for acceptable digit; record it if found. 15297403Sobrien ++__pos; 15397403Sobrien __xtrc += _S_atoms[__p - __watoms]; 15497403Sobrien ++__sep_pos; 15597403Sobrien __c = *(++__beg); 15697403Sobrien } 157102782Skan else if (__traits_type::eq(__c, __sep) 158102782Skan && __check_grouping && !__found_dec) 15997403Sobrien { 16097403Sobrien // NB: Thousands separator at the beginning of a string 16197403Sobrien // is a no-no, as is two consecutive thousands separators. 16297403Sobrien if (__sep_pos) 16397403Sobrien { 16497403Sobrien __found_grouping += static_cast<char>(__sep_pos); 16597403Sobrien __sep_pos = 0; 16697403Sobrien __c = *(++__beg); 16797403Sobrien } 16897403Sobrien else 16997403Sobrien { 17097403Sobrien __err |= ios_base::failbit; 17197403Sobrien break; 17297403Sobrien } 17397403Sobrien } 174102782Skan else if (__traits_type::eq(__c, __dec) && !__found_dec) 17597403Sobrien { 17697403Sobrien // According to the standard, if no grouping chars are seen, 17797403Sobrien // no grouping check is applied. Therefore __found_grouping 17897403Sobrien // must be adjusted only if __dec comes after some __sep. 17997403Sobrien if (__found_grouping.size()) 18097403Sobrien __found_grouping += static_cast<char>(__sep_pos); 18197403Sobrien ++__pos; 18297403Sobrien __xtrc += '.'; 18397403Sobrien __c = *(++__beg); 18497403Sobrien __found_dec = true; 18597403Sobrien } 186102782Skan else if ((__traits_type::eq(__c, __watoms[_M_e]) 187102782Skan || __traits_type::eq(__c, __watoms[_M_E])) 18897403Sobrien && !__found_sci && __pos) 18997403Sobrien { 19097403Sobrien // Scientific notation. 19197403Sobrien ++__pos; 19297403Sobrien __xtrc += __ctype.narrow(__c, char()); 19397403Sobrien __c = *(++__beg); 19497403Sobrien 19597403Sobrien // Remove optional plus or minus sign, if they exist. 196102782Skan if (__traits_type::eq(__c, __plus) 197102782Skan || __traits_type::eq(__c, __minus)) 19897403Sobrien { 19997403Sobrien ++__pos; 20097403Sobrien __xtrc += __ctype.narrow(__c, char()); 20197403Sobrien __c = *(++__beg); 20297403Sobrien } 20397403Sobrien __found_sci = true; 20497403Sobrien } 20597403Sobrien else 20697403Sobrien // Not a valid input item. 20797403Sobrien break; 20897403Sobrien } 20997403Sobrien 21097403Sobrien // Digit grouping is checked. If grouping and found_grouping don't 21197403Sobrien // match, then get very very upset, and set failbit. 21297403Sobrien if (__check_grouping && __found_grouping.size()) 21397403Sobrien { 21497403Sobrien // Add the ending grouping if a decimal wasn't found. 21597403Sobrien if (!__found_dec) 21697403Sobrien __found_grouping += static_cast<char>(__sep_pos); 21797403Sobrien if (!__verify_grouping(__grouping, __found_grouping)) 21897403Sobrien __err |= ios_base::failbit; 21997403Sobrien } 22097403Sobrien 22197403Sobrien // Finish up 22297403Sobrien __xtrc += char(); 22397403Sobrien if (__beg == __end) 22497403Sobrien __err |= ios_base::eofbit; 22597403Sobrien return __beg; 22697403Sobrien } 22797403Sobrien 22897403Sobrien // Stage 1: Determine a conversion specifier. 22997403Sobrien template<typename _CharT, typename _InIter> 23097403Sobrien _InIter 23197403Sobrien num_get<_CharT, _InIter>:: 23297403Sobrien _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 23397403Sobrien ios_base::iostate& __err, string& __xtrc, int& __base) const 23497403Sobrien { 235102782Skan typedef char_traits<_CharT> __traits_type; 23697403Sobrien const locale __loc = __io.getloc(); 23797403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 23897403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 23997403Sobrien 24097403Sobrien // NB: Iff __basefield == 0, this can change based on contents. 24197403Sobrien ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 24297403Sobrien if (__basefield == ios_base::oct) 24397403Sobrien __base = 8; 24497403Sobrien else if (__basefield == ios_base::hex) 24597403Sobrien __base = 16; 24697403Sobrien else 24797403Sobrien __base = 10; 24897403Sobrien 249102782Skan // First check for sign. 25097403Sobrien int __pos = 0; 25197403Sobrien char_type __c = *__beg; 252102782Skan const char_type __plus = __ctype.widen('+'); 253102782Skan const char_type __minus = __ctype.widen('-'); 254102782Skan 255102782Skan if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 25697403Sobrien && __beg != __end) 25797403Sobrien { 25897403Sobrien __xtrc += __ctype.narrow(__c, char()); 25997403Sobrien ++__pos; 26097403Sobrien __c = *(++__beg); 26197403Sobrien } 26297403Sobrien 26397403Sobrien // Next, strip leading zeros and check required digits for base formats. 26497403Sobrien const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); 26597403Sobrien const char_type __x = __ctype.widen('x'); 26697403Sobrien const char_type __X = __ctype.widen('X'); 26797403Sobrien if (__base == 10) 26897403Sobrien { 26997403Sobrien bool __found_zero = false; 270102782Skan while (__traits_type::eq(__c, __zero) && __beg != __end) 27197403Sobrien { 27297403Sobrien __c = *(++__beg); 27397403Sobrien __found_zero = true; 27497403Sobrien } 27597403Sobrien if (__found_zero) 27697403Sobrien { 27797403Sobrien __xtrc += _S_atoms[_M_zero]; 27897403Sobrien ++__pos; 27997403Sobrien if (__basefield == 0) 28097403Sobrien { 281102782Skan if ((__traits_type::eq(__c, __x) 282102782Skan || __traits_type::eq(__c, __X)) 283102782Skan && __beg != __end) 28497403Sobrien { 28597403Sobrien __xtrc += __ctype.narrow(__c, char()); 28697403Sobrien ++__pos; 28797403Sobrien __c = *(++__beg); 28897403Sobrien __base = 16; 28997403Sobrien } 29097403Sobrien else 29197403Sobrien __base = 8; 29297403Sobrien } 29397403Sobrien } 29497403Sobrien } 29597403Sobrien else if (__base == 16) 29697403Sobrien { 297102782Skan if (__traits_type::eq(__c, __zero) && __beg != __end) 29897403Sobrien { 29997403Sobrien __xtrc += _S_atoms[_M_zero]; 30097403Sobrien ++__pos; 30197403Sobrien __c = *(++__beg); 302102782Skan if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) 303102782Skan && __beg != __end) 30497403Sobrien { 30597403Sobrien __xtrc += __ctype.narrow(__c, char()); 30697403Sobrien ++__pos; 30797403Sobrien __c = *(++__beg); 30897403Sobrien } 30997403Sobrien } 31097403Sobrien } 31197403Sobrien 31297403Sobrien // At this point, base is determined. If not hex, only allow 31397403Sobrien // base digits as valid input. 31497403Sobrien size_t __len; 31597403Sobrien if (__base == 16) 31697403Sobrien __len = _M_size; 31797403Sobrien else 31897403Sobrien __len = __base; 31997403Sobrien 32097403Sobrien // Extract. 32197403Sobrien char_type __watoms[_M_size]; 32297403Sobrien __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); 32397403Sobrien string __found_grouping; 32497403Sobrien const string __grouping = __np.grouping(); 32597403Sobrien bool __check_grouping = __grouping.size(); 32697403Sobrien int __sep_pos = 0; 32797403Sobrien const char_type __sep = __np.thousands_sep(); 32897403Sobrien while (__beg != __end) 32997403Sobrien { 33097403Sobrien const char_type* __p = __traits_type::find(__watoms, __len, __c); 33197403Sobrien 33297403Sobrien // NB: strchr returns true for __c == 0x0 333102782Skan if (__p && !__traits_type::eq(__c, char_type())) 33497403Sobrien { 33597403Sobrien // Try first for acceptable digit; record it if found. 33697403Sobrien __xtrc += _S_atoms[__p - __watoms]; 33797403Sobrien ++__pos; 33897403Sobrien ++__sep_pos; 33997403Sobrien __c = *(++__beg); 34097403Sobrien } 341102782Skan else if (__traits_type::eq(__c, __sep) && __check_grouping) 34297403Sobrien { 34397403Sobrien // NB: Thousands separator at the beginning of a string 34497403Sobrien // is a no-no, as is two consecutive thousands separators. 34597403Sobrien if (__sep_pos) 34697403Sobrien { 34797403Sobrien __found_grouping += static_cast<char>(__sep_pos); 34897403Sobrien __sep_pos = 0; 34997403Sobrien __c = *(++__beg); 35097403Sobrien } 35197403Sobrien else 35297403Sobrien { 35397403Sobrien __err |= ios_base::failbit; 35497403Sobrien break; 35597403Sobrien } 35697403Sobrien } 35797403Sobrien else 35897403Sobrien // Not a valid input item. 35997403Sobrien break; 36097403Sobrien } 36197403Sobrien 36297403Sobrien // Digit grouping is checked. If grouping and found_grouping don't 36397403Sobrien // match, then get very very upset, and set failbit. 36497403Sobrien if (__check_grouping && __found_grouping.size()) 36597403Sobrien { 36697403Sobrien // Add the ending grouping. 36797403Sobrien __found_grouping += static_cast<char>(__sep_pos); 36897403Sobrien if (!__verify_grouping(__grouping, __found_grouping)) 36997403Sobrien __err |= ios_base::failbit; 37097403Sobrien } 37197403Sobrien 37297403Sobrien // Finish up. 37397403Sobrien __xtrc += char(); 37497403Sobrien if (__beg == __end) 37597403Sobrien __err |= ios_base::eofbit; 37697403Sobrien return __beg; 37797403Sobrien } 37897403Sobrien 37997403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 38097403Sobrien //17. Bad bool parsing 38197403Sobrien template<typename _CharT, typename _InIter> 38297403Sobrien _InIter 38397403Sobrien num_get<_CharT, _InIter>:: 38497403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 38597403Sobrien ios_base::iostate& __err, bool& __v) const 38697403Sobrien { 38797403Sobrien // Parse bool values as unsigned long 38897403Sobrien if (!(__io.flags() & ios_base::boolalpha)) 38997403Sobrien { 39097403Sobrien // NB: We can't just call do_get(long) here, as it might 39197403Sobrien // refer to a derived class. 39297403Sobrien string __xtrc; 39397403Sobrien int __base; 39497403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 39597403Sobrien 39697403Sobrien unsigned long __ul; 39797403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 39897403Sobrien if (!(__err & ios_base::failbit) && __ul <= 1) 39997403Sobrien __v = __ul; 40097403Sobrien else 40197403Sobrien __err |= ios_base::failbit; 40297403Sobrien } 40397403Sobrien 40497403Sobrien // Parse bool values as alphanumeric 40597403Sobrien else 40697403Sobrien { 407102782Skan typedef char_traits<_CharT> __traits_type; 408102782Skan typedef basic_string<_CharT> __string_type; 409102782Skan 41097403Sobrien locale __loc = __io.getloc(); 41197403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 41297403Sobrien const __string_type __true = __np.truename(); 41397403Sobrien const __string_type __false = __np.falsename(); 41497403Sobrien const char_type* __trues = __true.c_str(); 41597403Sobrien const char_type* __falses = __false.c_str(); 41697403Sobrien const size_t __truen = __true.size() - 1; 41797403Sobrien const size_t __falsen = __false.size() - 1; 41897403Sobrien 41997403Sobrien for (size_t __n = 0; __beg != __end; ++__n) 42097403Sobrien { 42197403Sobrien char_type __c = *__beg++; 422102782Skan bool __testf = __n <= __falsen 423102782Skan ? __traits_type::eq(__c, __falses[__n]) : false; 424102782Skan bool __testt = __n <= __truen 425102782Skan ? __traits_type::eq(__c, __trues[__n]) : false; 42697403Sobrien if (!(__testf || __testt)) 42797403Sobrien { 42897403Sobrien __err |= ios_base::failbit; 42997403Sobrien break; 43097403Sobrien } 43197403Sobrien else if (__testf && __n == __falsen) 43297403Sobrien { 43397403Sobrien __v = 0; 43497403Sobrien break; 43597403Sobrien } 43697403Sobrien else if (__testt && __n == __truen) 43797403Sobrien { 43897403Sobrien __v = 1; 43997403Sobrien break; 44097403Sobrien } 44197403Sobrien } 44297403Sobrien if (__beg == __end) 44397403Sobrien __err |= ios_base::eofbit; 44497403Sobrien } 44597403Sobrien return __beg; 44697403Sobrien } 44797403Sobrien#endif 44897403Sobrien 44997403Sobrien template<typename _CharT, typename _InIter> 45097403Sobrien _InIter 45197403Sobrien num_get<_CharT, _InIter>:: 45297403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 45397403Sobrien ios_base::iostate& __err, long& __v) const 45497403Sobrien { 45597403Sobrien string __xtrc; 45697403Sobrien int __base; 45797403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 45897403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 45997403Sobrien return __beg; 46097403Sobrien } 46197403Sobrien 46297403Sobrien template<typename _CharT, typename _InIter> 46397403Sobrien _InIter 46497403Sobrien num_get<_CharT, _InIter>:: 46597403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 46697403Sobrien ios_base::iostate& __err, unsigned short& __v) const 46797403Sobrien { 46897403Sobrien string __xtrc; 46997403Sobrien int __base; 47097403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 47197403Sobrien unsigned long __ul; 47297403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 47397403Sobrien if (!(__err & ios_base::failbit) 47497403Sobrien && __ul <= numeric_limits<unsigned short>::max()) 47597403Sobrien __v = static_cast<unsigned short>(__ul); 47697403Sobrien else 47797403Sobrien __err |= ios_base::failbit; 47897403Sobrien return __beg; 47997403Sobrien } 48097403Sobrien 48197403Sobrien template<typename _CharT, typename _InIter> 48297403Sobrien _InIter 48397403Sobrien num_get<_CharT, _InIter>:: 48497403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 48597403Sobrien ios_base::iostate& __err, unsigned int& __v) const 48697403Sobrien { 48797403Sobrien string __xtrc; 48897403Sobrien int __base; 48997403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 49097403Sobrien unsigned long __ul; 49197403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 49297403Sobrien if (!(__err & ios_base::failbit) 49397403Sobrien && __ul <= numeric_limits<unsigned int>::max()) 49497403Sobrien __v = static_cast<unsigned int>(__ul); 49597403Sobrien else 49697403Sobrien __err |= ios_base::failbit; 49797403Sobrien return __beg; 49897403Sobrien } 49997403Sobrien 50097403Sobrien template<typename _CharT, typename _InIter> 50197403Sobrien _InIter 50297403Sobrien num_get<_CharT, _InIter>:: 50397403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 50497403Sobrien ios_base::iostate& __err, unsigned long& __v) const 50597403Sobrien { 50697403Sobrien string __xtrc; 50797403Sobrien int __base; 50897403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 50997403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 51097403Sobrien return __beg; 51197403Sobrien } 51297403Sobrien 51397403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG 51497403Sobrien template<typename _CharT, typename _InIter> 51597403Sobrien _InIter 51697403Sobrien num_get<_CharT, _InIter>:: 51797403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 51897403Sobrien ios_base::iostate& __err, long long& __v) const 51997403Sobrien { 52097403Sobrien string __xtrc; 52197403Sobrien int __base; 52297403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 52397403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 52497403Sobrien return __beg; 52597403Sobrien } 52697403Sobrien 52797403Sobrien template<typename _CharT, typename _InIter> 52897403Sobrien _InIter 52997403Sobrien num_get<_CharT, _InIter>:: 53097403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 53197403Sobrien ios_base::iostate& __err, unsigned long long& __v) const 53297403Sobrien { 53397403Sobrien string __xtrc; 53497403Sobrien int __base; 53597403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 53697403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 53797403Sobrien return __beg; 53897403Sobrien } 53997403Sobrien#endif 54097403Sobrien 54197403Sobrien template<typename _CharT, typename _InIter> 54297403Sobrien _InIter 54397403Sobrien num_get<_CharT, _InIter>:: 54497403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 54597403Sobrien ios_base::iostate& __err, float& __v) const 54697403Sobrien { 54797403Sobrien string __xtrc; 54897403Sobrien __xtrc.reserve(32); 54997403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 55097403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 55197403Sobrien return __beg; 55297403Sobrien } 55397403Sobrien 55497403Sobrien template<typename _CharT, typename _InIter> 55597403Sobrien _InIter 55697403Sobrien num_get<_CharT, _InIter>:: 55797403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 55897403Sobrien ios_base::iostate& __err, double& __v) const 55997403Sobrien { 56097403Sobrien string __xtrc; 56197403Sobrien __xtrc.reserve(32); 56297403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 56397403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 56497403Sobrien return __beg; 56597403Sobrien } 56697403Sobrien 56797403Sobrien template<typename _CharT, typename _InIter> 56897403Sobrien _InIter 56997403Sobrien num_get<_CharT, _InIter>:: 57097403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 57197403Sobrien ios_base::iostate& __err, long double& __v) const 57297403Sobrien { 57397403Sobrien string __xtrc; 57497403Sobrien __xtrc.reserve(32); 57597403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 57697403Sobrien __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 57797403Sobrien return __beg; 57897403Sobrien } 57997403Sobrien 58097403Sobrien template<typename _CharT, typename _InIter> 58197403Sobrien _InIter 58297403Sobrien num_get<_CharT, _InIter>:: 58397403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 58497403Sobrien ios_base::iostate& __err, void*& __v) const 58597403Sobrien { 58697403Sobrien // Prepare for hex formatted input 58797403Sobrien typedef ios_base::fmtflags fmtflags; 58897403Sobrien fmtflags __fmt = __io.flags(); 58997403Sobrien fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield 59097403Sobrien | ios_base::uppercase | ios_base::internal); 59197403Sobrien __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); 59297403Sobrien 59397403Sobrien string __xtrc; 59497403Sobrien int __base; 59597403Sobrien __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 59697403Sobrien 59797403Sobrien // Reset from hex formatted input 59897403Sobrien __io.flags(__fmt); 59997403Sobrien 60097403Sobrien unsigned long __ul; 60197403Sobrien __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 60297403Sobrien if (!(__err & ios_base::failbit)) 60397403Sobrien __v = reinterpret_cast<void*>(__ul); 60497403Sobrien else 60597403Sobrien __err |= ios_base::failbit; 60697403Sobrien return __beg; 60797403Sobrien } 60897403Sobrien 60997403Sobrien // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99 61097403Sobrien // is not defined) to convert floating point values for insertion into a 61197403Sobrien // stream. An optimization would be to replace them with code that works 61297403Sobrien // directly on a wide buffer and then use __pad to do the padding. 61397403Sobrien // It would be good to replace them anyway to gain back the efficiency 61497403Sobrien // that C++ provides by knowing up front the type of the values to insert. 61597403Sobrien // Also, sprintf is dangerous since may lead to accidental buffer overruns. 61697403Sobrien // This implementation follows the C++ standard fairly directly as 61797403Sobrien // outlined in 22.2.2.2 [lib.locale.num.put] 61897403Sobrien template<typename _CharT, typename _OutIter> 61997403Sobrien template<typename _ValueT> 62097403Sobrien _OutIter 62197403Sobrien num_put<_CharT, _OutIter>:: 62297403Sobrien _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 62397403Sobrien _ValueT __v) const 62497403Sobrien { 62597403Sobrien // Note: digits10 is rounded down. We need to add 1 to ensure 62697403Sobrien // we get the full available precision. 62797403Sobrien const int __max_digits = numeric_limits<_ValueT>::digits10 + 1; 62897403Sobrien streamsize __prec = __io.precision(); 62997403Sobrien 63097403Sobrien if (__prec > static_cast<streamsize>(__max_digits)) 63197403Sobrien __prec = static_cast<streamsize>(__max_digits); 63297403Sobrien 63397403Sobrien // Long enough for the max format spec. 63497403Sobrien char __fbuf[16]; 63597403Sobrien 63697403Sobrien // [22.2.2.2.2] Stage 1, numeric conversion to character. 63797403Sobrien int __len; 63897403Sobrien#ifdef _GLIBCPP_USE_C99 63997403Sobrien // First try a buffer perhaps big enough (for sure sufficient for 64097403Sobrien // non-ios_base::fixed outputs) 64197403Sobrien int __cs_size = __max_digits * 3; 64297403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 64397403Sobrien 64497403Sobrien const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); 64597403Sobrien if (__fp) 64697403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 64797403Sobrien _S_c_locale, __prec); 64897403Sobrien else 64997403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); 65097403Sobrien 65197403Sobrien // If the buffer was not large enough, try again with the correct size. 65297403Sobrien if (__len >= __cs_size) 65397403Sobrien { 65497403Sobrien __cs_size = __len + 1; 65597403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 65697403Sobrien if (__fp) 65797403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 65897403Sobrien _S_c_locale, __prec); 65997403Sobrien else 66097403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 66197403Sobrien _S_c_locale); 66297403Sobrien } 66397403Sobrien#else 66497403Sobrien // Consider the possibility of long ios_base::fixed outputs 66597403Sobrien const bool __fixed = __io.flags() & ios_base::fixed; 66697403Sobrien const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 66797403Sobrien // ios_base::fixed outputs may need up to __max_exp+1 chars 66897403Sobrien // for the integer part + up to __max_digits chars for the 66997403Sobrien // fractional part + 3 chars for sign, decimal point, '\0'. On 67097403Sobrien // the other hand, for non-fixed outputs __max_digits*3 chars 67197403Sobrien // are largely sufficient. 67297403Sobrien const int __cs_size = __fixed ? __max_exp + __max_digits + 4 67397403Sobrien : __max_digits * 3; 67497403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 67597403Sobrien 67697403Sobrien if (_S_format_float(__io, __fbuf, __mod, __prec)) 67797403Sobrien __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); 67897403Sobrien else 67997403Sobrien __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 68097403Sobrien#endif 68197403Sobrien return _M_widen_float(__s, __io, __fill, __cs, __len); 68297403Sobrien } 68397403Sobrien 68497403Sobrien template<typename _CharT, typename _OutIter> 68597403Sobrien template<typename _ValueT> 68697403Sobrien _OutIter 68797403Sobrien num_put<_CharT, _OutIter>:: 68897403Sobrien _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 68997403Sobrien char __modl, _ValueT __v) const 69097403Sobrien { 69197403Sobrien // [22.2.2.2.2] Stage 1, numeric conversion to character. 69297403Sobrien 69397403Sobrien // Long enough for the max format spec. 69497403Sobrien char __fbuf[16]; 69597403Sobrien _S_format_int(__io, __fbuf, __mod, __modl); 69697403Sobrien#ifdef _GLIBCPP_USE_C99 69797403Sobrien // First try a buffer perhaps big enough. 69897403Sobrien int __cs_size = 64; 69997403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 70097403Sobrien int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 70197403Sobrien _S_c_locale); 70297403Sobrien // If the buffer was not large enough, try again with the correct size. 70397403Sobrien if (__len >= __cs_size) 70497403Sobrien { 70597403Sobrien __cs_size = __len + 1; 70697403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 70797403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 70897403Sobrien _S_c_locale); 70997403Sobrien } 71097403Sobrien#else 71197403Sobrien // Leave room for "+/-," "0x," and commas. This size is 71297403Sobrien // arbitrary, but should be largely sufficient. 71397403Sobrien char __cs[128]; 71497403Sobrien int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 71597403Sobrien#endif 71697403Sobrien return _M_widen_int(__s, __io, __fill, __cs, __len); 71797403Sobrien } 71897403Sobrien 71997403Sobrien template<typename _CharT, typename _OutIter> 72097403Sobrien _OutIter 72197403Sobrien num_put<_CharT, _OutIter>:: 72297403Sobrien _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 72397403Sobrien int __len) const 72497403Sobrien { 725102782Skan typedef char_traits<_CharT> __traits_type; 72697403Sobrien // [22.2.2.2.2] Stage 2, convert to char_type, using correct 72797403Sobrien // numpunct.decimal_point() values for '.' and adding grouping. 72897403Sobrien const locale __loc = __io.getloc(); 72997403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 73097403Sobrien _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 73197403Sobrien * __len)); 73297403Sobrien // Grouping can add (almost) as many separators as the number of 73397403Sobrien // digits, but no more. 73497403Sobrien _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 73597403Sobrien * __len * 2)); 73697403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 73797403Sobrien 73897403Sobrien // Replace decimal point. 73997403Sobrien const _CharT* __p; 74097403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 741102782Skan if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) 74297403Sobrien __ws[__p - __ws] = __np.decimal_point(); 74397403Sobrien 74497403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 74597403Sobrien//282. What types does numpunct grouping refer to? 74697403Sobrien // Add grouping, if necessary. 74797403Sobrien const string __grouping = __np.grouping(); 74897403Sobrien ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 74997403Sobrien if (__grouping.size()) 75097403Sobrien { 75197403Sobrien _CharT* __p2; 75297403Sobrien int __declen = __p ? __p - __ws : __len; 75397403Sobrien __p2 = __add_grouping(__ws2, __np.thousands_sep(), 75497403Sobrien __grouping.c_str(), 75597403Sobrien __grouping.c_str() + __grouping.size(), 75697403Sobrien __ws, __ws + __declen); 75797403Sobrien int __newlen = __p2 - __ws2; 75897403Sobrien 75997403Sobrien // Tack on decimal part. 76097403Sobrien if (__p) 76197403Sobrien { 762102782Skan __traits_type::copy(__p2, __p, __len - __declen); 76397403Sobrien __newlen += __len - __declen; 76497403Sobrien } 76597403Sobrien 76697403Sobrien // Switch strings, establish correct new length. 76797403Sobrien __ws = __ws2; 76897403Sobrien __len = __newlen; 76997403Sobrien } 77097403Sobrien#endif 77197403Sobrien return _M_insert(__s, __io, __fill, __ws, __len); 77297403Sobrien } 77397403Sobrien 77497403Sobrien template<typename _CharT, typename _OutIter> 77597403Sobrien _OutIter 77697403Sobrien num_put<_CharT, _OutIter>:: 77797403Sobrien _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 77897403Sobrien int __len) const 77997403Sobrien { 78097403Sobrien // [22.2.2.2.2] Stage 2, convert to char_type, using correct 78197403Sobrien // numpunct.decimal_point() values for '.' and adding grouping. 78297403Sobrien const locale __loc = __io.getloc(); 78397403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 78497403Sobrien _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 78597403Sobrien * __len)); 78697403Sobrien // Grouping can add (almost) as many separators as the number of 78797403Sobrien // digits, but no more. 78897403Sobrien _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 78997403Sobrien * __len * 2)); 79097403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 79197403Sobrien 79297403Sobrien // Add grouping, if necessary. 79397403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 79497403Sobrien const string __grouping = __np.grouping(); 79597403Sobrien const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 79697403Sobrien if (__grouping.size()) 79797403Sobrien { 79897403Sobrien // By itself __add_grouping cannot deal correctly with __ws when 79997403Sobrien // ios::showbase is set and ios_base::oct || ios_base::hex. 80097403Sobrien // Therefore we take care "by hand" of the initial 0, 0x or 0X. 80197403Sobrien streamsize __off = 0; 80297403Sobrien if (__io.flags() & ios_base::showbase) 80397403Sobrien if (__basefield == ios_base::oct) 80497403Sobrien { 80597403Sobrien __off = 1; 80697403Sobrien *__ws2 = *__ws; 80797403Sobrien } 80897403Sobrien else if (__basefield == ios_base::hex) 80997403Sobrien { 81097403Sobrien __off = 2; 81197403Sobrien *__ws2 = *__ws; 81297403Sobrien *(__ws2 + 1) = *(__ws + 1); 81397403Sobrien } 81497403Sobrien _CharT* __p; 81597403Sobrien __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 81697403Sobrien __grouping.c_str(), 81797403Sobrien __grouping.c_str() + __grouping.size(), 81897403Sobrien __ws + __off, __ws + __len); 81997403Sobrien __len = __p - __ws2; 82097403Sobrien // Switch strings. 82197403Sobrien __ws = __ws2; 82297403Sobrien } 82397403Sobrien return _M_insert(__s, __io, __fill, __ws, __len); 82497403Sobrien } 82597403Sobrien 82697403Sobrien // For use by integer and floating-point types after they have been 82797403Sobrien // converted into a char_type string. 82897403Sobrien template<typename _CharT, typename _OutIter> 82997403Sobrien _OutIter 83097403Sobrien num_put<_CharT, _OutIter>:: 83197403Sobrien _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 83297403Sobrien int __len) const 83397403Sobrien { 834102782Skan typedef char_traits<_CharT> __traits_type; 83597403Sobrien // [22.2.2.2.2] Stage 3. 83697403Sobrien streamsize __w = __io.width(); 83797403Sobrien _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 83897403Sobrien * __w)); 83997403Sobrien if (__w > static_cast<streamsize>(__len)) 84097403Sobrien { 841102782Skan __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 842102782Skan __w, __len, true); 84397403Sobrien __len = static_cast<int>(__w); 84497403Sobrien // Switch strings. 84597403Sobrien __ws = __ws2; 84697403Sobrien } 84797403Sobrien __io.width(0); 84897403Sobrien 84997403Sobrien // [22.2.2.2.2] Stage 4. 85097403Sobrien // Write resulting, fully-formatted string to output iterator. 85197403Sobrien for (int __j = 0; __j < __len; ++__j, ++__s) 85297403Sobrien *__s = __ws[__j]; 85397403Sobrien return __s; 85497403Sobrien } 85597403Sobrien 85697403Sobrien template<typename _CharT, typename _OutIter> 85797403Sobrien _OutIter 85897403Sobrien num_put<_CharT, _OutIter>:: 85997403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 86097403Sobrien { 86197403Sobrien ios_base::fmtflags __flags = __io.flags(); 86297403Sobrien if ((__flags & ios_base::boolalpha) == 0) 86397403Sobrien { 86497403Sobrien unsigned long __uv = __v; 865102782Skan __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv); 86697403Sobrien } 86797403Sobrien else 86897403Sobrien { 86997403Sobrien typedef basic_string<_CharT> __string_type; 87097403Sobrien locale __loc = __io.getloc(); 87197403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 87297403Sobrien __string_type __name; 87397403Sobrien if (__v) 87497403Sobrien __name = __np.truename(); 87597403Sobrien else 87697403Sobrien __name = __np.falsename(); 87797403Sobrien __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 87897403Sobrien } 87997403Sobrien return __s; 88097403Sobrien } 88197403Sobrien 88297403Sobrien template<typename _CharT, typename _OutIter> 88397403Sobrien _OutIter 88497403Sobrien num_put<_CharT, _OutIter>:: 88597403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 886102782Skan { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); } 88797403Sobrien 88897403Sobrien template<typename _CharT, typename _OutIter> 88997403Sobrien _OutIter 89097403Sobrien num_put<_CharT, _OutIter>:: 89197403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 89297403Sobrien unsigned long __v) const 893102782Skan { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); } 89497403Sobrien 89597403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG 89697403Sobrien template<typename _CharT, typename _OutIter> 89797403Sobrien _OutIter 89897403Sobrien num_put<_CharT, _OutIter>:: 89997403Sobrien do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 90097403Sobrien { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); } 90197403Sobrien 90297403Sobrien template<typename _CharT, typename _OutIter> 90397403Sobrien _OutIter 90497403Sobrien num_put<_CharT, _OutIter>:: 90597403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 90697403Sobrien unsigned long long __v) const 90797403Sobrien { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } 90897403Sobrien#endif 90997403Sobrien 91097403Sobrien template<typename _CharT, typename _OutIter> 91197403Sobrien _OutIter 91297403Sobrien num_put<_CharT, _OutIter>:: 91397403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 914102782Skan { return _M_convert_float(__s, __io, __fill, char(), __v); } 91597403Sobrien 91697403Sobrien template<typename _CharT, typename _OutIter> 91797403Sobrien _OutIter 91897403Sobrien num_put<_CharT, _OutIter>:: 91997403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 92097403Sobrien long double __v) const 92197403Sobrien { return _M_convert_float(__s, __io, __fill, 'L', __v); } 92297403Sobrien 92397403Sobrien template<typename _CharT, typename _OutIter> 92497403Sobrien _OutIter 92597403Sobrien num_put<_CharT, _OutIter>:: 92697403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 92797403Sobrien const void* __v) const 92897403Sobrien { 92997403Sobrien ios_base::fmtflags __flags = __io.flags(); 93097403Sobrien ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield 93197403Sobrien | ios_base::uppercase | ios_base::internal); 93297403Sobrien __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 93397403Sobrien try 93497403Sobrien { 935102782Skan __s = _M_convert_int(__s, __io, __fill, 'u', char(), 93697403Sobrien reinterpret_cast<unsigned long>(__v)); 93797403Sobrien __io.flags(__flags); 93897403Sobrien } 93997403Sobrien catch (...) 94097403Sobrien { 94197403Sobrien __io.flags(__flags); 94297403Sobrien __throw_exception_again; 94397403Sobrien } 94497403Sobrien return __s; 94597403Sobrien } 94697403Sobrien 94797403Sobrien 94897403Sobrien template<typename _CharT, typename _InIter> 94997403Sobrien _InIter 95097403Sobrien money_get<_CharT, _InIter>:: 95197403Sobrien do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 95297403Sobrien ios_base::iostate& __err, long double& __units) const 95397403Sobrien { 95497403Sobrien string_type __str; 95597403Sobrien __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 95697403Sobrien 95797403Sobrien const int __n = numeric_limits<long double>::digits10; 95897403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__n)); 95997403Sobrien const locale __loc = __io.getloc(); 96097403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 96197403Sobrien const _CharT* __wcs = __str.c_str(); 96297403Sobrien __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); 96397403Sobrien __convert_to_v(__cs, __units, __err, _S_c_locale); 96497403Sobrien return __beg; 96597403Sobrien } 96697403Sobrien 96797403Sobrien template<typename _CharT, typename _InIter> 96897403Sobrien _InIter 96997403Sobrien money_get<_CharT, _InIter>:: 97097403Sobrien do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 97197403Sobrien ios_base::iostate& __err, string_type& __units) const 97297403Sobrien { 97397403Sobrien // These contortions are quite unfortunate. 97497403Sobrien typedef moneypunct<_CharT, true> __money_true; 97597403Sobrien typedef moneypunct<_CharT, false> __money_false; 97697403Sobrien typedef money_base::part part; 97797403Sobrien typedef typename string_type::size_type size_type; 97897403Sobrien 97997403Sobrien const locale __loc = __io.getloc(); 98097403Sobrien const __money_true& __mpt = use_facet<__money_true>(__loc); 98197403Sobrien const __money_false& __mpf = use_facet<__money_false>(__loc); 98297403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 98397403Sobrien 98497403Sobrien const money_base::pattern __p = __intl ? __mpt.neg_format() 98597403Sobrien : __mpf.neg_format(); 98697403Sobrien 98797403Sobrien const string_type __pos_sign =__intl ? __mpt.positive_sign() 98897403Sobrien : __mpf.positive_sign(); 98997403Sobrien const string_type __neg_sign =__intl ? __mpt.negative_sign() 99097403Sobrien : __mpf.negative_sign(); 99197403Sobrien const char_type __d = __intl ? __mpt.decimal_point() 99297403Sobrien : __mpf.decimal_point(); 99397403Sobrien const char_type __sep = __intl ? __mpt.thousands_sep() 99497403Sobrien : __mpf.thousands_sep(); 99597403Sobrien 99697403Sobrien const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); 99797403Sobrien 99897403Sobrien // Set to deduced positive or negative sign, depending. 99997403Sobrien string_type __sign; 100097403Sobrien // String of grouping info from thousands_sep plucked from __units. 100197403Sobrien string __grouping_tmp; 100297403Sobrien // Marker for thousands_sep position. 100397403Sobrien int __sep_pos = 0; 100497403Sobrien // If input iterator is in a valid state. 100597403Sobrien bool __testvalid = true; 100697403Sobrien // Flag marking when a decimal point is found. 100797403Sobrien bool __testdecfound = false; 100897403Sobrien 100997403Sobrien // The tentative returned string is stored here. 101097403Sobrien string_type __temp_units; 101197403Sobrien 101297403Sobrien char_type __c = *__beg; 101397403Sobrien char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); 101497403Sobrien for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) 101597403Sobrien { 101697403Sobrien part __which = static_cast<part>(__p.field[__i]); 101797403Sobrien switch (__which) 101897403Sobrien { 101997403Sobrien case money_base::symbol: 102097403Sobrien if (__io.flags() & ios_base::showbase 102197403Sobrien || __i < 2 || __sign.size() > 1 102297403Sobrien || ((static_cast<part>(__p.field[3]) != money_base::none) 102397403Sobrien && __i == 2)) 102497403Sobrien { 102597403Sobrien // According to 22.2.6.1.2.2, symbol is required 102697403Sobrien // if (__io.flags() & ios_base::showbase), 102797403Sobrien // otherwise is optional and consumed only if 102897403Sobrien // other characters are needed to complete the 102997403Sobrien // format. 103097403Sobrien const string_type __symbol = __intl ? __mpt.curr_symbol() 103197403Sobrien : __mpf.curr_symbol(); 103297403Sobrien size_type __len = __symbol.size(); 103397403Sobrien size_type __j = 0; 103497403Sobrien while (__beg != __end 103597403Sobrien && __j < __len && __symbol[__j] == __c) 103697403Sobrien { 103797403Sobrien __c = *(++__beg); 103897403Sobrien ++__j; 103997403Sobrien } 104097403Sobrien // When (__io.flags() & ios_base::showbase) 104197403Sobrien // symbol is required. 104297403Sobrien if (__j != __len && (__io.flags() & ios_base::showbase)) 104397403Sobrien __testvalid = false; 104497403Sobrien } 104597403Sobrien break; 104697403Sobrien case money_base::sign: 104797403Sobrien // Sign might not exist, or be more than one character long. 104897403Sobrien if (__pos_sign.size() && __neg_sign.size()) 104997403Sobrien { 105097403Sobrien // Sign is mandatory. 105197403Sobrien if (__c == __pos_sign[0]) 105297403Sobrien { 105397403Sobrien __sign = __pos_sign; 105497403Sobrien __c = *(++__beg); 105597403Sobrien } 105697403Sobrien else if (__c == __neg_sign[0]) 105797403Sobrien { 105897403Sobrien __sign = __neg_sign; 105997403Sobrien __c = *(++__beg); 106097403Sobrien } 106197403Sobrien else 106297403Sobrien __testvalid = false; 106397403Sobrien } 106497403Sobrien else if (__pos_sign.size() && __c == __pos_sign[0]) 106597403Sobrien { 106697403Sobrien __sign = __pos_sign; 106797403Sobrien __c = *(++__beg); 106897403Sobrien } 106997403Sobrien else if (__neg_sign.size() && __c == __neg_sign[0]) 107097403Sobrien { 107197403Sobrien __sign = __neg_sign; 107297403Sobrien __c = *(++__beg); 107397403Sobrien } 107497403Sobrien break; 107597403Sobrien case money_base::value: 107697403Sobrien // Extract digits, remove and stash away the 107797403Sobrien // grouping of found thousands separators. 107897403Sobrien while (__beg != __end 107997403Sobrien && (__ctype.is(ctype_base::digit, __c) 108097403Sobrien || (__c == __d && !__testdecfound) 108197403Sobrien || __c == __sep)) 108297403Sobrien { 108397403Sobrien if (__c == __d) 108497403Sobrien { 108597403Sobrien __grouping_tmp += static_cast<char>(__sep_pos); 108697403Sobrien __sep_pos = 0; 108797403Sobrien __testdecfound = true; 108897403Sobrien } 108997403Sobrien else if (__c == __sep) 109097403Sobrien { 109197403Sobrien if (__grouping.size()) 109297403Sobrien { 109397403Sobrien // Mark position for later analysis. 109497403Sobrien __grouping_tmp += static_cast<char>(__sep_pos); 109597403Sobrien __sep_pos = 0; 109697403Sobrien } 109797403Sobrien else 109897403Sobrien { 109997403Sobrien __testvalid = false; 110097403Sobrien break; 110197403Sobrien } 110297403Sobrien } 110397403Sobrien else 110497403Sobrien { 110597403Sobrien __temp_units += __c; 110697403Sobrien ++__sep_pos; 110797403Sobrien } 110897403Sobrien __c = *(++__beg); 110997403Sobrien } 111097403Sobrien break; 111197403Sobrien case money_base::space: 111297403Sobrien case money_base::none: 111397403Sobrien // Only if not at the end of the pattern. 111497403Sobrien if (__i != 3) 111597403Sobrien while (__beg != __end 111697403Sobrien && __ctype.is(ctype_base::space, __c)) 111797403Sobrien __c = *(++__beg); 111897403Sobrien break; 111997403Sobrien } 112097403Sobrien } 112197403Sobrien 112297403Sobrien // Need to get the rest of the sign characters, if they exist. 112397403Sobrien if (__sign.size() > 1) 112497403Sobrien { 112597403Sobrien size_type __len = __sign.size(); 112697403Sobrien size_type __i = 1; 112797403Sobrien for (; __c != __eof && __i < __len; ++__i) 112897403Sobrien while (__beg != __end && __c != __sign[__i]) 112997403Sobrien __c = *(++__beg); 113097403Sobrien 113197403Sobrien if (__i != __len) 113297403Sobrien __testvalid = false; 113397403Sobrien } 113497403Sobrien 113597403Sobrien // Strip leading zeros. 113697403Sobrien while (__temp_units[0] == __ctype.widen('0')) 113797403Sobrien __temp_units.erase(__temp_units.begin()); 113897403Sobrien 113997403Sobrien if (__sign.size() && __sign == __neg_sign) 114097403Sobrien __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); 114197403Sobrien 114297403Sobrien // Test for grouping fidelity. 114397403Sobrien if (__grouping.size() && __grouping_tmp.size()) 114497403Sobrien { 114597403Sobrien if (!__verify_grouping(__grouping, __grouping_tmp)) 114697403Sobrien __testvalid = false; 114797403Sobrien } 114897403Sobrien 114997403Sobrien // Iff no more characters are available. 115097403Sobrien if (__c == __eof) 115197403Sobrien __err |= ios_base::eofbit; 115297403Sobrien 115397403Sobrien // Iff valid sequence is not recognized. 115497403Sobrien if (!__testvalid || !__temp_units.size()) 115597403Sobrien __err |= ios_base::failbit; 115697403Sobrien else 115797403Sobrien // Use the "swap trick" to copy __temp_units into __units. 115897403Sobrien __temp_units.swap(__units); 115997403Sobrien 116097403Sobrien return __beg; 116197403Sobrien } 116297403Sobrien 116397403Sobrien template<typename _CharT, typename _OutIter> 116497403Sobrien _OutIter 116597403Sobrien money_put<_CharT, _OutIter>:: 116697403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 116797403Sobrien long double __units) const 116897403Sobrien { 116997403Sobrien const locale __loc = __io.getloc(); 117097403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 117197403Sobrien#ifdef _GLIBCPP_USE_C99 117297403Sobrien // First try a buffer perhaps big enough. 117397403Sobrien int __cs_size = 64; 117497403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 117597403Sobrien int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 117697403Sobrien _S_c_locale); 117797403Sobrien // If the buffer was not large enough, try again with the correct size. 117897403Sobrien if (__len >= __cs_size) 117997403Sobrien { 118097403Sobrien __cs_size = __len + 1; 118197403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 118297403Sobrien __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 118397403Sobrien _S_c_locale); 118497403Sobrien } 118597403Sobrien#else 118697403Sobrien // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, 118797403Sobrien // decimal digit, '\0'. 118897403Sobrien const int __cs_size = numeric_limits<long double>::max_exponent10 + 5; 118997403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 119097403Sobrien int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); 119197403Sobrien#endif 119297403Sobrien _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); 119397403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 119497403Sobrien string_type __digits(__ws); 119597403Sobrien return this->do_put(__s, __intl, __io, __fill, __digits); 119697403Sobrien } 119797403Sobrien 119897403Sobrien template<typename _CharT, typename _OutIter> 119997403Sobrien _OutIter 120097403Sobrien money_put<_CharT, _OutIter>:: 120197403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 120297403Sobrien const string_type& __digits) const 120397403Sobrien { 120497403Sobrien typedef typename string_type::size_type size_type; 120597403Sobrien typedef money_base::part part; 120697403Sobrien 120797403Sobrien const locale __loc = __io.getloc(); 120897403Sobrien const size_type __width = static_cast<size_type>(__io.width()); 120997403Sobrien 121097403Sobrien // These contortions are quite unfortunate. 121197403Sobrien typedef moneypunct<_CharT, true> __money_true; 121297403Sobrien typedef moneypunct<_CharT, false> __money_false; 121397403Sobrien const __money_true& __mpt = use_facet<__money_true>(__loc); 121497403Sobrien const __money_false& __mpf = use_facet<__money_false>(__loc); 121597403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 121697403Sobrien 121797403Sobrien // Determine if negative or positive formats are to be used, and 121897403Sobrien // discard leading negative_sign if it is present. 121997403Sobrien const char_type* __beg = __digits.data(); 122097403Sobrien const char_type* __end = __beg + __digits.size(); 122197403Sobrien money_base::pattern __p; 122297403Sobrien string_type __sign; 122397403Sobrien if (*__beg != __ctype.widen('-')) 122497403Sobrien { 122597403Sobrien __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); 122697403Sobrien __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); 122797403Sobrien } 122897403Sobrien else 122997403Sobrien { 123097403Sobrien __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); 123197403Sobrien __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); 123297403Sobrien ++__beg; 123397403Sobrien } 123497403Sobrien 123597403Sobrien // Look for valid numbers in the current ctype facet within input digits. 123697403Sobrien __end = __ctype.scan_not(ctype_base::digit, __beg, __end); 123797403Sobrien if (__beg != __end) 123897403Sobrien { 123997403Sobrien // Assume valid input, and attempt to format. 124097403Sobrien // Break down input numbers into base components, as follows: 124197403Sobrien // final_value = grouped units + (decimal point) + (digits) 124297403Sobrien string_type __res; 124397403Sobrien string_type __value; 124497403Sobrien const string_type __symbol = __intl ? __mpt.curr_symbol() 124597403Sobrien : __mpf.curr_symbol(); 124697403Sobrien 124797403Sobrien // Deal with decimal point, decimal digits. 124897403Sobrien const int __frac = __intl ? __mpt.frac_digits() 124997403Sobrien : __mpf.frac_digits(); 125097403Sobrien if (__frac > 0) 125197403Sobrien { 125297403Sobrien const char_type __d = __intl ? __mpt.decimal_point() 125397403Sobrien : __mpf.decimal_point(); 125497403Sobrien if (__end - __beg >= __frac) 125597403Sobrien { 125697403Sobrien __value = string_type(__end - __frac, __end); 125797403Sobrien __value.insert(__value.begin(), __d); 125897403Sobrien __end -= __frac; 125997403Sobrien } 126097403Sobrien else 126197403Sobrien { 126297403Sobrien // Have to pad zeros in the decimal position. 126397403Sobrien __value = string_type(__beg, __end); 126497403Sobrien int __paddec = __frac - (__end - __beg); 126597403Sobrien char_type __zero = __ctype.widen('0'); 126697403Sobrien __value.insert(__value.begin(), __paddec, __zero); 126797403Sobrien __value.insert(__value.begin(), __d); 126897403Sobrien __beg = __end; 126997403Sobrien } 127097403Sobrien } 127197403Sobrien 127297403Sobrien // Add thousands separators to non-decimal digits, per 127397403Sobrien // grouping rules. 127497403Sobrien if (__beg != __end) 127597403Sobrien { 127697403Sobrien const string __grouping = __intl ? __mpt.grouping() 127797403Sobrien : __mpf.grouping(); 127897403Sobrien if (__grouping.size()) 127997403Sobrien { 128097403Sobrien const char_type __sep = __intl ? __mpt.thousands_sep() 128197403Sobrien : __mpf.thousands_sep(); 128297403Sobrien const char* __gbeg = __grouping.c_str(); 128397403Sobrien const char* __gend = __gbeg + __grouping.size(); 128497403Sobrien const int __n = (__end - __beg) * 2; 128597403Sobrien _CharT* __ws2 = 128697403Sobrien static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); 128797403Sobrien _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 128897403Sobrien __gend, __beg, __end); 128997403Sobrien __value.insert(0, __ws2, __ws_end - __ws2); 129097403Sobrien } 129197403Sobrien else 129297403Sobrien __value.insert(0, string_type(__beg, __end)); 129397403Sobrien } 129497403Sobrien 129597403Sobrien // Calculate length of resulting string. 129697403Sobrien ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; 129797403Sobrien size_type __len = __value.size() + __sign.size(); 129897403Sobrien __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; 129997403Sobrien bool __testipad = __f == ios_base::internal && __len < __width; 130097403Sobrien 130197403Sobrien // Fit formatted digits into the required pattern. 130297403Sobrien for (int __i = 0; __i < 4; ++__i) 130397403Sobrien { 130497403Sobrien part __which = static_cast<part>(__p.field[__i]); 130597403Sobrien switch (__which) 130697403Sobrien { 130797403Sobrien case money_base::symbol: 130897403Sobrien if (__io.flags() & ios_base::showbase) 130997403Sobrien __res += __symbol; 131097403Sobrien break; 131197403Sobrien case money_base::sign: 131297403Sobrien // Sign might not exist, or be more than one 131397403Sobrien // charater long. In that case, add in the rest 131497403Sobrien // below. 131597403Sobrien if (__sign.size()) 131697403Sobrien __res += __sign[0]; 131797403Sobrien break; 131897403Sobrien case money_base::value: 131997403Sobrien __res += __value; 132097403Sobrien break; 132197403Sobrien case money_base::space: 132297403Sobrien // At least one space is required, but if internal 132397403Sobrien // formatting is required, an arbitrary number of 132497403Sobrien // fill spaces will be necessary. 132597403Sobrien if (__testipad) 132697403Sobrien __res += string_type(__width - __len, __fill); 132797403Sobrien else 132897403Sobrien __res += __ctype.widen(__fill); 132997403Sobrien break; 133097403Sobrien case money_base::none: 133197403Sobrien if (__testipad) 133297403Sobrien __res += string_type(__width - __len, __fill); 133397403Sobrien break; 133497403Sobrien } 133597403Sobrien } 133697403Sobrien 133797403Sobrien // Special case of multi-part sign parts. 133897403Sobrien if (__sign.size() > 1) 133997403Sobrien __res += string_type(__sign.begin() + 1, __sign.end()); 134097403Sobrien 134197403Sobrien // Pad, if still necessary. 134297403Sobrien __len = __res.size(); 134397403Sobrien if (__width > __len) 134497403Sobrien { 134597403Sobrien if (__f == ios_base::left) 134697403Sobrien // After. 134797403Sobrien __res.append(__width - __len, __fill); 134897403Sobrien else 134997403Sobrien // Before. 135097403Sobrien __res.insert(0, string_type(__width - __len, __fill)); 135197403Sobrien __len = __width; 135297403Sobrien } 135397403Sobrien 135497403Sobrien // Write resulting, fully-formatted string to output iterator. 135597403Sobrien for (size_type __j = 0; __j < __len; ++__j, ++__s) 135697403Sobrien *__s = __res[__j]; 135797403Sobrien } 135897403Sobrien __io.width(0); 135997403Sobrien return __s; 136097403Sobrien } 136197403Sobrien 136297403Sobrien 136397403Sobrien // NB: Not especially useful. Without an ios_base object or some 136497403Sobrien // kind of locale reference, we are left clawing at the air where 136597403Sobrien // the side of the mountain used to be... 136697403Sobrien template<typename _CharT, typename _InIter> 136797403Sobrien time_base::dateorder 136897403Sobrien time_get<_CharT, _InIter>::do_date_order() const 136997403Sobrien { return time_base::no_order; } 137097403Sobrien 137197403Sobrien template<typename _CharT, typename _InIter> 137297403Sobrien void 137397403Sobrien time_get<_CharT, _InIter>:: 137497403Sobrien _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, 137597403Sobrien ios_base::iostate& __err, tm* __tm, 137697403Sobrien const _CharT* __format) const 137797403Sobrien { 137897403Sobrien locale __loc = __io.getloc(); 137997403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 138097403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 138197403Sobrien size_t __len = char_traits<_CharT>::length(__format); 138297403Sobrien 138397403Sobrien for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 138497403Sobrien { 138597403Sobrien char __c = __format[__i]; 138697403Sobrien if (__c == '%') 138797403Sobrien { 138897403Sobrien // Verify valid formatting code, attempt to extract. 138997403Sobrien __c = __format[++__i]; 139097403Sobrien char __mod = 0; 139197403Sobrien int __mem = 0; 139297403Sobrien if (__c == 'E' || __c == 'O') 139397403Sobrien { 139497403Sobrien __mod = __c; 139597403Sobrien __c = __format[++__i]; 139697403Sobrien } 139797403Sobrien switch (__c) 139897403Sobrien { 139997403Sobrien const char* __cs; 140097403Sobrien _CharT __wcs[10]; 140197403Sobrien case 'a': 140297403Sobrien // Abbreviated weekday name [tm_wday] 140397403Sobrien const char_type* __days1[7]; 140497403Sobrien __tp._M_days_abbreviated(__days1); 140597403Sobrien _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 140697403Sobrien __err); 140797403Sobrien break; 140897403Sobrien case 'A': 140997403Sobrien // Weekday name [tm_wday]. 141097403Sobrien const char_type* __days2[7]; 141197403Sobrien __tp._M_days(__days2); 141297403Sobrien _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 141397403Sobrien __err); 141497403Sobrien break; 141597403Sobrien case 'h': 141697403Sobrien case 'b': 141797403Sobrien // Abbreviated month name [tm_mon] 141897403Sobrien const char_type* __months1[12]; 141997403Sobrien __tp._M_months_abbreviated(__months1); 142097403Sobrien _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 142197403Sobrien __err); 142297403Sobrien break; 142397403Sobrien case 'B': 142497403Sobrien // Month name [tm_mon]. 142597403Sobrien const char_type* __months2[12]; 142697403Sobrien __tp._M_months(__months2); 142797403Sobrien _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 142897403Sobrien __err); 142997403Sobrien break; 143097403Sobrien case 'c': 143197403Sobrien // Default time and date representation. 143297403Sobrien const char_type* __dt[2]; 143397403Sobrien __tp._M_date_time_formats(__dt); 143497403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 143597403Sobrien __dt[0]); 143697403Sobrien break; 143797403Sobrien case 'd': 143897403Sobrien // Day [01, 31]. [tm_mday] 143997403Sobrien _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 144097403Sobrien __ctype, __err); 144197403Sobrien break; 144297403Sobrien case 'D': 144397403Sobrien // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 144497403Sobrien __cs = "%m/%d/%y"; 144597403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 144697403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 144797403Sobrien __wcs); 144897403Sobrien break; 144997403Sobrien case 'H': 145097403Sobrien // Hour [00, 23]. [tm_hour] 145197403Sobrien _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 145297403Sobrien __ctype, __err); 145397403Sobrien break; 145497403Sobrien case 'I': 145597403Sobrien // Hour [01, 12]. [tm_hour] 145697403Sobrien _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 145797403Sobrien __ctype, __err); 145897403Sobrien break; 145997403Sobrien case 'm': 146097403Sobrien // Month [01, 12]. [tm_mon] 146197403Sobrien _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 146297403Sobrien __err); 146397403Sobrien if (!__err) 146497403Sobrien __tm->tm_mon = __mem - 1; 146597403Sobrien break; 146697403Sobrien case 'M': 146797403Sobrien // Minute [00, 59]. [tm_min] 146897403Sobrien _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 146997403Sobrien __ctype, __err); 147097403Sobrien break; 147197403Sobrien case 'n': 147297403Sobrien if (__ctype.narrow(*__beg, 0) == '\n') 147397403Sobrien ++__beg; 147497403Sobrien else 147597403Sobrien __err |= ios_base::failbit; 147697403Sobrien break; 147797403Sobrien case 'R': 147897403Sobrien // Equivalent to (%H:%M). 147997403Sobrien __cs = "%H:%M"; 148097403Sobrien __ctype.widen(__cs, __cs + 6, __wcs); 148197403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 148297403Sobrien __wcs); 148397403Sobrien break; 148497403Sobrien case 'S': 148597403Sobrien // Seconds. 148697403Sobrien _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 148797403Sobrien __ctype, __err); 148897403Sobrien break; 148997403Sobrien case 't': 149097403Sobrien if (__ctype.narrow(*__beg, 0) == '\t') 149197403Sobrien ++__beg; 149297403Sobrien else 149397403Sobrien __err |= ios_base::failbit; 149497403Sobrien break; 149597403Sobrien case 'T': 149697403Sobrien // Equivalent to (%H:%M:%S). 149797403Sobrien __cs = "%H:%M:%S"; 149897403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 149997403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 150097403Sobrien __wcs); 150197403Sobrien break; 150297403Sobrien case 'x': 150397403Sobrien // Locale's date. 150497403Sobrien const char_type* __dates[2]; 150597403Sobrien __tp._M_date_formats(__dates); 150697403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 150797403Sobrien __dates[0]); 150897403Sobrien break; 150997403Sobrien case 'X': 151097403Sobrien // Locale's time. 151197403Sobrien const char_type* __times[2]; 151297403Sobrien __tp._M_time_formats(__times); 151397403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 151497403Sobrien __times[0]); 151597403Sobrien break; 151697403Sobrien case 'y': 151797403Sobrien // Two digit year. [tm_year] 151897403Sobrien _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 151997403Sobrien __ctype, __err); 152097403Sobrien break; 152197403Sobrien case 'Y': 152297403Sobrien // Year [1900). [tm_year] 152397403Sobrien _M_extract_num(__beg, __end, __mem, 0, 152497403Sobrien numeric_limits<int>::max(), 4, 152597403Sobrien __ctype, __err); 152697403Sobrien if (!__err) 152797403Sobrien __tm->tm_year = __mem - 1900; 152897403Sobrien break; 152997403Sobrien case 'Z': 153097403Sobrien // Timezone info. 153197403Sobrien if (__ctype.is(ctype_base::upper, *__beg)) 153297403Sobrien { 153397403Sobrien int __tmp; 153497403Sobrien _M_extract_name(__beg, __end, __tmp, 153597403Sobrien __timepunct<_CharT>::_S_timezones, 153697403Sobrien 14, __err); 153797403Sobrien 153897403Sobrien // GMT requires special effort. 153997403Sobrien char_type __c = *__beg; 154097403Sobrien if (!__err && __tmp == 0 154197403Sobrien && (__c == __ctype.widen('-') 154297403Sobrien || __c == __ctype.widen('+'))) 154397403Sobrien { 154497403Sobrien _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 154597403Sobrien __ctype, __err); 154697403Sobrien _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 154797403Sobrien __ctype, __err); 154897403Sobrien } 154997403Sobrien } 155097403Sobrien else 155197403Sobrien __err |= ios_base::failbit; 155297403Sobrien break; 155397403Sobrien default: 155497403Sobrien // Not recognized. 155597403Sobrien __err |= ios_base::failbit; 155697403Sobrien } 155797403Sobrien } 155897403Sobrien else 155997403Sobrien { 156097403Sobrien // Verify format and input match, extract and discard. 156197403Sobrien if (__c == __ctype.narrow(*__beg, 0)) 156297403Sobrien ++__beg; 156397403Sobrien else 156497403Sobrien __err |= ios_base::failbit; 156597403Sobrien } 156697403Sobrien } 156797403Sobrien } 156897403Sobrien 156997403Sobrien template<typename _CharT, typename _InIter> 157097403Sobrien void 157197403Sobrien time_get<_CharT, _InIter>:: 157297403Sobrien _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, 157397403Sobrien int __min, int __max, size_t __len, 157497403Sobrien const ctype<_CharT>& __ctype, 157597403Sobrien ios_base::iostate& __err) const 157697403Sobrien { 157797403Sobrien size_t __i = 0; 157897403Sobrien string __digits; 157997403Sobrien bool __testvalid = true; 158097403Sobrien char_type __c = *__beg; 158197403Sobrien while (__beg != __end && __i < __len 158297403Sobrien && __ctype.is(ctype_base::digit, __c)) 158397403Sobrien { 158497403Sobrien __digits += __ctype.narrow(__c, 0); 158597403Sobrien __c = *(++__beg); 158697403Sobrien ++__i; 158797403Sobrien } 158897403Sobrien if (__i == __len) 158997403Sobrien { 159097403Sobrien int __value = atoi(__digits.c_str()); 159197403Sobrien if (__min <= __value && __value <= __max) 159297403Sobrien __member = __value; 159397403Sobrien else 159497403Sobrien __testvalid = false; 159597403Sobrien } 159697403Sobrien else 159797403Sobrien __testvalid = false; 159897403Sobrien if (!__testvalid) 159997403Sobrien __err |= ios_base::failbit; 160097403Sobrien } 160197403Sobrien 160297403Sobrien // Assumptions: 160397403Sobrien // All elements in __names are unique. 160497403Sobrien template<typename _CharT, typename _InIter> 160597403Sobrien void 160697403Sobrien time_get<_CharT, _InIter>:: 160797403Sobrien _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, 160897403Sobrien const _CharT** __names, size_t __indexlen, 160997403Sobrien ios_base::iostate& __err) const 161097403Sobrien { 1611102782Skan typedef char_traits<_CharT> __traits_type; 161297403Sobrien int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen)); 161397403Sobrien size_t __nmatches = 0; 161497403Sobrien size_t __pos = 0; 161597403Sobrien bool __testvalid = true; 161697403Sobrien const char_type* __name; 161797403Sobrien 161897403Sobrien char_type __c = *__beg; 161997403Sobrien // Look for initial matches. 162097403Sobrien for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 162197403Sobrien if (__c == __names[__i1][0]) 162297403Sobrien __matches[__nmatches++] = __i1; 162397403Sobrien 162497403Sobrien while(__nmatches > 1) 162597403Sobrien { 162697403Sobrien // Find smallest matching string. 162797403Sobrien size_t __minlen = 10; 162897403Sobrien for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 162997403Sobrien __minlen = min(__minlen, 163097403Sobrien __traits_type::length(__names[__matches[__i2]])); 163197403Sobrien 163297403Sobrien if (__pos < __minlen && __beg != __end) 163397403Sobrien { 163497403Sobrien ++__pos; 163597403Sobrien __c = *(++__beg); 163697403Sobrien for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 163797403Sobrien { 163897403Sobrien __name = __names[__matches[__i3]]; 163997403Sobrien if (__name[__pos] != __c) 164097403Sobrien __matches[__i3] = __matches[--__nmatches]; 164197403Sobrien } 164297403Sobrien } 164397403Sobrien else 164497403Sobrien break; 164597403Sobrien } 164697403Sobrien 164797403Sobrien if (__nmatches == 1) 164897403Sobrien { 164997403Sobrien // Make sure found name is completely extracted. 165097403Sobrien __name = __names[__matches[0]]; 165197403Sobrien const size_t __len = __traits_type::length(__name); 165297403Sobrien while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 165397403Sobrien ++__beg, ++__pos; 165497403Sobrien 165597403Sobrien if (__len == __pos) 165697403Sobrien __member = __matches[0]; 165797403Sobrien else 165897403Sobrien __testvalid = false; 165997403Sobrien } 166097403Sobrien else 166197403Sobrien __testvalid = false; 166297403Sobrien if (!__testvalid) 166397403Sobrien __err |= ios_base::failbit; 166497403Sobrien } 166597403Sobrien 166697403Sobrien template<typename _CharT, typename _InIter> 166797403Sobrien _InIter 166897403Sobrien time_get<_CharT, _InIter>:: 166997403Sobrien do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 167097403Sobrien ios_base::iostate& __err, tm* __tm) const 167197403Sobrien { 167297403Sobrien _CharT __wcs[3]; 167397403Sobrien const char* __cs = "%X"; 167497403Sobrien locale __loc = __io.getloc(); 167597403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 167697403Sobrien __ctype.widen(__cs, __cs + 3, __wcs); 167797403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 167897403Sobrien if (__beg == __end) 167997403Sobrien __err |= ios_base::eofbit; 168097403Sobrien return __beg; 168197403Sobrien } 168297403Sobrien 168397403Sobrien template<typename _CharT, typename _InIter> 168497403Sobrien _InIter 168597403Sobrien time_get<_CharT, _InIter>:: 168697403Sobrien do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 168797403Sobrien ios_base::iostate& __err, tm* __tm) const 168897403Sobrien { 168997403Sobrien _CharT __wcs[3]; 169097403Sobrien const char* __cs = "%x"; 169197403Sobrien locale __loc = __io.getloc(); 169297403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 169397403Sobrien __ctype.widen(__cs, __cs + 3, __wcs); 169497403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 169597403Sobrien if (__beg == __end) 169697403Sobrien __err |= ios_base::eofbit; 169797403Sobrien return __beg; 169897403Sobrien } 169997403Sobrien 170097403Sobrien template<typename _CharT, typename _InIter> 170197403Sobrien _InIter 170297403Sobrien time_get<_CharT, _InIter>:: 170397403Sobrien do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 170497403Sobrien ios_base::iostate& __err, tm* __tm) const 170597403Sobrien { 1706102782Skan typedef char_traits<_CharT> __traits_type; 170797403Sobrien locale __loc = __io.getloc(); 170897403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 170997403Sobrien const char_type* __days[7]; 171097403Sobrien __tp._M_days_abbreviated(__days); 171197403Sobrien int __tmpwday; 171297403Sobrien _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); 171397403Sobrien 171497403Sobrien // Check to see if non-abbreviated name exists, and extract. 171597403Sobrien // NB: Assumes both _M_days and _M_days_abbreviated organized in 171697403Sobrien // exact same order, first to last, such that the resulting 171797403Sobrien // __days array with the same index points to a day, and that 171897403Sobrien // day's abbreviated form. 171997403Sobrien // NB: Also assumes that an abbreviated name is a subset of the name. 172097403Sobrien if (!__err) 172197403Sobrien { 172297403Sobrien size_t __pos = __traits_type::length(__days[__tmpwday]); 172397403Sobrien __tp._M_days(__days); 172497403Sobrien const char_type* __name = __days[__tmpwday]; 172597403Sobrien if (__name[__pos] == *__beg) 172697403Sobrien { 172797403Sobrien // Extract the rest of it. 172897403Sobrien const size_t __len = __traits_type::length(__name); 172997403Sobrien while (__pos < __len && __beg != __end 173097403Sobrien && __name[__pos] == *__beg) 173197403Sobrien ++__beg, ++__pos; 173297403Sobrien if (__len != __pos) 173397403Sobrien __err |= ios_base::failbit; 173497403Sobrien } 173597403Sobrien if (!__err) 173697403Sobrien __tm->tm_wday = __tmpwday; 173797403Sobrien } 173897403Sobrien if (__beg == __end) 173997403Sobrien __err |= ios_base::eofbit; 174097403Sobrien return __beg; 174197403Sobrien } 174297403Sobrien 174397403Sobrien template<typename _CharT, typename _InIter> 174497403Sobrien _InIter 174597403Sobrien time_get<_CharT, _InIter>:: 174697403Sobrien do_get_monthname(iter_type __beg, iter_type __end, 174797403Sobrien ios_base& __io, ios_base::iostate& __err, tm* __tm) const 174897403Sobrien { 1749102782Skan typedef char_traits<_CharT> __traits_type; 175097403Sobrien locale __loc = __io.getloc(); 175197403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 175297403Sobrien const char_type* __months[12]; 175397403Sobrien __tp._M_months_abbreviated(__months); 175497403Sobrien int __tmpmon; 175597403Sobrien _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); 175697403Sobrien 175797403Sobrien // Check to see if non-abbreviated name exists, and extract. 175897403Sobrien // NB: Assumes both _M_months and _M_months_abbreviated organized in 175997403Sobrien // exact same order, first to last, such that the resulting 176097403Sobrien // __months array with the same index points to a month, and that 176197403Sobrien // month's abbreviated form. 176297403Sobrien // NB: Also assumes that an abbreviated name is a subset of the name. 176397403Sobrien if (!__err) 176497403Sobrien { 176597403Sobrien size_t __pos = __traits_type::length(__months[__tmpmon]); 176697403Sobrien __tp._M_months(__months); 176797403Sobrien const char_type* __name = __months[__tmpmon]; 176897403Sobrien if (__name[__pos] == *__beg) 176997403Sobrien { 177097403Sobrien // Extract the rest of it. 177197403Sobrien const size_t __len = __traits_type::length(__name); 177297403Sobrien while (__pos < __len && __beg != __end 177397403Sobrien && __name[__pos] == *__beg) 177497403Sobrien ++__beg, ++__pos; 177597403Sobrien if (__len != __pos) 177697403Sobrien __err |= ios_base::failbit; 177797403Sobrien } 177897403Sobrien if (!__err) 177997403Sobrien __tm->tm_mon = __tmpmon; 178097403Sobrien } 178197403Sobrien 178297403Sobrien if (__beg == __end) 178397403Sobrien __err |= ios_base::eofbit; 178497403Sobrien return __beg; 178597403Sobrien } 178697403Sobrien 178797403Sobrien template<typename _CharT, typename _InIter> 178897403Sobrien _InIter 178997403Sobrien time_get<_CharT, _InIter>:: 179097403Sobrien do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 179197403Sobrien ios_base::iostate& __err, tm* __tm) const 179297403Sobrien { 179397403Sobrien locale __loc = __io.getloc(); 179497403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 179597403Sobrien 179697403Sobrien char_type __c = *__beg; 179797403Sobrien size_t __i = 0; 179897403Sobrien string __digits; 179997403Sobrien while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) 180097403Sobrien { 180197403Sobrien __digits += __ctype.narrow(__c, 0); 180297403Sobrien __c = *(++__beg); 180397403Sobrien ++__i; 180497403Sobrien } 180597403Sobrien if (__i == 2 || __i == 4) 180697403Sobrien { 180797403Sobrien long __l; 180897403Sobrien __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); 180997403Sobrien if (!(__err & ios_base::failbit) && __l <= INT_MAX) 181097403Sobrien { 181197403Sobrien __l = __i == 2 ? __l : __l - 1900; 181297403Sobrien __tm->tm_year = static_cast<int>(__l); 181397403Sobrien } 181497403Sobrien } 181597403Sobrien else 181697403Sobrien __err |= ios_base::failbit; 181797403Sobrien if (__beg == __end) 181897403Sobrien __err |= ios_base::eofbit; 181997403Sobrien return __beg; 182097403Sobrien } 182197403Sobrien 182297403Sobrien template<typename _CharT, typename _OutIter> 182397403Sobrien _OutIter 182497403Sobrien time_put<_CharT, _OutIter>:: 182597403Sobrien put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 182697403Sobrien const _CharT* __beg, const _CharT* __end) const 182797403Sobrien { 182897403Sobrien locale __loc = __io.getloc(); 182997403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 183097403Sobrien while (__beg != __end) 183197403Sobrien { 183297403Sobrien char __c = __ctype.narrow(*__beg, 0); 183397403Sobrien ++__beg; 183497403Sobrien if (__c == '%') 183597403Sobrien { 183697403Sobrien char __format; 183797403Sobrien char __mod = 0; 183897403Sobrien size_t __len = 1; 183997403Sobrien __c = __ctype.narrow(*__beg, 0); 184097403Sobrien ++__beg; 184197403Sobrien if (__c == 'E' || __c == 'O') 184297403Sobrien { 184397403Sobrien __mod = __c; 184497403Sobrien __format = __ctype.narrow(*__beg, 0); 184597403Sobrien ++__beg; 184697403Sobrien } 184797403Sobrien else 184897403Sobrien __format = __c; 184997403Sobrien __s = this->do_put(__s, __io, char_type(), __tm, __format, 185097403Sobrien __mod); 185197403Sobrien } 185297403Sobrien else 185397403Sobrien { 185497403Sobrien *__s = __c; 185597403Sobrien ++__s; 185697403Sobrien } 185797403Sobrien } 185897403Sobrien return __s; 185997403Sobrien } 186097403Sobrien 186197403Sobrien template<typename _CharT, typename _OutIter> 186297403Sobrien _OutIter 186397403Sobrien time_put<_CharT, _OutIter>:: 186497403Sobrien do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 186597403Sobrien char __format, char __mod) const 186697403Sobrien { 186797403Sobrien locale __loc = __io.getloc(); 186897403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 186997403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 187097403Sobrien 187197403Sobrien // NB: This size is arbitrary. Should this be a data member, 187297403Sobrien // initialized at construction? 187397403Sobrien const size_t __maxlen = 64; 187497403Sobrien char_type* __res = 187597403Sobrien static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 187697403Sobrien 187797403Sobrien // NB: In IEE 1003.1-200x, and perhaps other locale models, it 187897403Sobrien // is possible that the format character will be longer than one 187997403Sobrien // character. Possibilities include 'E' or 'O' followed by a 188097403Sobrien // format character: if __mod is not the default argument, assume 188197403Sobrien // it's a valid modifier. 188297403Sobrien char_type __fmt[4]; 188397403Sobrien __fmt[0] = __ctype.widen('%'); 188497403Sobrien if (!__mod) 188597403Sobrien { 188697403Sobrien __fmt[1] = __format; 188797403Sobrien __fmt[2] = char_type(); 188897403Sobrien } 188997403Sobrien else 189097403Sobrien { 189197403Sobrien __fmt[1] = __mod; 189297403Sobrien __fmt[2] = __format; 189397403Sobrien __fmt[3] = char_type(); 189497403Sobrien } 189597403Sobrien 189697403Sobrien __tp._M_put(__res, __maxlen, __fmt, __tm); 189797403Sobrien 189897403Sobrien // Write resulting, fully-formatted string to output iterator. 189997403Sobrien size_t __len = char_traits<char_type>::length(__res); 190097403Sobrien for (size_t __i = 0; __i < __len; ++__i, ++__s) 190197403Sobrien *__s = __res[__i]; 190297403Sobrien return __s; 190397403Sobrien } 190497403Sobrien 190597403Sobrien 190697403Sobrien // Generic version does nothing. 190797403Sobrien template<typename _CharT> 190897403Sobrien int 190997403Sobrien collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 191097403Sobrien { return 0; } 191197403Sobrien 191297403Sobrien // Generic version does nothing. 191397403Sobrien template<typename _CharT> 191497403Sobrien size_t 191597403Sobrien collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 191697403Sobrien { return 0; } 191797403Sobrien 191897403Sobrien template<typename _CharT> 191997403Sobrien int 192097403Sobrien collate<_CharT>:: 192197403Sobrien do_compare(const _CharT* __lo1, const _CharT* __hi1, 192297403Sobrien const _CharT* __lo2, const _CharT* __hi2) const 192397403Sobrien { 192497403Sobrien const string_type __one(__lo1, __hi1); 192597403Sobrien const string_type __two(__lo2, __hi2); 192697403Sobrien return _M_compare(__one.c_str(), __two.c_str()); 192797403Sobrien } 192897403Sobrien 192997403Sobrien template<typename _CharT> 193097403Sobrien typename collate<_CharT>::string_type 193197403Sobrien collate<_CharT>:: 193297403Sobrien do_transform(const _CharT* __lo, const _CharT* __hi) const 193397403Sobrien { 193497403Sobrien size_t __len = (__hi - __lo) * 2; 193597403Sobrien // First try a buffer perhaps big enough. 193697403Sobrien _CharT* __c = 193797403Sobrien static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 193897403Sobrien size_t __res = _M_transform(__c, __lo, __len); 193997403Sobrien // If the buffer was not large enough, try again with the correct size. 194097403Sobrien if (__res >= __len) 194197403Sobrien { 194297403Sobrien __c = 194397403Sobrien static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); 194497403Sobrien _M_transform(__c, __lo, __res + 1); 194597403Sobrien } 194697403Sobrien return string_type(__c); 194797403Sobrien } 194897403Sobrien 194997403Sobrien template<typename _CharT> 195097403Sobrien long 195197403Sobrien collate<_CharT>:: 195297403Sobrien do_hash(const _CharT* __lo, const _CharT* __hi) const 195397403Sobrien { 195497403Sobrien unsigned long __val = 0; 195597403Sobrien for (; __lo < __hi; ++__lo) 195697403Sobrien __val = *__lo + ((__val << 7) | 195797403Sobrien (__val >> (numeric_limits<unsigned long>::digits - 7))); 195897403Sobrien return static_cast<long>(__val); 195997403Sobrien } 196097403Sobrien 196197403Sobrien // Convert string to numeric value of type _Tv and store results. 196297403Sobrien // NB: This is specialized for all required types, there is no 196397403Sobrien // generic definition. 196497403Sobrien template<typename _Tv> 196597403Sobrien void 196697403Sobrien __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, 196797403Sobrien const __c_locale& __cloc, int __base = 10); 196897403Sobrien 196997403Sobrien // Convert numeric value of type _Tv to string and return length of string. 197097403Sobrien // If snprintf is available use it, otherwise fall back to the unsafe sprintf 197197403Sobrien // which, in general, can be dangerous and should be avoided. 197297403Sobrien#ifdef _GLIBCPP_USE_C99 197397403Sobrien template<typename _Tv> 197497403Sobrien int 197597403Sobrien __convert_from_v(char* __out, const int __size, const char* __fmt, 197697403Sobrien _Tv __v, const __c_locale&, int __prec = -1) 197797403Sobrien { 197897403Sobrien int __ret; 1979102782Skan char* __old = strdup(setlocale(LC_ALL, NULL)); 1980102782Skan setlocale(LC_ALL, "C"); 198197403Sobrien if (__prec >= 0) 198297403Sobrien __ret = snprintf(__out, __size, __fmt, __prec, __v); 198397403Sobrien else 198497403Sobrien __ret = snprintf(__out, __size, __fmt, __v); 198597403Sobrien setlocale(LC_ALL, __old); 1986102782Skan free(__old); 198797403Sobrien return __ret; 198897403Sobrien } 198997403Sobrien#else 199097403Sobrien template<typename _Tv> 199197403Sobrien int 199297403Sobrien __convert_from_v(char* __out, const int, const char* __fmt, _Tv __v, 199397403Sobrien const __c_locale&, int __prec = -1) 199497403Sobrien { 199597403Sobrien int __ret; 1996102782Skan char* __old = strdup(setlocale(LC_ALL, NULL)); 1997102782Skan setlocale(LC_ALL, "C"); 199897403Sobrien if (__prec >= 0) 199997403Sobrien __ret = sprintf(__out, __fmt, __prec, __v); 200097403Sobrien else 200197403Sobrien __ret = sprintf(__out, __fmt, __v); 200297403Sobrien setlocale(LC_ALL, __old); 2003102782Skan free(__old); 200497403Sobrien return __ret; 200597403Sobrien } 200697403Sobrien#endif 200797403Sobrien 200897403Sobrien // Construct correctly padded string, as per 22.2.2.2.2 200997403Sobrien // Assumes 201097403Sobrien // __newlen > __oldlen 201197403Sobrien // __news is allocated for __newlen size 201297403Sobrien // Used by both num_put and ostream inserters: if __num, 201397403Sobrien // internal-adjusted objects are padded according to the rules below 201497403Sobrien // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 201597403Sobrien // ones are. 2016102782Skan 2017102782Skan // NB: Of the two parameters, _CharT can be deduced from the 2018102782Skan // function arguments. The other (_Traits) has to be explicitly specified. 201997403Sobrien template<typename _CharT, typename _Traits> 2020102782Skan struct __pad 202197403Sobrien { 2022102782Skan static void 2023102782Skan _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, 2024102782Skan const _CharT* __olds, const streamsize __newlen, 2025102782Skan const streamsize __oldlen, const bool __num); 2026102782Skan }; 202797403Sobrien 2028102782Skan template<typename _CharT, typename _Traits> 2029102782Skan void 2030102782Skan __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2031102782Skan _CharT* __news, const _CharT* __olds, 2032102782Skan const streamsize __newlen, 2033102782Skan const streamsize __oldlen, const bool __num) 2034102782Skan { 2035102782Skan size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2036102782Skan _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen)); 2037102782Skan _Traits::assign(__pads, __plen, __fill); 2038102782Skan 2039102782Skan _CharT* __beg; 2040102782Skan _CharT* __end; 204197403Sobrien size_t __mod = 0; 204297403Sobrien size_t __beglen; //either __plen or __oldlen 204397403Sobrien ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 204497403Sobrien 204597403Sobrien if (__adjust == ios_base::left) 204697403Sobrien { 204797403Sobrien // Padding last. 2048102782Skan __beg = const_cast<_CharT*>(__olds); 204997403Sobrien __beglen = __oldlen; 205097403Sobrien __end = __pads; 205197403Sobrien } 205297403Sobrien else if (__adjust == ios_base::internal && __num) 205397403Sobrien { 205497403Sobrien // Pad after the sign, if there is one. 205597403Sobrien // Pad after 0[xX], if there is one. 205697403Sobrien // Who came up with these rules, anyway? Jeeze. 205797403Sobrien locale __loc = __io.getloc(); 205897403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2059102782Skan const _CharT __minus = __ctype.widen('-'); 2060102782Skan const _CharT __plus = __ctype.widen('+'); 2061102782Skan bool __testsign = _Traits::eq(__olds[0], __minus) 2062102782Skan || _Traits::eq(__olds[0], __plus); 2063102782Skan 2064102782Skan bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 2065102782Skan && (_Traits::eq(__ctype.widen('x'), __olds[1]) 2066102782Skan || _Traits::eq(__ctype.widen('X'), __olds[1])); 206797403Sobrien if (__testhex) 206897403Sobrien { 206997403Sobrien __news[0] = __olds[0]; 207097403Sobrien __news[1] = __olds[1]; 207197403Sobrien __mod += 2; 207297403Sobrien __news += 2; 207397403Sobrien __beg = __pads; 207497403Sobrien __beglen = __plen; 2075102782Skan __end = const_cast<_CharT*>(__olds + __mod); 207697403Sobrien } 207797403Sobrien else if (__testsign) 207897403Sobrien { 2079102782Skan _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; 208097403Sobrien ++__mod; 208197403Sobrien ++__news; 208297403Sobrien __beg = __pads; 208397403Sobrien __beglen = __plen; 2084102782Skan __end = const_cast<_CharT*>(__olds + __mod); 208597403Sobrien } 208697403Sobrien else 208797403Sobrien { 208897403Sobrien // Padding first. 208997403Sobrien __beg = __pads; 209097403Sobrien __beglen = __plen; 2091102782Skan __end = const_cast<_CharT*>(__olds); 209297403Sobrien } 209397403Sobrien } 209497403Sobrien else 209597403Sobrien { 209697403Sobrien // Padding first. 209797403Sobrien __beg = __pads; 209897403Sobrien __beglen = __plen; 2099102782Skan __end = const_cast<_CharT*>(__olds); 210097403Sobrien } 2101102782Skan _Traits::copy(__news, __beg, __beglen); 2102102782Skan _Traits::copy(__news + __beglen, __end, 2103102782Skan __newlen - __beglen - __mod); 210497403Sobrien } 210597403Sobrien 210697403Sobrien // Used by both numeric and monetary facets. 210797403Sobrien // Check to make sure that the __grouping_tmp string constructed in 210897403Sobrien // money_get or num_get matches the canonical grouping for a given 210997403Sobrien // locale. 211097403Sobrien // __grouping_tmp is parsed L to R 211197403Sobrien // 1,222,444 == __grouping_tmp of "/1/3/3" 211297403Sobrien // __grouping is parsed R to L 211397403Sobrien // 1,222,444 == __grouping of "/3" == "/3/3/3" 211497403Sobrien template<typename _CharT> 211597403Sobrien bool 211697403Sobrien __verify_grouping(const basic_string<_CharT>& __grouping, 211797403Sobrien basic_string<_CharT>& __grouping_tmp) 211897403Sobrien { 211997403Sobrien int __i = 0; 212097403Sobrien int __j = 0; 212197403Sobrien const int __len = __grouping.size(); 212297403Sobrien const int __n = __grouping_tmp.size(); 212397403Sobrien bool __test = true; 212497403Sobrien 212597403Sobrien // Parsed number groupings have to match the 212697403Sobrien // numpunct::grouping string exactly, starting at the 212797403Sobrien // right-most point of the parsed sequence of elements ... 212897403Sobrien while (__test && __i < __n - 1) 212997403Sobrien for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) 213097403Sobrien __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; 213197403Sobrien // ... but the last parsed grouping can be <= numpunct 213297403Sobrien // grouping. 213397403Sobrien __j == __len ? __j = 0 : __j; 213497403Sobrien __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; 213597403Sobrien return __test; 213697403Sobrien } 213797403Sobrien 213897403Sobrien // Used by both numeric and monetary facets. 213997403Sobrien // Inserts "group separator" characters into an array of characters. 214097403Sobrien // It's recursive, one iteration per group. It moves the characters 214197403Sobrien // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this 214297403Sobrien // only with __gbeg != __gend. 214397403Sobrien template<typename _CharT> 214497403Sobrien _CharT* 214597403Sobrien __add_grouping(_CharT* __s, _CharT __sep, 214697403Sobrien const char* __gbeg, const char* __gend, 214797403Sobrien const _CharT* __first, const _CharT* __last) 214897403Sobrien { 214997403Sobrien if (__last - __first > *__gbeg) 215097403Sobrien { 215197403Sobrien __s = __add_grouping(__s, __sep, 215297403Sobrien (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), 215397403Sobrien __gend, __first, __last - *__gbeg); 215497403Sobrien __first = __last - *__gbeg; 215597403Sobrien *__s++ = __sep; 215697403Sobrien } 215797403Sobrien do 215897403Sobrien *__s++ = *__first++; 215997403Sobrien while (__first != __last); 216097403Sobrien return __s; 216197403Sobrien } 216297403Sobrien 216397403Sobrien // Inhibit implicit instantiations for required instantiations, 216497403Sobrien // which are defined via explicit instantiations elsewhere. 216597403Sobrien // NB: This syntax is a GNU extension. 216697403Sobrien extern template class moneypunct<char, false>; 216797403Sobrien extern template class moneypunct<char, true>; 216897403Sobrien extern template class moneypunct_byname<char, false>; 216997403Sobrien extern template class moneypunct_byname<char, true>; 217097403Sobrien extern template class money_get<char>; 217197403Sobrien extern template class money_put<char>; 217297403Sobrien extern template class moneypunct<wchar_t, false>; 217397403Sobrien extern template class moneypunct<wchar_t, true>; 217497403Sobrien extern template class moneypunct_byname<wchar_t, false>; 217597403Sobrien extern template class moneypunct_byname<wchar_t, true>; 217697403Sobrien extern template class money_get<wchar_t>; 217797403Sobrien extern template class money_put<wchar_t>; 217897403Sobrien extern template class numpunct<char>; 217997403Sobrien extern template class numpunct_byname<char>; 218097403Sobrien extern template class num_get<char>; 218197403Sobrien extern template class num_put<char>; 218297403Sobrien extern template class numpunct<wchar_t>; 218397403Sobrien extern template class numpunct_byname<wchar_t>; 218497403Sobrien extern template class num_get<wchar_t>; 218597403Sobrien extern template class num_put<wchar_t>; 218697403Sobrien extern template class __timepunct<char>; 218797403Sobrien extern template class time_put<char>; 218897403Sobrien extern template class time_put_byname<char>; 218997403Sobrien extern template class time_get<char>; 219097403Sobrien extern template class time_get_byname<char>; 219197403Sobrien extern template class __timepunct<wchar_t>; 219297403Sobrien extern template class time_put<wchar_t>; 219397403Sobrien extern template class time_put_byname<wchar_t>; 219497403Sobrien extern template class time_get<wchar_t>; 219597403Sobrien extern template class time_get_byname<wchar_t>; 219697403Sobrien extern template class messages<char>; 219797403Sobrien extern template class messages_byname<char>; 219897403Sobrien extern template class messages<wchar_t>; 219997403Sobrien extern template class messages_byname<wchar_t>; 220097403Sobrien extern template class ctype_byname<char>; 220197403Sobrien extern template class ctype_byname<wchar_t>; 220297403Sobrien extern template class codecvt_byname<char, char, mbstate_t>; 220397403Sobrien extern template class codecvt_byname<wchar_t, char, mbstate_t>; 220497403Sobrien extern template class collate<char>; 220597403Sobrien extern template class collate_byname<char>; 220697403Sobrien extern template class collate<wchar_t>; 220797403Sobrien extern template class collate_byname<wchar_t>; 220897403Sobrien 220997403Sobrien extern template 221097403Sobrien const codecvt<char, char, mbstate_t>& 221197403Sobrien use_facet<codecvt<char, char, mbstate_t> >(const locale&); 221297403Sobrien 221397403Sobrien extern template 221497403Sobrien const collate<char>& 221597403Sobrien use_facet<collate<char> >(const locale&); 221697403Sobrien 221797403Sobrien extern template 221897403Sobrien const numpunct<char>& 221997403Sobrien use_facet<numpunct<char> >(const locale&); 222097403Sobrien 222197403Sobrien extern template 222297403Sobrien const num_put<char>& 222397403Sobrien use_facet<num_put<char> >(const locale&); 222497403Sobrien 222597403Sobrien extern template 222697403Sobrien const num_get<char>& 222797403Sobrien use_facet<num_get<char> >(const locale&); 222897403Sobrien 222997403Sobrien extern template 223097403Sobrien const moneypunct<char, true>& 223197403Sobrien use_facet<moneypunct<char, true> >(const locale&); 223297403Sobrien 223397403Sobrien extern template 223497403Sobrien const moneypunct<char, false>& 223597403Sobrien use_facet<moneypunct<char, false> >(const locale&); 223697403Sobrien 223797403Sobrien extern template 223897403Sobrien const money_put<char>& 223997403Sobrien use_facet<money_put<char> >(const locale&); 224097403Sobrien 224197403Sobrien extern template 224297403Sobrien const money_get<char>& 224397403Sobrien use_facet<money_get<char> >(const locale&); 224497403Sobrien 224597403Sobrien extern template 224697403Sobrien const __timepunct<char>& 224797403Sobrien use_facet<__timepunct<char> >(const locale&); 224897403Sobrien 224997403Sobrien extern template 225097403Sobrien const time_put<char>& 225197403Sobrien use_facet<time_put<char> >(const locale&); 225297403Sobrien 225397403Sobrien extern template 225497403Sobrien const time_get<char>& 225597403Sobrien use_facet<time_get<char> >(const locale&); 225697403Sobrien 225797403Sobrien extern template 225897403Sobrien const messages<char>& 225997403Sobrien use_facet<messages<char> >(const locale&); 226097403Sobrien 226197403Sobrien extern template 226297403Sobrien const codecvt<wchar_t, char, mbstate_t>& 226397403Sobrien use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 226497403Sobrien 226597403Sobrien extern template 226697403Sobrien const collate<wchar_t>& 226797403Sobrien use_facet<collate<wchar_t> >(const locale&); 226897403Sobrien 226997403Sobrien extern template 227097403Sobrien const numpunct<wchar_t>& 227197403Sobrien use_facet<numpunct<wchar_t> >(const locale&); 227297403Sobrien 227397403Sobrien extern template 227497403Sobrien const num_put<wchar_t>& 227597403Sobrien use_facet<num_put<wchar_t> >(const locale&); 227697403Sobrien 227797403Sobrien extern template 227897403Sobrien const num_get<wchar_t>& 227997403Sobrien use_facet<num_get<wchar_t> >(const locale&); 228097403Sobrien 228197403Sobrien extern template 228297403Sobrien const moneypunct<wchar_t, true>& 228397403Sobrien use_facet<moneypunct<wchar_t, true> >(const locale&); 228497403Sobrien 228597403Sobrien extern template 228697403Sobrien const moneypunct<wchar_t, false>& 228797403Sobrien use_facet<moneypunct<wchar_t, false> >(const locale&); 228897403Sobrien 228997403Sobrien extern template 229097403Sobrien const money_put<wchar_t>& 229197403Sobrien use_facet<money_put<wchar_t> >(const locale&); 229297403Sobrien 229397403Sobrien extern template 229497403Sobrien const money_get<wchar_t>& 229597403Sobrien use_facet<money_get<wchar_t> >(const locale&); 229697403Sobrien 229797403Sobrien extern template 229897403Sobrien const __timepunct<wchar_t>& 229997403Sobrien use_facet<__timepunct<wchar_t> >(const locale&); 230097403Sobrien 230197403Sobrien extern template 230297403Sobrien const time_put<wchar_t>& 230397403Sobrien use_facet<time_put<wchar_t> >(const locale&); 230497403Sobrien 230597403Sobrien extern template 230697403Sobrien const time_get<wchar_t>& 230797403Sobrien use_facet<time_get<wchar_t> >(const locale&); 230897403Sobrien 230997403Sobrien extern template 231097403Sobrien const messages<wchar_t>& 231197403Sobrien use_facet<messages<wchar_t> >(const locale&); 231297403Sobrien 231397403Sobrien 231497403Sobrien extern template 231597403Sobrien bool 231697403Sobrien has_facet<ctype<char> >(const locale&); 231797403Sobrien 231897403Sobrien extern template 231997403Sobrien bool 232097403Sobrien has_facet<codecvt<char, char, mbstate_t> >(const locale&); 232197403Sobrien 232297403Sobrien extern template 232397403Sobrien bool 232497403Sobrien has_facet<collate<char> >(const locale&); 232597403Sobrien 232697403Sobrien extern template 232797403Sobrien bool 232897403Sobrien has_facet<numpunct<char> >(const locale&); 232997403Sobrien 233097403Sobrien extern template 233197403Sobrien bool 233297403Sobrien has_facet<num_put<char> >(const locale&); 233397403Sobrien 233497403Sobrien extern template 233597403Sobrien bool 233697403Sobrien has_facet<num_get<char> >(const locale&); 233797403Sobrien 233897403Sobrien extern template 233997403Sobrien bool 234097403Sobrien has_facet<moneypunct<char> >(const locale&); 234197403Sobrien 234297403Sobrien extern template 234397403Sobrien bool 234497403Sobrien has_facet<money_put<char> >(const locale&); 234597403Sobrien 234697403Sobrien extern template 234797403Sobrien bool 234897403Sobrien has_facet<money_get<char> >(const locale&); 234997403Sobrien 235097403Sobrien extern template 235197403Sobrien bool 235297403Sobrien has_facet<__timepunct<char> >(const locale&); 235397403Sobrien 235497403Sobrien extern template 235597403Sobrien bool 235697403Sobrien has_facet<time_put<char> >(const locale&); 235797403Sobrien 235897403Sobrien extern template 235997403Sobrien bool 236097403Sobrien has_facet<time_get<char> >(const locale&); 236197403Sobrien 236297403Sobrien extern template 236397403Sobrien bool 236497403Sobrien has_facet<messages<char> >(const locale&); 236597403Sobrien 236697403Sobrien extern template 236797403Sobrien bool 236897403Sobrien has_facet<ctype<wchar_t> >(const locale&); 236997403Sobrien 237097403Sobrien extern template 237197403Sobrien bool 237297403Sobrien has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 237397403Sobrien 237497403Sobrien extern template 237597403Sobrien bool 237697403Sobrien has_facet<collate<wchar_t> >(const locale&); 237797403Sobrien 237897403Sobrien extern template 237997403Sobrien bool 238097403Sobrien has_facet<numpunct<wchar_t> >(const locale&); 238197403Sobrien 238297403Sobrien extern template 238397403Sobrien bool 238497403Sobrien has_facet<num_put<wchar_t> >(const locale&); 238597403Sobrien 238697403Sobrien extern template 238797403Sobrien bool 238897403Sobrien has_facet<num_get<wchar_t> >(const locale&); 238997403Sobrien 239097403Sobrien extern template 239197403Sobrien bool 239297403Sobrien has_facet<moneypunct<wchar_t> >(const locale&); 239397403Sobrien 239497403Sobrien extern template 239597403Sobrien bool 239697403Sobrien has_facet<money_put<wchar_t> >(const locale&); 239797403Sobrien 239897403Sobrien extern template 239997403Sobrien bool 240097403Sobrien has_facet<money_get<wchar_t> >(const locale&); 240197403Sobrien 240297403Sobrien extern template 240397403Sobrien bool 240497403Sobrien has_facet<__timepunct<wchar_t> >(const locale&); 240597403Sobrien 240697403Sobrien extern template 240797403Sobrien bool 240897403Sobrien has_facet<time_put<wchar_t> >(const locale&); 240997403Sobrien 241097403Sobrien extern template 241197403Sobrien bool 241297403Sobrien has_facet<time_get<wchar_t> >(const locale&); 241397403Sobrien 241497403Sobrien extern template 241597403Sobrien bool 241697403Sobrien has_facet<messages<wchar_t> >(const locale&); 241797403Sobrien} // namespace std 241897403Sobrien 241997403Sobrien#endif 2420