locale_facets.tcc revision 110614
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 { 625110614Skan // Note: digits10 is rounded down: we need to add 1 to ensure 62697403Sobrien // we get the full available precision. 627110614Skan // Then, in general, one more 1 needs to be added since, when the 628110614Skan // %{g,G} conversion specifiers are chosen inside _S_format_float, the 629110614Skan // precision field is "the maximum number of significant digits", *not* 630110614Skan // the "number of digits to appear after the decimal point", as happens 631110614Skan // for %{e,E,f,F} (C99, 7.19.6.1,4). 632110614Skan const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; 63397403Sobrien streamsize __prec = __io.precision(); 63497403Sobrien 63597403Sobrien if (__prec > static_cast<streamsize>(__max_digits)) 63697403Sobrien __prec = static_cast<streamsize>(__max_digits); 63797403Sobrien 63897403Sobrien // Long enough for the max format spec. 63997403Sobrien char __fbuf[16]; 64097403Sobrien 64197403Sobrien // [22.2.2.2.2] Stage 1, numeric conversion to character. 64297403Sobrien int __len; 64397403Sobrien#ifdef _GLIBCPP_USE_C99 64497403Sobrien // First try a buffer perhaps big enough (for sure sufficient for 64597403Sobrien // non-ios_base::fixed outputs) 64697403Sobrien int __cs_size = __max_digits * 3; 64797403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 64897403Sobrien 64997403Sobrien const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); 65097403Sobrien if (__fp) 65197403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 65297403Sobrien _S_c_locale, __prec); 65397403Sobrien else 65497403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); 65597403Sobrien 65697403Sobrien // If the buffer was not large enough, try again with the correct size. 65797403Sobrien if (__len >= __cs_size) 65897403Sobrien { 65997403Sobrien __cs_size = __len + 1; 66097403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 66197403Sobrien if (__fp) 66297403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 66397403Sobrien _S_c_locale, __prec); 66497403Sobrien else 66597403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 66697403Sobrien _S_c_locale); 66797403Sobrien } 66897403Sobrien#else 66997403Sobrien // Consider the possibility of long ios_base::fixed outputs 67097403Sobrien const bool __fixed = __io.flags() & ios_base::fixed; 67197403Sobrien const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 67297403Sobrien // ios_base::fixed outputs may need up to __max_exp+1 chars 67397403Sobrien // for the integer part + up to __max_digits chars for the 67497403Sobrien // fractional part + 3 chars for sign, decimal point, '\0'. On 67597403Sobrien // the other hand, for non-fixed outputs __max_digits*3 chars 67697403Sobrien // are largely sufficient. 67797403Sobrien const int __cs_size = __fixed ? __max_exp + __max_digits + 4 67897403Sobrien : __max_digits * 3; 67997403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 68097403Sobrien 68197403Sobrien if (_S_format_float(__io, __fbuf, __mod, __prec)) 68297403Sobrien __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); 68397403Sobrien else 68497403Sobrien __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 68597403Sobrien#endif 68697403Sobrien return _M_widen_float(__s, __io, __fill, __cs, __len); 68797403Sobrien } 68897403Sobrien 68997403Sobrien template<typename _CharT, typename _OutIter> 69097403Sobrien template<typename _ValueT> 69197403Sobrien _OutIter 69297403Sobrien num_put<_CharT, _OutIter>:: 69397403Sobrien _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 69497403Sobrien char __modl, _ValueT __v) const 69597403Sobrien { 69697403Sobrien // [22.2.2.2.2] Stage 1, numeric conversion to character. 69797403Sobrien 69897403Sobrien // Long enough for the max format spec. 69997403Sobrien char __fbuf[16]; 70097403Sobrien _S_format_int(__io, __fbuf, __mod, __modl); 70197403Sobrien#ifdef _GLIBCPP_USE_C99 70297403Sobrien // First try a buffer perhaps big enough. 70397403Sobrien int __cs_size = 64; 70497403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 70597403Sobrien int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 70697403Sobrien _S_c_locale); 70797403Sobrien // If the buffer was not large enough, try again with the correct size. 70897403Sobrien if (__len >= __cs_size) 70997403Sobrien { 71097403Sobrien __cs_size = __len + 1; 71197403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 71297403Sobrien __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 71397403Sobrien _S_c_locale); 71497403Sobrien } 71597403Sobrien#else 71697403Sobrien // Leave room for "+/-," "0x," and commas. This size is 71797403Sobrien // arbitrary, but should be largely sufficient. 71897403Sobrien char __cs[128]; 71997403Sobrien int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 72097403Sobrien#endif 72197403Sobrien return _M_widen_int(__s, __io, __fill, __cs, __len); 72297403Sobrien } 72397403Sobrien 72497403Sobrien template<typename _CharT, typename _OutIter> 72597403Sobrien _OutIter 72697403Sobrien num_put<_CharT, _OutIter>:: 72797403Sobrien _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 72897403Sobrien int __len) const 72997403Sobrien { 730102782Skan typedef char_traits<_CharT> __traits_type; 73197403Sobrien // [22.2.2.2.2] Stage 2, convert to char_type, using correct 73297403Sobrien // numpunct.decimal_point() values for '.' and adding grouping. 73397403Sobrien const locale __loc = __io.getloc(); 73497403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 73597403Sobrien _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 73697403Sobrien * __len)); 73797403Sobrien // Grouping can add (almost) as many separators as the number of 73897403Sobrien // digits, but no more. 73997403Sobrien _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 74097403Sobrien * __len * 2)); 74197403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 74297403Sobrien 74397403Sobrien // Replace decimal point. 74497403Sobrien const _CharT* __p; 74597403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 746102782Skan if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) 74797403Sobrien __ws[__p - __ws] = __np.decimal_point(); 74897403Sobrien 74997403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 75097403Sobrien//282. What types does numpunct grouping refer to? 75197403Sobrien // Add grouping, if necessary. 75297403Sobrien const string __grouping = __np.grouping(); 75397403Sobrien ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 75497403Sobrien if (__grouping.size()) 75597403Sobrien { 75697403Sobrien _CharT* __p2; 75797403Sobrien int __declen = __p ? __p - __ws : __len; 75897403Sobrien __p2 = __add_grouping(__ws2, __np.thousands_sep(), 75997403Sobrien __grouping.c_str(), 76097403Sobrien __grouping.c_str() + __grouping.size(), 76197403Sobrien __ws, __ws + __declen); 76297403Sobrien int __newlen = __p2 - __ws2; 76397403Sobrien 76497403Sobrien // Tack on decimal part. 76597403Sobrien if (__p) 76697403Sobrien { 767102782Skan __traits_type::copy(__p2, __p, __len - __declen); 76897403Sobrien __newlen += __len - __declen; 76997403Sobrien } 77097403Sobrien 77197403Sobrien // Switch strings, establish correct new length. 77297403Sobrien __ws = __ws2; 77397403Sobrien __len = __newlen; 77497403Sobrien } 77597403Sobrien#endif 77697403Sobrien return _M_insert(__s, __io, __fill, __ws, __len); 77797403Sobrien } 77897403Sobrien 77997403Sobrien template<typename _CharT, typename _OutIter> 78097403Sobrien _OutIter 78197403Sobrien num_put<_CharT, _OutIter>:: 78297403Sobrien _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 78397403Sobrien int __len) const 78497403Sobrien { 78597403Sobrien // [22.2.2.2.2] Stage 2, convert to char_type, using correct 78697403Sobrien // numpunct.decimal_point() values for '.' and adding grouping. 78797403Sobrien const locale __loc = __io.getloc(); 78897403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 78997403Sobrien _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 79097403Sobrien * __len)); 79197403Sobrien // Grouping can add (almost) as many separators as the number of 79297403Sobrien // digits, but no more. 79397403Sobrien _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 79497403Sobrien * __len * 2)); 79597403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 79697403Sobrien 79797403Sobrien // Add grouping, if necessary. 79897403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 79997403Sobrien const string __grouping = __np.grouping(); 80097403Sobrien const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 80197403Sobrien if (__grouping.size()) 80297403Sobrien { 80397403Sobrien // By itself __add_grouping cannot deal correctly with __ws when 80497403Sobrien // ios::showbase is set and ios_base::oct || ios_base::hex. 80597403Sobrien // Therefore we take care "by hand" of the initial 0, 0x or 0X. 806104754Skan // However, remember that the latter do not occur if the number 807104754Skan // printed is '0' (__len == 1). 80897403Sobrien streamsize __off = 0; 809104754Skan if ((__io.flags() & ios_base::showbase) && __len > 1) 81097403Sobrien if (__basefield == ios_base::oct) 81197403Sobrien { 81297403Sobrien __off = 1; 81397403Sobrien *__ws2 = *__ws; 81497403Sobrien } 81597403Sobrien else if (__basefield == ios_base::hex) 81697403Sobrien { 81797403Sobrien __off = 2; 81897403Sobrien *__ws2 = *__ws; 81997403Sobrien *(__ws2 + 1) = *(__ws + 1); 82097403Sobrien } 82197403Sobrien _CharT* __p; 82297403Sobrien __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 82397403Sobrien __grouping.c_str(), 82497403Sobrien __grouping.c_str() + __grouping.size(), 82597403Sobrien __ws + __off, __ws + __len); 82697403Sobrien __len = __p - __ws2; 82797403Sobrien // Switch strings. 82897403Sobrien __ws = __ws2; 82997403Sobrien } 83097403Sobrien return _M_insert(__s, __io, __fill, __ws, __len); 83197403Sobrien } 83297403Sobrien 83397403Sobrien // For use by integer and floating-point types after they have been 83497403Sobrien // converted into a char_type string. 83597403Sobrien template<typename _CharT, typename _OutIter> 83697403Sobrien _OutIter 83797403Sobrien num_put<_CharT, _OutIter>:: 83897403Sobrien _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 83997403Sobrien int __len) const 84097403Sobrien { 841102782Skan typedef char_traits<_CharT> __traits_type; 84297403Sobrien // [22.2.2.2.2] Stage 3. 84397403Sobrien streamsize __w = __io.width(); 84497403Sobrien _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 84597403Sobrien * __w)); 84697403Sobrien if (__w > static_cast<streamsize>(__len)) 84797403Sobrien { 848102782Skan __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 849102782Skan __w, __len, true); 85097403Sobrien __len = static_cast<int>(__w); 85197403Sobrien // Switch strings. 85297403Sobrien __ws = __ws2; 85397403Sobrien } 85497403Sobrien __io.width(0); 85597403Sobrien 85697403Sobrien // [22.2.2.2.2] Stage 4. 85797403Sobrien // Write resulting, fully-formatted string to output iterator. 85897403Sobrien for (int __j = 0; __j < __len; ++__j, ++__s) 85997403Sobrien *__s = __ws[__j]; 86097403Sobrien return __s; 86197403Sobrien } 86297403Sobrien 86397403Sobrien template<typename _CharT, typename _OutIter> 86497403Sobrien _OutIter 86597403Sobrien num_put<_CharT, _OutIter>:: 86697403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 86797403Sobrien { 86897403Sobrien ios_base::fmtflags __flags = __io.flags(); 86997403Sobrien if ((__flags & ios_base::boolalpha) == 0) 87097403Sobrien { 87197403Sobrien unsigned long __uv = __v; 872102782Skan __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv); 87397403Sobrien } 87497403Sobrien else 87597403Sobrien { 87697403Sobrien typedef basic_string<_CharT> __string_type; 87797403Sobrien locale __loc = __io.getloc(); 87897403Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 87997403Sobrien __string_type __name; 88097403Sobrien if (__v) 88197403Sobrien __name = __np.truename(); 88297403Sobrien else 88397403Sobrien __name = __np.falsename(); 88497403Sobrien __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 88597403Sobrien } 88697403Sobrien return __s; 88797403Sobrien } 88897403Sobrien 88997403Sobrien template<typename _CharT, typename _OutIter> 89097403Sobrien _OutIter 89197403Sobrien num_put<_CharT, _OutIter>:: 89297403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 893102782Skan { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); } 89497403Sobrien 89597403Sobrien template<typename _CharT, typename _OutIter> 89697403Sobrien _OutIter 89797403Sobrien num_put<_CharT, _OutIter>:: 89897403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 89997403Sobrien unsigned long __v) const 900102782Skan { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); } 90197403Sobrien 90297403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG 90397403Sobrien template<typename _CharT, typename _OutIter> 90497403Sobrien _OutIter 90597403Sobrien num_put<_CharT, _OutIter>:: 90697403Sobrien do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 90797403Sobrien { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); } 90897403Sobrien 90997403Sobrien template<typename _CharT, typename _OutIter> 91097403Sobrien _OutIter 91197403Sobrien num_put<_CharT, _OutIter>:: 91297403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 91397403Sobrien unsigned long long __v) const 91497403Sobrien { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } 91597403Sobrien#endif 91697403Sobrien 91797403Sobrien template<typename _CharT, typename _OutIter> 91897403Sobrien _OutIter 91997403Sobrien num_put<_CharT, _OutIter>:: 92097403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 921102782Skan { return _M_convert_float(__s, __io, __fill, char(), __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 long double __v) const 92897403Sobrien { return _M_convert_float(__s, __io, __fill, 'L', __v); } 92997403Sobrien 93097403Sobrien template<typename _CharT, typename _OutIter> 93197403Sobrien _OutIter 93297403Sobrien num_put<_CharT, _OutIter>:: 93397403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 93497403Sobrien const void* __v) const 93597403Sobrien { 93697403Sobrien ios_base::fmtflags __flags = __io.flags(); 93797403Sobrien ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield 93897403Sobrien | ios_base::uppercase | ios_base::internal); 93997403Sobrien __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 94097403Sobrien try 94197403Sobrien { 942102782Skan __s = _M_convert_int(__s, __io, __fill, 'u', char(), 94397403Sobrien reinterpret_cast<unsigned long>(__v)); 94497403Sobrien __io.flags(__flags); 94597403Sobrien } 94697403Sobrien catch (...) 94797403Sobrien { 94897403Sobrien __io.flags(__flags); 94997403Sobrien __throw_exception_again; 95097403Sobrien } 95197403Sobrien return __s; 95297403Sobrien } 95397403Sobrien 95497403Sobrien 95597403Sobrien template<typename _CharT, typename _InIter> 95697403Sobrien _InIter 95797403Sobrien money_get<_CharT, _InIter>:: 95897403Sobrien do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 95997403Sobrien ios_base::iostate& __err, long double& __units) const 96097403Sobrien { 96197403Sobrien string_type __str; 96297403Sobrien __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 96397403Sobrien 96497403Sobrien const int __n = numeric_limits<long double>::digits10; 96597403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__n)); 96697403Sobrien const locale __loc = __io.getloc(); 96797403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 96897403Sobrien const _CharT* __wcs = __str.c_str(); 96997403Sobrien __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); 97097403Sobrien __convert_to_v(__cs, __units, __err, _S_c_locale); 97197403Sobrien return __beg; 97297403Sobrien } 97397403Sobrien 97497403Sobrien template<typename _CharT, typename _InIter> 97597403Sobrien _InIter 97697403Sobrien money_get<_CharT, _InIter>:: 97797403Sobrien do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 97897403Sobrien ios_base::iostate& __err, string_type& __units) const 97997403Sobrien { 98097403Sobrien // These contortions are quite unfortunate. 98197403Sobrien typedef moneypunct<_CharT, true> __money_true; 98297403Sobrien typedef moneypunct<_CharT, false> __money_false; 98397403Sobrien typedef money_base::part part; 98497403Sobrien typedef typename string_type::size_type size_type; 98597403Sobrien 98697403Sobrien const locale __loc = __io.getloc(); 98797403Sobrien const __money_true& __mpt = use_facet<__money_true>(__loc); 98897403Sobrien const __money_false& __mpf = use_facet<__money_false>(__loc); 98997403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 99097403Sobrien 99197403Sobrien const money_base::pattern __p = __intl ? __mpt.neg_format() 99297403Sobrien : __mpf.neg_format(); 99397403Sobrien 99497403Sobrien const string_type __pos_sign =__intl ? __mpt.positive_sign() 99597403Sobrien : __mpf.positive_sign(); 99697403Sobrien const string_type __neg_sign =__intl ? __mpt.negative_sign() 99797403Sobrien : __mpf.negative_sign(); 99897403Sobrien const char_type __d = __intl ? __mpt.decimal_point() 99997403Sobrien : __mpf.decimal_point(); 100097403Sobrien const char_type __sep = __intl ? __mpt.thousands_sep() 100197403Sobrien : __mpf.thousands_sep(); 100297403Sobrien 100397403Sobrien const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); 100497403Sobrien 100597403Sobrien // Set to deduced positive or negative sign, depending. 100697403Sobrien string_type __sign; 100797403Sobrien // String of grouping info from thousands_sep plucked from __units. 100897403Sobrien string __grouping_tmp; 100997403Sobrien // Marker for thousands_sep position. 101097403Sobrien int __sep_pos = 0; 101197403Sobrien // If input iterator is in a valid state. 101297403Sobrien bool __testvalid = true; 101397403Sobrien // Flag marking when a decimal point is found. 101497403Sobrien bool __testdecfound = false; 101597403Sobrien 101697403Sobrien // The tentative returned string is stored here. 101797403Sobrien string_type __temp_units; 101897403Sobrien 101997403Sobrien char_type __c = *__beg; 102097403Sobrien char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); 102197403Sobrien for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) 102297403Sobrien { 102397403Sobrien part __which = static_cast<part>(__p.field[__i]); 102497403Sobrien switch (__which) 102597403Sobrien { 102697403Sobrien case money_base::symbol: 102797403Sobrien if (__io.flags() & ios_base::showbase 102897403Sobrien || __i < 2 || __sign.size() > 1 102997403Sobrien || ((static_cast<part>(__p.field[3]) != money_base::none) 103097403Sobrien && __i == 2)) 103197403Sobrien { 103297403Sobrien // According to 22.2.6.1.2.2, symbol is required 103397403Sobrien // if (__io.flags() & ios_base::showbase), 103497403Sobrien // otherwise is optional and consumed only if 103597403Sobrien // other characters are needed to complete the 103697403Sobrien // format. 103797403Sobrien const string_type __symbol = __intl ? __mpt.curr_symbol() 103897403Sobrien : __mpf.curr_symbol(); 103997403Sobrien size_type __len = __symbol.size(); 104097403Sobrien size_type __j = 0; 104197403Sobrien while (__beg != __end 104297403Sobrien && __j < __len && __symbol[__j] == __c) 104397403Sobrien { 104497403Sobrien __c = *(++__beg); 104597403Sobrien ++__j; 104697403Sobrien } 104797403Sobrien // When (__io.flags() & ios_base::showbase) 104897403Sobrien // symbol is required. 104997403Sobrien if (__j != __len && (__io.flags() & ios_base::showbase)) 105097403Sobrien __testvalid = false; 105197403Sobrien } 105297403Sobrien break; 105397403Sobrien case money_base::sign: 105497403Sobrien // Sign might not exist, or be more than one character long. 105597403Sobrien if (__pos_sign.size() && __neg_sign.size()) 105697403Sobrien { 105797403Sobrien // Sign is mandatory. 105897403Sobrien if (__c == __pos_sign[0]) 105997403Sobrien { 106097403Sobrien __sign = __pos_sign; 106197403Sobrien __c = *(++__beg); 106297403Sobrien } 106397403Sobrien else if (__c == __neg_sign[0]) 106497403Sobrien { 106597403Sobrien __sign = __neg_sign; 106697403Sobrien __c = *(++__beg); 106797403Sobrien } 106897403Sobrien else 106997403Sobrien __testvalid = false; 107097403Sobrien } 107197403Sobrien else if (__pos_sign.size() && __c == __pos_sign[0]) 107297403Sobrien { 107397403Sobrien __sign = __pos_sign; 107497403Sobrien __c = *(++__beg); 107597403Sobrien } 107697403Sobrien else if (__neg_sign.size() && __c == __neg_sign[0]) 107797403Sobrien { 107897403Sobrien __sign = __neg_sign; 107997403Sobrien __c = *(++__beg); 108097403Sobrien } 108197403Sobrien break; 108297403Sobrien case money_base::value: 108397403Sobrien // Extract digits, remove and stash away the 108497403Sobrien // grouping of found thousands separators. 108597403Sobrien while (__beg != __end 108697403Sobrien && (__ctype.is(ctype_base::digit, __c) 108797403Sobrien || (__c == __d && !__testdecfound) 108897403Sobrien || __c == __sep)) 108997403Sobrien { 109097403Sobrien if (__c == __d) 109197403Sobrien { 109297403Sobrien __grouping_tmp += static_cast<char>(__sep_pos); 109397403Sobrien __sep_pos = 0; 109497403Sobrien __testdecfound = true; 109597403Sobrien } 109697403Sobrien else if (__c == __sep) 109797403Sobrien { 109897403Sobrien if (__grouping.size()) 109997403Sobrien { 110097403Sobrien // Mark position for later analysis. 110197403Sobrien __grouping_tmp += static_cast<char>(__sep_pos); 110297403Sobrien __sep_pos = 0; 110397403Sobrien } 110497403Sobrien else 110597403Sobrien { 110697403Sobrien __testvalid = false; 110797403Sobrien break; 110897403Sobrien } 110997403Sobrien } 111097403Sobrien else 111197403Sobrien { 111297403Sobrien __temp_units += __c; 111397403Sobrien ++__sep_pos; 111497403Sobrien } 111597403Sobrien __c = *(++__beg); 111697403Sobrien } 111797403Sobrien break; 111897403Sobrien case money_base::space: 111997403Sobrien case money_base::none: 112097403Sobrien // Only if not at the end of the pattern. 112197403Sobrien if (__i != 3) 112297403Sobrien while (__beg != __end 112397403Sobrien && __ctype.is(ctype_base::space, __c)) 112497403Sobrien __c = *(++__beg); 112597403Sobrien break; 112697403Sobrien } 112797403Sobrien } 112897403Sobrien 112997403Sobrien // Need to get the rest of the sign characters, if they exist. 113097403Sobrien if (__sign.size() > 1) 113197403Sobrien { 113297403Sobrien size_type __len = __sign.size(); 113397403Sobrien size_type __i = 1; 113497403Sobrien for (; __c != __eof && __i < __len; ++__i) 113597403Sobrien while (__beg != __end && __c != __sign[__i]) 113697403Sobrien __c = *(++__beg); 113797403Sobrien 113897403Sobrien if (__i != __len) 113997403Sobrien __testvalid = false; 114097403Sobrien } 114197403Sobrien 114297403Sobrien // Strip leading zeros. 114397403Sobrien while (__temp_units[0] == __ctype.widen('0')) 114497403Sobrien __temp_units.erase(__temp_units.begin()); 114597403Sobrien 114697403Sobrien if (__sign.size() && __sign == __neg_sign) 114797403Sobrien __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); 114897403Sobrien 114997403Sobrien // Test for grouping fidelity. 115097403Sobrien if (__grouping.size() && __grouping_tmp.size()) 115197403Sobrien { 115297403Sobrien if (!__verify_grouping(__grouping, __grouping_tmp)) 115397403Sobrien __testvalid = false; 115497403Sobrien } 115597403Sobrien 115697403Sobrien // Iff no more characters are available. 115797403Sobrien if (__c == __eof) 115897403Sobrien __err |= ios_base::eofbit; 115997403Sobrien 116097403Sobrien // Iff valid sequence is not recognized. 116197403Sobrien if (!__testvalid || !__temp_units.size()) 116297403Sobrien __err |= ios_base::failbit; 116397403Sobrien else 116497403Sobrien // Use the "swap trick" to copy __temp_units into __units. 116597403Sobrien __temp_units.swap(__units); 116697403Sobrien 116797403Sobrien return __beg; 116897403Sobrien } 116997403Sobrien 117097403Sobrien template<typename _CharT, typename _OutIter> 117197403Sobrien _OutIter 117297403Sobrien money_put<_CharT, _OutIter>:: 117397403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 117497403Sobrien long double __units) const 117597403Sobrien { 117697403Sobrien const locale __loc = __io.getloc(); 117797403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 117897403Sobrien#ifdef _GLIBCPP_USE_C99 117997403Sobrien // First try a buffer perhaps big enough. 118097403Sobrien int __cs_size = 64; 118197403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 118297403Sobrien int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 118397403Sobrien _S_c_locale); 118497403Sobrien // If the buffer was not large enough, try again with the correct size. 118597403Sobrien if (__len >= __cs_size) 118697403Sobrien { 118797403Sobrien __cs_size = __len + 1; 118897403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 118997403Sobrien __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 119097403Sobrien _S_c_locale); 119197403Sobrien } 119297403Sobrien#else 119397403Sobrien // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, 119497403Sobrien // decimal digit, '\0'. 119597403Sobrien const int __cs_size = numeric_limits<long double>::max_exponent10 + 5; 119697403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 119797403Sobrien int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); 119897403Sobrien#endif 119997403Sobrien _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); 120097403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 120197403Sobrien string_type __digits(__ws); 120297403Sobrien return this->do_put(__s, __intl, __io, __fill, __digits); 120397403Sobrien } 120497403Sobrien 120597403Sobrien template<typename _CharT, typename _OutIter> 120697403Sobrien _OutIter 120797403Sobrien money_put<_CharT, _OutIter>:: 120897403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 120997403Sobrien const string_type& __digits) const 121097403Sobrien { 121197403Sobrien typedef typename string_type::size_type size_type; 121297403Sobrien typedef money_base::part part; 121397403Sobrien 121497403Sobrien const locale __loc = __io.getloc(); 121597403Sobrien const size_type __width = static_cast<size_type>(__io.width()); 121697403Sobrien 121797403Sobrien // These contortions are quite unfortunate. 121897403Sobrien typedef moneypunct<_CharT, true> __money_true; 121997403Sobrien typedef moneypunct<_CharT, false> __money_false; 122097403Sobrien const __money_true& __mpt = use_facet<__money_true>(__loc); 122197403Sobrien const __money_false& __mpf = use_facet<__money_false>(__loc); 122297403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 122397403Sobrien 122497403Sobrien // Determine if negative or positive formats are to be used, and 122597403Sobrien // discard leading negative_sign if it is present. 122697403Sobrien const char_type* __beg = __digits.data(); 122797403Sobrien const char_type* __end = __beg + __digits.size(); 122897403Sobrien money_base::pattern __p; 122997403Sobrien string_type __sign; 123097403Sobrien if (*__beg != __ctype.widen('-')) 123197403Sobrien { 123297403Sobrien __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); 123397403Sobrien __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); 123497403Sobrien } 123597403Sobrien else 123697403Sobrien { 123797403Sobrien __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); 123897403Sobrien __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); 123997403Sobrien ++__beg; 124097403Sobrien } 124197403Sobrien 124297403Sobrien // Look for valid numbers in the current ctype facet within input digits. 124397403Sobrien __end = __ctype.scan_not(ctype_base::digit, __beg, __end); 124497403Sobrien if (__beg != __end) 124597403Sobrien { 124697403Sobrien // Assume valid input, and attempt to format. 124797403Sobrien // Break down input numbers into base components, as follows: 124897403Sobrien // final_value = grouped units + (decimal point) + (digits) 124997403Sobrien string_type __res; 125097403Sobrien string_type __value; 125197403Sobrien const string_type __symbol = __intl ? __mpt.curr_symbol() 125297403Sobrien : __mpf.curr_symbol(); 125397403Sobrien 125497403Sobrien // Deal with decimal point, decimal digits. 125597403Sobrien const int __frac = __intl ? __mpt.frac_digits() 125697403Sobrien : __mpf.frac_digits(); 125797403Sobrien if (__frac > 0) 125897403Sobrien { 125997403Sobrien const char_type __d = __intl ? __mpt.decimal_point() 126097403Sobrien : __mpf.decimal_point(); 126197403Sobrien if (__end - __beg >= __frac) 126297403Sobrien { 126397403Sobrien __value = string_type(__end - __frac, __end); 126497403Sobrien __value.insert(__value.begin(), __d); 126597403Sobrien __end -= __frac; 126697403Sobrien } 126797403Sobrien else 126897403Sobrien { 126997403Sobrien // Have to pad zeros in the decimal position. 127097403Sobrien __value = string_type(__beg, __end); 127197403Sobrien int __paddec = __frac - (__end - __beg); 127297403Sobrien char_type __zero = __ctype.widen('0'); 127397403Sobrien __value.insert(__value.begin(), __paddec, __zero); 127497403Sobrien __value.insert(__value.begin(), __d); 127597403Sobrien __beg = __end; 127697403Sobrien } 127797403Sobrien } 127897403Sobrien 127997403Sobrien // Add thousands separators to non-decimal digits, per 128097403Sobrien // grouping rules. 128197403Sobrien if (__beg != __end) 128297403Sobrien { 128397403Sobrien const string __grouping = __intl ? __mpt.grouping() 128497403Sobrien : __mpf.grouping(); 128597403Sobrien if (__grouping.size()) 128697403Sobrien { 128797403Sobrien const char_type __sep = __intl ? __mpt.thousands_sep() 128897403Sobrien : __mpf.thousands_sep(); 128997403Sobrien const char* __gbeg = __grouping.c_str(); 129097403Sobrien const char* __gend = __gbeg + __grouping.size(); 129197403Sobrien const int __n = (__end - __beg) * 2; 129297403Sobrien _CharT* __ws2 = 129397403Sobrien static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); 129497403Sobrien _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 129597403Sobrien __gend, __beg, __end); 129697403Sobrien __value.insert(0, __ws2, __ws_end - __ws2); 129797403Sobrien } 129897403Sobrien else 129997403Sobrien __value.insert(0, string_type(__beg, __end)); 130097403Sobrien } 130197403Sobrien 130297403Sobrien // Calculate length of resulting string. 130397403Sobrien ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; 130497403Sobrien size_type __len = __value.size() + __sign.size(); 130597403Sobrien __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; 130697403Sobrien bool __testipad = __f == ios_base::internal && __len < __width; 130797403Sobrien 130897403Sobrien // Fit formatted digits into the required pattern. 130997403Sobrien for (int __i = 0; __i < 4; ++__i) 131097403Sobrien { 131197403Sobrien part __which = static_cast<part>(__p.field[__i]); 131297403Sobrien switch (__which) 131397403Sobrien { 131497403Sobrien case money_base::symbol: 131597403Sobrien if (__io.flags() & ios_base::showbase) 131697403Sobrien __res += __symbol; 131797403Sobrien break; 131897403Sobrien case money_base::sign: 131997403Sobrien // Sign might not exist, or be more than one 132097403Sobrien // charater long. In that case, add in the rest 132197403Sobrien // below. 132297403Sobrien if (__sign.size()) 132397403Sobrien __res += __sign[0]; 132497403Sobrien break; 132597403Sobrien case money_base::value: 132697403Sobrien __res += __value; 132797403Sobrien break; 132897403Sobrien case money_base::space: 132997403Sobrien // At least one space is required, but if internal 133097403Sobrien // formatting is required, an arbitrary number of 133197403Sobrien // fill spaces will be necessary. 133297403Sobrien if (__testipad) 133397403Sobrien __res += string_type(__width - __len, __fill); 133497403Sobrien else 133597403Sobrien __res += __ctype.widen(__fill); 133697403Sobrien break; 133797403Sobrien case money_base::none: 133897403Sobrien if (__testipad) 133997403Sobrien __res += string_type(__width - __len, __fill); 134097403Sobrien break; 134197403Sobrien } 134297403Sobrien } 134397403Sobrien 134497403Sobrien // Special case of multi-part sign parts. 134597403Sobrien if (__sign.size() > 1) 134697403Sobrien __res += string_type(__sign.begin() + 1, __sign.end()); 134797403Sobrien 134897403Sobrien // Pad, if still necessary. 134997403Sobrien __len = __res.size(); 135097403Sobrien if (__width > __len) 135197403Sobrien { 135297403Sobrien if (__f == ios_base::left) 135397403Sobrien // After. 135497403Sobrien __res.append(__width - __len, __fill); 135597403Sobrien else 135697403Sobrien // Before. 135797403Sobrien __res.insert(0, string_type(__width - __len, __fill)); 135897403Sobrien __len = __width; 135997403Sobrien } 136097403Sobrien 136197403Sobrien // Write resulting, fully-formatted string to output iterator. 136297403Sobrien for (size_type __j = 0; __j < __len; ++__j, ++__s) 136397403Sobrien *__s = __res[__j]; 136497403Sobrien } 136597403Sobrien __io.width(0); 136697403Sobrien return __s; 136797403Sobrien } 136897403Sobrien 136997403Sobrien 137097403Sobrien // NB: Not especially useful. Without an ios_base object or some 137197403Sobrien // kind of locale reference, we are left clawing at the air where 137297403Sobrien // the side of the mountain used to be... 137397403Sobrien template<typename _CharT, typename _InIter> 137497403Sobrien time_base::dateorder 137597403Sobrien time_get<_CharT, _InIter>::do_date_order() const 137697403Sobrien { return time_base::no_order; } 137797403Sobrien 137897403Sobrien template<typename _CharT, typename _InIter> 137997403Sobrien void 138097403Sobrien time_get<_CharT, _InIter>:: 138197403Sobrien _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, 138297403Sobrien ios_base::iostate& __err, tm* __tm, 138397403Sobrien const _CharT* __format) const 138497403Sobrien { 138597403Sobrien locale __loc = __io.getloc(); 138697403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 138797403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 138897403Sobrien size_t __len = char_traits<_CharT>::length(__format); 138997403Sobrien 139097403Sobrien for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 139197403Sobrien { 139297403Sobrien char __c = __format[__i]; 139397403Sobrien if (__c == '%') 139497403Sobrien { 139597403Sobrien // Verify valid formatting code, attempt to extract. 139697403Sobrien __c = __format[++__i]; 139797403Sobrien char __mod = 0; 139897403Sobrien int __mem = 0; 139997403Sobrien if (__c == 'E' || __c == 'O') 140097403Sobrien { 140197403Sobrien __mod = __c; 140297403Sobrien __c = __format[++__i]; 140397403Sobrien } 140497403Sobrien switch (__c) 140597403Sobrien { 140697403Sobrien const char* __cs; 140797403Sobrien _CharT __wcs[10]; 140897403Sobrien case 'a': 140997403Sobrien // Abbreviated weekday name [tm_wday] 141097403Sobrien const char_type* __days1[7]; 141197403Sobrien __tp._M_days_abbreviated(__days1); 141297403Sobrien _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 141397403Sobrien __err); 141497403Sobrien break; 141597403Sobrien case 'A': 141697403Sobrien // Weekday name [tm_wday]. 141797403Sobrien const char_type* __days2[7]; 141897403Sobrien __tp._M_days(__days2); 141997403Sobrien _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 142097403Sobrien __err); 142197403Sobrien break; 142297403Sobrien case 'h': 142397403Sobrien case 'b': 142497403Sobrien // Abbreviated month name [tm_mon] 142597403Sobrien const char_type* __months1[12]; 142697403Sobrien __tp._M_months_abbreviated(__months1); 142797403Sobrien _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 142897403Sobrien __err); 142997403Sobrien break; 143097403Sobrien case 'B': 143197403Sobrien // Month name [tm_mon]. 143297403Sobrien const char_type* __months2[12]; 143397403Sobrien __tp._M_months(__months2); 143497403Sobrien _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 143597403Sobrien __err); 143697403Sobrien break; 143797403Sobrien case 'c': 143897403Sobrien // Default time and date representation. 143997403Sobrien const char_type* __dt[2]; 144097403Sobrien __tp._M_date_time_formats(__dt); 144197403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 144297403Sobrien __dt[0]); 144397403Sobrien break; 144497403Sobrien case 'd': 144597403Sobrien // Day [01, 31]. [tm_mday] 144697403Sobrien _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 144797403Sobrien __ctype, __err); 144897403Sobrien break; 144997403Sobrien case 'D': 145097403Sobrien // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 145197403Sobrien __cs = "%m/%d/%y"; 145297403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 145397403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 145497403Sobrien __wcs); 145597403Sobrien break; 145697403Sobrien case 'H': 145797403Sobrien // Hour [00, 23]. [tm_hour] 145897403Sobrien _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 145997403Sobrien __ctype, __err); 146097403Sobrien break; 146197403Sobrien case 'I': 146297403Sobrien // Hour [01, 12]. [tm_hour] 146397403Sobrien _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 146497403Sobrien __ctype, __err); 146597403Sobrien break; 146697403Sobrien case 'm': 146797403Sobrien // Month [01, 12]. [tm_mon] 146897403Sobrien _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 146997403Sobrien __err); 147097403Sobrien if (!__err) 147197403Sobrien __tm->tm_mon = __mem - 1; 147297403Sobrien break; 147397403Sobrien case 'M': 147497403Sobrien // Minute [00, 59]. [tm_min] 147597403Sobrien _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 147697403Sobrien __ctype, __err); 147797403Sobrien break; 147897403Sobrien case 'n': 147997403Sobrien if (__ctype.narrow(*__beg, 0) == '\n') 148097403Sobrien ++__beg; 148197403Sobrien else 148297403Sobrien __err |= ios_base::failbit; 148397403Sobrien break; 148497403Sobrien case 'R': 148597403Sobrien // Equivalent to (%H:%M). 148697403Sobrien __cs = "%H:%M"; 148797403Sobrien __ctype.widen(__cs, __cs + 6, __wcs); 148897403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 148997403Sobrien __wcs); 149097403Sobrien break; 149197403Sobrien case 'S': 149297403Sobrien // Seconds. 149397403Sobrien _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 149497403Sobrien __ctype, __err); 149597403Sobrien break; 149697403Sobrien case 't': 149797403Sobrien if (__ctype.narrow(*__beg, 0) == '\t') 149897403Sobrien ++__beg; 149997403Sobrien else 150097403Sobrien __err |= ios_base::failbit; 150197403Sobrien break; 150297403Sobrien case 'T': 150397403Sobrien // Equivalent to (%H:%M:%S). 150497403Sobrien __cs = "%H:%M:%S"; 150597403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 150697403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 150797403Sobrien __wcs); 150897403Sobrien break; 150997403Sobrien case 'x': 151097403Sobrien // Locale's date. 151197403Sobrien const char_type* __dates[2]; 151297403Sobrien __tp._M_date_formats(__dates); 151397403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 151497403Sobrien __dates[0]); 151597403Sobrien break; 151697403Sobrien case 'X': 151797403Sobrien // Locale's time. 151897403Sobrien const char_type* __times[2]; 151997403Sobrien __tp._M_time_formats(__times); 152097403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, 152197403Sobrien __times[0]); 152297403Sobrien break; 152397403Sobrien case 'y': 152497403Sobrien // Two digit year. [tm_year] 152597403Sobrien _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 152697403Sobrien __ctype, __err); 152797403Sobrien break; 152897403Sobrien case 'Y': 152997403Sobrien // Year [1900). [tm_year] 153097403Sobrien _M_extract_num(__beg, __end, __mem, 0, 153197403Sobrien numeric_limits<int>::max(), 4, 153297403Sobrien __ctype, __err); 153397403Sobrien if (!__err) 153497403Sobrien __tm->tm_year = __mem - 1900; 153597403Sobrien break; 153697403Sobrien case 'Z': 153797403Sobrien // Timezone info. 153897403Sobrien if (__ctype.is(ctype_base::upper, *__beg)) 153997403Sobrien { 154097403Sobrien int __tmp; 154197403Sobrien _M_extract_name(__beg, __end, __tmp, 154297403Sobrien __timepunct<_CharT>::_S_timezones, 154397403Sobrien 14, __err); 154497403Sobrien 154597403Sobrien // GMT requires special effort. 154697403Sobrien char_type __c = *__beg; 154797403Sobrien if (!__err && __tmp == 0 154897403Sobrien && (__c == __ctype.widen('-') 154997403Sobrien || __c == __ctype.widen('+'))) 155097403Sobrien { 155197403Sobrien _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 155297403Sobrien __ctype, __err); 155397403Sobrien _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 155497403Sobrien __ctype, __err); 155597403Sobrien } 155697403Sobrien } 155797403Sobrien else 155897403Sobrien __err |= ios_base::failbit; 155997403Sobrien break; 156097403Sobrien default: 156197403Sobrien // Not recognized. 156297403Sobrien __err |= ios_base::failbit; 156397403Sobrien } 156497403Sobrien } 156597403Sobrien else 156697403Sobrien { 156797403Sobrien // Verify format and input match, extract and discard. 156897403Sobrien if (__c == __ctype.narrow(*__beg, 0)) 156997403Sobrien ++__beg; 157097403Sobrien else 157197403Sobrien __err |= ios_base::failbit; 157297403Sobrien } 157397403Sobrien } 157497403Sobrien } 157597403Sobrien 157697403Sobrien template<typename _CharT, typename _InIter> 157797403Sobrien void 157897403Sobrien time_get<_CharT, _InIter>:: 157997403Sobrien _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, 158097403Sobrien int __min, int __max, size_t __len, 158197403Sobrien const ctype<_CharT>& __ctype, 158297403Sobrien ios_base::iostate& __err) const 158397403Sobrien { 158497403Sobrien size_t __i = 0; 158597403Sobrien string __digits; 158697403Sobrien bool __testvalid = true; 158797403Sobrien char_type __c = *__beg; 158897403Sobrien while (__beg != __end && __i < __len 158997403Sobrien && __ctype.is(ctype_base::digit, __c)) 159097403Sobrien { 159197403Sobrien __digits += __ctype.narrow(__c, 0); 159297403Sobrien __c = *(++__beg); 159397403Sobrien ++__i; 159497403Sobrien } 159597403Sobrien if (__i == __len) 159697403Sobrien { 159797403Sobrien int __value = atoi(__digits.c_str()); 159897403Sobrien if (__min <= __value && __value <= __max) 159997403Sobrien __member = __value; 160097403Sobrien else 160197403Sobrien __testvalid = false; 160297403Sobrien } 160397403Sobrien else 160497403Sobrien __testvalid = false; 160597403Sobrien if (!__testvalid) 160697403Sobrien __err |= ios_base::failbit; 160797403Sobrien } 160897403Sobrien 160997403Sobrien // Assumptions: 161097403Sobrien // All elements in __names are unique. 161197403Sobrien template<typename _CharT, typename _InIter> 161297403Sobrien void 161397403Sobrien time_get<_CharT, _InIter>:: 161497403Sobrien _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, 161597403Sobrien const _CharT** __names, size_t __indexlen, 161697403Sobrien ios_base::iostate& __err) const 161797403Sobrien { 1618102782Skan typedef char_traits<_CharT> __traits_type; 161997403Sobrien int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen)); 162097403Sobrien size_t __nmatches = 0; 162197403Sobrien size_t __pos = 0; 162297403Sobrien bool __testvalid = true; 162397403Sobrien const char_type* __name; 162497403Sobrien 162597403Sobrien char_type __c = *__beg; 162697403Sobrien // Look for initial matches. 162797403Sobrien for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 162897403Sobrien if (__c == __names[__i1][0]) 162997403Sobrien __matches[__nmatches++] = __i1; 163097403Sobrien 163197403Sobrien while(__nmatches > 1) 163297403Sobrien { 163397403Sobrien // Find smallest matching string. 163497403Sobrien size_t __minlen = 10; 163597403Sobrien for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 1636110614Skan __minlen = min(__minlen, 163797403Sobrien __traits_type::length(__names[__matches[__i2]])); 163897403Sobrien 163997403Sobrien if (__pos < __minlen && __beg != __end) 164097403Sobrien { 164197403Sobrien ++__pos; 164297403Sobrien __c = *(++__beg); 164397403Sobrien for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 164497403Sobrien { 164597403Sobrien __name = __names[__matches[__i3]]; 164697403Sobrien if (__name[__pos] != __c) 164797403Sobrien __matches[__i3] = __matches[--__nmatches]; 164897403Sobrien } 164997403Sobrien } 165097403Sobrien else 165197403Sobrien break; 165297403Sobrien } 165397403Sobrien 165497403Sobrien if (__nmatches == 1) 165597403Sobrien { 165697403Sobrien // Make sure found name is completely extracted. 165797403Sobrien __name = __names[__matches[0]]; 165897403Sobrien const size_t __len = __traits_type::length(__name); 165997403Sobrien while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 166097403Sobrien ++__beg, ++__pos; 166197403Sobrien 166297403Sobrien if (__len == __pos) 166397403Sobrien __member = __matches[0]; 166497403Sobrien else 166597403Sobrien __testvalid = false; 166697403Sobrien } 166797403Sobrien else 166897403Sobrien __testvalid = false; 166997403Sobrien if (!__testvalid) 167097403Sobrien __err |= ios_base::failbit; 167197403Sobrien } 167297403Sobrien 167397403Sobrien template<typename _CharT, typename _InIter> 167497403Sobrien _InIter 167597403Sobrien time_get<_CharT, _InIter>:: 167697403Sobrien do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 167797403Sobrien ios_base::iostate& __err, tm* __tm) const 167897403Sobrien { 167997403Sobrien _CharT __wcs[3]; 168097403Sobrien const char* __cs = "%X"; 168197403Sobrien locale __loc = __io.getloc(); 168297403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 168397403Sobrien __ctype.widen(__cs, __cs + 3, __wcs); 168497403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 168597403Sobrien if (__beg == __end) 168697403Sobrien __err |= ios_base::eofbit; 168797403Sobrien return __beg; 168897403Sobrien } 168997403Sobrien 169097403Sobrien template<typename _CharT, typename _InIter> 169197403Sobrien _InIter 169297403Sobrien time_get<_CharT, _InIter>:: 169397403Sobrien do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 169497403Sobrien ios_base::iostate& __err, tm* __tm) const 169597403Sobrien { 169697403Sobrien _CharT __wcs[3]; 169797403Sobrien const char* __cs = "%x"; 169897403Sobrien locale __loc = __io.getloc(); 169997403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 170097403Sobrien __ctype.widen(__cs, __cs + 3, __wcs); 170197403Sobrien _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 170297403Sobrien if (__beg == __end) 170397403Sobrien __err |= ios_base::eofbit; 170497403Sobrien return __beg; 170597403Sobrien } 170697403Sobrien 170797403Sobrien template<typename _CharT, typename _InIter> 170897403Sobrien _InIter 170997403Sobrien time_get<_CharT, _InIter>:: 171097403Sobrien do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 171197403Sobrien ios_base::iostate& __err, tm* __tm) const 171297403Sobrien { 1713102782Skan typedef char_traits<_CharT> __traits_type; 171497403Sobrien locale __loc = __io.getloc(); 171597403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 171697403Sobrien const char_type* __days[7]; 171797403Sobrien __tp._M_days_abbreviated(__days); 171897403Sobrien int __tmpwday; 171997403Sobrien _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); 172097403Sobrien 172197403Sobrien // Check to see if non-abbreviated name exists, and extract. 172297403Sobrien // NB: Assumes both _M_days and _M_days_abbreviated organized in 172397403Sobrien // exact same order, first to last, such that the resulting 172497403Sobrien // __days array with the same index points to a day, and that 172597403Sobrien // day's abbreviated form. 172697403Sobrien // NB: Also assumes that an abbreviated name is a subset of the name. 172797403Sobrien if (!__err) 172897403Sobrien { 172997403Sobrien size_t __pos = __traits_type::length(__days[__tmpwday]); 173097403Sobrien __tp._M_days(__days); 173197403Sobrien const char_type* __name = __days[__tmpwday]; 173297403Sobrien if (__name[__pos] == *__beg) 173397403Sobrien { 173497403Sobrien // Extract the rest of it. 173597403Sobrien const size_t __len = __traits_type::length(__name); 173697403Sobrien while (__pos < __len && __beg != __end 173797403Sobrien && __name[__pos] == *__beg) 173897403Sobrien ++__beg, ++__pos; 173997403Sobrien if (__len != __pos) 174097403Sobrien __err |= ios_base::failbit; 174197403Sobrien } 174297403Sobrien if (!__err) 174397403Sobrien __tm->tm_wday = __tmpwday; 174497403Sobrien } 174597403Sobrien if (__beg == __end) 174697403Sobrien __err |= ios_base::eofbit; 174797403Sobrien return __beg; 174897403Sobrien } 174997403Sobrien 175097403Sobrien template<typename _CharT, typename _InIter> 175197403Sobrien _InIter 175297403Sobrien time_get<_CharT, _InIter>:: 175397403Sobrien do_get_monthname(iter_type __beg, iter_type __end, 175497403Sobrien ios_base& __io, ios_base::iostate& __err, tm* __tm) const 175597403Sobrien { 1756102782Skan typedef char_traits<_CharT> __traits_type; 175797403Sobrien locale __loc = __io.getloc(); 175897403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 175997403Sobrien const char_type* __months[12]; 176097403Sobrien __tp._M_months_abbreviated(__months); 176197403Sobrien int __tmpmon; 176297403Sobrien _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); 176397403Sobrien 176497403Sobrien // Check to see if non-abbreviated name exists, and extract. 176597403Sobrien // NB: Assumes both _M_months and _M_months_abbreviated organized in 176697403Sobrien // exact same order, first to last, such that the resulting 176797403Sobrien // __months array with the same index points to a month, and that 176897403Sobrien // month's abbreviated form. 176997403Sobrien // NB: Also assumes that an abbreviated name is a subset of the name. 177097403Sobrien if (!__err) 177197403Sobrien { 177297403Sobrien size_t __pos = __traits_type::length(__months[__tmpmon]); 177397403Sobrien __tp._M_months(__months); 177497403Sobrien const char_type* __name = __months[__tmpmon]; 177597403Sobrien if (__name[__pos] == *__beg) 177697403Sobrien { 177797403Sobrien // Extract the rest of it. 177897403Sobrien const size_t __len = __traits_type::length(__name); 177997403Sobrien while (__pos < __len && __beg != __end 178097403Sobrien && __name[__pos] == *__beg) 178197403Sobrien ++__beg, ++__pos; 178297403Sobrien if (__len != __pos) 178397403Sobrien __err |= ios_base::failbit; 178497403Sobrien } 178597403Sobrien if (!__err) 178697403Sobrien __tm->tm_mon = __tmpmon; 178797403Sobrien } 178897403Sobrien 178997403Sobrien if (__beg == __end) 179097403Sobrien __err |= ios_base::eofbit; 179197403Sobrien return __beg; 179297403Sobrien } 179397403Sobrien 179497403Sobrien template<typename _CharT, typename _InIter> 179597403Sobrien _InIter 179697403Sobrien time_get<_CharT, _InIter>:: 179797403Sobrien do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 179897403Sobrien ios_base::iostate& __err, tm* __tm) const 179997403Sobrien { 180097403Sobrien locale __loc = __io.getloc(); 180197403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 180297403Sobrien 180397403Sobrien char_type __c = *__beg; 180497403Sobrien size_t __i = 0; 180597403Sobrien string __digits; 180697403Sobrien while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) 180797403Sobrien { 180897403Sobrien __digits += __ctype.narrow(__c, 0); 180997403Sobrien __c = *(++__beg); 181097403Sobrien ++__i; 181197403Sobrien } 181297403Sobrien if (__i == 2 || __i == 4) 181397403Sobrien { 181497403Sobrien long __l; 181597403Sobrien __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); 181697403Sobrien if (!(__err & ios_base::failbit) && __l <= INT_MAX) 181797403Sobrien { 181897403Sobrien __l = __i == 2 ? __l : __l - 1900; 181997403Sobrien __tm->tm_year = static_cast<int>(__l); 182097403Sobrien } 182197403Sobrien } 182297403Sobrien else 182397403Sobrien __err |= ios_base::failbit; 182497403Sobrien if (__beg == __end) 182597403Sobrien __err |= ios_base::eofbit; 182697403Sobrien return __beg; 182797403Sobrien } 182897403Sobrien 182997403Sobrien template<typename _CharT, typename _OutIter> 183097403Sobrien _OutIter 183197403Sobrien time_put<_CharT, _OutIter>:: 183297403Sobrien put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 183397403Sobrien const _CharT* __beg, const _CharT* __end) const 183497403Sobrien { 183597403Sobrien locale __loc = __io.getloc(); 183697403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 183797403Sobrien while (__beg != __end) 183897403Sobrien { 183997403Sobrien char __c = __ctype.narrow(*__beg, 0); 184097403Sobrien ++__beg; 184197403Sobrien if (__c == '%') 184297403Sobrien { 184397403Sobrien char __format; 184497403Sobrien char __mod = 0; 184597403Sobrien size_t __len = 1; 184697403Sobrien __c = __ctype.narrow(*__beg, 0); 184797403Sobrien ++__beg; 184897403Sobrien if (__c == 'E' || __c == 'O') 184997403Sobrien { 185097403Sobrien __mod = __c; 185197403Sobrien __format = __ctype.narrow(*__beg, 0); 185297403Sobrien ++__beg; 185397403Sobrien } 185497403Sobrien else 185597403Sobrien __format = __c; 185697403Sobrien __s = this->do_put(__s, __io, char_type(), __tm, __format, 185797403Sobrien __mod); 185897403Sobrien } 185997403Sobrien else 186097403Sobrien { 186197403Sobrien *__s = __c; 186297403Sobrien ++__s; 186397403Sobrien } 186497403Sobrien } 186597403Sobrien return __s; 186697403Sobrien } 186797403Sobrien 186897403Sobrien template<typename _CharT, typename _OutIter> 186997403Sobrien _OutIter 187097403Sobrien time_put<_CharT, _OutIter>:: 187197403Sobrien do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 187297403Sobrien char __format, char __mod) const 187397403Sobrien { 187497403Sobrien locale __loc = __io.getloc(); 187597403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 187697403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 187797403Sobrien 187897403Sobrien // NB: This size is arbitrary. Should this be a data member, 187997403Sobrien // initialized at construction? 188097403Sobrien const size_t __maxlen = 64; 188197403Sobrien char_type* __res = 188297403Sobrien static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 188397403Sobrien 188497403Sobrien // NB: In IEE 1003.1-200x, and perhaps other locale models, it 188597403Sobrien // is possible that the format character will be longer than one 188697403Sobrien // character. Possibilities include 'E' or 'O' followed by a 188797403Sobrien // format character: if __mod is not the default argument, assume 188897403Sobrien // it's a valid modifier. 188997403Sobrien char_type __fmt[4]; 189097403Sobrien __fmt[0] = __ctype.widen('%'); 189197403Sobrien if (!__mod) 189297403Sobrien { 189397403Sobrien __fmt[1] = __format; 189497403Sobrien __fmt[2] = char_type(); 189597403Sobrien } 189697403Sobrien else 189797403Sobrien { 189897403Sobrien __fmt[1] = __mod; 189997403Sobrien __fmt[2] = __format; 190097403Sobrien __fmt[3] = char_type(); 190197403Sobrien } 190297403Sobrien 190397403Sobrien __tp._M_put(__res, __maxlen, __fmt, __tm); 190497403Sobrien 190597403Sobrien // Write resulting, fully-formatted string to output iterator. 190697403Sobrien size_t __len = char_traits<char_type>::length(__res); 190797403Sobrien for (size_t __i = 0; __i < __len; ++__i, ++__s) 190897403Sobrien *__s = __res[__i]; 190997403Sobrien return __s; 191097403Sobrien } 191197403Sobrien 191297403Sobrien 191397403Sobrien // Generic version does nothing. 191497403Sobrien template<typename _CharT> 191597403Sobrien int 191697403Sobrien collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 191797403Sobrien { return 0; } 191897403Sobrien 191997403Sobrien // Generic version does nothing. 192097403Sobrien template<typename _CharT> 192197403Sobrien size_t 192297403Sobrien collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 192397403Sobrien { return 0; } 192497403Sobrien 192597403Sobrien template<typename _CharT> 192697403Sobrien int 192797403Sobrien collate<_CharT>:: 192897403Sobrien do_compare(const _CharT* __lo1, const _CharT* __hi1, 192997403Sobrien const _CharT* __lo2, const _CharT* __hi2) const 193097403Sobrien { 193197403Sobrien const string_type __one(__lo1, __hi1); 193297403Sobrien const string_type __two(__lo2, __hi2); 193397403Sobrien return _M_compare(__one.c_str(), __two.c_str()); 193497403Sobrien } 193597403Sobrien 193697403Sobrien template<typename _CharT> 193797403Sobrien typename collate<_CharT>::string_type 193897403Sobrien collate<_CharT>:: 193997403Sobrien do_transform(const _CharT* __lo, const _CharT* __hi) const 194097403Sobrien { 194197403Sobrien size_t __len = (__hi - __lo) * 2; 194297403Sobrien // First try a buffer perhaps big enough. 194397403Sobrien _CharT* __c = 194497403Sobrien static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 194597403Sobrien size_t __res = _M_transform(__c, __lo, __len); 194697403Sobrien // If the buffer was not large enough, try again with the correct size. 194797403Sobrien if (__res >= __len) 194897403Sobrien { 194997403Sobrien __c = 195097403Sobrien static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); 195197403Sobrien _M_transform(__c, __lo, __res + 1); 195297403Sobrien } 195397403Sobrien return string_type(__c); 195497403Sobrien } 195597403Sobrien 195697403Sobrien template<typename _CharT> 195797403Sobrien long 195897403Sobrien collate<_CharT>:: 195997403Sobrien do_hash(const _CharT* __lo, const _CharT* __hi) const 196097403Sobrien { 196197403Sobrien unsigned long __val = 0; 196297403Sobrien for (; __lo < __hi; ++__lo) 196397403Sobrien __val = *__lo + ((__val << 7) | 196497403Sobrien (__val >> (numeric_limits<unsigned long>::digits - 7))); 196597403Sobrien return static_cast<long>(__val); 196697403Sobrien } 196797403Sobrien 196897403Sobrien // Convert string to numeric value of type _Tv and store results. 196997403Sobrien // NB: This is specialized for all required types, there is no 197097403Sobrien // generic definition. 197197403Sobrien template<typename _Tv> 197297403Sobrien void 197397403Sobrien __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, 197497403Sobrien const __c_locale& __cloc, int __base = 10); 197597403Sobrien 197697403Sobrien // Convert numeric value of type _Tv to string and return length of string. 197797403Sobrien // If snprintf is available use it, otherwise fall back to the unsafe sprintf 197897403Sobrien // which, in general, can be dangerous and should be avoided. 197997403Sobrien template<typename _Tv> 198097403Sobrien int 198197403Sobrien __convert_from_v(char* __out, const int __size, const char* __fmt, 1982103447Skan _Tv __v, const __c_locale&, int __prec = -1); 198397403Sobrien 198497403Sobrien // Construct correctly padded string, as per 22.2.2.2.2 198597403Sobrien // Assumes 198697403Sobrien // __newlen > __oldlen 198797403Sobrien // __news is allocated for __newlen size 198897403Sobrien // Used by both num_put and ostream inserters: if __num, 198997403Sobrien // internal-adjusted objects are padded according to the rules below 199097403Sobrien // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 199197403Sobrien // ones are. 1992102782Skan 1993102782Skan // NB: Of the two parameters, _CharT can be deduced from the 1994102782Skan // function arguments. The other (_Traits) has to be explicitly specified. 199597403Sobrien template<typename _CharT, typename _Traits> 1996102782Skan struct __pad 199797403Sobrien { 1998102782Skan static void 1999102782Skan _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, 2000102782Skan const _CharT* __olds, const streamsize __newlen, 2001102782Skan const streamsize __oldlen, const bool __num); 2002102782Skan }; 200397403Sobrien 2004102782Skan template<typename _CharT, typename _Traits> 2005102782Skan void 2006102782Skan __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2007102782Skan _CharT* __news, const _CharT* __olds, 2008102782Skan const streamsize __newlen, 2009102782Skan const streamsize __oldlen, const bool __num) 2010102782Skan { 2011102782Skan size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2012102782Skan _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen)); 2013102782Skan _Traits::assign(__pads, __plen, __fill); 2014102782Skan 2015102782Skan _CharT* __beg; 2016102782Skan _CharT* __end; 201797403Sobrien size_t __mod = 0; 201897403Sobrien size_t __beglen; //either __plen or __oldlen 201997403Sobrien ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 202097403Sobrien 202197403Sobrien if (__adjust == ios_base::left) 202297403Sobrien { 202397403Sobrien // Padding last. 2024102782Skan __beg = const_cast<_CharT*>(__olds); 202597403Sobrien __beglen = __oldlen; 202697403Sobrien __end = __pads; 202797403Sobrien } 202897403Sobrien else if (__adjust == ios_base::internal && __num) 202997403Sobrien { 203097403Sobrien // Pad after the sign, if there is one. 203197403Sobrien // Pad after 0[xX], if there is one. 203297403Sobrien // Who came up with these rules, anyway? Jeeze. 203397403Sobrien locale __loc = __io.getloc(); 203497403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2035102782Skan const _CharT __minus = __ctype.widen('-'); 2036102782Skan const _CharT __plus = __ctype.widen('+'); 2037102782Skan bool __testsign = _Traits::eq(__olds[0], __minus) 2038102782Skan || _Traits::eq(__olds[0], __plus); 2039102782Skan 2040102782Skan bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 2041102782Skan && (_Traits::eq(__ctype.widen('x'), __olds[1]) 2042102782Skan || _Traits::eq(__ctype.widen('X'), __olds[1])); 204397403Sobrien if (__testhex) 204497403Sobrien { 204597403Sobrien __news[0] = __olds[0]; 204697403Sobrien __news[1] = __olds[1]; 204797403Sobrien __mod += 2; 204897403Sobrien __news += 2; 204997403Sobrien __beg = __pads; 205097403Sobrien __beglen = __plen; 2051102782Skan __end = const_cast<_CharT*>(__olds + __mod); 205297403Sobrien } 205397403Sobrien else if (__testsign) 205497403Sobrien { 2055102782Skan _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; 205697403Sobrien ++__mod; 205797403Sobrien ++__news; 205897403Sobrien __beg = __pads; 205997403Sobrien __beglen = __plen; 2060102782Skan __end = const_cast<_CharT*>(__olds + __mod); 206197403Sobrien } 206297403Sobrien else 206397403Sobrien { 206497403Sobrien // Padding first. 206597403Sobrien __beg = __pads; 206697403Sobrien __beglen = __plen; 2067102782Skan __end = const_cast<_CharT*>(__olds); 206897403Sobrien } 206997403Sobrien } 207097403Sobrien else 207197403Sobrien { 207297403Sobrien // Padding first. 207397403Sobrien __beg = __pads; 207497403Sobrien __beglen = __plen; 2075102782Skan __end = const_cast<_CharT*>(__olds); 207697403Sobrien } 2077102782Skan _Traits::copy(__news, __beg, __beglen); 2078102782Skan _Traits::copy(__news + __beglen, __end, 2079102782Skan __newlen - __beglen - __mod); 208097403Sobrien } 208197403Sobrien 208297403Sobrien // Used by both numeric and monetary facets. 208397403Sobrien // Check to make sure that the __grouping_tmp string constructed in 208497403Sobrien // money_get or num_get matches the canonical grouping for a given 208597403Sobrien // locale. 208697403Sobrien // __grouping_tmp is parsed L to R 208797403Sobrien // 1,222,444 == __grouping_tmp of "/1/3/3" 208897403Sobrien // __grouping is parsed R to L 208997403Sobrien // 1,222,444 == __grouping of "/3" == "/3/3/3" 209097403Sobrien template<typename _CharT> 209197403Sobrien bool 209297403Sobrien __verify_grouping(const basic_string<_CharT>& __grouping, 209397403Sobrien basic_string<_CharT>& __grouping_tmp) 209497403Sobrien { 209597403Sobrien int __i = 0; 209697403Sobrien int __j = 0; 209797403Sobrien const int __len = __grouping.size(); 209897403Sobrien const int __n = __grouping_tmp.size(); 209997403Sobrien bool __test = true; 210097403Sobrien 210197403Sobrien // Parsed number groupings have to match the 210297403Sobrien // numpunct::grouping string exactly, starting at the 210397403Sobrien // right-most point of the parsed sequence of elements ... 210497403Sobrien while (__test && __i < __n - 1) 210597403Sobrien for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) 210697403Sobrien __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; 210797403Sobrien // ... but the last parsed grouping can be <= numpunct 210897403Sobrien // grouping. 210997403Sobrien __j == __len ? __j = 0 : __j; 211097403Sobrien __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; 211197403Sobrien return __test; 211297403Sobrien } 211397403Sobrien 211497403Sobrien // Used by both numeric and monetary facets. 211597403Sobrien // Inserts "group separator" characters into an array of characters. 211697403Sobrien // It's recursive, one iteration per group. It moves the characters 211797403Sobrien // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this 211897403Sobrien // only with __gbeg != __gend. 211997403Sobrien template<typename _CharT> 212097403Sobrien _CharT* 212197403Sobrien __add_grouping(_CharT* __s, _CharT __sep, 212297403Sobrien const char* __gbeg, const char* __gend, 212397403Sobrien const _CharT* __first, const _CharT* __last) 212497403Sobrien { 212597403Sobrien if (__last - __first > *__gbeg) 212697403Sobrien { 212797403Sobrien __s = __add_grouping(__s, __sep, 212897403Sobrien (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), 212997403Sobrien __gend, __first, __last - *__gbeg); 213097403Sobrien __first = __last - *__gbeg; 213197403Sobrien *__s++ = __sep; 213297403Sobrien } 213397403Sobrien do 213497403Sobrien *__s++ = *__first++; 213597403Sobrien while (__first != __last); 213697403Sobrien return __s; 213797403Sobrien } 213897403Sobrien 213997403Sobrien // Inhibit implicit instantiations for required instantiations, 214097403Sobrien // which are defined via explicit instantiations elsewhere. 214197403Sobrien // NB: This syntax is a GNU extension. 214297403Sobrien extern template class moneypunct<char, false>; 214397403Sobrien extern template class moneypunct<char, true>; 214497403Sobrien extern template class moneypunct_byname<char, false>; 214597403Sobrien extern template class moneypunct_byname<char, true>; 214697403Sobrien extern template class money_get<char>; 214797403Sobrien extern template class money_put<char>; 214897403Sobrien extern template class numpunct<char>; 214997403Sobrien extern template class numpunct_byname<char>; 215097403Sobrien extern template class num_get<char>; 215197403Sobrien extern template class num_put<char>; 215297403Sobrien extern template class __timepunct<char>; 215397403Sobrien extern template class time_put<char>; 215497403Sobrien extern template class time_put_byname<char>; 215597403Sobrien extern template class time_get<char>; 215697403Sobrien extern template class time_get_byname<char>; 215797403Sobrien extern template class messages<char>; 215897403Sobrien extern template class messages_byname<char>; 215997403Sobrien extern template class ctype_byname<char>; 216097403Sobrien extern template class codecvt_byname<char, char, mbstate_t>; 216197403Sobrien extern template class collate<char>; 216297403Sobrien extern template class collate_byname<char>; 216397403Sobrien 216497403Sobrien extern template 216597403Sobrien const codecvt<char, char, mbstate_t>& 216697403Sobrien use_facet<codecvt<char, char, mbstate_t> >(const locale&); 216797403Sobrien 216897403Sobrien extern template 216997403Sobrien const collate<char>& 217097403Sobrien use_facet<collate<char> >(const locale&); 217197403Sobrien 217297403Sobrien extern template 217397403Sobrien const numpunct<char>& 217497403Sobrien use_facet<numpunct<char> >(const locale&); 217597403Sobrien 217697403Sobrien extern template 217797403Sobrien const num_put<char>& 217897403Sobrien use_facet<num_put<char> >(const locale&); 217997403Sobrien 218097403Sobrien extern template 218197403Sobrien const num_get<char>& 218297403Sobrien use_facet<num_get<char> >(const locale&); 218397403Sobrien 218497403Sobrien extern template 218597403Sobrien const moneypunct<char, true>& 218697403Sobrien use_facet<moneypunct<char, true> >(const locale&); 218797403Sobrien 218897403Sobrien extern template 218997403Sobrien const moneypunct<char, false>& 219097403Sobrien use_facet<moneypunct<char, false> >(const locale&); 219197403Sobrien 219297403Sobrien extern template 219397403Sobrien const money_put<char>& 219497403Sobrien use_facet<money_put<char> >(const locale&); 219597403Sobrien 219697403Sobrien extern template 219797403Sobrien const money_get<char>& 219897403Sobrien use_facet<money_get<char> >(const locale&); 219997403Sobrien 220097403Sobrien extern template 220197403Sobrien const __timepunct<char>& 220297403Sobrien use_facet<__timepunct<char> >(const locale&); 220397403Sobrien 220497403Sobrien extern template 220597403Sobrien const time_put<char>& 220697403Sobrien use_facet<time_put<char> >(const locale&); 220797403Sobrien 220897403Sobrien extern template 220997403Sobrien const time_get<char>& 221097403Sobrien use_facet<time_get<char> >(const locale&); 221197403Sobrien 221297403Sobrien extern template 221397403Sobrien const messages<char>& 221497403Sobrien use_facet<messages<char> >(const locale&); 221597403Sobrien 2216107606Sobrien extern template 2217107606Sobrien bool 2218107606Sobrien has_facet<ctype<char> >(const locale&); 2219107606Sobrien 2220107606Sobrien extern template 2221107606Sobrien bool 2222107606Sobrien has_facet<codecvt<char, char, mbstate_t> >(const locale&); 2223107606Sobrien 2224107606Sobrien extern template 2225107606Sobrien bool 2226107606Sobrien has_facet<collate<char> >(const locale&); 2227107606Sobrien 2228107606Sobrien extern template 2229107606Sobrien bool 2230107606Sobrien has_facet<numpunct<char> >(const locale&); 2231107606Sobrien 2232107606Sobrien extern template 2233107606Sobrien bool 2234107606Sobrien has_facet<num_put<char> >(const locale&); 2235107606Sobrien 2236107606Sobrien extern template 2237107606Sobrien bool 2238107606Sobrien has_facet<num_get<char> >(const locale&); 2239107606Sobrien 2240107606Sobrien extern template 2241107606Sobrien bool 2242107606Sobrien has_facet<moneypunct<char> >(const locale&); 2243107606Sobrien 2244107606Sobrien extern template 2245107606Sobrien bool 2246107606Sobrien has_facet<money_put<char> >(const locale&); 2247107606Sobrien 2248107606Sobrien extern template 2249107606Sobrien bool 2250107606Sobrien has_facet<money_get<char> >(const locale&); 2251107606Sobrien 2252107606Sobrien extern template 2253107606Sobrien bool 2254107606Sobrien has_facet<__timepunct<char> >(const locale&); 2255107606Sobrien 2256107606Sobrien extern template 2257107606Sobrien bool 2258107606Sobrien has_facet<time_put<char> >(const locale&); 2259107606Sobrien 2260107606Sobrien extern template 2261107606Sobrien bool 2262107606Sobrien has_facet<time_get<char> >(const locale&); 2263107606Sobrien 2264107606Sobrien extern template 2265107606Sobrien bool 2266107606Sobrien has_facet<messages<char> >(const locale&); 2267107606Sobrien 2268107606Sobrien#ifdef _GLIBCPP_USE_WCHAR_T 2269107606Sobrien extern template class moneypunct<wchar_t, false>; 2270107606Sobrien extern template class moneypunct<wchar_t, true>; 2271107606Sobrien extern template class moneypunct_byname<wchar_t, false>; 2272107606Sobrien extern template class moneypunct_byname<wchar_t, true>; 2273107606Sobrien extern template class money_get<wchar_t>; 2274107606Sobrien extern template class money_put<wchar_t>; 2275107606Sobrien extern template class numpunct<wchar_t>; 2276107606Sobrien extern template class numpunct_byname<wchar_t>; 2277107606Sobrien extern template class num_get<wchar_t>; 2278107606Sobrien extern template class num_put<wchar_t>; 2279107606Sobrien extern template class __timepunct<wchar_t>; 2280107606Sobrien extern template class time_put<wchar_t>; 2281107606Sobrien extern template class time_put_byname<wchar_t>; 2282107606Sobrien extern template class time_get<wchar_t>; 2283107606Sobrien extern template class time_get_byname<wchar_t>; 2284107606Sobrien extern template class messages<wchar_t>; 2285107606Sobrien extern template class messages_byname<wchar_t>; 2286107606Sobrien extern template class ctype_byname<wchar_t>; 2287107606Sobrien extern template class codecvt_byname<wchar_t, char, mbstate_t>; 2288107606Sobrien extern template class collate<wchar_t>; 2289107606Sobrien extern template class collate_byname<wchar_t>; 2290107606Sobrien 229197403Sobrien extern template 229297403Sobrien const codecvt<wchar_t, char, mbstate_t>& 229397403Sobrien use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 229497403Sobrien 229597403Sobrien extern template 229697403Sobrien const collate<wchar_t>& 229797403Sobrien use_facet<collate<wchar_t> >(const locale&); 229897403Sobrien 229997403Sobrien extern template 230097403Sobrien const numpunct<wchar_t>& 230197403Sobrien use_facet<numpunct<wchar_t> >(const locale&); 230297403Sobrien 230397403Sobrien extern template 230497403Sobrien const num_put<wchar_t>& 230597403Sobrien use_facet<num_put<wchar_t> >(const locale&); 230697403Sobrien 230797403Sobrien extern template 230897403Sobrien const num_get<wchar_t>& 230997403Sobrien use_facet<num_get<wchar_t> >(const locale&); 231097403Sobrien 231197403Sobrien extern template 231297403Sobrien const moneypunct<wchar_t, true>& 231397403Sobrien use_facet<moneypunct<wchar_t, true> >(const locale&); 231497403Sobrien 231597403Sobrien extern template 231697403Sobrien const moneypunct<wchar_t, false>& 231797403Sobrien use_facet<moneypunct<wchar_t, false> >(const locale&); 231897403Sobrien 231997403Sobrien extern template 232097403Sobrien const money_put<wchar_t>& 232197403Sobrien use_facet<money_put<wchar_t> >(const locale&); 232297403Sobrien 232397403Sobrien extern template 232497403Sobrien const money_get<wchar_t>& 232597403Sobrien use_facet<money_get<wchar_t> >(const locale&); 232697403Sobrien 232797403Sobrien extern template 232897403Sobrien const __timepunct<wchar_t>& 232997403Sobrien use_facet<__timepunct<wchar_t> >(const locale&); 233097403Sobrien 233197403Sobrien extern template 233297403Sobrien const time_put<wchar_t>& 233397403Sobrien use_facet<time_put<wchar_t> >(const locale&); 233497403Sobrien 233597403Sobrien extern template 233697403Sobrien const time_get<wchar_t>& 233797403Sobrien use_facet<time_get<wchar_t> >(const locale&); 233897403Sobrien 233997403Sobrien extern template 234097403Sobrien const messages<wchar_t>& 234197403Sobrien use_facet<messages<wchar_t> >(const locale&); 234297403Sobrien 234397403Sobrien extern template 234497403Sobrien bool 234597403Sobrien has_facet<ctype<wchar_t> >(const locale&); 234697403Sobrien 234797403Sobrien extern template 234897403Sobrien bool 234997403Sobrien has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 235097403Sobrien 235197403Sobrien extern template 235297403Sobrien bool 235397403Sobrien has_facet<collate<wchar_t> >(const locale&); 235497403Sobrien 235597403Sobrien extern template 235697403Sobrien bool 235797403Sobrien has_facet<numpunct<wchar_t> >(const locale&); 235897403Sobrien 235997403Sobrien extern template 236097403Sobrien bool 236197403Sobrien has_facet<num_put<wchar_t> >(const locale&); 236297403Sobrien 236397403Sobrien extern template 236497403Sobrien bool 236597403Sobrien has_facet<num_get<wchar_t> >(const locale&); 236697403Sobrien 236797403Sobrien extern template 236897403Sobrien bool 236997403Sobrien has_facet<moneypunct<wchar_t> >(const locale&); 237097403Sobrien 237197403Sobrien extern template 237297403Sobrien bool 237397403Sobrien has_facet<money_put<wchar_t> >(const locale&); 237497403Sobrien 237597403Sobrien extern template 237697403Sobrien bool 237797403Sobrien has_facet<money_get<wchar_t> >(const locale&); 237897403Sobrien 237997403Sobrien extern template 238097403Sobrien bool 238197403Sobrien has_facet<__timepunct<wchar_t> >(const locale&); 238297403Sobrien 238397403Sobrien extern template 238497403Sobrien bool 238597403Sobrien has_facet<time_put<wchar_t> >(const locale&); 238697403Sobrien 238797403Sobrien extern template 238897403Sobrien bool 238997403Sobrien has_facet<time_get<wchar_t> >(const locale&); 239097403Sobrien 239197403Sobrien extern template 239297403Sobrien bool 239397403Sobrien has_facet<messages<wchar_t> >(const locale&); 2394107606Sobrien#endif 239597403Sobrien} // namespace std 239697403Sobrien 239797403Sobrien#endif 2398