locale_facets.tcc revision 117397
11590Srgrimes// Locale support -*- C++ -*- 21590Srgrimes 31590Srgrimes// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 41590Srgrimes// Free Software Foundation, Inc. 51590Srgrimes// 61590Srgrimes// This file is part of the GNU ISO C++ Library. This library is free 71590Srgrimes// software; you can redistribute it and/or modify it under the 81590Srgrimes// terms of the GNU General Public License as published by the 91590Srgrimes// Free Software Foundation; either version 2, or (at your option) 101590Srgrimes// any later version. 111590Srgrimes 121590Srgrimes// This library is distributed in the hope that it will be useful, 131590Srgrimes// but WITHOUT ANY WARRANTY; without even the implied warranty of 141590Srgrimes// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151590Srgrimes// GNU General Public License for more details. 161590Srgrimes 171590Srgrimes// You should have received a copy of the GNU General Public License along 181590Srgrimes// with this library; see the file COPYING. If not, write to the Free 191590Srgrimes// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 201590Srgrimes// USA. 211590Srgrimes 221590Srgrimes// As a special exception, you may use this file as part of a free software 231590Srgrimes// library without restriction. Specifically, if other files instantiate 241590Srgrimes// templates or use macros or inline functions from this file, or you compile 251590Srgrimes// this file and link it with other files to produce an executable, this 261590Srgrimes// file does not by itself cause the resulting executable to be covered by 271590Srgrimes// the GNU General Public License. This exception does not however 281590Srgrimes// invalidate any other reasons why the executable file might be covered by 291590Srgrimes// the GNU General Public License. 301590Srgrimes 311590Srgrimes// Warning: this file is not meant for user inclusion. Use <locale>. 321590Srgrimes 331590Srgrimes#ifndef _CPP_BITS_LOCFACETS_TCC 3423246Swosch#define _CPP_BITS_LOCFACETS_TCC 1 351590Srgrimes 361590Srgrimes#pragma GCC system_header 371590Srgrimes 3823246Swosch#include <cerrno> 391590Srgrimes#include <clocale> // For localeconv 401590Srgrimes#include <cstdlib> // For strof, strtold 4127605Scharnier#include <cmath> // For ceil 421590Srgrimes#include <cctype> // For isspace 4327605Scharnier#include <limits> // For numeric_limits 4427605Scharnier#include <typeinfo> // For bad_cast. 4550477Speter#include <bits/streambuf_iterator.h> 461590Srgrimes 471590Srgrimesnamespace std 481590Srgrimes{ 491590Srgrimes template<typename _Facet> 501590Srgrimes locale 511590Srgrimes locale::combine(const locale& __other) const 521590Srgrimes { 531590Srgrimes _Impl* __tmp = new _Impl(*_M_impl, 1); 5423246Swosch __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 551590Srgrimes return locale(__tmp); 561590Srgrimes } 5757339Sshin 581590Srgrimes template<typename _CharT, typename _Traits, typename _Alloc> 591590Srgrimes bool 601590Srgrimes locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 6116423Sache const basic_string<_CharT, _Traits, _Alloc>& __s2) const 6216423Sache { 631590Srgrimes typedef std::collate<_CharT> __collate_type; 641590Srgrimes const __collate_type& __collate = use_facet<__collate_type>(*this); 651590Srgrimes return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 661590Srgrimes __s2.data(), __s2.data() + __s2.length()) < 0); 6740102Smarkm } 6841079Sjdp 6916423Sache template<typename _Facet> 701590Srgrimes const _Facet& 711590Srgrimes use_facet(const locale& __loc) 721590Srgrimes { 731590Srgrimes size_t __i = _Facet::id._M_id(); 741590Srgrimes locale::facet** __facets = __loc._M_impl->_M_facets; 751590Srgrimes if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) 761590Srgrimes __throw_bad_cast(); 771590Srgrimes return static_cast<const _Facet&>(*__facets[__i]); 781590Srgrimes } 791590Srgrimes 801590Srgrimes template<typename _Facet> 8174874Smarkm bool 8241279Sjdp has_facet(const locale& __loc) throw() 8341279Sjdp { 8474874Smarkm size_t __i = _Facet::id._M_id(); 8574874Smarkm locale::facet** __facets = __loc._M_impl->_M_facets; 863702Spst return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); 871590Srgrimes } 881590Srgrimes 8957339Sshin // Routine to access a cache for the locale. If the cache didn't 9057339Sshin // exist before, it gets constructed on the fly. 9157339Sshin template<typename _Facet> 9257339Sshin inline const __locale_cache<_Facet>& 9357339Sshin __use_cache(const locale& __loc) 941590Srgrimes { 951590Srgrimes size_t __i = _Facet::id._M_id(); 961590Srgrimes if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false)) 971590Srgrimes __throw_bad_cast(); 9821528Sdavidn __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i); 991590Srgrimes if (__builtin_expect(!__cache, false)) 1001590Srgrimes { 1011590Srgrimes __cache = new __locale_cache<_Facet>(__loc); 10223985Sdavidn __loc._M_impl->_M_install_cache(__cache, __i); 1031590Srgrimes } 1041590Srgrimes return static_cast<const __locale_cache<_Facet>&>(*__cache); 10529922Smarkm } 1062224Sguido 1071590Srgrimes // Stage 1: Determine a conversion specifier. 10874874Smarkm template<typename _CharT, typename _InIter> 10941279Sjdp _InIter 11072215Snectar num_get<_CharT, _InIter>:: 11172215Snectar _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 11274874Smarkm ios_base::iostate& __err, string& __xtrc) const 11374874Smarkm { 11474874Smarkm typedef char_traits<_CharT> __traits_type; 11574874Smarkm const locale __loc = __io.getloc(); 11674874Smarkm const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 11774874Smarkm const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 11874874Smarkm 11974874Smarkm // First check for sign. 12074874Smarkm const char_type __plus = __ctype.widen('+'); 12174874Smarkm const char_type __minus = __ctype.widen('-'); 12274874Smarkm int __pos = 0; 12374874Smarkm char_type __c = *__beg; 12474874Smarkm if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 12541279Sjdp && __beg != __end) 1261590Srgrimes { 12727605Scharnier __xtrc += __ctype.narrow(__c, char()); 1281590Srgrimes ++__pos; 1291590Srgrimes __c = *(++__beg); 13023985Sdavidn } 13123985Sdavidn 13276786Sobrien // Next, strip leading zeros. 13376786Sobrien const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); 1341590Srgrimes bool __found_zero = false; 1351590Srgrimes while (__traits_type::eq(__c, __zero) && __beg != __end) 1361590Srgrimes { 1371590Srgrimes __c = *(++__beg); 1381590Srgrimes __found_zero = true; 1391590Srgrimes } 1401590Srgrimes if (__found_zero) 14142272Seivind { 14242272Seivind __xtrc += _S_atoms_in[_M_zero]; 14342272Seivind ++__pos; 1441590Srgrimes } 1451590Srgrimes 14676786Sobrien // Only need acceptable digits for floating point numbers. 14716423Sache const size_t __len = _M_E - _M_zero + 1; 1481590Srgrimes char_type __watoms[__len]; 1491590Srgrimes __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); 1501590Srgrimes bool __found_dec = false; 1511590Srgrimes bool __found_sci = false; 1521590Srgrimes const char_type __dec = __np.decimal_point(); 1531590Srgrimes 1541590Srgrimes string __found_grouping; 1551590Srgrimes const string __grouping = __np.grouping(); 1561590Srgrimes bool __check_grouping = __grouping.size(); 1571590Srgrimes int __sep_pos = 0; 1581590Srgrimes const char_type __sep = __np.thousands_sep(); 15923985Sdavidn 1601590Srgrimes while (__beg != __end) 1614878Sugen { 16223985Sdavidn // Only look in digits. 16335559Speter const char_type* __p = __traits_type::find(__watoms, 10, __c); 16446007Sache 16545431Sbrian // NB: strchr returns true for __c == 0x0 16642272Seivind if (__p && !__traits_type::eq(__c, char_type())) 16742272Seivind { 16823985Sdavidn // Try first for acceptable digit; record it if found. 16921528Sdavidn ++__pos; 17074874Smarkm __xtrc += _S_atoms_in[__p - __watoms]; 17174874Smarkm ++__sep_pos; 17274874Smarkm __c = *(++__beg); 17374874Smarkm } 1741590Srgrimes else if (__traits_type::eq(__c, __sep) 17542272Seivind && __check_grouping && !__found_dec) 17642272Seivind { 17776942Sguido // NB: Thousands separator at the beginning of a string 17842272Seivind // is a no-no, as is two consecutive thousands separators. 17942272Seivind if (__sep_pos) 18042272Seivind { 18176788Sobrien __found_grouping += static_cast<char>(__sep_pos); 18276788Sobrien __sep_pos = 0; 18342272Seivind __c = *(++__beg); 18442272Seivind } 1851590Srgrimes else 1861590Srgrimes { 1871590Srgrimes __err |= ios_base::failbit; 1881590Srgrimes break; 1891590Srgrimes } 1901590Srgrimes } 1911590Srgrimes else if (__traits_type::eq(__c, __dec) && !__found_dec) 1921590Srgrimes { 1931590Srgrimes // According to the standard, if no grouping chars are seen, 1941590Srgrimes // no grouping check is applied. Therefore __found_grouping 1951590Srgrimes // must be adjusted only if __dec comes after some __sep. 1961590Srgrimes if (__found_grouping.size()) 1973205Spst __found_grouping += static_cast<char>(__sep_pos); 19823985Sdavidn ++__pos; 1991590Srgrimes __xtrc += '.'; 2001590Srgrimes __c = *(++__beg); 2011590Srgrimes __found_dec = true; 20235557Speter } 20346007Sache else if ((__traits_type::eq(__c, __watoms[_M_e]) 20424360Simp || __traits_type::eq(__c, __watoms[_M_E])) 2051590Srgrimes && !__found_sci && __pos) 2061590Srgrimes { 2071590Srgrimes // Scientific notation. 2081590Srgrimes ++__pos; 2091590Srgrimes __xtrc += __ctype.narrow(__c, char()); 2101590Srgrimes __c = *(++__beg); 2111590Srgrimes 2121590Srgrimes // Remove optional plus or minus sign, if they exist. 2133205Spst if (__traits_type::eq(__c, __plus) 21436559Samurai || __traits_type::eq(__c, __minus)) 21545431Sbrian { 21636559Samurai ++__pos; 21716423Sache __xtrc += __ctype.narrow(__c, char()); 21857339Sshin __c = *(++__beg); 21957339Sshin } 22057339Sshin __found_sci = true; 22157339Sshin } 22257339Sshin else 22357339Sshin // Not a valid input item. 22476788Sobrien break; 22557339Sshin } 22657339Sshin 22716423Sache // Digit grouping is checked. If grouping and found_grouping don't 22857339Sshin // match, then get very very upset, and set failbit. 22976788Sobrien if (__check_grouping && __found_grouping.size()) 23076788Sobrien { 23176788Sobrien // Add the ending grouping if a decimal wasn't found. 23276788Sobrien if (!__found_dec) 23376788Sobrien __found_grouping += static_cast<char>(__sep_pos); 23457339Sshin if (!__verify_grouping(__grouping, __found_grouping)) 23516423Sache __err |= ios_base::failbit; 23616423Sache } 23757339Sshin 23857339Sshin // Finish up 23916423Sache __xtrc += char(); 2401590Srgrimes if (__beg == __end) 2411590Srgrimes __err |= ios_base::eofbit; 2421590Srgrimes return __beg; 2431590Srgrimes } 2441590Srgrimes 2451590Srgrimes // Stage 1: Determine a conversion specifier. 2461590Srgrimes template<typename _CharT, typename _InIter> 2471590Srgrimes _InIter 2481590Srgrimes num_get<_CharT, _InIter>:: 24927605Scharnier _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 2501590Srgrimes ios_base::iostate& __err, string& __xtrc, int& __base) const 2511590Srgrimes { 2521590Srgrimes typedef char_traits<_CharT> __traits_type; 2531590Srgrimes const locale __loc = __io.getloc(); 2541590Srgrimes const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2551590Srgrimes const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2561590Srgrimes 2571590Srgrimes // NB: Iff __basefield == 0, this can change based on contents. 2581590Srgrimes ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 2591590Srgrimes if (__basefield == ios_base::oct) 2601590Srgrimes __base = 8; 2611590Srgrimes else if (__basefield == ios_base::hex) 2621590Srgrimes __base = 16; 2631590Srgrimes else 2641590Srgrimes __base = 10; 2651590Srgrimes 2661590Srgrimes // First check for sign. 2671590Srgrimes int __pos = 0; 26823985Sdavidn char_type __c = *__beg; 2691590Srgrimes const char_type __plus = __ctype.widen('+'); 2701590Srgrimes const char_type __minus = __ctype.widen('-'); 2711590Srgrimes 2721590Srgrimes if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 27323985Sdavidn && __beg != __end) 27423985Sdavidn { 27523985Sdavidn __xtrc += __ctype.narrow(__c, char()); 27623985Sdavidn ++__pos; 27776786Sobrien __c = *(++__beg); 27876786Sobrien } 27976786Sobrien 28076788Sobrien // Next, strip leading zeros and check required digits for base formats. 28176788Sobrien const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); 28276788Sobrien const char_type __x = __ctype.widen('x'); 28376788Sobrien const char_type __X = __ctype.widen('X'); 28423985Sdavidn if (__base == 10) 28523985Sdavidn { 28621528Sdavidn bool __found_zero = false; 2871590Srgrimes while (__traits_type::eq(__c, __zero) && __beg != __end) 2881590Srgrimes { 2891590Srgrimes __c = *(++__beg); 2901590Srgrimes __found_zero = true; 2911590Srgrimes } 2921590Srgrimes if (__found_zero) 29321528Sdavidn { 29421528Sdavidn __xtrc += _S_atoms_in[_M_zero]; 2951590Srgrimes ++__pos; 2961590Srgrimes if (__basefield == 0) 2971590Srgrimes { 2981590Srgrimes if ((__traits_type::eq(__c, __x) 2991590Srgrimes || __traits_type::eq(__c, __X)) 3001590Srgrimes && __beg != __end) 3011590Srgrimes { 3021590Srgrimes __xtrc += __ctype.narrow(__c, char()); 3031590Srgrimes ++__pos; 3041590Srgrimes __c = *(++__beg); 3051590Srgrimes __base = 16; 3061590Srgrimes } 30727605Scharnier else 30827605Scharnier __base = 8; 3091590Srgrimes } 31041279Sjdp } 31123985Sdavidn } 31223985Sdavidn else if (__base == 16) 3131590Srgrimes { 3141590Srgrimes if (__traits_type::eq(__c, __zero) && __beg != __end) 3151590Srgrimes { 3161590Srgrimes __xtrc += _S_atoms_in[_M_zero]; 3171590Srgrimes ++__pos; 31821528Sdavidn __c = *(++__beg); 3193205Spst if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) 3203205Spst && __beg != __end) 3213205Spst { 32223985Sdavidn __xtrc += __ctype.narrow(__c, char()); 32376788Sobrien ++__pos; 3243205Spst __c = *(++__beg); 3253205Spst } 3263205Spst } 32724321Sdavidn } 32824251Sdavidn 32924251Sdavidn // At this point, base is determined. If not hex, only allow 33024251Sdavidn // base digits as valid input. 33124251Sdavidn size_t __len; 3323205Spst if (__base == 16) 3333205Spst __len = _M_size; 3343205Spst else 3351590Srgrimes __len = __base; 3361590Srgrimes 3371590Srgrimes // Extract. 3381590Srgrimes char_type __watoms[_M_size]; 33974874Smarkm __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); 34041279Sjdp string __found_grouping; 34141279Sjdp const string __grouping = __np.grouping(); 34241279Sjdp bool __check_grouping = __grouping.size(); 34341279Sjdp int __sep_pos = 0; 34441279Sjdp const char_type __sep = __np.thousands_sep(); 34541279Sjdp while (__beg != __end) 34674874Smarkm { 34741279Sjdp const char_type* __p = __traits_type::find(__watoms, __len, __c); 34823985Sdavidn 34941279Sjdp // NB: strchr returns true for __c == 0x0 35023985Sdavidn if (__p && !__traits_type::eq(__c, char_type())) 35174874Smarkm { 35241279Sjdp // Try first for acceptable digit; record it if found. 35341279Sjdp __xtrc += _S_atoms_in[__p - __watoms]; 35441279Sjdp ++__pos; 35541279Sjdp ++__sep_pos; 35641279Sjdp __c = *(++__beg); 35741279Sjdp } 35841279Sjdp else if (__traits_type::eq(__c, __sep) && __check_grouping) 35974874Smarkm { 3601590Srgrimes // NB: Thousands separator at the beginning of a string 3613205Spst // is a no-no, as is two consecutive thousands separators. 3621590Srgrimes if (__sep_pos) 3631590Srgrimes { 3641590Srgrimes __found_grouping += static_cast<char>(__sep_pos); 3651590Srgrimes __sep_pos = 0; 36624222Sdavidn __c = *(++__beg); 36724222Sdavidn } 36824222Sdavidn else 36924222Sdavidn { 37024222Sdavidn __err |= ios_base::failbit; 3711590Srgrimes break; 3721590Srgrimes } 3731590Srgrimes } 3741590Srgrimes else 37523985Sdavidn // Not a valid input item. 37623985Sdavidn break; 37723985Sdavidn } 37823985Sdavidn 37923985Sdavidn // Digit grouping is checked. If grouping and found_grouping don't 38023985Sdavidn // match, then get very very upset, and set failbit. 38123985Sdavidn if (__check_grouping && __found_grouping.size()) 3821590Srgrimes { 3831590Srgrimes // Add the ending grouping. 3841590Srgrimes __found_grouping += static_cast<char>(__sep_pos); 38538374Sjkoshy if (!__verify_grouping(__grouping, __found_grouping)) 3861590Srgrimes __err |= ios_base::failbit; 3871590Srgrimes } 3881590Srgrimes 3891590Srgrimes // Finish up. 3901590Srgrimes __xtrc += char(); 39176942Sguido if (__beg == __end) 3921590Srgrimes __err |= ios_base::eofbit; 3931590Srgrimes return __beg; 3941590Srgrimes } 39541279Sjdp 39641279Sjdp#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 39741279Sjdp //17. Bad bool parsing 39841279Sjdp template<typename _CharT, typename _InIter> 39941279Sjdp _InIter 4001590Srgrimes num_get<_CharT, _InIter>:: 4011590Srgrimes do_get(iter_type __beg, iter_type __end, ios_base& __io, 40221528Sdavidn ios_base::iostate& __err, bool& __v) const 4031590Srgrimes { 40421528Sdavidn // Parse bool values as unsigned long 40546007Sache if (!(__io.flags() & ios_base::boolalpha)) 40646007Sache { 40735557Speter // NB: We can't just call do_get(long) here, as it might 40821528Sdavidn // refer to a derived class. 40926021Spst string __xtrc; 41023985Sdavidn int __base; 41124485Sdavidn __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 41223985Sdavidn 41323985Sdavidn unsigned long __ul; 41423985Sdavidn __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 41557546Sache if (!(__err & ios_base::failbit) && __ul <= 1) 4161590Srgrimes __v = __ul; 41735557Speter else 41846007Sache __err |= ios_base::failbit; 41921528Sdavidn } 42021528Sdavidn 4211590Srgrimes // Parse bool values as alphanumeric 4221590Srgrimes else 4231590Srgrimes { 4242532Sjkh typedef char_traits<_CharT> __traits_type; 42576791Sobrien typedef basic_string<_CharT> __string_type; 42621528Sdavidn 42776710Seric locale __loc = __io.getloc(); 42876788Sobrien const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 42976788Sobrien const __string_type __true = __np.truename(); 43076710Seric const __string_type __false = __np.falsename(); 43176710Seric const char_type* __trues = __true.c_str(); 43276710Seric const char_type* __falses = __false.c_str(); 43376788Sobrien const size_t __truen = __true.size() - 1; 43476788Sobrien const size_t __falsen = __false.size() - 1; 43576710Seric 43676788Sobrien for (size_t __n = 0; __beg != __end; ++__n) 43776788Sobrien { 43876710Seric char_type __c = *__beg++; 43976710Seric bool __testf = __n <= __falsen 44076788Sobrien ? __traits_type::eq(__c, __falses[__n]) : false; 44176788Sobrien bool __testt = __n <= __truen 44223985Sdavidn ? __traits_type::eq(__c, __trues[__n]) : false; 44376791Sobrien if (!(__testf || __testt)) 44421528Sdavidn { 4451590Srgrimes __err |= ios_base::failbit; 4461590Srgrimes break; 44776791Sobrien } 44876788Sobrien else if (__testf && __n == __falsen) 44976788Sobrien { 45023985Sdavidn __v = 0; 45176788Sobrien break; 45276788Sobrien } 45323985Sdavidn else if (__testt && __n == __truen) 45423985Sdavidn { 45521528Sdavidn __v = 1; 45621528Sdavidn break; 45757339Sshin } 45857339Sshin } 45921528Sdavidn if (__beg == __end) 46057339Sshin __err |= ios_base::eofbit; 46157339Sshin } 46257339Sshin return __beg; 46357339Sshin } 46457339Sshin#endif 46557339Sshin 46657339Sshin template<typename _CharT, typename _InIter> 46757339Sshin _InIter 46876788Sobrien num_get<_CharT, _InIter>:: 46976788Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 47057339Sshin ios_base::iostate& __err, long& __v) const 47157339Sshin { 47221528Sdavidn string __xtrc; 47357339Sshin int __base; 47457339Sshin __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 47523985Sdavidn __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 47623985Sdavidn return __beg; 47721528Sdavidn } 47821528Sdavidn 47923985Sdavidn template<typename _CharT, typename _InIter> 48023985Sdavidn _InIter 48121528Sdavidn num_get<_CharT, _InIter>:: 48223985Sdavidn do_get(iter_type __beg, iter_type __end, ios_base& __io, 48323985Sdavidn ios_base::iostate& __err, unsigned short& __v) const 48421528Sdavidn { 48576788Sobrien string __xtrc; 48623985Sdavidn int __base; 48723985Sdavidn __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 48823985Sdavidn unsigned long __ul; 48923985Sdavidn __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 49023985Sdavidn if (!(__err & ios_base::failbit) 49123985Sdavidn && __ul <= numeric_limits<unsigned short>::max()) 49223985Sdavidn __v = static_cast<unsigned short>(__ul); 49323985Sdavidn else 49421528Sdavidn __err |= ios_base::failbit; 49521528Sdavidn return __beg; 49623985Sdavidn } 49723985Sdavidn 49821528Sdavidn template<typename _CharT, typename _InIter> 49921528Sdavidn _InIter 5001590Srgrimes num_get<_CharT, _InIter>:: 5011590Srgrimes do_get(iter_type __beg, iter_type __end, ios_base& __io, 5021590Srgrimes ios_base::iostate& __err, unsigned int& __v) const 5031590Srgrimes { 5041590Srgrimes string __xtrc; 5051590Srgrimes int __base; 5061590Srgrimes __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 5071590Srgrimes unsigned long __ul; 5081590Srgrimes __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 5091590Srgrimes if (!(__err & ios_base::failbit) 5101590Srgrimes && __ul <= numeric_limits<unsigned int>::max()) 5112224Sguido __v = static_cast<unsigned int>(__ul); 5122224Sguido else 5132224Sguido __err |= ios_base::failbit; 5142224Sguido return __beg; 5152224Sguido } 5162224Sguido 5172224Sguido template<typename _CharT, typename _InIter> 51850124Simp _InIter 51950124Simp num_get<_CharT, _InIter>:: 52050124Simp do_get(iter_type __beg, iter_type __end, ios_base& __io, 52150124Simp ios_base::iostate& __err, unsigned long& __v) const 52250124Simp { 52350124Simp string __xtrc; 52459621Ssheldonh int __base; 52550124Simp __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 52650124Simp __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 52750124Simp return __beg; 52850124Simp } 5291590Srgrimes 53050124Simp#ifdef _GLIBCPP_USE_LONG_LONG 53123985Sdavidn template<typename _CharT, typename _InIter> 53223985Sdavidn _InIter 53323985Sdavidn num_get<_CharT, _InIter>:: 53424222Sdavidn do_get(iter_type __beg, iter_type __end, ios_base& __io, 53524222Sdavidn ios_base::iostate& __err, long long& __v) const 5361590Srgrimes { 53723985Sdavidn string __xtrc; 53823985Sdavidn int __base; 53923985Sdavidn __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 54023985Sdavidn __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 54123985Sdavidn return __beg; 54224894Sdavidn } 5431590Srgrimes 5441590Srgrimes template<typename _CharT, typename _InIter> 5453205Spst _InIter 5463205Spst num_get<_CharT, _InIter>:: 5473205Spst do_get(iter_type __beg, iter_type __end, ios_base& __io, 5483205Spst ios_base::iostate& __err, unsigned long long& __v) const 5493205Spst { 55023985Sdavidn string __xtrc; 55123985Sdavidn int __base; 55223985Sdavidn __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 55323985Sdavidn __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 55423985Sdavidn return __beg; 55523985Sdavidn } 55621528Sdavidn#endif 55721528Sdavidn 55823985Sdavidn template<typename _CharT, typename _InIter> 55923985Sdavidn _InIter 56023985Sdavidn num_get<_CharT, _InIter>:: 56123985Sdavidn do_get(iter_type __beg, iter_type __end, ios_base& __io, 56223985Sdavidn ios_base::iostate& __err, float& __v) const 56323985Sdavidn { 56423985Sdavidn string __xtrc; 56576788Sobrien __xtrc.reserve(32); 56623985Sdavidn __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 56723985Sdavidn __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 56876788Sobrien return __beg; 56923985Sdavidn } 57023985Sdavidn 57123985Sdavidn template<typename _CharT, typename _InIter> 57223985Sdavidn _InIter 57323985Sdavidn num_get<_CharT, _InIter>:: 57423985Sdavidn do_get(iter_type __beg, iter_type __end, ios_base& __io, 57523985Sdavidn ios_base::iostate& __err, double& __v) const 57621528Sdavidn { 57721528Sdavidn string __xtrc; 57821528Sdavidn __xtrc.reserve(32); 57974874Smarkm __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 58023985Sdavidn __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 58172215Snectar return __beg; 58272215Snectar } 58372215Snectar 58474874Smarkm template<typename _CharT, typename _InIter> 58574874Smarkm _InIter 58674874Smarkm num_get<_CharT, _InIter>:: 58774874Smarkm do_get(iter_type __beg, iter_type __end, ios_base& __io, 58874874Smarkm ios_base::iostate& __err, long double& __v) const 58974874Smarkm { 59072215Snectar string __xtrc; 59172215Snectar __xtrc.reserve(32); 59274874Smarkm __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 59374874Smarkm __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 59474874Smarkm return __beg; 59574874Smarkm } 59674874Smarkm 59774874Smarkm template<typename _CharT, typename _InIter> 59874874Smarkm _InIter 59974874Smarkm num_get<_CharT, _InIter>:: 60074874Smarkm do_get(iter_type __beg, iter_type __end, ios_base& __io, 60174874Smarkm ios_base::iostate& __err, void*& __v) const 60276788Sobrien { 60376788Sobrien // Prepare for hex formatted input 60476788Sobrien typedef ios_base::fmtflags fmtflags; 60576788Sobrien fmtflags __fmt = __io.flags(); 60676788Sobrien fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield 60776788Sobrien | ios_base::uppercase | ios_base::internal); 60874874Smarkm __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); 60974874Smarkm 61074874Smarkm string __xtrc; 61174874Smarkm int __base; 61274874Smarkm __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 61374874Smarkm 61474874Smarkm // Reset from hex formatted input 61574874Smarkm __io.flags(__fmt); 61674874Smarkm 61774874Smarkm unsigned long __ul; 61874874Smarkm __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 61974874Smarkm if (!(__err & ios_base::failbit)) 62076788Sobrien __v = reinterpret_cast<void*>(__ul); 62176788Sobrien else 62274874Smarkm __err |= ios_base::failbit; 62374874Smarkm return __beg; 62474874Smarkm } 62574874Smarkm 62674874Smarkm // For use by integer and floating-point types after they have been 62776788Sobrien // converted into a char_type string. 62876788Sobrien template<typename _CharT, typename _OutIter> 62974874Smarkm void 63074874Smarkm num_put<_CharT, _OutIter>:: 63174874Smarkm _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 63274874Smarkm _CharT* __new, const _CharT* __cs, int& __len) const 63374874Smarkm { 63423985Sdavidn // [22.2.2.2.2] Stage 3. 63521528Sdavidn // If necessary, pad. 63621528Sdavidn __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 63741279Sjdp __w, __len, true); 63841279Sjdp __len = static_cast<int>(__w); 63941279Sjdp } 64041279Sjdp 64141279Sjdp // Forwarding functions to peel signed from unsigned integer types. 64274874Smarkm template<typename _CharT> 64321528Sdavidn inline int 64421528Sdavidn __int_to_char(_CharT* __out, const int __size, long __v, 6453205Spst const _CharT* __lit, ios_base::fmtflags __flags) 64621528Sdavidn { 64723148Sache unsigned long __ul = static_cast<unsigned long>(__v); 64821528Sdavidn bool __neg = false; 64923985Sdavidn if (__v < 0) 65076788Sobrien { 65121528Sdavidn __ul = -__ul; 65223985Sdavidn __neg = true; 65321528Sdavidn } 65441279Sjdp return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); 65541279Sjdp } 65621528Sdavidn 65721528Sdavidn template<typename _CharT> 6581590Srgrimes inline int 65923985Sdavidn __int_to_char(_CharT* __out, const int __size, unsigned long __v, 66023985Sdavidn const _CharT* __lit, ios_base::fmtflags __flags) 66123985Sdavidn { return __int_to_char(__out, __size, __v, __lit, __flags, false); } 66221528Sdavidn 66321528Sdavidn#ifdef _GLIBCPP_USE_LONG_LONG 66421528Sdavidn template<typename _CharT> 66523985Sdavidn inline int 66623985Sdavidn __int_to_char(_CharT* __out, const int __size, long long __v, 66723985Sdavidn const _CharT* __lit, ios_base::fmtflags __flags) 66823985Sdavidn { 66923985Sdavidn unsigned long long __ull = static_cast<unsigned long long>(__v); 67023985Sdavidn bool __neg = false; 67123985Sdavidn if (__v < 0) 67221528Sdavidn { 67321528Sdavidn __ull = -__ull; 67421528Sdavidn __neg = true; 67521528Sdavidn } 67623985Sdavidn return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); 67721528Sdavidn } 67821528Sdavidn 67921528Sdavidn template<typename _CharT> 68021528Sdavidn inline int 68121528Sdavidn __int_to_char(_CharT* __out, const int __size, unsigned long long __v, 68276788Sobrien const _CharT* __lit, ios_base::fmtflags __flags) 68376788Sobrien { return __int_to_char(__out, __size, __v, __lit, __flags, false); } 6841590Srgrimes#endif 68523985Sdavidn 68676788Sobrien template<typename _CharT, typename _ValueT> 6871590Srgrimes int 6881590Srgrimes __int_to_char(_CharT* __out, const int __size, _ValueT __v, 68921528Sdavidn const _CharT* __lit, ios_base::fmtflags __flags, bool __neg) 6903205Spst { 6911590Srgrimes // Don't write base if already 0. 6921590Srgrimes const bool __showbase = (__flags & ios_base::showbase) && __v; 6931590Srgrimes const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 6941590Srgrimes _CharT* __buf = __out + __size - 1; 6951590Srgrimes _CharT* __bufend = __out + __size; 6964878Sugen 69721528Sdavidn if (__builtin_expect(__basefield != ios_base::oct && 6984878Sugen __basefield != ios_base::hex, true)) 6994878Sugen { 7004878Sugen // Decimal. 70123985Sdavidn do 70223985Sdavidn { 70323985Sdavidn *__buf-- = __lit[(__v % 10) + __num_base::_S_digits]; 70423985Sdavidn __v /= 10; 70576788Sobrien } 70676788Sobrien while (__v != 0); 70723985Sdavidn if (__neg) 70821528Sdavidn *__buf-- = __lit[__num_base::_S_minus]; 70921528Sdavidn else if (__flags & ios_base::showpos) 7101590Srgrimes *__buf-- = __lit[__num_base::_S_plus]; 7111590Srgrimes } 71241279Sjdp else if (__basefield == ios_base::oct) 71341279Sjdp { 71441279Sjdp // Octal. 71541279Sjdp do 71641279Sjdp { 71741279Sjdp *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits]; 71841279Sjdp __v >>= 3; 71941279Sjdp } 72041279Sjdp while (__v != 0); 72141279Sjdp if (__showbase) 72241279Sjdp *__buf-- = __lit[__num_base::_S_digits]; 72376786Sobrien } 72441279Sjdp else 72541279Sjdp { 72641279Sjdp // Hex. 72741279Sjdp const bool __uppercase = __flags & ios_base::uppercase; 72841279Sjdp int __case_offset = __uppercase 72941279Sjdp ? __num_base::_S_udigits : __num_base::_S_digits; 73041279Sjdp do 73141279Sjdp { 73241279Sjdp *__buf-- = __lit[(__v & 0xf) + __case_offset]; 73341279Sjdp __v >>= 4; 73441279Sjdp } 73541279Sjdp while (__v != 0); 73641279Sjdp if (__showbase) 73741279Sjdp { 73874874Smarkm // 'x' or 'X' 73941279Sjdp *__buf-- = __lit[__num_base::_S_x + __uppercase]; 74041279Sjdp // '0' 74141279Sjdp *__buf-- = __lit[__num_base::_S_digits]; 74241279Sjdp } 74341279Sjdp } 74441279Sjdp int __ret = __bufend - __buf - 1; 74541279Sjdp return __ret; 74641279Sjdp } 74741279Sjdp 74841279Sjdp template<typename _CharT, typename _OutIter> 74941279Sjdp void 75041279Sjdp num_put<_CharT, _OutIter>:: 75141279Sjdp _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 75241279Sjdp _CharT* __new, _CharT* __cs, int& __len) const 75341279Sjdp { 75441279Sjdp // By itself __add_grouping cannot deal correctly with __ws when 75541279Sjdp // ios::showbase is set and ios_base::oct || ios_base::hex. 75641279Sjdp // Therefore we take care "by hand" of the initial 0, 0x or 0X. 75741279Sjdp // However, remember that the latter do not occur if the number 75841279Sjdp // printed is '0' (__len == 1). 75941279Sjdp streamsize __off = 0; 76041279Sjdp const ios_base::fmtflags __basefield = __io.flags() 76141279Sjdp & ios_base::basefield; 76241279Sjdp if ((__io.flags() & ios_base::showbase) && __len > 1) 76341279Sjdp if (__basefield == ios_base::oct) 76441279Sjdp { 76541279Sjdp __off = 1; 76641279Sjdp *__new = *__cs; 76741279Sjdp } 76841279Sjdp else if (__basefield == ios_base::hex) 76941279Sjdp { 77041279Sjdp __off = 2; 77141279Sjdp *__new = *__cs; 77241279Sjdp *(__new + 1) = *(__cs + 1); 77341279Sjdp } 77441279Sjdp _CharT* __p; 77541279Sjdp __p = __add_grouping(__new + __off, __sep, 77641279Sjdp __grouping.c_str(), 77741279Sjdp __grouping.c_str() + __grouping.size(), 77841279Sjdp __cs + __off, __cs + __len); 77941279Sjdp __len = __p - __new; 78041279Sjdp } 78141279Sjdp 78241279Sjdp template<typename _CharT, typename _OutIter> 78341279Sjdp template<typename _ValueT> 78441279Sjdp _OutIter 78541279Sjdp num_put<_CharT, _OutIter>:: 78641279Sjdp _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 78741279Sjdp _ValueT __v) const 78841279Sjdp { 78941279Sjdp typedef numpunct<_CharT> __facet_type; 79041279Sjdp typedef __locale_cache<numpunct<_CharT> > __cache_type; 79141279Sjdp const locale& __loc = __io._M_getloc(); 79241279Sjdp const __cache_type& __lc = __use_cache<__facet_type>(__loc); 79341279Sjdp const _CharT* __lit = __lc._M_atoms_out; 79441279Sjdp 79541279Sjdp // Long enough to hold hex, dec, and octal representations. 79641279Sjdp int __ilen = 4 * sizeof(_ValueT); 79741279Sjdp _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 79841279Sjdp * __ilen)); 79941279Sjdp // [22.2.2.2.2] Stage 1, numeric conversion to character. 80041279Sjdp // Result is returned right-justified in the buffer. 80141279Sjdp int __len; 80241279Sjdp __len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags()); 80341279Sjdp __cs = __cs + __ilen - __len; 80441279Sjdp 80541279Sjdp // Add grouping, if necessary. 80641279Sjdp _CharT* __cs2; 80741279Sjdp if (__lc._M_use_grouping) 80841279Sjdp { 80974874Smarkm // Grouping can add (almost) as many separators as the 81041279Sjdp // number of digits, but no more. 81141279Sjdp __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 81241279Sjdp * __len * 2)); 81374874Smarkm _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, 81474874Smarkm __cs2, __cs, __len); 81574874Smarkm __cs = __cs2; 81674874Smarkm } 81774874Smarkm 81874874Smarkm // Pad. 81976788Sobrien _CharT* __cs3; 82076788Sobrien streamsize __w = __io.width(); 82174874Smarkm if (__w > static_cast<streamsize>(__len)) 82274874Smarkm { 82374874Smarkm __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 82474874Smarkm * __w)); 82574874Smarkm _M_pad(__fill, __w, __io, __cs3, __cs, __len); 82641279Sjdp __cs = __cs3; 82774874Smarkm } 82874874Smarkm __io.width(0); 82974874Smarkm 83074874Smarkm // [22.2.2.2.2] Stage 4. 83174874Smarkm // Write resulting, fully-formatted string to output iterator. 83274874Smarkm return __write(__s, __cs, __len); 83374874Smarkm } 83441279Sjdp 83541279Sjdp template<typename _CharT, typename _OutIter> 83672215Snectar void 83772215Snectar num_put<_CharT, _OutIter>:: 83872215Snectar _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 83972215Snectar _CharT* __new, _CharT* __cs, int& __len) const 84072215Snectar { 84172215Snectar#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 84272215Snectar //282. What types does numpunct grouping refer to? 84372215Snectar // Add grouping, if necessary. 84472215Snectar _CharT* __p2; 84572215Snectar int __declen = __p ? __p - __cs : __len; 84672215Snectar __p2 = __add_grouping(__new, __sep, 84772215Snectar __grouping.c_str(), 84872215Snectar __grouping.c_str() + __grouping.size(), 84972215Snectar __cs, __cs + __declen); 85072215Snectar 85172215Snectar // Tack on decimal part. 85272215Snectar int __newlen = __p2 - __new; 85372215Snectar if (__p) 85472215Snectar { 85572215Snectar char_traits<_CharT>::copy(__p2, __p, __len - __declen); 85672215Snectar __newlen += __len - __declen; 85772215Snectar } 85872215Snectar __len = __newlen; 85972215Snectar#endif 86072215Snectar } 86172215Snectar 86272215Snectar // The following code uses snprintf (or sprintf(), when 86372215Snectar // _GLIBCPP_USE_C99 is not defined) to convert floating point values 86472215Snectar // for insertion into a stream. An optimization would be to replace 86572215Snectar // them with code that works directly on a wide buffer and then use 86672215Snectar // __pad to do the padding. It would be good to replace them anyway 86772215Snectar // to gain back the efficiency that C++ provides by knowing up front 86872215Snectar // the type of the values to insert. Also, sprintf is dangerous 86972215Snectar // since may lead to accidental buffer overruns. This 87072215Snectar // implementation follows the C++ standard fairly directly as 87172215Snectar // outlined in 22.2.2.2 [lib.locale.num.put] 87272215Snectar template<typename _CharT, typename _OutIter> 87372215Snectar template<typename _ValueT> 87472215Snectar _OutIter 87572215Snectar num_put<_CharT, _OutIter>:: 87672215Snectar _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 87772215Snectar _ValueT __v) const 87872215Snectar { 87974874Smarkm // Note: digits10 is rounded down: add 1 to ensure the maximum 88041279Sjdp // available precision. Then, in general, one more 1 needs to 88127605Scharnier // be added since, when the %{g,G} conversion specifiers are 88227605Scharnier // chosen inside _S_format_float, the precision field is "the 88327605Scharnier // maximum number of significant digits", *not* the "number of 88476791Sobrien // digits to appear after the decimal point", as happens for 88527605Scharnier // %{e,E,f,F} (C99, 7.19.6.1,4). 88627605Scharnier const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; 88727605Scharnier 8881590Srgrimes // Use default precision if out of range. 88923985Sdavidn streamsize __prec = __io.precision(); 89023985Sdavidn if (__prec > static_cast<streamsize>(__max_digits)) 89174874Smarkm __prec = static_cast<streamsize>(__max_digits); 89221528Sdavidn else if (__prec < static_cast<streamsize>(0)) 89321528Sdavidn __prec = static_cast<streamsize>(6); 89421528Sdavidn 8951590Srgrimes typedef numpunct<_CharT> __facet_type; 8961590Srgrimes typedef __locale_cache<numpunct<_CharT> > __cache_type; 8971590Srgrimes const locale __loc = __io._M_getloc(); 8981590Srgrimes const __cache_type& __lc = __use_cache<__facet_type>(__loc); 8991590Srgrimes 9001590Srgrimes // [22.2.2.2.2] Stage 1, numeric conversion to character. 9011590Srgrimes int __len; 9021590Srgrimes // Long enough for the max format spec. 90376786Sobrien char __fbuf[16]; 9041590Srgrimes 9051590Srgrimes#ifdef _GLIBCPP_USE_C99 9061590Srgrimes // First try a buffer perhaps big enough (for sure sufficient 9071590Srgrimes // for non-ios_base::fixed outputs) 9081590Srgrimes int __cs_size = __max_digits * 3; 9091590Srgrimes char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 9101590Srgrimes 9111590Srgrimes _S_format_float(__io, __fbuf, __mod, __prec); 91259645Ssheldonh __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 9131590Srgrimes _S_c_locale, __prec); 9141590Srgrimes 9151590Srgrimes // If the buffer was not large enough, try again with the correct size. 9161590Srgrimes if (__len >= __cs_size) 9171590Srgrimes { 9181590Srgrimes __cs_size = __len + 1; 9191590Srgrimes __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 9201590Srgrimes __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 92159645Ssheldonh _S_c_locale, __prec); 9221590Srgrimes } 9231590Srgrimes#else 9241590Srgrimes // Consider the possibility of long ios_base::fixed outputs 9251590Srgrimes const bool __fixed = __io.flags() & ios_base::fixed; 9261590Srgrimes const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 9271590Srgrimes 9281590Srgrimes // ios_base::fixed outputs may need up to __max_exp+1 chars 9291590Srgrimes // for the integer part + up to __max_digits chars for the 93023985Sdavidn // fractional part + 3 chars for sign, decimal point, '\0'. On 9311590Srgrimes // the other hand, for non-fixed outputs __max_digits*3 chars 9321590Srgrimes // are largely sufficient. 9331590Srgrimes const int __cs_size = __fixed ? __max_exp + __max_digits + 4 93421528Sdavidn : __max_digits * 3; 9351590Srgrimes char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 93621528Sdavidn 9371590Srgrimes _S_format_float(__io, __fbuf, __mod, __prec); 93821528Sdavidn __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); 93921528Sdavidn#endif 9401590Srgrimes 94121528Sdavidn // [22.2.2.2.2] Stage 2, convert to char_type, using correct 94221528Sdavidn // numpunct.decimal_point() values for '.' and adding grouping. 94321528Sdavidn const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 94421528Sdavidn 94521528Sdavidn _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 94621528Sdavidn * __len)); 94721528Sdavidn __ctype.widen(__cs, __cs + __len, __ws); 9481590Srgrimes 9491590Srgrimes // Replace decimal point. 95021528Sdavidn const _CharT __cdec = __ctype.widen('.'); 9511590Srgrimes const _CharT __dec = __lc._M_decimal_point; 95221528Sdavidn const _CharT* __p; 9531590Srgrimes if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) 95421528Sdavidn __ws[__p - __ws] = __dec; 9551590Srgrimes 95621528Sdavidn // Add grouping, if necessary. 95721528Sdavidn _CharT* __ws2; 9581590Srgrimes if (__lc._M_use_grouping) 9591590Srgrimes { 9601590Srgrimes // Grouping can add (almost) as many separators as the 9611590Srgrimes // number of digits, but no more. 9621590Srgrimes __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 9631590Srgrimes * __len * 2)); 9641590Srgrimes _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p, 9651590Srgrimes __ws2, __ws, __len); 9661590Srgrimes __ws = __ws2; 96776788Sobrien } 96842272Seivind 9691590Srgrimes // Pad. 9701590Srgrimes _CharT* __ws3; 9711590Srgrimes streamsize __w = __io.width(); 9721590Srgrimes if (__w > static_cast<streamsize>(__len)) 9731590Srgrimes { 9741590Srgrimes __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); 9751590Srgrimes _M_pad(__fill, __w, __io, __ws3, __ws, __len); 9761590Srgrimes __ws = __ws3; 9771590Srgrimes } 9781590Srgrimes __io.width(0); 9791590Srgrimes 9801590Srgrimes // [22.2.2.2.2] Stage 4. 9811590Srgrimes // Write resulting, fully-formatted string to output iterator. 9821590Srgrimes return __write(__s, __ws, __len); 9831590Srgrimes } 9841590Srgrimes 9851590Srgrimes template<typename _CharT, typename _OutIter> 9861590Srgrimes _OutIter 9871590Srgrimes num_put<_CharT, _OutIter>:: 9881590Srgrimes do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 9891590Srgrimes { 9901590Srgrimes ios_base::fmtflags __flags = __io.flags(); 9911590Srgrimes if ((__flags & ios_base::boolalpha) == 0) 9921590Srgrimes { 9931590Srgrimes unsigned long __uv = __v; 9941590Srgrimes __s = _M_convert_int(__s, __io, __fill, __uv); 9951590Srgrimes } 9961590Srgrimes else 9971590Srgrimes { 9981590Srgrimes typedef numpunct<_CharT> __facet_type; 9991590Srgrimes typedef __locale_cache<numpunct<_CharT> > __cache_type; 10001590Srgrimes const locale __loc = __io._M_getloc(); 10011590Srgrimes const __cache_type& __lc = __use_cache<__facet_type>(__loc); 10021590Srgrimes 10031590Srgrimes typedef basic_string<_CharT> __string_type; 10041590Srgrimes __string_type __name; 10051590Srgrimes if (__v) 10061590Srgrimes __name = __lc._M_truename; 10071590Srgrimes else 10081590Srgrimes __name = __lc._M_falsename; 10091590Srgrimes 10101590Srgrimes const _CharT* __cs = __name.c_str(); 10111590Srgrimes int __len = __name.size(); 10121590Srgrimes _CharT* __cs3; 10131590Srgrimes streamsize __w = __io.width(); 10141590Srgrimes if (__w > static_cast<streamsize>(__len)) 10151590Srgrimes { 101616423Sache __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 10171590Srgrimes * __w)); 10181590Srgrimes _M_pad(__fill, __w, __io, __cs3, __cs, __len); 101916423Sache __cs = __cs3; 10201590Srgrimes } 10211590Srgrimes __io.width(0); 10221590Srgrimes __s = __write(__s, __cs, __len); 10231590Srgrimes } 10241590Srgrimes return __s; 10251590Srgrimes } 10261590Srgrimes 102742272Seivind template<typename _CharT, typename _OutIter> 10281590Srgrimes _OutIter 10291590Srgrimes num_put<_CharT, _OutIter>:: 10301590Srgrimes do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 10311590Srgrimes { return _M_convert_int(__s, __io, __fill, __v); } 10321590Srgrimes 10331590Srgrimes template<typename _CharT, typename _OutIter> 10341590Srgrimes _OutIter 10351590Srgrimes num_put<_CharT, _OutIter>:: 10361590Srgrimes do_put(iter_type __s, ios_base& __io, char_type __fill, 10371590Srgrimes unsigned long __v) const 103823985Sdavidn { return _M_convert_int(__s, __io, __fill, __v); } 10391590Srgrimes 10401590Srgrimes#ifdef _GLIBCPP_USE_LONG_LONG 10411590Srgrimes template<typename _CharT, typename _OutIter> 10421590Srgrimes _OutIter 104323985Sdavidn num_put<_CharT, _OutIter>:: 104423985Sdavidn do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 104523985Sdavidn { return _M_convert_int(__s, __b, __fill, __v); } 104623985Sdavidn 104723985Sdavidn template<typename _CharT, typename _OutIter> 104823985Sdavidn _OutIter 104923985Sdavidn num_put<_CharT, _OutIter>:: 105023985Sdavidn do_put(iter_type __s, ios_base& __io, char_type __fill, 105123985Sdavidn unsigned long long __v) const 105223985Sdavidn { return _M_convert_int(__s, __io, __fill, __v); } 105376788Sobrien#endif 105423985Sdavidn 105523985Sdavidn template<typename _CharT, typename _OutIter> 105676788Sobrien _OutIter 105723985Sdavidn num_put<_CharT, _OutIter>:: 105823985Sdavidn do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 105923985Sdavidn { return _M_convert_float(__s, __io, __fill, char(), __v); } 106023985Sdavidn 106123985Sdavidn template<typename _CharT, typename _OutIter> 10621590Srgrimes _OutIter 10631590Srgrimes num_put<_CharT, _OutIter>:: 10641590Srgrimes do_put(iter_type __s, ios_base& __io, char_type __fill, 106523985Sdavidn long double __v) const 10661590Srgrimes { return _M_convert_float(__s, __io, __fill, 'L', __v); } 10671590Srgrimes 10681590Srgrimes template<typename _CharT, typename _OutIter> 1069 _OutIter 1070 num_put<_CharT, _OutIter>:: 1071 do_put(iter_type __s, ios_base& __io, char_type __fill, 1072 const void* __v) const 1073 { 1074 ios_base::fmtflags __flags = __io.flags(); 1075 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield 1076 | ios_base::uppercase | ios_base::internal); 1077 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 1078 try 1079 { 1080 __s = _M_convert_int(__s, __io, __fill, 1081 reinterpret_cast<unsigned long>(__v)); 1082 __io.flags(__flags); 1083 } 1084 catch (...) 1085 { 1086 __io.flags(__flags); 1087 __throw_exception_again; 1088 } 1089 return __s; 1090 } 1091 1092 1093 template<typename _CharT, typename _InIter> 1094 _InIter 1095 money_get<_CharT, _InIter>:: 1096 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1097 ios_base::iostate& __err, long double& __units) const 1098 { 1099 string_type __str; 1100 __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 1101 1102 const int __n = numeric_limits<long double>::digits10; 1103 char* __cs = static_cast<char*>(__builtin_alloca(__n)); 1104 const locale __loc = __io.getloc(); 1105 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1106 const _CharT* __wcs = __str.c_str(); 1107 __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); 1108 __convert_to_v(__cs, __units, __err, _S_c_locale); 1109 return __beg; 1110 } 1111 1112 template<typename _CharT, typename _InIter> 1113 _InIter 1114 money_get<_CharT, _InIter>:: 1115 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1116 ios_base::iostate& __err, string_type& __units) const 1117 { 1118 // These contortions are quite unfortunate. 1119 typedef moneypunct<_CharT, true> __money_true; 1120 typedef moneypunct<_CharT, false> __money_false; 1121 typedef money_base::part part; 1122 typedef typename string_type::size_type size_type; 1123 1124 const locale __loc = __io.getloc(); 1125 const __money_true& __mpt = use_facet<__money_true>(__loc); 1126 const __money_false& __mpf = use_facet<__money_false>(__loc); 1127 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1128 1129 const money_base::pattern __p = __intl ? __mpt.neg_format() 1130 : __mpf.neg_format(); 1131 1132 const string_type __pos_sign =__intl ? __mpt.positive_sign() 1133 : __mpf.positive_sign(); 1134 const string_type __neg_sign =__intl ? __mpt.negative_sign() 1135 : __mpf.negative_sign(); 1136 const char_type __d = __intl ? __mpt.decimal_point() 1137 : __mpf.decimal_point(); 1138 const char_type __sep = __intl ? __mpt.thousands_sep() 1139 : __mpf.thousands_sep(); 1140 1141 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); 1142 1143 // Set to deduced positive or negative sign, depending. 1144 string_type __sign; 1145 // String of grouping info from thousands_sep plucked from __units. 1146 string __grouping_tmp; 1147 // Marker for thousands_sep position. 1148 int __sep_pos = 0; 1149 // If input iterator is in a valid state. 1150 bool __testvalid = true; 1151 // Flag marking when a decimal point is found. 1152 bool __testdecfound = false; 1153 1154 // The tentative returned string is stored here. 1155 string_type __temp_units; 1156 1157 char_type __c = *__beg; 1158 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); 1159 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) 1160 { 1161 part __which = static_cast<part>(__p.field[__i]); 1162 switch (__which) 1163 { 1164 case money_base::symbol: 1165 if (__io.flags() & ios_base::showbase 1166 || __i < 2 || __sign.size() > 1 1167 || ((static_cast<part>(__p.field[3]) != money_base::none) 1168 && __i == 2)) 1169 { 1170 // According to 22.2.6.1.2.2, symbol is required 1171 // if (__io.flags() & ios_base::showbase), 1172 // otherwise is optional and consumed only if 1173 // other characters are needed to complete the 1174 // format. 1175 const string_type __symbol = __intl ? __mpt.curr_symbol() 1176 : __mpf.curr_symbol(); 1177 size_type __len = __symbol.size(); 1178 size_type __j = 0; 1179 while (__beg != __end 1180 && __j < __len && __symbol[__j] == __c) 1181 { 1182 __c = *(++__beg); 1183 ++__j; 1184 } 1185 // When (__io.flags() & ios_base::showbase) 1186 // symbol is required. 1187 if (__j != __len && (__io.flags() & ios_base::showbase)) 1188 __testvalid = false; 1189 } 1190 break; 1191 case money_base::sign: 1192 // Sign might not exist, or be more than one character long. 1193 if (__pos_sign.size() && __neg_sign.size()) 1194 { 1195 // Sign is mandatory. 1196 if (__c == __pos_sign[0]) 1197 { 1198 __sign = __pos_sign; 1199 __c = *(++__beg); 1200 } 1201 else if (__c == __neg_sign[0]) 1202 { 1203 __sign = __neg_sign; 1204 __c = *(++__beg); 1205 } 1206 else 1207 __testvalid = false; 1208 } 1209 else if (__pos_sign.size() && __c == __pos_sign[0]) 1210 { 1211 __sign = __pos_sign; 1212 __c = *(++__beg); 1213 } 1214 else if (__neg_sign.size() && __c == __neg_sign[0]) 1215 { 1216 __sign = __neg_sign; 1217 __c = *(++__beg); 1218 } 1219 break; 1220 case money_base::value: 1221 // Extract digits, remove and stash away the 1222 // grouping of found thousands separators. 1223 while (__beg != __end 1224 && (__ctype.is(ctype_base::digit, __c) 1225 || (__c == __d && !__testdecfound) 1226 || __c == __sep)) 1227 { 1228 if (__c == __d) 1229 { 1230 __grouping_tmp += static_cast<char>(__sep_pos); 1231 __sep_pos = 0; 1232 __testdecfound = true; 1233 } 1234 else if (__c == __sep) 1235 { 1236 if (__grouping.size()) 1237 { 1238 // Mark position for later analysis. 1239 __grouping_tmp += static_cast<char>(__sep_pos); 1240 __sep_pos = 0; 1241 } 1242 else 1243 { 1244 __testvalid = false; 1245 break; 1246 } 1247 } 1248 else 1249 { 1250 __temp_units += __c; 1251 ++__sep_pos; 1252 } 1253 __c = *(++__beg); 1254 } 1255 break; 1256 case money_base::space: 1257 case money_base::none: 1258 // Only if not at the end of the pattern. 1259 if (__i != 3) 1260 while (__beg != __end 1261 && __ctype.is(ctype_base::space, __c)) 1262 __c = *(++__beg); 1263 break; 1264 } 1265 } 1266 1267 // Need to get the rest of the sign characters, if they exist. 1268 if (__sign.size() > 1) 1269 { 1270 size_type __len = __sign.size(); 1271 size_type __i = 1; 1272 for (; __c != __eof && __i < __len; ++__i) 1273 while (__beg != __end && __c != __sign[__i]) 1274 __c = *(++__beg); 1275 1276 if (__i != __len) 1277 __testvalid = false; 1278 } 1279 1280 // Strip leading zeros. 1281 while (__temp_units[0] == __ctype.widen('0')) 1282 __temp_units.erase(__temp_units.begin()); 1283 1284 if (__sign.size() && __sign == __neg_sign) 1285 __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); 1286 1287 // Test for grouping fidelity. 1288 if (__grouping.size() && __grouping_tmp.size()) 1289 { 1290 if (!__verify_grouping(__grouping, __grouping_tmp)) 1291 __testvalid = false; 1292 } 1293 1294 // Iff no more characters are available. 1295 if (__c == __eof) 1296 __err |= ios_base::eofbit; 1297 1298 // Iff valid sequence is not recognized. 1299 if (!__testvalid || !__temp_units.size()) 1300 __err |= ios_base::failbit; 1301 else 1302 // Use the "swap trick" to copy __temp_units into __units. 1303 __temp_units.swap(__units); 1304 1305 return __beg; 1306 } 1307 1308 template<typename _CharT, typename _OutIter> 1309 _OutIter 1310 money_put<_CharT, _OutIter>:: 1311 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 1312 long double __units) const 1313 { 1314 const locale __loc = __io.getloc(); 1315 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1316#ifdef _GLIBCPP_USE_C99 1317 // First try a buffer perhaps big enough. 1318 int __cs_size = 64; 1319 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1320 int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 1321 _S_c_locale); 1322 // If the buffer was not large enough, try again with the correct size. 1323 if (__len >= __cs_size) 1324 { 1325 __cs_size = __len + 1; 1326 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1327 __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 1328 _S_c_locale); 1329 } 1330#else 1331 // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, 1332 // decimal digit, '\0'. 1333 const int __cs_size = numeric_limits<long double>::max_exponent10 + 5; 1334 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1335 int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); 1336#endif 1337 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1338 * __cs_size)); 1339 __ctype.widen(__cs, __cs + __len, __ws); 1340 string_type __digits(__ws); 1341 return this->do_put(__s, __intl, __io, __fill, __digits); 1342 } 1343 1344 template<typename _CharT, typename _OutIter> 1345 _OutIter 1346 money_put<_CharT, _OutIter>:: 1347 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 1348 const string_type& __digits) const 1349 { 1350 typedef typename string_type::size_type size_type; 1351 typedef money_base::part part; 1352 1353 const locale __loc = __io.getloc(); 1354 const size_type __width = static_cast<size_type>(__io.width()); 1355 1356 // These contortions are quite unfortunate. 1357 typedef moneypunct<_CharT, true> __money_true; 1358 typedef moneypunct<_CharT, false> __money_false; 1359 const __money_true& __mpt = use_facet<__money_true>(__loc); 1360 const __money_false& __mpf = use_facet<__money_false>(__loc); 1361 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1362 1363 // Determine if negative or positive formats are to be used, and 1364 // discard leading negative_sign if it is present. 1365 const char_type* __beg = __digits.data(); 1366 const char_type* __end = __beg + __digits.size(); 1367 money_base::pattern __p; 1368 string_type __sign; 1369 if (*__beg != __ctype.widen('-')) 1370 { 1371 __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); 1372 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); 1373 } 1374 else 1375 { 1376 __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); 1377 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); 1378 ++__beg; 1379 } 1380 1381 // Look for valid numbers in the current ctype facet within input digits. 1382 __end = __ctype.scan_not(ctype_base::digit, __beg, __end); 1383 if (__beg != __end) 1384 { 1385 // Assume valid input, and attempt to format. 1386 // Break down input numbers into base components, as follows: 1387 // final_value = grouped units + (decimal point) + (digits) 1388 string_type __res; 1389 string_type __value; 1390 const string_type __symbol = __intl ? __mpt.curr_symbol() 1391 : __mpf.curr_symbol(); 1392 1393 // Deal with decimal point, decimal digits. 1394 const int __frac = __intl ? __mpt.frac_digits() 1395 : __mpf.frac_digits(); 1396 if (__frac > 0) 1397 { 1398 const char_type __d = __intl ? __mpt.decimal_point() 1399 : __mpf.decimal_point(); 1400 if (__end - __beg >= __frac) 1401 { 1402 __value = string_type(__end - __frac, __end); 1403 __value.insert(__value.begin(), __d); 1404 __end -= __frac; 1405 } 1406 else 1407 { 1408 // Have to pad zeros in the decimal position. 1409 __value = string_type(__beg, __end); 1410 int __paddec = __frac - (__end - __beg); 1411 char_type __zero = __ctype.widen('0'); 1412 __value.insert(__value.begin(), __paddec, __zero); 1413 __value.insert(__value.begin(), __d); 1414 __beg = __end; 1415 } 1416 } 1417 1418 // Add thousands separators to non-decimal digits, per 1419 // grouping rules. 1420 if (__beg != __end) 1421 { 1422 const string __grouping = __intl ? __mpt.grouping() 1423 : __mpf.grouping(); 1424 if (__grouping.size()) 1425 { 1426 const char_type __sep = __intl ? __mpt.thousands_sep() 1427 : __mpf.thousands_sep(); 1428 const char* __gbeg = __grouping.c_str(); 1429 const char* __gend = __gbeg + __grouping.size(); 1430 const int __n = (__end - __beg) * 2; 1431 _CharT* __ws2 = 1432 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); 1433 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 1434 __gend, __beg, __end); 1435 __value.insert(0, __ws2, __ws_end - __ws2); 1436 } 1437 else 1438 __value.insert(0, string_type(__beg, __end)); 1439 } 1440 1441 // Calculate length of resulting string. 1442 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; 1443 size_type __len = __value.size() + __sign.size(); 1444 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; 1445 bool __testipad = __f == ios_base::internal && __len < __width; 1446 1447 // Fit formatted digits into the required pattern. 1448 for (int __i = 0; __i < 4; ++__i) 1449 { 1450 part __which = static_cast<part>(__p.field[__i]); 1451 switch (__which) 1452 { 1453 case money_base::symbol: 1454 if (__io.flags() & ios_base::showbase) 1455 __res += __symbol; 1456 break; 1457 case money_base::sign: 1458 // Sign might not exist, or be more than one 1459 // charater long. In that case, add in the rest 1460 // below. 1461 if (__sign.size()) 1462 __res += __sign[0]; 1463 break; 1464 case money_base::value: 1465 __res += __value; 1466 break; 1467 case money_base::space: 1468 // At least one space is required, but if internal 1469 // formatting is required, an arbitrary number of 1470 // fill spaces will be necessary. 1471 if (__testipad) 1472 __res += string_type(__width - __len, __fill); 1473 else 1474 __res += __ctype.widen(__fill); 1475 break; 1476 case money_base::none: 1477 if (__testipad) 1478 __res += string_type(__width - __len, __fill); 1479 break; 1480 } 1481 } 1482 1483 // Special case of multi-part sign parts. 1484 if (__sign.size() > 1) 1485 __res += string_type(__sign.begin() + 1, __sign.end()); 1486 1487 // Pad, if still necessary. 1488 __len = __res.size(); 1489 if (__width > __len) 1490 { 1491 if (__f == ios_base::left) 1492 // After. 1493 __res.append(__width - __len, __fill); 1494 else 1495 // Before. 1496 __res.insert(0, string_type(__width - __len, __fill)); 1497 __len = __width; 1498 } 1499 1500 // Write resulting, fully-formatted string to output iterator. 1501 __s = __write(__s, __res.c_str(), __len); 1502 } 1503 __io.width(0); 1504 return __s; 1505 } 1506 1507 1508 // NB: Not especially useful. Without an ios_base object or some 1509 // kind of locale reference, we are left clawing at the air where 1510 // the side of the mountain used to be... 1511 template<typename _CharT, typename _InIter> 1512 time_base::dateorder 1513 time_get<_CharT, _InIter>::do_date_order() const 1514 { return time_base::no_order; } 1515 1516 template<typename _CharT, typename _InIter> 1517 void 1518 time_get<_CharT, _InIter>:: 1519 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, 1520 ios_base::iostate& __err, tm* __tm, 1521 const _CharT* __format) const 1522 { 1523 locale __loc = __io.getloc(); 1524 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1525 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1526 size_t __len = char_traits<_CharT>::length(__format); 1527 1528 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 1529 { 1530 char __c = __format[__i]; 1531 if (__c == '%') 1532 { 1533 // Verify valid formatting code, attempt to extract. 1534 __c = __format[++__i]; 1535 char __mod = 0; 1536 int __mem = 0; 1537 if (__c == 'E' || __c == 'O') 1538 { 1539 __mod = __c; 1540 __c = __format[++__i]; 1541 } 1542 switch (__c) 1543 { 1544 const char* __cs; 1545 _CharT __wcs[10]; 1546 case 'a': 1547 // Abbreviated weekday name [tm_wday] 1548 const char_type* __days1[7]; 1549 __tp._M_days_abbreviated(__days1); 1550 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 1551 __err); 1552 break; 1553 case 'A': 1554 // Weekday name [tm_wday]. 1555 const char_type* __days2[7]; 1556 __tp._M_days(__days2); 1557 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 1558 __err); 1559 break; 1560 case 'h': 1561 case 'b': 1562 // Abbreviated month name [tm_mon] 1563 const char_type* __months1[12]; 1564 __tp._M_months_abbreviated(__months1); 1565 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 1566 __err); 1567 break; 1568 case 'B': 1569 // Month name [tm_mon]. 1570 const char_type* __months2[12]; 1571 __tp._M_months(__months2); 1572 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 1573 __err); 1574 break; 1575 case 'c': 1576 // Default time and date representation. 1577 const char_type* __dt[2]; 1578 __tp._M_date_time_formats(__dt); 1579 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1580 __dt[0]); 1581 break; 1582 case 'd': 1583 // Day [01, 31]. [tm_mday] 1584 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 1585 __ctype, __err); 1586 break; 1587 case 'D': 1588 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 1589 __cs = "%m/%d/%y"; 1590 __ctype.widen(__cs, __cs + 9, __wcs); 1591 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1592 __wcs); 1593 break; 1594 case 'H': 1595 // Hour [00, 23]. [tm_hour] 1596 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 1597 __ctype, __err); 1598 break; 1599 case 'I': 1600 // Hour [01, 12]. [tm_hour] 1601 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 1602 __ctype, __err); 1603 break; 1604 case 'm': 1605 // Month [01, 12]. [tm_mon] 1606 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 1607 __err); 1608 if (!__err) 1609 __tm->tm_mon = __mem - 1; 1610 break; 1611 case 'M': 1612 // Minute [00, 59]. [tm_min] 1613 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 1614 __ctype, __err); 1615 break; 1616 case 'n': 1617 if (__ctype.narrow(*__beg, 0) == '\n') 1618 ++__beg; 1619 else 1620 __err |= ios_base::failbit; 1621 break; 1622 case 'R': 1623 // Equivalent to (%H:%M). 1624 __cs = "%H:%M"; 1625 __ctype.widen(__cs, __cs + 6, __wcs); 1626 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1627 __wcs); 1628 break; 1629 case 'S': 1630 // Seconds. 1631 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 1632 __ctype, __err); 1633 break; 1634 case 't': 1635 if (__ctype.narrow(*__beg, 0) == '\t') 1636 ++__beg; 1637 else 1638 __err |= ios_base::failbit; 1639 break; 1640 case 'T': 1641 // Equivalent to (%H:%M:%S). 1642 __cs = "%H:%M:%S"; 1643 __ctype.widen(__cs, __cs + 9, __wcs); 1644 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1645 __wcs); 1646 break; 1647 case 'x': 1648 // Locale's date. 1649 const char_type* __dates[2]; 1650 __tp._M_date_formats(__dates); 1651 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1652 __dates[0]); 1653 break; 1654 case 'X': 1655 // Locale's time. 1656 const char_type* __times[2]; 1657 __tp._M_time_formats(__times); 1658 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1659 __times[0]); 1660 break; 1661 case 'y': 1662 // Two digit year. [tm_year] 1663 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 1664 __ctype, __err); 1665 break; 1666 case 'Y': 1667 // Year [1900). [tm_year] 1668 _M_extract_num(__beg, __end, __mem, 0, 1669 numeric_limits<int>::max(), 4, 1670 __ctype, __err); 1671 if (!__err) 1672 __tm->tm_year = __mem - 1900; 1673 break; 1674 case 'Z': 1675 // Timezone info. 1676 if (__ctype.is(ctype_base::upper, *__beg)) 1677 { 1678 int __tmp; 1679 _M_extract_name(__beg, __end, __tmp, 1680 __timepunct<_CharT>::_S_timezones, 1681 14, __err); 1682 1683 // GMT requires special effort. 1684 char_type __c = *__beg; 1685 if (!__err && __tmp == 0 1686 && (__c == __ctype.widen('-') 1687 || __c == __ctype.widen('+'))) 1688 { 1689 _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 1690 __ctype, __err); 1691 _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 1692 __ctype, __err); 1693 } 1694 } 1695 else 1696 __err |= ios_base::failbit; 1697 break; 1698 default: 1699 // Not recognized. 1700 __err |= ios_base::failbit; 1701 } 1702 } 1703 else 1704 { 1705 // Verify format and input match, extract and discard. 1706 if (__c == __ctype.narrow(*__beg, 0)) 1707 ++__beg; 1708 else 1709 __err |= ios_base::failbit; 1710 } 1711 } 1712 } 1713 1714 template<typename _CharT, typename _InIter> 1715 void 1716 time_get<_CharT, _InIter>:: 1717 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, 1718 int __min, int __max, size_t __len, 1719 const ctype<_CharT>& __ctype, 1720 ios_base::iostate& __err) const 1721 { 1722 size_t __i = 0; 1723 string __digits; 1724 bool __testvalid = true; 1725 char_type __c = *__beg; 1726 while (__beg != __end && __i < __len 1727 && __ctype.is(ctype_base::digit, __c)) 1728 { 1729 __digits += __ctype.narrow(__c, 0); 1730 __c = *(++__beg); 1731 ++__i; 1732 } 1733 if (__i == __len) 1734 { 1735 int __value = atoi(__digits.c_str()); 1736 if (__min <= __value && __value <= __max) 1737 __member = __value; 1738 else 1739 __testvalid = false; 1740 } 1741 else 1742 __testvalid = false; 1743 if (!__testvalid) 1744 __err |= ios_base::failbit; 1745 } 1746 1747 // Assumptions: 1748 // All elements in __names are unique. 1749 template<typename _CharT, typename _InIter> 1750 void 1751 time_get<_CharT, _InIter>:: 1752 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, 1753 const _CharT** __names, size_t __indexlen, 1754 ios_base::iostate& __err) const 1755 { 1756 typedef char_traits<_CharT> __traits_type; 1757 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 1758 * __indexlen)); 1759 size_t __nmatches = 0; 1760 size_t __pos = 0; 1761 bool __testvalid = true; 1762 const char_type* __name; 1763 1764 char_type __c = *__beg; 1765 // Look for initial matches. 1766 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 1767 if (__c == __names[__i1][0]) 1768 __matches[__nmatches++] = __i1; 1769 1770 while (__nmatches > 1) 1771 { 1772 // Find smallest matching string. 1773 size_t __minlen = 10; 1774 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 1775 __minlen = min(__minlen, 1776 __traits_type::length(__names[__matches[__i2]])); 1777 1778 if (__pos < __minlen && __beg != __end) 1779 { 1780 ++__pos; 1781 __c = *(++__beg); 1782 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 1783 { 1784 __name = __names[__matches[__i3]]; 1785 if (__name[__pos] != __c) 1786 __matches[__i3] = __matches[--__nmatches]; 1787 } 1788 } 1789 else 1790 break; 1791 } 1792 1793 if (__nmatches == 1) 1794 { 1795 // Make sure found name is completely extracted. 1796 __name = __names[__matches[0]]; 1797 const size_t __len = __traits_type::length(__name); 1798 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 1799 ++__beg, ++__pos; 1800 1801 if (__len == __pos) 1802 __member = __matches[0]; 1803 else 1804 __testvalid = false; 1805 } 1806 else 1807 __testvalid = false; 1808 if (!__testvalid) 1809 __err |= ios_base::failbit; 1810 } 1811 1812 template<typename _CharT, typename _InIter> 1813 _InIter 1814 time_get<_CharT, _InIter>:: 1815 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 1816 ios_base::iostate& __err, tm* __tm) const 1817 { 1818 _CharT __wcs[3]; 1819 const char* __cs = "%X"; 1820 locale __loc = __io.getloc(); 1821 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1822 __ctype.widen(__cs, __cs + 3, __wcs); 1823 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 1824 if (__beg == __end) 1825 __err |= ios_base::eofbit; 1826 return __beg; 1827 } 1828 1829 template<typename _CharT, typename _InIter> 1830 _InIter 1831 time_get<_CharT, _InIter>:: 1832 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 1833 ios_base::iostate& __err, tm* __tm) const 1834 { 1835 _CharT __wcs[3]; 1836 const char* __cs = "%x"; 1837 locale __loc = __io.getloc(); 1838 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1839 __ctype.widen(__cs, __cs + 3, __wcs); 1840 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 1841 if (__beg == __end) 1842 __err |= ios_base::eofbit; 1843 return __beg; 1844 } 1845 1846 template<typename _CharT, typename _InIter> 1847 _InIter 1848 time_get<_CharT, _InIter>:: 1849 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 1850 ios_base::iostate& __err, tm* __tm) const 1851 { 1852 typedef char_traits<_CharT> __traits_type; 1853 locale __loc = __io.getloc(); 1854 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1855 const char_type* __days[7]; 1856 __tp._M_days_abbreviated(__days); 1857 int __tmpwday; 1858 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); 1859 1860 // Check to see if non-abbreviated name exists, and extract. 1861 // NB: Assumes both _M_days and _M_days_abbreviated organized in 1862 // exact same order, first to last, such that the resulting 1863 // __days array with the same index points to a day, and that 1864 // day's abbreviated form. 1865 // NB: Also assumes that an abbreviated name is a subset of the name. 1866 if (!__err) 1867 { 1868 size_t __pos = __traits_type::length(__days[__tmpwday]); 1869 __tp._M_days(__days); 1870 const char_type* __name = __days[__tmpwday]; 1871 if (__name[__pos] == *__beg) 1872 { 1873 // Extract the rest of it. 1874 const size_t __len = __traits_type::length(__name); 1875 while (__pos < __len && __beg != __end 1876 && __name[__pos] == *__beg) 1877 ++__beg, ++__pos; 1878 if (__len != __pos) 1879 __err |= ios_base::failbit; 1880 } 1881 if (!__err) 1882 __tm->tm_wday = __tmpwday; 1883 } 1884 if (__beg == __end) 1885 __err |= ios_base::eofbit; 1886 return __beg; 1887 } 1888 1889 template<typename _CharT, typename _InIter> 1890 _InIter 1891 time_get<_CharT, _InIter>:: 1892 do_get_monthname(iter_type __beg, iter_type __end, 1893 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 1894 { 1895 typedef char_traits<_CharT> __traits_type; 1896 locale __loc = __io.getloc(); 1897 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1898 const char_type* __months[12]; 1899 __tp._M_months_abbreviated(__months); 1900 int __tmpmon; 1901 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); 1902 1903 // Check to see if non-abbreviated name exists, and extract. 1904 // NB: Assumes both _M_months and _M_months_abbreviated organized in 1905 // exact same order, first to last, such that the resulting 1906 // __months array with the same index points to a month, and that 1907 // month's abbreviated form. 1908 // NB: Also assumes that an abbreviated name is a subset of the name. 1909 if (!__err) 1910 { 1911 size_t __pos = __traits_type::length(__months[__tmpmon]); 1912 __tp._M_months(__months); 1913 const char_type* __name = __months[__tmpmon]; 1914 if (__name[__pos] == *__beg) 1915 { 1916 // Extract the rest of it. 1917 const size_t __len = __traits_type::length(__name); 1918 while (__pos < __len && __beg != __end 1919 && __name[__pos] == *__beg) 1920 ++__beg, ++__pos; 1921 if (__len != __pos) 1922 __err |= ios_base::failbit; 1923 } 1924 if (!__err) 1925 __tm->tm_mon = __tmpmon; 1926 } 1927 1928 if (__beg == __end) 1929 __err |= ios_base::eofbit; 1930 return __beg; 1931 } 1932 1933 template<typename _CharT, typename _InIter> 1934 _InIter 1935 time_get<_CharT, _InIter>:: 1936 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 1937 ios_base::iostate& __err, tm* __tm) const 1938 { 1939 locale __loc = __io.getloc(); 1940 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1941 1942 char_type __c = *__beg; 1943 size_t __i = 0; 1944 string __digits; 1945 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) 1946 { 1947 __digits += __ctype.narrow(__c, 0); 1948 __c = *(++__beg); 1949 ++__i; 1950 } 1951 if (__i == 2 || __i == 4) 1952 { 1953 long __l; 1954 __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); 1955 if (!(__err & ios_base::failbit) && __l <= INT_MAX) 1956 { 1957 __l = __i == 2 ? __l : __l - 1900; 1958 __tm->tm_year = static_cast<int>(__l); 1959 } 1960 } 1961 else 1962 __err |= ios_base::failbit; 1963 if (__beg == __end) 1964 __err |= ios_base::eofbit; 1965 return __beg; 1966 } 1967 1968 template<typename _CharT, typename _OutIter> 1969 _OutIter 1970 time_put<_CharT, _OutIter>:: 1971 put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 1972 const _CharT* __beg, const _CharT* __end) const 1973 { 1974 locale __loc = __io.getloc(); 1975 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1976 while (__beg != __end) 1977 { 1978 char __c = __ctype.narrow(*__beg, 0); 1979 ++__beg; 1980 if (__c == '%') 1981 { 1982 char __format; 1983 char __mod = 0; 1984 size_t __len = 1; 1985 __c = __ctype.narrow(*__beg, 0); 1986 ++__beg; 1987 if (__c == 'E' || __c == 'O') 1988 { 1989 __mod = __c; 1990 __format = __ctype.narrow(*__beg, 0); 1991 ++__beg; 1992 } 1993 else 1994 __format = __c; 1995 __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod); 1996 } 1997 else 1998 { 1999 *__s = __c; 2000 ++__s; 2001 } 2002 } 2003 return __s; 2004 } 2005 2006 template<typename _CharT, typename _OutIter> 2007 _OutIter 2008 time_put<_CharT, _OutIter>:: 2009 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 2010 char __format, char __mod) const 2011 { 2012 locale __loc = __io.getloc(); 2013 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 2014 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 2015 2016 // NB: This size is arbitrary. Should this be a data member, 2017 // initialized at construction? 2018 const size_t __maxlen = 64; 2019 char_type* __res = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 2020 2021 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 2022 // is possible that the format character will be longer than one 2023 // character. Possibilities include 'E' or 'O' followed by a 2024 // format character: if __mod is not the default argument, assume 2025 // it's a valid modifier. 2026 char_type __fmt[4]; 2027 __fmt[0] = __ctype.widen('%'); 2028 if (!__mod) 2029 { 2030 __fmt[1] = __format; 2031 __fmt[2] = char_type(); 2032 } 2033 else 2034 { 2035 __fmt[1] = __mod; 2036 __fmt[2] = __format; 2037 __fmt[3] = char_type(); 2038 } 2039 2040 __tp._M_put(__res, __maxlen, __fmt, __tm); 2041 2042 // Write resulting, fully-formatted string to output iterator. 2043 return __write(__s, __res, char_traits<char_type>::length(__res)); 2044 } 2045 2046 2047 // Generic version does nothing. 2048 template<typename _CharT> 2049 int 2050 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 2051 { return 0; } 2052 2053 // Generic version does nothing. 2054 template<typename _CharT> 2055 size_t 2056 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 2057 { return 0; } 2058 2059 template<typename _CharT> 2060 int 2061 collate<_CharT>:: 2062 do_compare(const _CharT* __lo1, const _CharT* __hi1, 2063 const _CharT* __lo2, const _CharT* __hi2) const 2064 { 2065 // strcoll assumes zero-terminated strings so we make a copy 2066 // and then put a zero at the end. 2067 const string_type __one(__lo1, __hi1); 2068 const string_type __two(__lo2, __hi2); 2069 2070 const _CharT* __p = __one.c_str(); 2071 const _CharT* __pend = __one.c_str() + __one.length(); 2072 const _CharT* __q = __two.c_str(); 2073 const _CharT* __qend = __two.c_str() + __two.length(); 2074 2075 // strcoll stops when it sees a nul character so we break 2076 // the strings into zero-terminated substrings and pass those 2077 // to strcoll. 2078 for (;;) 2079 { 2080 int __res = _M_compare(__p, __q); 2081 if (__res) 2082 return __res; 2083 2084 __p += char_traits<_CharT>::length(__p); 2085 __q += char_traits<_CharT>::length(__q); 2086 if (__p == __pend && __q == __qend) 2087 return 0; 2088 else if (__p == __pend) 2089 return -1; 2090 else if (__q == __qend) 2091 return 1; 2092 2093 __p++; 2094 __q++; 2095 } 2096 } 2097 2098 template<typename _CharT> 2099 typename collate<_CharT>::string_type 2100 collate<_CharT>:: 2101 do_transform(const _CharT* __lo, const _CharT* __hi) const 2102 { 2103 // strxfrm assumes zero-terminated strings so we make a copy 2104 string_type __str(__lo, __hi); 2105 2106 const _CharT* __p = __str.c_str(); 2107 const _CharT* __pend = __str.c_str() + __str.length(); 2108 2109 size_t __len = (__hi - __lo) * 2; 2110 2111 string_type __ret; 2112 2113 // strxfrm stops when it sees a nul character so we break 2114 // the string into zero-terminated substrings and pass those 2115 // to strxfrm. 2116 for (;;) 2117 { 2118 // First try a buffer perhaps big enough. 2119 _CharT* __c = 2120 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 2121 size_t __res = _M_transform(__c, __p, __len); 2122 // If the buffer was not large enough, try again with the 2123 // correct size. 2124 if (__res >= __len) 2125 { 2126 __len = __res + 1; 2127 __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2128 * __len)); 2129 __res = _M_transform(__c, __p, __res + 1); 2130 } 2131 2132 __ret.append(__c, __res); 2133 __p += char_traits<_CharT>::length(__p); 2134 if (__p == __pend) 2135 return __ret; 2136 2137 __p++; 2138 __ret.push_back(_CharT()); 2139 } 2140 } 2141 2142 template<typename _CharT> 2143 long 2144 collate<_CharT>:: 2145 do_hash(const _CharT* __lo, const _CharT* __hi) const 2146 { 2147 unsigned long __val = 0; 2148 for (; __lo < __hi; ++__lo) 2149 __val = *__lo + ((__val << 7) | 2150 (__val >> (numeric_limits<unsigned long>::digits - 7))); 2151 return static_cast<long>(__val); 2152 } 2153 2154 // Construct correctly padded string, as per 22.2.2.2.2 2155 // Assumes 2156 // __newlen > __oldlen 2157 // __news is allocated for __newlen size 2158 // Used by both num_put and ostream inserters: if __num, 2159 // internal-adjusted objects are padded according to the rules below 2160 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 2161 // ones are. 2162 2163 // NB: Of the two parameters, _CharT can be deduced from the 2164 // function arguments. The other (_Traits) has to be explicitly specified. 2165 template<typename _CharT, typename _Traits> 2166 void 2167 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2168 _CharT* __news, const _CharT* __olds, 2169 const streamsize __newlen, 2170 const streamsize __oldlen, const bool __num) 2171 { 2172 size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2173 _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2174 * __plen)); 2175 _Traits::assign(__pads, __plen, __fill); 2176 2177 _CharT* __beg; 2178 _CharT* __end; 2179 size_t __mod = 0; 2180 size_t __beglen; //either __plen or __oldlen 2181 ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 2182 2183 if (__adjust == ios_base::left) 2184 { 2185 // Padding last. 2186 __beg = const_cast<_CharT*>(__olds); 2187 __beglen = __oldlen; 2188 __end = __pads; 2189 } 2190 else if (__adjust == ios_base::internal && __num) 2191 { 2192 // Pad after the sign, if there is one. 2193 // Pad after 0[xX], if there is one. 2194 // Who came up with these rules, anyway? Jeeze. 2195 locale __loc = __io.getloc(); 2196 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2197 const _CharT __minus = __ctype.widen('-'); 2198 const _CharT __plus = __ctype.widen('+'); 2199 bool __testsign = _Traits::eq(__olds[0], __minus) 2200 || _Traits::eq(__olds[0], __plus); 2201 2202 bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 2203 && (_Traits::eq(__ctype.widen('x'), __olds[1]) 2204 || _Traits::eq(__ctype.widen('X'), __olds[1])); 2205 if (__testhex) 2206 { 2207 __news[0] = __olds[0]; 2208 __news[1] = __olds[1]; 2209 __mod += 2; 2210 __news += 2; 2211 __beg = __pads; 2212 __beglen = __plen; 2213 __end = const_cast<_CharT*>(__olds + __mod); 2214 } 2215 else if (__testsign) 2216 { 2217 _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; 2218 ++__mod; 2219 ++__news; 2220 __beg = __pads; 2221 __beglen = __plen; 2222 __end = const_cast<_CharT*>(__olds + __mod); 2223 } 2224 else 2225 { 2226 // Padding first. 2227 __beg = __pads; 2228 __beglen = __plen; 2229 __end = const_cast<_CharT*>(__olds); 2230 } 2231 } 2232 else 2233 { 2234 // Padding first. 2235 __beg = __pads; 2236 __beglen = __plen; 2237 __end = const_cast<_CharT*>(__olds); 2238 } 2239 _Traits::copy(__news, __beg, __beglen); 2240 _Traits::copy(__news + __beglen, __end, 2241 __newlen - __beglen - __mod); 2242 } 2243 2244 template<typename _CharT> 2245 bool 2246 __verify_grouping(const basic_string<_CharT>& __grouping, 2247 basic_string<_CharT>& __grouping_tmp) 2248 { 2249 int __i = 0; 2250 int __j = 0; 2251 const int __len = __grouping.size(); 2252 const int __n = __grouping_tmp.size(); 2253 bool __test = true; 2254 2255 // Parsed number groupings have to match the 2256 // numpunct::grouping string exactly, starting at the 2257 // right-most point of the parsed sequence of elements ... 2258 while (__test && __i < __n - 1) 2259 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) 2260 __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; 2261 // ... but the last parsed grouping can be <= numpunct 2262 // grouping. 2263 __j == __len ? __j = 0 : __j; 2264 __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; 2265 return __test; 2266 } 2267 2268 template<typename _CharT> 2269 _CharT* 2270 __add_grouping(_CharT* __s, _CharT __sep, 2271 const char* __gbeg, const char* __gend, 2272 const _CharT* __first, const _CharT* __last) 2273 { 2274 if (__last - __first > *__gbeg) 2275 { 2276 __s = __add_grouping(__s, __sep, 2277 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), 2278 __gend, __first, __last - *__gbeg); 2279 __first = __last - *__gbeg; 2280 *__s++ = __sep; 2281 } 2282 do 2283 *__s++ = *__first++; 2284 while (__first != __last); 2285 return __s; 2286 } 2287 2288#if 1 2289 // XXX GLIBCXX_ABI Deprecated, compatibility only. 2290 template<typename _CharT, typename _OutIter> 2291 template<typename _ValueT> 2292 _OutIter 2293 num_put<_CharT, _OutIter>:: 2294 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 2295 char __modl, _ValueT __v) const 2296 { 2297 // [22.2.2.2.2] Stage 1, numeric conversion to character. 2298 2299 // Long enough for the max format spec. 2300 char __fbuf[16]; 2301 _S_format_int(__io, __fbuf, __mod, __modl); 2302#ifdef _GLIBCPP_USE_C99 2303 // First try a buffer perhaps big enough. 2304 int __cs_size = 64; 2305 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 2306 int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 2307 _S_c_locale); 2308 // If the buffer was not large enough, try again with the correct size. 2309 if (__len >= __cs_size) 2310 { 2311 __cs_size = __len + 1; 2312 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 2313 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 2314 _S_c_locale); 2315 } 2316#else 2317 // Leave room for "+/-," "0x," and commas. This size is 2318 // arbitrary, but should be largely sufficient. 2319 char __cs[128]; 2320 int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 2321#endif 2322 return _M_widen_int(__s, __io, __fill, __cs, __len); 2323 } 2324 2325 template<typename _CharT, typename _OutIter> 2326 _OutIter 2327 num_put<_CharT, _OutIter>:: 2328 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 2329 int __len) const 2330 { 2331 typedef char_traits<_CharT> __traits_type; 2332 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 2333 // numpunct.decimal_point() values for '.' and adding grouping. 2334 const locale __loc = __io.getloc(); 2335 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2336 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2337 * __len)); 2338 // Grouping can add (almost) as many separators as the number of 2339 // digits, but no more. 2340 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2341 * __len * 2)); 2342 __ctype.widen(__cs, __cs + __len, __ws); 2343 2344 // Replace decimal point. 2345 const _CharT* __p; 2346 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2347 if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) 2348 __ws[__p - __ws] = __np.decimal_point(); 2349 2350#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 2351//282. What types does numpunct grouping refer to? 2352 // Add grouping, if necessary. 2353 const string __grouping = __np.grouping(); 2354 if (__grouping.size()) 2355 { 2356 _CharT* __p2; 2357 int __declen = __p ? __p - __ws : __len; 2358 __p2 = __add_grouping(__ws2, __np.thousands_sep(), 2359 __grouping.c_str(), 2360 __grouping.c_str() + __grouping.size(), 2361 __ws, __ws + __declen); 2362 int __newlen = __p2 - __ws2; 2363 2364 // Tack on decimal part. 2365 if (__p) 2366 { 2367 __traits_type::copy(__p2, __p, __len - __declen); 2368 __newlen += __len - __declen; 2369 } 2370 2371 // Switch strings, establish correct new length. 2372 __ws = __ws2; 2373 __len = __newlen; 2374 } 2375#endif 2376 return _M_insert(__s, __io, __fill, __ws, __len); 2377 } 2378 2379 template<typename _CharT, typename _OutIter> 2380 _OutIter 2381 num_put<_CharT, _OutIter>:: 2382 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 2383 int __len) const 2384 { 2385 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 2386 // numpunct.decimal_point() values for '.' and adding grouping. 2387 const locale __loc = __io.getloc(); 2388 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2389 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2390 * __len)); 2391 // Grouping can add (almost) as many separators as the number of 2392 // digits, but no more. 2393 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2394 * __len * 2)); 2395 __ctype.widen(__cs, __cs + __len, __ws); 2396 2397 // Add grouping, if necessary. 2398 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2399 const string __grouping = __np.grouping(); 2400 if (__grouping.size()) 2401 { 2402 // By itself __add_grouping cannot deal correctly with __ws when 2403 // ios::showbase is set and ios_base::oct || ios_base::hex. 2404 // Therefore we take care "by hand" of the initial 0, 0x or 0X. 2405 // However, remember that the latter do not occur if the number 2406 // printed is '0' (__len == 1). 2407 streamsize __off = 0; 2408 const ios_base::fmtflags __basefield = __io.flags() 2409 & ios_base::basefield; 2410 if ((__io.flags() & ios_base::showbase) && __len > 1) 2411 if (__basefield == ios_base::oct) 2412 { 2413 __off = 1; 2414 *__ws2 = *__ws; 2415 } 2416 else if (__basefield == ios_base::hex) 2417 { 2418 __off = 2; 2419 *__ws2 = *__ws; 2420 *(__ws2 + 1) = *(__ws + 1); 2421 } 2422 _CharT* __p; 2423 __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 2424 __grouping.c_str(), 2425 __grouping.c_str() + __grouping.size(), 2426 __ws + __off, __ws + __len); 2427 __len = __p - __ws2; 2428 // Switch strings. 2429 __ws = __ws2; 2430 } 2431 return _M_insert(__s, __io, __fill, __ws, __len); 2432 } 2433 2434 // For use by integer and floating-point types after they have been 2435 // converted into a char_type string. 2436 template<typename _CharT, typename _OutIter> 2437 _OutIter 2438 num_put<_CharT, _OutIter>:: 2439 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 2440 int __len) const 2441 { 2442 typedef char_traits<_CharT> __traits_type; 2443 // [22.2.2.2.2] Stage 3. 2444 // If necessary, pad. 2445 streamsize __w = __io.width(); 2446 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2447 * __w)); 2448 if (__w > static_cast<streamsize>(__len)) 2449 { 2450 __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 2451 __w, __len, true); 2452 __len = static_cast<int>(__w); 2453 // Switch strings. 2454 __ws = __ws2; 2455 } 2456 __io.width(0); 2457 2458 // [22.2.2.2.2] Stage 4. 2459 // Write resulting, fully-formatted string to output iterator. 2460 return __write(__s, __ws, __len); 2461 } 2462#endif 2463 2464 template<typename _CharT> 2465 __locale_cache<numpunct<_CharT> >::__locale_cache(const locale& __loc) 2466 : _M_truename(0), _M_falsename(0), _M_use_grouping(false), 2467 _M_grouping(0) 2468 { 2469 if (has_facet<numpunct<_CharT> >(__loc)) 2470 { 2471 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2472 _M_decimal_point = __np.decimal_point(); 2473 _M_thousands_sep = __np.thousands_sep(); 2474 2475 string_type __false = __np.falsename(); 2476 _CharT* __falsename = new _CharT[__false.length() + 1]; 2477 __false.copy(__falsename, __false.length()); 2478 __falsename[__false.length()] = _CharT(); 2479 _M_falsename = __falsename; 2480 2481 string_type __true = __np.truename(); 2482 _CharT* __truename = new _CharT[__true.length() + 1]; 2483 __true.copy(__truename, __true.length()); 2484 __truename[__true.length()] = _CharT(); 2485 _M_truename = __truename; 2486 2487 string __grouping = __np.grouping(); 2488 char* __group = new char[__grouping.length() + 1]; 2489 __grouping.copy(__group, __grouping.length()); 2490 __group[__grouping.length()] = 0; 2491 _M_grouping = __group; 2492 2493 _M_use_grouping = __grouping.length() != 0 2494 && __grouping.data()[0] != 0; 2495 } 2496 2497 if (has_facet<ctype<_CharT> >(__loc)) 2498 { 2499 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 2500 __ct.widen(__num_base::_S_atoms_out, 2501 __num_base::_S_atoms_out + __num_base::_S_end, 2502 _M_atoms_out); 2503 } 2504 } 2505 2506 // Static locale cache initialization. Only instantiated with char 2507 // and wchar_t, so no need to check has_facet. 2508 template<typename _CharT> 2509 __locale_cache<numpunct<_CharT> >:: 2510 __locale_cache(const locale& __loc, bool) 2511 { 2512 // Grab pointers to numpunct static strings 2513 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2514 _M_thousands_sep = __np._M_thousands_sep; 2515 _M_decimal_point = __np._M_decimal_point; 2516 _M_falsename = __np._M_falsename; 2517 _M_truename = __np._M_truename; 2518 _M_grouping = __np._M_grouping; 2519 _M_use_grouping = false; 2520 2521 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 2522 __ct.widen(__num_base::_S_atoms_out, 2523 __num_base::_S_atoms_out + __num_base::_S_end, 2524 _M_atoms_out); 2525 } 2526 2527 // Inhibit implicit instantiations for required instantiations, 2528 // which are defined via explicit instantiations elsewhere. 2529 // NB: This syntax is a GNU extension. 2530#if _GLIBCPP_EXTERN_TEMPLATE 2531 extern template class moneypunct<char, false>; 2532 extern template class moneypunct<char, true>; 2533 extern template class moneypunct_byname<char, false>; 2534 extern template class moneypunct_byname<char, true>; 2535 extern template class money_get<char>; 2536 extern template class money_put<char>; 2537 extern template class numpunct<char>; 2538 extern template class numpunct_byname<char>; 2539 extern template class num_get<char>; 2540 extern template class num_put<char>; 2541 extern template class __timepunct<char>; 2542 extern template class time_put<char>; 2543 extern template class time_put_byname<char>; 2544 extern template class time_get<char>; 2545 extern template class time_get_byname<char>; 2546 extern template class messages<char>; 2547 extern template class messages_byname<char>; 2548 extern template class ctype_byname<char>; 2549 extern template class codecvt_byname<char, char, mbstate_t>; 2550 extern template class collate<char>; 2551 extern template class collate_byname<char>; 2552 2553 extern template 2554 const codecvt<char, char, mbstate_t>& 2555 use_facet<codecvt<char, char, mbstate_t> >(const locale&); 2556 2557 extern template 2558 const collate<char>& 2559 use_facet<collate<char> >(const locale&); 2560 2561 extern template 2562 const numpunct<char>& 2563 use_facet<numpunct<char> >(const locale&); 2564 2565 extern template 2566 const num_put<char>& 2567 use_facet<num_put<char> >(const locale&); 2568 2569 extern template 2570 const num_get<char>& 2571 use_facet<num_get<char> >(const locale&); 2572 2573 extern template 2574 const moneypunct<char, true>& 2575 use_facet<moneypunct<char, true> >(const locale&); 2576 2577 extern template 2578 const moneypunct<char, false>& 2579 use_facet<moneypunct<char, false> >(const locale&); 2580 2581 extern template 2582 const money_put<char>& 2583 use_facet<money_put<char> >(const locale&); 2584 2585 extern template 2586 const money_get<char>& 2587 use_facet<money_get<char> >(const locale&); 2588 2589 extern template 2590 const __timepunct<char>& 2591 use_facet<__timepunct<char> >(const locale&); 2592 2593 extern template 2594 const time_put<char>& 2595 use_facet<time_put<char> >(const locale&); 2596 2597 extern template 2598 const time_get<char>& 2599 use_facet<time_get<char> >(const locale&); 2600 2601 extern template 2602 const messages<char>& 2603 use_facet<messages<char> >(const locale&); 2604 2605 extern template 2606 bool 2607 has_facet<ctype<char> >(const locale&); 2608 2609 extern template 2610 bool 2611 has_facet<codecvt<char, char, mbstate_t> >(const locale&); 2612 2613 extern template 2614 bool 2615 has_facet<collate<char> >(const locale&); 2616 2617 extern template 2618 bool 2619 has_facet<numpunct<char> >(const locale&); 2620 2621 extern template 2622 bool 2623 has_facet<num_put<char> >(const locale&); 2624 2625 extern template 2626 bool 2627 has_facet<num_get<char> >(const locale&); 2628 2629 extern template 2630 bool 2631 has_facet<moneypunct<char> >(const locale&); 2632 2633 extern template 2634 bool 2635 has_facet<money_put<char> >(const locale&); 2636 2637 extern template 2638 bool 2639 has_facet<money_get<char> >(const locale&); 2640 2641 extern template 2642 bool 2643 has_facet<__timepunct<char> >(const locale&); 2644 2645 extern template 2646 bool 2647 has_facet<time_put<char> >(const locale&); 2648 2649 extern template 2650 bool 2651 has_facet<time_get<char> >(const locale&); 2652 2653 extern template 2654 bool 2655 has_facet<messages<char> >(const locale&); 2656 2657#ifdef _GLIBCPP_USE_WCHAR_T 2658 extern template class moneypunct<wchar_t, false>; 2659 extern template class moneypunct<wchar_t, true>; 2660 extern template class moneypunct_byname<wchar_t, false>; 2661 extern template class moneypunct_byname<wchar_t, true>; 2662 extern template class money_get<wchar_t>; 2663 extern template class money_put<wchar_t>; 2664 extern template class numpunct<wchar_t>; 2665 extern template class numpunct_byname<wchar_t>; 2666 extern template class num_get<wchar_t>; 2667 extern template class num_put<wchar_t>; 2668 extern template class __timepunct<wchar_t>; 2669 extern template class time_put<wchar_t>; 2670 extern template class time_put_byname<wchar_t>; 2671 extern template class time_get<wchar_t>; 2672 extern template class time_get_byname<wchar_t>; 2673 extern template class messages<wchar_t>; 2674 extern template class messages_byname<wchar_t>; 2675 extern template class ctype_byname<wchar_t>; 2676 extern template class codecvt_byname<wchar_t, char, mbstate_t>; 2677 extern template class collate<wchar_t>; 2678 extern template class collate_byname<wchar_t>; 2679 2680 extern template 2681 const codecvt<wchar_t, char, mbstate_t>& 2682 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 2683 2684 extern template 2685 const collate<wchar_t>& 2686 use_facet<collate<wchar_t> >(const locale&); 2687 2688 extern template 2689 const numpunct<wchar_t>& 2690 use_facet<numpunct<wchar_t> >(const locale&); 2691 2692 extern template 2693 const num_put<wchar_t>& 2694 use_facet<num_put<wchar_t> >(const locale&); 2695 2696 extern template 2697 const num_get<wchar_t>& 2698 use_facet<num_get<wchar_t> >(const locale&); 2699 2700 extern template 2701 const moneypunct<wchar_t, true>& 2702 use_facet<moneypunct<wchar_t, true> >(const locale&); 2703 2704 extern template 2705 const moneypunct<wchar_t, false>& 2706 use_facet<moneypunct<wchar_t, false> >(const locale&); 2707 2708 extern template 2709 const money_put<wchar_t>& 2710 use_facet<money_put<wchar_t> >(const locale&); 2711 2712 extern template 2713 const money_get<wchar_t>& 2714 use_facet<money_get<wchar_t> >(const locale&); 2715 2716 extern template 2717 const __timepunct<wchar_t>& 2718 use_facet<__timepunct<wchar_t> >(const locale&); 2719 2720 extern template 2721 const time_put<wchar_t>& 2722 use_facet<time_put<wchar_t> >(const locale&); 2723 2724 extern template 2725 const time_get<wchar_t>& 2726 use_facet<time_get<wchar_t> >(const locale&); 2727 2728 extern template 2729 const messages<wchar_t>& 2730 use_facet<messages<wchar_t> >(const locale&); 2731 2732 extern template 2733 bool 2734 has_facet<ctype<wchar_t> >(const locale&); 2735 2736 extern template 2737 bool 2738 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 2739 2740 extern template 2741 bool 2742 has_facet<collate<wchar_t> >(const locale&); 2743 2744 extern template 2745 bool 2746 has_facet<numpunct<wchar_t> >(const locale&); 2747 2748 extern template 2749 bool 2750 has_facet<num_put<wchar_t> >(const locale&); 2751 2752 extern template 2753 bool 2754 has_facet<num_get<wchar_t> >(const locale&); 2755 2756 extern template 2757 bool 2758 has_facet<moneypunct<wchar_t> >(const locale&); 2759 2760 extern template 2761 bool 2762 has_facet<money_put<wchar_t> >(const locale&); 2763 2764 extern template 2765 bool 2766 has_facet<money_get<wchar_t> >(const locale&); 2767 2768 extern template 2769 bool 2770 has_facet<__timepunct<wchar_t> >(const locale&); 2771 2772 extern template 2773 bool 2774 has_facet<time_put<wchar_t> >(const locale&); 2775 2776 extern template 2777 bool 2778 has_facet<time_get<wchar_t> >(const locale&); 2779 2780 extern template 2781 bool 2782 has_facet<messages<wchar_t> >(const locale&); 2783#endif 2784#endif 2785} // namespace std 2786 2787#endif 2788