locale_facets.tcc revision 132720
197403Sobrien// Locale support -*- C++ -*- 297403Sobrien 3132720Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 497403Sobrien// Free Software Foundation, Inc. 597403Sobrien// 697403Sobrien// This file is part of the GNU ISO C++ Library. This library is free 797403Sobrien// software; you can redistribute it and/or modify it under the 897403Sobrien// terms of the GNU General Public License as published by the 997403Sobrien// Free Software Foundation; either version 2, or (at your option) 1097403Sobrien// any later version. 1197403Sobrien 1297403Sobrien// This library is distributed in the hope that it will be useful, 1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1597403Sobrien// GNU General Public License for more details. 1697403Sobrien 1797403Sobrien// You should have received a copy of the GNU General Public License along 1897403Sobrien// with this library; see the file COPYING. If not, write to the Free 1997403Sobrien// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 2097403Sobrien// USA. 2197403Sobrien 2297403Sobrien// As a special exception, you may use this file as part of a free software 2397403Sobrien// library without restriction. Specifically, if other files instantiate 2497403Sobrien// templates or use macros or inline functions from this file, or you compile 2597403Sobrien// this file and link it with other files to produce an executable, this 2697403Sobrien// file does not by itself cause the resulting executable to be covered by 2797403Sobrien// the GNU General Public License. This exception does not however 2897403Sobrien// invalidate any other reasons why the executable file might be covered by 2997403Sobrien// the GNU General Public License. 3097403Sobrien 3197403Sobrien// Warning: this file is not meant for user inclusion. Use <locale>. 3297403Sobrien 33132720Skan#ifndef _LOCALE_FACETS_TCC 34132720Skan#define _LOCALE_FACETS_TCC 1 3597403Sobrien 3697403Sobrien#pragma GCC system_header 3797403Sobrien 38132720Skan#include <limits> // For numeric_limits 39132720Skan#include <typeinfo> // For bad_cast. 4097403Sobrien#include <bits/streambuf_iterator.h> 4197403Sobrien 4297403Sobriennamespace std 4397403Sobrien{ 4497403Sobrien template<typename _Facet> 4597403Sobrien locale 4697403Sobrien locale::combine(const locale& __other) const 4797403Sobrien { 4897403Sobrien _Impl* __tmp = new _Impl(*_M_impl, 1); 49132720Skan try 50132720Skan { 51132720Skan __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 52132720Skan } 53132720Skan catch(...) 54132720Skan { 55132720Skan __tmp->_M_remove_reference(); 56132720Skan __throw_exception_again; 57132720Skan } 5897403Sobrien return locale(__tmp); 5997403Sobrien } 6097403Sobrien 6197403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 6297403Sobrien bool 6397403Sobrien locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 6497403Sobrien const basic_string<_CharT, _Traits, _Alloc>& __s2) const 6597403Sobrien { 6697403Sobrien typedef std::collate<_CharT> __collate_type; 6797403Sobrien const __collate_type& __collate = use_facet<__collate_type>(*this); 6897403Sobrien return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 6997403Sobrien __s2.data(), __s2.data() + __s2.length()) < 0); 7097403Sobrien } 7197403Sobrien 72132720Skan /** 73132720Skan * @brief Test for the presence of a facet. 74132720Skan * 75132720Skan * has_facet tests the locale argument for the presence of the facet type 76132720Skan * provided as the template parameter. Facets derived from the facet 77132720Skan * parameter will also return true. 78132720Skan * 79132720Skan * @param Facet The facet type to test the presence of. 80132720Skan * @param locale The locale to test. 81132720Skan * @return true if locale contains a facet of type Facet, else false. 82132720Skan */ 8397403Sobrien template<typename _Facet> 84132720Skan inline bool 85132720Skan has_facet(const locale& __loc) throw() 86132720Skan { 87132720Skan const size_t __i = _Facet::id._M_id(); 88132720Skan const locale::facet** __facets = __loc._M_impl->_M_facets; 89132720Skan return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); 90132720Skan } 91132720Skan 92132720Skan /** 93132720Skan * @brief Return a facet. 94132720Skan * 95132720Skan * use_facet looks for and returns a reference to a facet of type Facet 96132720Skan * where Facet is the template parameter. If has_facet(locale) is true, 97132720Skan * there is a suitable facet to return. It throws std::bad_cast if the 98132720Skan * locale doesn't contain a facet of type Facet. 99132720Skan * 100132720Skan * @param Facet The facet type to access. 101132720Skan * @param locale The locale to use. 102132720Skan * @return Reference to facet of type Facet. 103132720Skan * @throw std::bad_cast if locale doesn't contain a facet of type Facet. 104132720Skan */ 105132720Skan template<typename _Facet> 106132720Skan inline const _Facet& 10797403Sobrien use_facet(const locale& __loc) 10897403Sobrien { 109132720Skan const size_t __i = _Facet::id._M_id(); 110132720Skan const locale::facet** __facets = __loc._M_impl->_M_facets; 11197403Sobrien if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) 11297403Sobrien __throw_bad_cast(); 11397403Sobrien return static_cast<const _Facet&>(*__facets[__i]); 11497403Sobrien } 11597403Sobrien 116132720Skan // Routine to access a cache for the facet. If the cache didn't 117132720Skan // exist before, it gets constructed on the fly. 11897403Sobrien template<typename _Facet> 119132720Skan struct __use_cache 12097403Sobrien { 121132720Skan const _Facet* 122132720Skan operator() (const locale& __loc) const; 123132720Skan }; 124132720Skan 125132720Skan // Specializations. 126132720Skan template<typename _CharT> 127132720Skan struct __use_cache<__numpunct_cache<_CharT> > 128132720Skan { 129132720Skan const __numpunct_cache<_CharT>* 130132720Skan operator() (const locale& __loc) const 131132720Skan { 132132720Skan const size_t __i = numpunct<_CharT>::id._M_id(); 133132720Skan const locale::facet** __caches = __loc._M_impl->_M_caches; 134132720Skan if (!__caches[__i]) 135132720Skan { 136132720Skan __numpunct_cache<_CharT>* __tmp = NULL; 137132720Skan try 138132720Skan { 139132720Skan __tmp = new __numpunct_cache<_CharT>; 140132720Skan __tmp->_M_cache(__loc); 141132720Skan } 142132720Skan catch(...) 143132720Skan { 144132720Skan delete __tmp; 145132720Skan __throw_exception_again; 146132720Skan } 147132720Skan __loc._M_impl->_M_install_cache(__tmp, __i); 148132720Skan } 149132720Skan return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]); 150132720Skan } 151132720Skan }; 152132720Skan 153132720Skan template<typename _CharT, bool _Intl> 154132720Skan struct __use_cache<__moneypunct_cache<_CharT, _Intl> > 155132720Skan { 156132720Skan const __moneypunct_cache<_CharT, _Intl>* 157132720Skan operator() (const locale& __loc) const 158132720Skan { 159132720Skan const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); 160132720Skan const locale::facet** __caches = __loc._M_impl->_M_caches; 161132720Skan if (!__caches[__i]) 162132720Skan { 163132720Skan __moneypunct_cache<_CharT, _Intl>* __tmp = NULL; 164132720Skan try 165132720Skan { 166132720Skan __tmp = new __moneypunct_cache<_CharT, _Intl>; 167132720Skan __tmp->_M_cache(__loc); 168132720Skan } 169132720Skan catch(...) 170132720Skan { 171132720Skan delete __tmp; 172132720Skan __throw_exception_again; 173132720Skan } 174132720Skan __loc._M_impl->_M_install_cache(__tmp, __i); 175132720Skan } 176132720Skan return static_cast< 177132720Skan const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); 178132720Skan } 179132720Skan }; 180132720Skan 181132720Skan template<typename _CharT> 182132720Skan void 183132720Skan __numpunct_cache<_CharT>::_M_cache(const locale& __loc) 184132720Skan { 185132720Skan _M_allocated = true; 186132720Skan 187132720Skan const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 188132720Skan 189132720Skan _M_grouping_size = __np.grouping().size(); 190132720Skan char* __grouping = new char[_M_grouping_size]; 191132720Skan __np.grouping().copy(__grouping, _M_grouping_size); 192132720Skan _M_grouping = __grouping; 193132720Skan _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0; 194132720Skan 195132720Skan _M_truename_size = __np.truename().size(); 196132720Skan _CharT* __truename = new _CharT[_M_truename_size]; 197132720Skan __np.truename().copy(__truename, _M_truename_size); 198132720Skan _M_truename = __truename; 199132720Skan 200132720Skan _M_falsename_size = __np.falsename().size(); 201132720Skan _CharT* __falsename = new _CharT[_M_falsename_size]; 202132720Skan __np.falsename().copy(__falsename, _M_falsename_size); 203132720Skan _M_falsename = __falsename; 204132720Skan 205132720Skan _M_decimal_point = __np.decimal_point(); 206132720Skan _M_thousands_sep = __np.thousands_sep(); 207132720Skan 208132720Skan const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 209132720Skan __ct.widen(__num_base::_S_atoms_out, 210132720Skan __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out); 211132720Skan __ct.widen(__num_base::_S_atoms_in, 212132720Skan __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in); 21397403Sobrien } 21497403Sobrien 215132720Skan template<typename _CharT, bool _Intl> 216132720Skan void 217132720Skan __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) 218117397Skan { 219132720Skan _M_allocated = true; 220132720Skan 221132720Skan const moneypunct<_CharT, _Intl>& __mp = 222132720Skan use_facet<moneypunct<_CharT, _Intl> >(__loc); 223132720Skan 224132720Skan _M_grouping_size = __mp.grouping().size(); 225132720Skan char* __grouping = new char[_M_grouping_size]; 226132720Skan __mp.grouping().copy(__grouping, _M_grouping_size); 227132720Skan _M_grouping = __grouping; 228132720Skan _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0; 229132720Skan 230132720Skan _M_decimal_point = __mp.decimal_point(); 231132720Skan _M_thousands_sep = __mp.thousands_sep(); 232132720Skan _M_frac_digits = __mp.frac_digits(); 233132720Skan 234132720Skan _M_curr_symbol_size = __mp.curr_symbol().size(); 235132720Skan _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size]; 236132720Skan __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size); 237132720Skan _M_curr_symbol = __curr_symbol; 238132720Skan 239132720Skan _M_positive_sign_size = __mp.positive_sign().size(); 240132720Skan _CharT* __positive_sign = new _CharT[_M_positive_sign_size]; 241132720Skan __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size); 242132720Skan _M_positive_sign = __positive_sign; 243132720Skan 244132720Skan _M_negative_sign_size = __mp.negative_sign().size(); 245132720Skan _CharT* __negative_sign = new _CharT[_M_negative_sign_size]; 246132720Skan __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size); 247132720Skan _M_negative_sign = __negative_sign; 248132720Skan 249132720Skan _M_pos_format = __mp.pos_format(); 250132720Skan _M_neg_format = __mp.neg_format(); 251132720Skan 252132720Skan const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 253132720Skan __ct.widen(money_base::_S_atoms, 254132720Skan money_base::_S_atoms + money_base::_S_end, _M_atoms); 255117397Skan } 25697403Sobrien 257132720Skan 258132720Skan // Used by both numeric and monetary facets. 259132720Skan // Check to make sure that the __grouping_tmp string constructed in 260132720Skan // money_get or num_get matches the canonical grouping for a given 261132720Skan // locale. 262132720Skan // __grouping_tmp is parsed L to R 263132720Skan // 1,222,444 == __grouping_tmp of "\1\3\3" 264132720Skan // __grouping is parsed R to L 265132720Skan // 1,222,444 == __grouping of "\3" == "\3\3\3" 266132720Skan static bool 267132720Skan __verify_grouping(const char* __grouping, size_t __grouping_size, 268132720Skan const string& __grouping_tmp); 269132720Skan 27097403Sobrien template<typename _CharT, typename _InIter> 27197403Sobrien _InIter 27297403Sobrien num_get<_CharT, _InIter>:: 27397403Sobrien _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 27497403Sobrien ios_base::iostate& __err, string& __xtrc) const 27597403Sobrien { 276132720Skan typedef char_traits<_CharT> __traits_type; 277132720Skan typedef typename numpunct<_CharT>::__cache_type __cache_type; 278132720Skan __use_cache<__cache_type> __uc; 279132720Skan const locale& __loc = __io._M_getloc(); 280132720Skan const __cache_type* __lc = __uc(__loc); 281132720Skan const _CharT* __lit = __lc->_M_atoms_in; 28297403Sobrien 283132720Skan // True if a mantissa is found. 284132720Skan bool __found_mantissa = false; 285132720Skan 28697403Sobrien // First check for sign. 287132720Skan if (__beg != __end) 28897403Sobrien { 289132720Skan const char_type __c = *__beg; 290132720Skan const bool __plus = __c == __lit[__num_base::_S_iplus]; 291132720Skan if ((__plus || __c == __lit[__num_base::_S_iminus]) 292132720Skan && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 293132720Skan && !(__c == __lc->_M_decimal_point)) 294132720Skan { 295132720Skan __xtrc += __plus ? '+' : '-'; 296132720Skan ++__beg; 297132720Skan } 29897403Sobrien } 29997403Sobrien 300132720Skan // Next, look for leading zeros. 301132720Skan while (__beg != __end) 30297403Sobrien { 303132720Skan const char_type __c = *__beg; 304132720Skan if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep 305132720Skan || __c == __lc->_M_decimal_point) 306132720Skan break; 307132720Skan else if (__c == __lit[__num_base::_S_izero]) 308132720Skan { 309132720Skan if (!__found_mantissa) 310132720Skan { 311132720Skan __xtrc += '0'; 312132720Skan __found_mantissa = true; 313132720Skan } 314132720Skan ++__beg; 315132720Skan } 316132720Skan else 317132720Skan break; 31897403Sobrien } 31997403Sobrien 32097403Sobrien // Only need acceptable digits for floating point numbers. 32197403Sobrien bool __found_dec = false; 32297403Sobrien bool __found_sci = false; 32397403Sobrien string __found_grouping; 324132720Skan if (__lc->_M_use_grouping) 325132720Skan __found_grouping.reserve(32); 32697403Sobrien int __sep_pos = 0; 327132720Skan const char_type* __lit_zero = __lit + __num_base::_S_izero; 328132720Skan const char_type* __q; 32997403Sobrien while (__beg != __end) 33097403Sobrien { 331132720Skan // According to 22.2.2.1.2, p8-9, first look for thousands_sep 332132720Skan // and decimal_point. 333132720Skan const char_type __c = *__beg; 334132720Skan if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 33597403Sobrien { 336132720Skan if (!__found_dec && !__found_sci) 33797403Sobrien { 338132720Skan // NB: Thousands separator at the beginning of a string 339132720Skan // is a no-no, as is two consecutive thousands separators. 340132720Skan if (__sep_pos) 341132720Skan { 342132720Skan __found_grouping += static_cast<char>(__sep_pos); 343132720Skan __sep_pos = 0; 344132720Skan ++__beg; 345132720Skan } 346132720Skan else 347132720Skan { 348132720Skan __err |= ios_base::failbit; 349132720Skan break; 350132720Skan } 35197403Sobrien } 352132720Skan else 353132720Skan break; 35497403Sobrien } 355132720Skan else if (__c == __lc->_M_decimal_point) 35697403Sobrien { 357132720Skan if (!__found_dec && !__found_sci) 358132720Skan { 359132720Skan // If no grouping chars are seen, no grouping check 360132720Skan // is applied. Therefore __found_grouping is adjusted 361132720Skan // only if decimal_point comes after some thousands_sep. 362132720Skan if (__found_grouping.size()) 363132720Skan __found_grouping += static_cast<char>(__sep_pos); 364132720Skan __xtrc += '.'; 365132720Skan __found_dec = true; 366132720Skan ++__beg; 367132720Skan } 368132720Skan else 369132720Skan break; 37097403Sobrien } 371132720Skan else if (__q = __traits_type::find(__lit_zero, 10, __c)) 37297403Sobrien { 373132720Skan __xtrc += __num_base::_S_atoms_in[__q - __lit]; 374132720Skan __found_mantissa = true; 375132720Skan ++__sep_pos; 376132720Skan ++__beg; 377132720Skan } 378132720Skan else if ((__c == __lit[__num_base::_S_ie] 379132720Skan || __c == __lit[__num_base::_S_iE]) 380132720Skan && __found_mantissa && !__found_sci) 381132720Skan { 38297403Sobrien // Scientific notation. 383132720Skan if (__found_grouping.size() && !__found_dec) 384132720Skan __found_grouping += static_cast<char>(__sep_pos); 385132720Skan __xtrc += 'e'; 386132720Skan __found_sci = true; 38797403Sobrien 38897403Sobrien // Remove optional plus or minus sign, if they exist. 389132720Skan if (++__beg != __end) 39097403Sobrien { 391132720Skan const bool __plus = *__beg == __lit[__num_base::_S_iplus]; 392132720Skan if ((__plus || *__beg == __lit[__num_base::_S_iminus]) 393132720Skan && !(__lc->_M_use_grouping 394132720Skan && *__beg == __lc->_M_thousands_sep) 395132720Skan && !(*__beg == __lc->_M_decimal_point)) 396132720Skan { 397132720Skan __xtrc += __plus ? '+' : '-'; 398132720Skan ++__beg; 399132720Skan } 40097403Sobrien } 40197403Sobrien } 40297403Sobrien else 40397403Sobrien // Not a valid input item. 40497403Sobrien break; 40597403Sobrien } 40697403Sobrien 40797403Sobrien // Digit grouping is checked. If grouping and found_grouping don't 40897403Sobrien // match, then get very very upset, and set failbit. 409132720Skan if (__lc->_M_use_grouping && __found_grouping.size()) 41097403Sobrien { 411132720Skan // Add the ending grouping if a decimal or 'e'/'E' wasn't found. 412132720Skan if (!__found_dec && !__found_sci) 41397403Sobrien __found_grouping += static_cast<char>(__sep_pos); 414132720Skan 415132720Skan if (!std::__verify_grouping(__lc->_M_grouping, 416132720Skan __lc->_M_grouping_size, 417132720Skan __found_grouping)) 41897403Sobrien __err |= ios_base::failbit; 41997403Sobrien } 42097403Sobrien 421132720Skan // Finish up. 42297403Sobrien if (__beg == __end) 42397403Sobrien __err |= ios_base::eofbit; 42497403Sobrien return __beg; 42597403Sobrien } 42697403Sobrien 42797403Sobrien template<typename _CharT, typename _InIter> 428132720Skan template<typename _ValueT> 429132720Skan _InIter 430132720Skan num_get<_CharT, _InIter>:: 431132720Skan _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 432132720Skan ios_base::iostate& __err, _ValueT& __v) const 433132720Skan { 434132720Skan typedef char_traits<_CharT> __traits_type; 435132720Skan typedef typename numpunct<_CharT>::__cache_type __cache_type; 436132720Skan __use_cache<__cache_type> __uc; 437132720Skan const locale& __loc = __io._M_getloc(); 438132720Skan const __cache_type* __lc = __uc(__loc); 439132720Skan const _CharT* __lit = __lc->_M_atoms_in; 44097403Sobrien 441132720Skan // NB: Iff __basefield == 0, __base can change based on contents. 442132720Skan const ios_base::fmtflags __basefield = __io.flags() 443132720Skan & ios_base::basefield; 444132720Skan const bool __oct = __basefield == ios_base::oct; 445132720Skan int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); 446102782Skan 447132720Skan // True if numeric digits are found. 448132720Skan bool __found_num = false; 44997403Sobrien 450132720Skan // First check for sign. 451132720Skan bool __negative = false; 452132720Skan if (__beg != __end) 453132720Skan { 454132720Skan const char_type __c = *__beg; 455132720Skan if (numeric_limits<_ValueT>::is_signed) 456132720Skan __negative = __c == __lit[__num_base::_S_iminus]; 457132720Skan if ((__negative || __c == __lit[__num_base::_S_iplus]) 458132720Skan && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 459132720Skan && !(__c == __lc->_M_decimal_point)) 460132720Skan ++__beg; 461132720Skan } 462132720Skan 463132720Skan // Next, look for leading zeros and check required digits 464132720Skan // for base formats. 465132720Skan while (__beg != __end) 466132720Skan { 467132720Skan const char_type __c = *__beg; 468132720Skan if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep 469132720Skan || __c == __lc->_M_decimal_point) 470132720Skan break; 471132720Skan else if (__c == __lit[__num_base::_S_izero] 472132720Skan && (!__found_num || __base == 10)) 473132720Skan { 474132720Skan __found_num = true; 475132720Skan ++__beg; 476132720Skan } 477132720Skan else if (__found_num) 478132720Skan { 479132720Skan if (__c == __lit[__num_base::_S_ix] 480132720Skan || __c == __lit[__num_base::_S_iX]) 481132720Skan { 482132720Skan if (__basefield == 0) 48397403Sobrien __base = 16; 484132720Skan if (__base == 16) 485132720Skan { 486132720Skan __found_num = false; 487132720Skan ++__beg; 488132720Skan } 489132720Skan } 490132720Skan else if (__basefield == 0) 491132720Skan __base = 8; 492132720Skan break; 493132720Skan } 494132720Skan else 495132720Skan break; 496132720Skan } 49797403Sobrien 498132720Skan // At this point, base is determined. If not hex, only allow 499132720Skan // base digits as valid input. 500132720Skan const size_t __len = __base == 16 ? (__num_base::_S_iend 501132720Skan - __num_base::_S_izero) 502132720Skan : __base; 50397403Sobrien 504132720Skan // Extract. 505132720Skan string __found_grouping; 506132720Skan if (__lc->_M_use_grouping) 507132720Skan __found_grouping.reserve(32); 508132720Skan int __sep_pos = 0; 509132720Skan bool __overflow = false; 510132720Skan _ValueT __result = 0; 511132720Skan const char_type* __lit_zero = __lit + __num_base::_S_izero; 512132720Skan const char_type* __q; 513132720Skan if (__negative) 514132720Skan { 515132720Skan const _ValueT __min = numeric_limits<_ValueT>::min() / __base; 516132720Skan for (; __beg != __end; ++__beg) 517132720Skan { 518132720Skan // According to 22.2.2.1.2, p8-9, first look for thousands_sep 519132720Skan // and decimal_point. 520132720Skan const char_type __c = *__beg; 521132720Skan if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 522132720Skan { 523132720Skan // NB: Thousands separator at the beginning of a string 524132720Skan // is a no-no, as is two consecutive thousands separators. 525132720Skan if (__sep_pos) 526132720Skan { 527132720Skan __found_grouping += static_cast<char>(__sep_pos); 528132720Skan __sep_pos = 0; 529132720Skan } 530132720Skan else 531132720Skan { 532132720Skan __err |= ios_base::failbit; 533132720Skan break; 534132720Skan } 535132720Skan } 536132720Skan else if (__c == __lc->_M_decimal_point) 53797403Sobrien break; 538132720Skan else if (__q = __traits_type::find(__lit_zero, __len, __c)) 539132720Skan { 540132720Skan int __digit = __q - __lit_zero; 541132720Skan if (__digit > 15) 542132720Skan __digit -= 6; 543132720Skan if (__result < __min) 544132720Skan __overflow = true; 545132720Skan else 546132720Skan { 547132720Skan const _ValueT __new_result = __result * __base 548132720Skan - __digit; 549132720Skan __overflow |= __new_result > __result; 550132720Skan __result = __new_result; 551132720Skan ++__sep_pos; 552132720Skan __found_num = true; 553132720Skan } 554132720Skan } 555132720Skan else 556132720Skan // Not a valid input item. 557132720Skan break; 558132720Skan } 559132720Skan } 560132720Skan else 561132720Skan { 562132720Skan const _ValueT __max = numeric_limits<_ValueT>::max() / __base; 563132720Skan for (; __beg != __end; ++__beg) 564132720Skan { 565132720Skan const char_type __c = *__beg; 566132720Skan if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 567132720Skan { 568132720Skan if (__sep_pos) 569132720Skan { 570132720Skan __found_grouping += static_cast<char>(__sep_pos); 571132720Skan __sep_pos = 0; 572132720Skan } 573132720Skan else 574132720Skan { 575132720Skan __err |= ios_base::failbit; 576132720Skan break; 577132720Skan } 578132720Skan } 579132720Skan else if (__c == __lc->_M_decimal_point) 580132720Skan break; 581132720Skan else if (__q = __traits_type::find(__lit_zero, __len, __c)) 582132720Skan { 583132720Skan int __digit = __q - __lit_zero; 584132720Skan if (__digit > 15) 585132720Skan __digit -= 6; 586132720Skan if (__result > __max) 587132720Skan __overflow = true; 588132720Skan else 589132720Skan { 590132720Skan const _ValueT __new_result = __result * __base 591132720Skan + __digit; 592132720Skan __overflow |= __new_result < __result; 593132720Skan __result = __new_result; 594132720Skan ++__sep_pos; 595132720Skan __found_num = true; 596132720Skan } 597132720Skan } 598132720Skan else 599132720Skan break; 600132720Skan } 601132720Skan } 60297403Sobrien 603132720Skan // Digit grouping is checked. If grouping and found_grouping don't 604132720Skan // match, then get very very upset, and set failbit. 605132720Skan if (__lc->_M_use_grouping && __found_grouping.size()) 606132720Skan { 607132720Skan // Add the ending grouping. 608132720Skan __found_grouping += static_cast<char>(__sep_pos); 60997403Sobrien 610132720Skan if (!std::__verify_grouping(__lc->_M_grouping, 611132720Skan __lc->_M_grouping_size, 612132720Skan __found_grouping)) 613132720Skan __err |= ios_base::failbit; 614132720Skan } 61597403Sobrien 616132720Skan if (!(__err & ios_base::failbit) && !__overflow 617132720Skan && __found_num) 618132720Skan __v = __result; 619132720Skan else 620132720Skan __err |= ios_base::failbit; 621132720Skan 622132720Skan if (__beg == __end) 623132720Skan __err |= ios_base::eofbit; 624132720Skan return __beg; 625132720Skan } 626132720Skan 627132720Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 628132720Skan // 17. Bad bool parsing 62997403Sobrien template<typename _CharT, typename _InIter> 63097403Sobrien _InIter 63197403Sobrien num_get<_CharT, _InIter>:: 63297403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 63397403Sobrien ios_base::iostate& __err, bool& __v) const 63497403Sobrien { 63597403Sobrien if (!(__io.flags() & ios_base::boolalpha)) 63697403Sobrien { 637132720Skan // Parse bool values as long. 63897403Sobrien // NB: We can't just call do_get(long) here, as it might 63997403Sobrien // refer to a derived class. 640132720Skan long __l = -1; 641132720Skan __beg = _M_extract_int(__beg, __end, __io, __err, __l); 642132720Skan if (__l == 0 || __l == 1) 643132720Skan __v = __l; 644132720Skan else 64597403Sobrien __err |= ios_base::failbit; 64697403Sobrien } 64797403Sobrien else 64897403Sobrien { 649132720Skan // Parse bool values as alphanumeric. 650132720Skan typedef char_traits<_CharT> __traits_type; 651132720Skan typedef typename numpunct<_CharT>::__cache_type __cache_type; 652132720Skan __use_cache<__cache_type> __uc; 653132720Skan const locale& __loc = __io._M_getloc(); 654132720Skan const __cache_type* __lc = __uc(__loc); 655102782Skan 656132720Skan bool __testf = true; 657132720Skan bool __testt = true; 658132720Skan size_t __n; 659132720Skan for (__n = 0; __beg != __end; ++__n, ++__beg) 660132720Skan { 661132720Skan if (__testf) 662132720Skan if (__n < __lc->_M_falsename_size) 663132720Skan __testf = *__beg == __lc->_M_falsename[__n]; 664132720Skan else 665132720Skan break; 66697403Sobrien 667132720Skan if (__testt) 668132720Skan if (__n < __lc->_M_truename_size) 669132720Skan __testt = *__beg == __lc->_M_truename[__n]; 670132720Skan else 671132720Skan break; 672132720Skan 673132720Skan if (!__testf && !__testt) 674132720Skan break; 67597403Sobrien } 676132720Skan if (__testf && __n == __lc->_M_falsename_size) 677132720Skan __v = 0; 678132720Skan else if (__testt && __n == __lc->_M_truename_size) 679132720Skan __v = 1; 680132720Skan else 681132720Skan __err |= ios_base::failbit; 682132720Skan 68397403Sobrien if (__beg == __end) 68497403Sobrien __err |= ios_base::eofbit; 68597403Sobrien } 68697403Sobrien return __beg; 68797403Sobrien } 68897403Sobrien 68997403Sobrien template<typename _CharT, typename _InIter> 69097403Sobrien _InIter 69197403Sobrien num_get<_CharT, _InIter>:: 69297403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 69397403Sobrien ios_base::iostate& __err, long& __v) const 694132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 69597403Sobrien 69697403Sobrien template<typename _CharT, typename _InIter> 69797403Sobrien _InIter 69897403Sobrien num_get<_CharT, _InIter>:: 69997403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 70097403Sobrien ios_base::iostate& __err, unsigned short& __v) const 701132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 70297403Sobrien 70397403Sobrien template<typename _CharT, typename _InIter> 70497403Sobrien _InIter 70597403Sobrien num_get<_CharT, _InIter>:: 70697403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 70797403Sobrien ios_base::iostate& __err, unsigned int& __v) const 708132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 70997403Sobrien 71097403Sobrien template<typename _CharT, typename _InIter> 71197403Sobrien _InIter 71297403Sobrien num_get<_CharT, _InIter>:: 71397403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 71497403Sobrien ios_base::iostate& __err, unsigned long& __v) const 715132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 71697403Sobrien 717132720Skan#ifdef _GLIBCXX_USE_LONG_LONG 71897403Sobrien template<typename _CharT, typename _InIter> 71997403Sobrien _InIter 72097403Sobrien num_get<_CharT, _InIter>:: 72197403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 72297403Sobrien ios_base::iostate& __err, long long& __v) const 723132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 72497403Sobrien 72597403Sobrien template<typename _CharT, typename _InIter> 72697403Sobrien _InIter 72797403Sobrien num_get<_CharT, _InIter>:: 72897403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 72997403Sobrien ios_base::iostate& __err, unsigned long long& __v) const 730132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 73197403Sobrien#endif 73297403Sobrien 73397403Sobrien template<typename _CharT, typename _InIter> 73497403Sobrien _InIter 73597403Sobrien num_get<_CharT, _InIter>:: 736132720Skan do_get(iter_type __beg, iter_type __end, ios_base& __io, 73797403Sobrien ios_base::iostate& __err, float& __v) const 73897403Sobrien { 73997403Sobrien string __xtrc; 74097403Sobrien __xtrc.reserve(32); 74197403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 742132720Skan std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 74397403Sobrien return __beg; 74497403Sobrien } 74597403Sobrien 74697403Sobrien template<typename _CharT, typename _InIter> 74797403Sobrien _InIter 74897403Sobrien num_get<_CharT, _InIter>:: 74997403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 75097403Sobrien ios_base::iostate& __err, double& __v) const 75197403Sobrien { 75297403Sobrien string __xtrc; 75397403Sobrien __xtrc.reserve(32); 75497403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 755132720Skan std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 75697403Sobrien return __beg; 75797403Sobrien } 75897403Sobrien 75997403Sobrien template<typename _CharT, typename _InIter> 76097403Sobrien _InIter 76197403Sobrien num_get<_CharT, _InIter>:: 76297403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 76397403Sobrien ios_base::iostate& __err, long double& __v) const 76497403Sobrien { 76597403Sobrien string __xtrc; 76697403Sobrien __xtrc.reserve(32); 76797403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 768132720Skan std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 76997403Sobrien return __beg; 77097403Sobrien } 77197403Sobrien 77297403Sobrien template<typename _CharT, typename _InIter> 77397403Sobrien _InIter 77497403Sobrien num_get<_CharT, _InIter>:: 77597403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 77697403Sobrien ios_base::iostate& __err, void*& __v) const 77797403Sobrien { 778132720Skan // Prepare for hex formatted input. 77997403Sobrien typedef ios_base::fmtflags fmtflags; 780132720Skan const fmtflags __fmt = __io.flags(); 781132720Skan __io.flags(__fmt & ~ios_base::basefield | ios_base::hex); 78297403Sobrien 783132720Skan unsigned long __ul; 784132720Skan __beg = _M_extract_int(__beg, __end, __io, __err, __ul); 78597403Sobrien 786132720Skan // Reset from hex formatted input. 78797403Sobrien __io.flags(__fmt); 78897403Sobrien 78997403Sobrien if (!(__err & ios_base::failbit)) 79097403Sobrien __v = reinterpret_cast<void*>(__ul); 791132720Skan else 79297403Sobrien __err |= ios_base::failbit; 79397403Sobrien return __beg; 79497403Sobrien } 79597403Sobrien 796117397Skan // For use by integer and floating-point types after they have been 797117397Skan // converted into a char_type string. 798117397Skan template<typename _CharT, typename _OutIter> 799117397Skan void 800117397Skan num_put<_CharT, _OutIter>:: 801132720Skan _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 802117397Skan _CharT* __new, const _CharT* __cs, int& __len) const 803117397Skan { 804117397Skan // [22.2.2.2.2] Stage 3. 805117397Skan // If necessary, pad. 806132720Skan __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 807117397Skan __w, __len, true); 808117397Skan __len = static_cast<int>(__w); 809117397Skan } 810117397Skan 811117397Skan // Forwarding functions to peel signed from unsigned integer types. 812117397Skan template<typename _CharT> 813117397Skan inline int 814132720Skan __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit, 815132720Skan ios_base::fmtflags __flags) 816117397Skan { 817117397Skan unsigned long __ul = static_cast<unsigned long>(__v); 818117397Skan bool __neg = false; 819132720Skan if (__v < 0) 820117397Skan { 821117397Skan __ul = -__ul; 822117397Skan __neg = true; 823117397Skan } 824132720Skan return __int_to_char(__bufend, __ul, __lit, __flags, __neg); 825117397Skan } 826117397Skan 827117397Skan template<typename _CharT> 828117397Skan inline int 829132720Skan __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit, 830132720Skan ios_base::fmtflags __flags) 831132720Skan { 832132720Skan // About showpos, see Table 60 and C99 7.19.6.1, p6 (+). 833132720Skan return __int_to_char(__bufend, __v, __lit, 834132720Skan __flags & ~ios_base::showpos, false); 835132720Skan } 836117397Skan 837132720Skan#ifdef _GLIBCXX_USE_LONG_LONG 838117397Skan template<typename _CharT> 839117397Skan inline int 840132720Skan __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit, 841132720Skan ios_base::fmtflags __flags) 842132720Skan { 843117397Skan unsigned long long __ull = static_cast<unsigned long long>(__v); 844117397Skan bool __neg = false; 845132720Skan if (__v < 0) 846117397Skan { 847117397Skan __ull = -__ull; 848117397Skan __neg = true; 849117397Skan } 850132720Skan return __int_to_char(__bufend, __ull, __lit, __flags, __neg); 851117397Skan } 852117397Skan 853117397Skan template<typename _CharT> 854117397Skan inline int 855132720Skan __int_to_char(_CharT* __bufend, unsigned long long __v, 856132720Skan const _CharT* __lit, ios_base::fmtflags __flags) 857132720Skan { return __int_to_char(__bufend, __v, __lit, 858132720Skan __flags & ~ios_base::showpos, false); } 859117397Skan#endif 860132720Skan 861117397Skan template<typename _CharT, typename _ValueT> 862117397Skan int 863132720Skan __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, 864132720Skan ios_base::fmtflags __flags, bool __neg) 865117397Skan { 866117397Skan // Don't write base if already 0. 867117397Skan const bool __showbase = (__flags & ios_base::showbase) && __v; 868117397Skan const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 869132720Skan _CharT* __buf = __bufend - 1; 870117397Skan 871117397Skan if (__builtin_expect(__basefield != ios_base::oct && 872117397Skan __basefield != ios_base::hex, true)) 873117397Skan { 874117397Skan // Decimal. 875132720Skan do 876117397Skan { 877132720Skan *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits]; 878117397Skan __v /= 10; 879132720Skan } 880117397Skan while (__v != 0); 881117397Skan if (__neg) 882132720Skan *__buf-- = __lit[__num_base::_S_ominus]; 883117397Skan else if (__flags & ios_base::showpos) 884132720Skan *__buf-- = __lit[__num_base::_S_oplus]; 885117397Skan } 886117397Skan else if (__basefield == ios_base::oct) 887117397Skan { 888117397Skan // Octal. 889132720Skan do 890117397Skan { 891132720Skan *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits]; 892117397Skan __v >>= 3; 893132720Skan } 894117397Skan while (__v != 0); 895117397Skan if (__showbase) 896132720Skan *__buf-- = __lit[__num_base::_S_odigits]; 897117397Skan } 898117397Skan else 899117397Skan { 900117397Skan // Hex. 901117397Skan const bool __uppercase = __flags & ios_base::uppercase; 902132720Skan const int __case_offset = __uppercase ? __num_base::_S_oudigits 903132720Skan : __num_base::_S_odigits; 904132720Skan do 905117397Skan { 906117397Skan *__buf-- = __lit[(__v & 0xf) + __case_offset]; 907117397Skan __v >>= 4; 908132720Skan } 909117397Skan while (__v != 0); 910117397Skan if (__showbase) 911117397Skan { 912117397Skan // 'x' or 'X' 913132720Skan *__buf-- = __lit[__num_base::_S_ox + __uppercase]; 914117397Skan // '0' 915132720Skan *__buf-- = __lit[__num_base::_S_odigits]; 916117397Skan } 917117397Skan } 918132720Skan return __bufend - __buf - 1; 919117397Skan } 920117397Skan 921117397Skan template<typename _CharT, typename _OutIter> 922117397Skan void 923117397Skan num_put<_CharT, _OutIter>:: 924132720Skan _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, 925132720Skan ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const 926117397Skan { 927132720Skan // By itself __add_grouping cannot deal correctly with __cs when 928117397Skan // ios::showbase is set and ios_base::oct || ios_base::hex. 929117397Skan // Therefore we take care "by hand" of the initial 0, 0x or 0X. 930117397Skan // However, remember that the latter do not occur if the number 931117397Skan // printed is '0' (__len == 1). 932117397Skan streamsize __off = 0; 933132720Skan const ios_base::fmtflags __basefield = __io.flags() 934117397Skan & ios_base::basefield; 935117397Skan if ((__io.flags() & ios_base::showbase) && __len > 1) 936117397Skan if (__basefield == ios_base::oct) 937117397Skan { 938117397Skan __off = 1; 939132720Skan __new[0] = __cs[0]; 940117397Skan } 941117397Skan else if (__basefield == ios_base::hex) 942117397Skan { 943117397Skan __off = 2; 944132720Skan __new[0] = __cs[0]; 945132720Skan __new[1] = __cs[1]; 946117397Skan } 947117397Skan _CharT* __p; 948132720Skan __p = std::__add_grouping(__new + __off, __sep, __grouping, 949132720Skan __grouping_size, __cs + __off, 950132720Skan __cs + __len); 951117397Skan __len = __p - __new; 952117397Skan } 953117397Skan 954117397Skan template<typename _CharT, typename _OutIter> 955117397Skan template<typename _ValueT> 956117397Skan _OutIter 957117397Skan num_put<_CharT, _OutIter>:: 958132720Skan _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, 959132720Skan _ValueT __v) const 960117397Skan { 961132720Skan typedef typename numpunct<_CharT>::__cache_type __cache_type; 962132720Skan __use_cache<__cache_type> __uc; 963132720Skan const locale& __loc = __io._M_getloc(); 964132720Skan const __cache_type* __lc = __uc(__loc); 965132720Skan const _CharT* __lit = __lc->_M_atoms_out; 966117397Skan 967117397Skan // Long enough to hold hex, dec, and octal representations. 968132720Skan const int __ilen = 4 * sizeof(_ValueT); 969132720Skan _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 970117397Skan * __ilen)); 971132720Skan 972117397Skan // [22.2.2.2.2] Stage 1, numeric conversion to character. 973117397Skan // Result is returned right-justified in the buffer. 974117397Skan int __len; 975132720Skan __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags()); 976132720Skan __cs += __ilen - __len; 977132720Skan 978132720Skan // Add grouping, if necessary. 979132720Skan if (__lc->_M_use_grouping) 980117397Skan { 981117397Skan // Grouping can add (almost) as many separators as the 982117397Skan // number of digits, but no more. 983132720Skan _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 984132720Skan * __len * 2)); 985132720Skan _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, 986132720Skan __lc->_M_thousands_sep, __io, __cs2, __cs, __len); 987117397Skan __cs = __cs2; 988117397Skan } 989132720Skan 990117397Skan // Pad. 991132720Skan const streamsize __w = __io.width(); 992117397Skan if (__w > static_cast<streamsize>(__len)) 993117397Skan { 994132720Skan _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 995132720Skan * __w)); 996117397Skan _M_pad(__fill, __w, __io, __cs3, __cs, __len); 997117397Skan __cs = __cs3; 998117397Skan } 999117397Skan __io.width(0); 1000117397Skan 1001117397Skan // [22.2.2.2.2] Stage 4. 1002117397Skan // Write resulting, fully-formatted string to output iterator. 1003132720Skan return std::__write(__s, __cs, __len); 1004132720Skan } 1005117397Skan 1006117397Skan template<typename _CharT, typename _OutIter> 1007117397Skan void 1008117397Skan num_put<_CharT, _OutIter>:: 1009132720Skan _M_group_float(const char* __grouping, size_t __grouping_size, 1010132720Skan _CharT __sep, const _CharT* __p, _CharT* __new, 1011132720Skan _CharT* __cs, int& __len) const 1012117397Skan { 1013132720Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 1014132720Skan // 282. What types does numpunct grouping refer to? 1015132720Skan // Add grouping, if necessary. 1016117397Skan _CharT* __p2; 1017132720Skan const int __declen = __p ? __p - __cs : __len; 1018132720Skan __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size, 1019132720Skan __cs, __cs + __declen); 1020132720Skan 1021117397Skan // Tack on decimal part. 1022117397Skan int __newlen = __p2 - __new; 1023117397Skan if (__p) 1024117397Skan { 1025117397Skan char_traits<_CharT>::copy(__p2, __p, __len - __declen); 1026117397Skan __newlen += __len - __declen; 1027132720Skan } 1028117397Skan __len = __newlen; 1029117397Skan } 1030117397Skan 1031117397Skan // The following code uses snprintf (or sprintf(), when 1032132720Skan // _GLIBCXX_USE_C99 is not defined) to convert floating point values 1033117397Skan // for insertion into a stream. An optimization would be to replace 1034117397Skan // them with code that works directly on a wide buffer and then use 1035117397Skan // __pad to do the padding. It would be good to replace them anyway 1036117397Skan // to gain back the efficiency that C++ provides by knowing up front 1037117397Skan // the type of the values to insert. Also, sprintf is dangerous 1038117397Skan // since may lead to accidental buffer overruns. This 1039117397Skan // implementation follows the C++ standard fairly directly as 104097403Sobrien // outlined in 22.2.2.2 [lib.locale.num.put] 104197403Sobrien template<typename _CharT, typename _OutIter> 104297403Sobrien template<typename _ValueT> 104397403Sobrien _OutIter 104497403Sobrien num_put<_CharT, _OutIter>:: 1045132720Skan _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 104697403Sobrien _ValueT __v) const 104797403Sobrien { 1048132720Skan typedef typename numpunct<_CharT>::__cache_type __cache_type; 1049132720Skan __use_cache<__cache_type> __uc; 1050132720Skan const locale& __loc = __io._M_getloc(); 1051132720Skan const __cache_type* __lc = __uc(__loc); 1052117397Skan 1053117397Skan // Use default precision if out of range. 105497403Sobrien streamsize __prec = __io.precision(); 1055132720Skan if (__prec < static_cast<streamsize>(0)) 1056117397Skan __prec = static_cast<streamsize>(6); 105797403Sobrien 1058132720Skan const int __max_digits = numeric_limits<_ValueT>::digits10; 1059117397Skan 1060117397Skan // [22.2.2.2.2] Stage 1, numeric conversion to character. 1061117397Skan int __len; 106297403Sobrien // Long enough for the max format spec. 106397403Sobrien char __fbuf[16]; 106497403Sobrien 1065132720Skan#ifdef _GLIBCXX_USE_C99 1066132720Skan // First try a buffer perhaps big enough (most probably sufficient 1067117397Skan // for non-ios_base::fixed outputs) 106897403Sobrien int __cs_size = __max_digits * 3; 106997403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 107097403Sobrien 1071132720Skan __num_base::_S_format_float(__io, __fbuf, __mod); 1072132720Skan __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v, 1073132720Skan _S_get_c_locale(), __prec); 107497403Sobrien 107597403Sobrien // If the buffer was not large enough, try again with the correct size. 107697403Sobrien if (__len >= __cs_size) 107797403Sobrien { 1078132720Skan __cs_size = __len + 1; 107997403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1080132720Skan __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v, 1081132720Skan _S_get_c_locale(), __prec); 108297403Sobrien } 108397403Sobrien#else 108497403Sobrien // Consider the possibility of long ios_base::fixed outputs 108597403Sobrien const bool __fixed = __io.flags() & ios_base::fixed; 108697403Sobrien const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 1087117397Skan 1088132720Skan // The size of the output string is computed as follows. 1089132720Skan // ios_base::fixed outputs may need up to __max_exp + 1 chars 1090132720Skan // for the integer part + __prec chars for the fractional part 1091132720Skan // + 3 chars for sign, decimal point, '\0'. On the other hand, 1092132720Skan // for non-fixed outputs __max_digits * 2 + __prec chars are 1093132720Skan // largely sufficient. 1094132720Skan const int __cs_size = __fixed ? __max_exp + __prec + 4 1095132720Skan : __max_digits * 2 + __prec; 109697403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 109797403Sobrien 1098132720Skan __num_base::_S_format_float(__io, __fbuf, __mod); 1099132720Skan __len = std::__convert_from_v(__cs, 0, __fbuf, __v, 1100132720Skan _S_get_c_locale(), __prec); 110197403Sobrien#endif 110297403Sobrien 110397403Sobrien // [22.2.2.2.2] Stage 2, convert to char_type, using correct 110497403Sobrien // numpunct.decimal_point() values for '.' and adding grouping. 110597403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1106117397Skan 1107132720Skan _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 110897403Sobrien * __len)); 110997403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 1110132720Skan 111197403Sobrien // Replace decimal point. 1112117397Skan const _CharT __cdec = __ctype.widen('.'); 1113132720Skan const _CharT __dec = __lc->_M_decimal_point; 111497403Sobrien const _CharT* __p; 1115117397Skan if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) 1116117397Skan __ws[__p - __ws] = __dec; 111797403Sobrien 1118132720Skan // Add grouping, if necessary. 1119132720Skan if (__lc->_M_use_grouping) 112097403Sobrien { 1121132720Skan // Grouping can add (almost) as many separators as the 1122132720Skan // number of digits, but no more. 1123132720Skan _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1124132720Skan * __len * 2)); 1125132720Skan _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, 1126132720Skan __lc->_M_thousands_sep, __p, __ws2, __ws, __len); 1127132720Skan __ws = __ws2; 112897403Sobrien } 112997403Sobrien 1130117397Skan // Pad. 1131132720Skan const streamsize __w = __io.width(); 113297403Sobrien if (__w > static_cast<streamsize>(__len)) 113397403Sobrien { 1134132720Skan _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1135132720Skan * __w)); 1136117397Skan _M_pad(__fill, __w, __io, __ws3, __ws, __len); 1137117397Skan __ws = __ws3; 113897403Sobrien } 113997403Sobrien __io.width(0); 1140132720Skan 114197403Sobrien // [22.2.2.2.2] Stage 4. 114297403Sobrien // Write resulting, fully-formatted string to output iterator. 1143132720Skan return std::__write(__s, __ws, __len); 1144117397Skan } 114597403Sobrien 114697403Sobrien template<typename _CharT, typename _OutIter> 114797403Sobrien _OutIter 114897403Sobrien num_put<_CharT, _OutIter>:: 114997403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 115097403Sobrien { 1151132720Skan const ios_base::fmtflags __flags = __io.flags(); 115297403Sobrien if ((__flags & ios_base::boolalpha) == 0) 115397403Sobrien { 115497403Sobrien unsigned long __uv = __v; 1155132720Skan __s = _M_insert_int(__s, __io, __fill, __uv); 115697403Sobrien } 115797403Sobrien else 115897403Sobrien { 1159132720Skan typedef typename numpunct<_CharT>::__cache_type __cache_type; 1160132720Skan __use_cache<__cache_type> __uc; 1161132720Skan const locale& __loc = __io._M_getloc(); 1162132720Skan const __cache_type* __lc = __uc(__loc); 1163117397Skan 1164132720Skan const _CharT* __name = __v ? __lc->_M_truename 1165132720Skan : __lc->_M_falsename; 1166132720Skan int __len = __v ? __lc->_M_truename_size 1167132720Skan : __lc->_M_falsename_size; 1168117397Skan 1169132720Skan const streamsize __w = __io.width(); 1170117397Skan if (__w > static_cast<streamsize>(__len)) 1171117397Skan { 1172132720Skan _CharT* __cs 1173132720Skan = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1174132720Skan * __w)); 1175132720Skan _M_pad(__fill, __w, __io, __cs, __name, __len); 1176132720Skan __name = __cs; 1177117397Skan } 1178117397Skan __io.width(0); 1179132720Skan __s = std::__write(__s, __name, __len); 118097403Sobrien } 118197403Sobrien return __s; 118297403Sobrien } 118397403Sobrien 118497403Sobrien template<typename _CharT, typename _OutIter> 118597403Sobrien _OutIter 118697403Sobrien num_put<_CharT, _OutIter>:: 118797403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 1188132720Skan { return _M_insert_int(__s, __io, __fill, __v); } 118997403Sobrien 119097403Sobrien template<typename _CharT, typename _OutIter> 119197403Sobrien _OutIter 119297403Sobrien num_put<_CharT, _OutIter>:: 119397403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 119497403Sobrien unsigned long __v) const 1195132720Skan { return _M_insert_int(__s, __io, __fill, __v); } 119697403Sobrien 1197132720Skan#ifdef _GLIBCXX_USE_LONG_LONG 119897403Sobrien template<typename _CharT, typename _OutIter> 119997403Sobrien _OutIter 120097403Sobrien num_put<_CharT, _OutIter>:: 120197403Sobrien do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 1202132720Skan { return _M_insert_int(__s, __b, __fill, __v); } 120397403Sobrien 120497403Sobrien template<typename _CharT, typename _OutIter> 120597403Sobrien _OutIter 120697403Sobrien num_put<_CharT, _OutIter>:: 120797403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 120897403Sobrien unsigned long long __v) const 1209132720Skan { return _M_insert_int(__s, __io, __fill, __v); } 121097403Sobrien#endif 121197403Sobrien 121297403Sobrien template<typename _CharT, typename _OutIter> 121397403Sobrien _OutIter 121497403Sobrien num_put<_CharT, _OutIter>:: 121597403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 1216132720Skan { return _M_insert_float(__s, __io, __fill, char(), __v); } 121797403Sobrien 121897403Sobrien template<typename _CharT, typename _OutIter> 121997403Sobrien _OutIter 122097403Sobrien num_put<_CharT, _OutIter>:: 1221132720Skan do_put(iter_type __s, ios_base& __io, char_type __fill, 122297403Sobrien long double __v) const 1223132720Skan { return _M_insert_float(__s, __io, __fill, 'L', __v); } 122497403Sobrien 122597403Sobrien template<typename _CharT, typename _OutIter> 122697403Sobrien _OutIter 122797403Sobrien num_put<_CharT, _OutIter>:: 122897403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 122997403Sobrien const void* __v) const 123097403Sobrien { 1231132720Skan const ios_base::fmtflags __flags = __io.flags(); 1232132720Skan const ios_base::fmtflags __fmt = ~(ios_base::showpos 1233132720Skan | ios_base::basefield 1234132720Skan | ios_base::uppercase 1235132720Skan | ios_base::internal); 123697403Sobrien __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 1237132720Skan 1238132720Skan __s = _M_insert_int(__s, __io, __fill, 1239132720Skan reinterpret_cast<unsigned long>(__v)); 1240132720Skan __io.flags(__flags); 124197403Sobrien return __s; 124297403Sobrien } 124397403Sobrien 124497403Sobrien template<typename _CharT, typename _InIter> 1245132720Skan template<bool _Intl> 1246132720Skan _InIter 1247132720Skan money_get<_CharT, _InIter>:: 1248132720Skan _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 1249132720Skan ios_base::iostate& __err, string& __units) const 1250132720Skan { 1251132720Skan typedef char_traits<_CharT> __traits_type; 1252132720Skan typedef typename string_type::size_type size_type; 1253132720Skan typedef money_base::part part; 1254132720Skan typedef moneypunct<_CharT, _Intl> __moneypunct_type; 1255132720Skan typedef typename __moneypunct_type::__cache_type __cache_type; 1256132720Skan 1257132720Skan const locale& __loc = __io._M_getloc(); 1258132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 125997403Sobrien 1260132720Skan __use_cache<__cache_type> __uc; 1261132720Skan const __cache_type* __lc = __uc(__loc); 1262132720Skan const char_type* __lit = __lc->_M_atoms; 126397403Sobrien 1264132720Skan // Deduced sign. 1265132720Skan bool __negative = false; 1266132720Skan // Sign size. 1267132720Skan size_type __sign_size = 0; 1268132720Skan // True if sign is mandatory. 1269132720Skan const bool __mandatory_sign = (__lc->_M_positive_sign_size 1270132720Skan && __lc->_M_negative_sign_size); 1271132720Skan // String of grouping info from thousands_sep plucked from __units. 1272132720Skan string __grouping_tmp; 1273132720Skan if (__lc->_M_use_grouping) 1274132720Skan __grouping_tmp.reserve(32); 1275132720Skan // Last position before the decimal point. 1276132720Skan int __last_pos = 0; 1277132720Skan // Separator positions, then, possibly, fractional digits. 1278132720Skan int __n = 0; 1279132720Skan // If input iterator is in a valid state. 1280132720Skan bool __testvalid = true; 1281132720Skan // Flag marking when a decimal point is found. 1282132720Skan bool __testdecfound = false; 128397403Sobrien 1284132720Skan // The tentative returned string is stored here. 1285132720Skan string __res; 1286132720Skan __res.reserve(32); 128797403Sobrien 1288132720Skan const char_type* __lit_zero = __lit + money_base::_S_zero; 1289132720Skan const char_type* __q; 1290132720Skan const money_base::pattern __p = __lc->_M_neg_format; 1291132720Skan for (int __i = 0; __i < 4 && __testvalid; ++__i) 1292132720Skan { 1293132720Skan const part __which = static_cast<part>(__p.field[__i]); 1294132720Skan switch (__which) 1295132720Skan { 1296132720Skan case money_base::symbol: 1297132720Skan // According to 22.2.6.1.2, p2, symbol is required 1298132720Skan // if (__io.flags() & ios_base::showbase), otherwise 1299132720Skan // is optional and consumed only if other characters 1300132720Skan // are needed to complete the format. 1301132720Skan if (__io.flags() & ios_base::showbase || __sign_size > 1 1302132720Skan || __i == 0 1303132720Skan || (__i == 1 && (__mandatory_sign 1304132720Skan || (static_cast<part>(__p.field[0]) 1305132720Skan == money_base::sign) 1306132720Skan || (static_cast<part>(__p.field[2]) 1307132720Skan == money_base::space))) 1308132720Skan || (__i == 2 && ((static_cast<part>(__p.field[3]) 1309132720Skan == money_base::value) 1310132720Skan || __mandatory_sign 1311132720Skan && (static_cast<part>(__p.field[3]) 1312132720Skan == money_base::sign)))) 131397403Sobrien { 1314132720Skan const size_type __len = __lc->_M_curr_symbol_size; 1315132720Skan size_type __j = 0; 1316132720Skan for (; __beg != __end && __j < __len 1317132720Skan && *__beg == __lc->_M_curr_symbol[__j]; 1318132720Skan ++__beg, ++__j); 1319132720Skan if (__j != __len 1320132720Skan && (__j || __io.flags() & ios_base::showbase)) 132197403Sobrien __testvalid = false; 132297403Sobrien } 1323132720Skan break; 1324132720Skan case money_base::sign: 1325132720Skan // Sign might not exist, or be more than one character long. 1326132720Skan if (__lc->_M_positive_sign_size && __beg != __end 1327132720Skan && *__beg == __lc->_M_positive_sign[0]) 1328132720Skan { 1329132720Skan __sign_size = __lc->_M_positive_sign_size; 1330132720Skan ++__beg; 1331132720Skan } 1332132720Skan else if (__lc->_M_negative_sign_size && __beg != __end 1333132720Skan && *__beg == __lc->_M_negative_sign[0]) 1334132720Skan { 1335132720Skan __negative = true; 1336132720Skan __sign_size = __lc->_M_negative_sign_size; 1337132720Skan ++__beg; 1338132720Skan } 1339132720Skan else if (__lc->_M_positive_sign_size 1340132720Skan && !__lc->_M_negative_sign_size) 1341132720Skan // "... if no sign is detected, the result is given the sign 1342132720Skan // that corresponds to the source of the empty string" 1343132720Skan __negative = true; 1344132720Skan else if (__mandatory_sign) 1345132720Skan __testvalid = false; 1346132720Skan break; 1347132720Skan case money_base::value: 1348132720Skan // Extract digits, remove and stash away the 1349132720Skan // grouping of found thousands separators. 1350132720Skan for (; __beg != __end; ++__beg) 1351132720Skan if (__q = __traits_type::find(__lit_zero, 10, *__beg)) 135297403Sobrien { 1353132720Skan __res += money_base::_S_atoms[__q - __lit]; 1354132720Skan ++__n; 135597403Sobrien } 1356132720Skan else if (*__beg == __lc->_M_decimal_point && !__testdecfound) 135797403Sobrien { 1358132720Skan __last_pos = __n; 1359132720Skan __n = 0; 1360132720Skan __testdecfound = true; 136197403Sobrien } 1362132720Skan else if (__lc->_M_use_grouping 1363132720Skan && *__beg == __lc->_M_thousands_sep 1364132720Skan && !__testdecfound) 136597403Sobrien { 1366132720Skan if (__n) 136797403Sobrien { 1368132720Skan // Mark position for later analysis. 1369132720Skan __grouping_tmp += static_cast<char>(__n); 1370132720Skan __n = 0; 137197403Sobrien } 137297403Sobrien else 137397403Sobrien { 1374132720Skan __testvalid = false; 1375132720Skan break; 137697403Sobrien } 137797403Sobrien } 1378132720Skan else 1379132720Skan break; 1380132720Skan if (__res.empty()) 1381132720Skan __testvalid = false; 1382132720Skan break; 1383132720Skan case money_base::space: 1384132720Skan // At least one space is required. 1385132720Skan if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) 1386132720Skan ++__beg; 1387132720Skan else 1388132720Skan __testvalid = false; 1389132720Skan case money_base::none: 1390132720Skan // Only if not at the end of the pattern. 1391132720Skan if (__i != 3) 1392132720Skan for (; __beg != __end 1393132720Skan && __ctype.is(ctype_base::space, *__beg); ++__beg); 1394132720Skan break; 1395132720Skan } 1396132720Skan } 139797403Sobrien 1398132720Skan // Need to get the rest of the sign characters, if they exist. 1399132720Skan if (__sign_size > 1 && __testvalid) 1400132720Skan { 1401132720Skan const char_type* __sign = __negative ? __lc->_M_negative_sign 1402132720Skan : __lc->_M_positive_sign; 1403132720Skan size_type __i = 1; 1404132720Skan for (; __beg != __end && __i < __sign_size 1405132720Skan && *__beg == __sign[__i]; ++__beg, ++__i); 1406132720Skan 1407132720Skan if (__i != __sign_size) 1408132720Skan __testvalid = false; 1409132720Skan } 141097403Sobrien 1411132720Skan if (__testvalid) 1412132720Skan { 1413132720Skan // Strip leading zeros. 1414132720Skan if (__res.size() > 1) 1415132720Skan { 1416132720Skan const size_type __first = __res.find_first_not_of('0'); 1417132720Skan const bool __only_zeros = __first == string::npos; 1418132720Skan if (__first) 1419132720Skan __res.erase(0, __only_zeros ? __res.size() - 1 : __first); 1420132720Skan } 142197403Sobrien 1422132720Skan // 22.2.6.1.2, p4 1423132720Skan if (__negative && __res[0] != '0') 1424132720Skan __res.insert(__res.begin(), '-'); 1425132720Skan 1426132720Skan // Test for grouping fidelity. 1427132720Skan if (__grouping_tmp.size()) 1428132720Skan { 1429132720Skan // Add the ending grouping. 1430132720Skan __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos 1431132720Skan : __n); 1432132720Skan if (!std::__verify_grouping(__lc->_M_grouping, 1433132720Skan __lc->_M_grouping_size, 1434132720Skan __grouping_tmp)) 1435132720Skan __testvalid = false; 1436132720Skan } 1437132720Skan 1438132720Skan // Iff not enough digits were supplied after the decimal-point. 1439132720Skan if (__testdecfound && __lc->_M_frac_digits > 0 1440132720Skan && __n != __lc->_M_frac_digits) 1441132720Skan __testvalid = false; 1442132720Skan } 1443132720Skan 1444132720Skan // Iff no more characters are available. 1445132720Skan if (__beg == __end) 1446132720Skan __err |= ios_base::eofbit; 1447132720Skan 1448132720Skan // Iff valid sequence is not recognized. 1449132720Skan if (!__testvalid) 1450132720Skan __err |= ios_base::failbit; 1451132720Skan else 1452132720Skan __units.swap(__res); 1453132720Skan 1454132720Skan return __beg; 1455132720Skan } 145697403Sobrien 1457132720Skan template<typename _CharT, typename _InIter> 1458132720Skan _InIter 1459132720Skan money_get<_CharT, _InIter>:: 1460132720Skan do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1461132720Skan ios_base::iostate& __err, long double& __units) const 1462132720Skan { 1463132720Skan string __str; 1464132720Skan if (__intl) 1465132720Skan __beg = _M_extract<true>(__beg, __end, __io, __err, __str); 1466132720Skan else 1467132720Skan __beg = _M_extract<false>(__beg, __end, __io, __err, __str); 1468132720Skan std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 1469132720Skan return __beg; 1470132720Skan } 1471132720Skan 1472132720Skan template<typename _CharT, typename _InIter> 1473132720Skan _InIter 1474132720Skan money_get<_CharT, _InIter>:: 1475132720Skan do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1476132720Skan ios_base::iostate& __err, string_type& __units) const 1477132720Skan { 1478132720Skan typedef typename string::size_type size_type; 1479132720Skan 1480132720Skan const locale& __loc = __io._M_getloc(); 1481132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1482132720Skan 1483132720Skan string __str; 1484132720Skan const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io, 1485132720Skan __err, __str) 1486132720Skan : _M_extract<false>(__beg, __end, __io, 1487132720Skan __err, __str); 1488132720Skan const size_type __len = __str.size(); 1489132720Skan if (__len) 149097403Sobrien { 1491132720Skan _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1492132720Skan * __len)); 1493132720Skan __ctype.widen(__str.data(), __str.data() + __len, __ws); 1494132720Skan __units.assign(__ws, __len); 149597403Sobrien } 149697403Sobrien 1497132720Skan return __ret; 1498132720Skan } 149997403Sobrien 1500132720Skan template<typename _CharT, typename _OutIter> 1501132720Skan template<bool _Intl> 1502132720Skan _OutIter 1503132720Skan money_put<_CharT, _OutIter>:: 1504132720Skan _M_insert(iter_type __s, ios_base& __io, char_type __fill, 1505132720Skan const string_type& __digits) const 1506132720Skan { 1507132720Skan typedef typename string_type::size_type size_type; 1508132720Skan typedef money_base::part part; 1509132720Skan typedef moneypunct<_CharT, _Intl> __moneypunct_type; 1510132720Skan typedef typename __moneypunct_type::__cache_type __cache_type; 1511132720Skan 1512132720Skan const locale& __loc = __io._M_getloc(); 1513132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 151497403Sobrien 1515132720Skan __use_cache<__cache_type> __uc; 1516132720Skan const __cache_type* __lc = __uc(__loc); 1517132720Skan const char_type* __lit = __lc->_M_atoms; 151897403Sobrien 1519132720Skan // Determine if negative or positive formats are to be used, and 1520132720Skan // discard leading negative_sign if it is present. 1521132720Skan const char_type* __beg = __digits.data(); 1522132720Skan 1523132720Skan money_base::pattern __p; 1524132720Skan const char_type* __sign; 1525132720Skan size_type __sign_size; 1526132720Skan if (*__beg != __lit[money_base::_S_minus]) 1527132720Skan { 1528132720Skan __p = __lc->_M_pos_format; 1529132720Skan __sign = __lc->_M_positive_sign; 1530132720Skan __sign_size = __lc->_M_positive_sign_size; 1531132720Skan } 1532132720Skan else 1533132720Skan { 1534132720Skan __p = __lc->_M_neg_format; 1535132720Skan __sign = __lc->_M_negative_sign; 1536132720Skan __sign_size = __lc->_M_negative_sign_size; 1537132720Skan if (__digits.size()) 1538132720Skan ++__beg; 1539132720Skan } 1540132720Skan 1541132720Skan // Look for valid numbers in the ctype facet within input digits. 1542132720Skan size_type __len = __ctype.scan_not(ctype_base::digit, __beg, 1543132720Skan __beg + __digits.size()) - __beg; 1544132720Skan if (__len) 1545132720Skan { 1546132720Skan // Assume valid input, and attempt to format. 1547132720Skan // Break down input numbers into base components, as follows: 1548132720Skan // final_value = grouped units + (decimal point) + (digits) 1549132720Skan string_type __value; 1550132720Skan __value.reserve(2 * __len); 1551132720Skan 1552132720Skan // Add thousands separators to non-decimal digits, per 1553132720Skan // grouping rules. 1554132720Skan int __paddec = __len - __lc->_M_frac_digits; 1555132720Skan if (__paddec > 0) 1556132720Skan { 1557132720Skan if (__lc->_M_frac_digits < 0) 1558132720Skan __paddec = __len; 1559132720Skan if (__lc->_M_grouping_size) 1560132720Skan { 1561132720Skan _CharT* __ws = 1562132720Skan static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1563132720Skan * 2 * __len)); 1564132720Skan _CharT* __ws_end = 1565132720Skan std::__add_grouping(__ws, __lc->_M_thousands_sep, 1566132720Skan __lc->_M_grouping, 1567132720Skan __lc->_M_grouping_size, 1568132720Skan __beg, __beg + __paddec); 1569132720Skan __value.assign(__ws, __ws_end - __ws); 1570132720Skan } 1571132720Skan else 1572132720Skan __value.assign(__beg, __paddec); 1573132720Skan } 1574132720Skan 1575132720Skan // Deal with decimal point, decimal digits. 1576132720Skan if (__lc->_M_frac_digits > 0) 1577132720Skan { 1578132720Skan __value += __lc->_M_decimal_point; 1579132720Skan if (__paddec >= 0) 1580132720Skan __value.append(__beg + __paddec, __lc->_M_frac_digits); 1581132720Skan else 1582132720Skan { 1583132720Skan // Have to pad zeros in the decimal position. 1584132720Skan __value.append(-__paddec, __lit[money_base::_S_zero]); 1585132720Skan __value.append(__beg, __len); 1586132720Skan } 1587132720Skan } 1588132720Skan 1589132720Skan // Calculate length of resulting string. 1590132720Skan const ios_base::fmtflags __f = __io.flags() 1591132720Skan & ios_base::adjustfield; 1592132720Skan __len = __value.size() + __sign_size; 1593132720Skan __len += ((__io.flags() & ios_base::showbase) 1594132720Skan ? __lc->_M_curr_symbol_size : 0); 1595132720Skan 1596132720Skan string_type __res; 1597132720Skan __res.reserve(2 * __len); 1598132720Skan 1599132720Skan const size_type __width = static_cast<size_type>(__io.width()); 1600132720Skan const bool __testipad = (__f == ios_base::internal 1601132720Skan && __len < __width); 1602132720Skan // Fit formatted digits into the required pattern. 1603132720Skan for (int __i = 0; __i < 4; ++__i) 1604132720Skan { 1605132720Skan const part __which = static_cast<part>(__p.field[__i]); 1606132720Skan switch (__which) 1607132720Skan { 1608132720Skan case money_base::symbol: 1609132720Skan if (__io.flags() & ios_base::showbase) 1610132720Skan __res.append(__lc->_M_curr_symbol, 1611132720Skan __lc->_M_curr_symbol_size); 1612132720Skan break; 1613132720Skan case money_base::sign: 1614132720Skan // Sign might not exist, or be more than one 1615132720Skan // charater long. In that case, add in the rest 1616132720Skan // below. 1617132720Skan if (__sign_size) 1618132720Skan __res += __sign[0]; 1619132720Skan break; 1620132720Skan case money_base::value: 1621132720Skan __res += __value; 1622132720Skan break; 1623132720Skan case money_base::space: 1624132720Skan // At least one space is required, but if internal 1625132720Skan // formatting is required, an arbitrary number of 1626132720Skan // fill spaces will be necessary. 1627132720Skan if (__testipad) 1628132720Skan __res.append(__width - __len, __fill); 1629132720Skan else 1630132720Skan __res += __fill; 1631132720Skan break; 1632132720Skan case money_base::none: 1633132720Skan if (__testipad) 1634132720Skan __res.append(__width - __len, __fill); 1635132720Skan break; 1636132720Skan } 1637132720Skan } 1638132720Skan 1639132720Skan // Special case of multi-part sign parts. 1640132720Skan if (__sign_size > 1) 1641132720Skan __res.append(__sign + 1, __sign_size - 1); 1642132720Skan 1643132720Skan // Pad, if still necessary. 1644132720Skan __len = __res.size(); 1645132720Skan if (__width > __len) 1646132720Skan { 1647132720Skan if (__f == ios_base::left) 1648132720Skan // After. 1649132720Skan __res.append(__width - __len, __fill); 1650132720Skan else 1651132720Skan // Before. 1652132720Skan __res.insert(0, __width - __len, __fill); 1653132720Skan __len = __width; 1654132720Skan } 1655132720Skan 1656132720Skan // Write resulting, fully-formatted string to output iterator. 1657132720Skan __s = std::__write(__s, __res.data(), __len); 1658132720Skan } 1659132720Skan __io.width(0); 1660132720Skan return __s; 1661132720Skan } 1662132720Skan 166397403Sobrien template<typename _CharT, typename _OutIter> 166497403Sobrien _OutIter 166597403Sobrien money_put<_CharT, _OutIter>:: 166697403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 166797403Sobrien long double __units) const 1668132720Skan { 166997403Sobrien const locale __loc = __io.getloc(); 167097403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1671132720Skan#ifdef _GLIBCXX_USE_C99 167297403Sobrien // First try a buffer perhaps big enough. 167397403Sobrien int __cs_size = 64; 167497403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1675132720Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 1676132720Skan // 328. Bad sprintf format modifier in money_put<>::do_put() 1677132720Skan int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units, 1678132720Skan _S_get_c_locale()); 167997403Sobrien // If the buffer was not large enough, try again with the correct size. 168097403Sobrien if (__len >= __cs_size) 168197403Sobrien { 168297403Sobrien __cs_size = __len + 1; 168397403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1684132720Skan __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units, 1685132720Skan _S_get_c_locale()); 168697403Sobrien } 168797403Sobrien#else 1688132720Skan // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 1689132720Skan const int __cs_size = numeric_limits<long double>::max_exponent10 + 3; 169097403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1691132720Skan int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units, 1692132720Skan _S_get_c_locale()); 169397403Sobrien#endif 1694132720Skan _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1695117397Skan * __cs_size)); 169697403Sobrien __ctype.widen(__cs, __cs + __len, __ws); 1697132720Skan const string_type __digits(__ws, __len); 1698132720Skan return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 1699132720Skan : _M_insert<false>(__s, __io, __fill, __digits); 170097403Sobrien } 170197403Sobrien 170297403Sobrien template<typename _CharT, typename _OutIter> 170397403Sobrien _OutIter 170497403Sobrien money_put<_CharT, _OutIter>:: 170597403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 170697403Sobrien const string_type& __digits) const 1707132720Skan { return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 1708132720Skan : _M_insert<false>(__s, __io, __fill, __digits); } 170997403Sobrien 171097403Sobrien 171197403Sobrien // NB: Not especially useful. Without an ios_base object or some 171297403Sobrien // kind of locale reference, we are left clawing at the air where 171397403Sobrien // the side of the mountain used to be... 171497403Sobrien template<typename _CharT, typename _InIter> 171597403Sobrien time_base::dateorder 171697403Sobrien time_get<_CharT, _InIter>::do_date_order() const 171797403Sobrien { return time_base::no_order; } 171897403Sobrien 1719132720Skan // Expand a strftime format string and parse it. E.g., do_get_date() may 1720132720Skan // pass %m/%d/%Y => extracted characters. 172197403Sobrien template<typename _CharT, typename _InIter> 1722132720Skan _InIter 172397403Sobrien time_get<_CharT, _InIter>:: 1724132720Skan _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 1725132720Skan ios_base::iostate& __err, tm* __tm, 172697403Sobrien const _CharT* __format) const 1727132720Skan { 1728132720Skan const locale& __loc = __io._M_getloc(); 1729132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1730132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1731132720Skan const size_t __len = char_traits<_CharT>::length(__format); 173297403Sobrien 173397403Sobrien for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 173497403Sobrien { 1735132720Skan if (__ctype.narrow(__format[__i], 0) == '%') 173697403Sobrien { 173797403Sobrien // Verify valid formatting code, attempt to extract. 1738132720Skan char __c = __ctype.narrow(__format[++__i], 0); 1739132720Skan int __mem = 0; 174097403Sobrien if (__c == 'E' || __c == 'O') 1741132720Skan __c = __ctype.narrow(__format[++__i], 0); 174297403Sobrien switch (__c) 174397403Sobrien { 174497403Sobrien const char* __cs; 174597403Sobrien _CharT __wcs[10]; 174697403Sobrien case 'a': 174797403Sobrien // Abbreviated weekday name [tm_wday] 174897403Sobrien const char_type* __days1[7]; 174997403Sobrien __tp._M_days_abbreviated(__days1); 1750132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 1751132720Skan 7, __io, __err); 175297403Sobrien break; 175397403Sobrien case 'A': 175497403Sobrien // Weekday name [tm_wday]. 175597403Sobrien const char_type* __days2[7]; 175697403Sobrien __tp._M_days(__days2); 1757132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 1758132720Skan 7, __io, __err); 175997403Sobrien break; 176097403Sobrien case 'h': 176197403Sobrien case 'b': 176297403Sobrien // Abbreviated month name [tm_mon] 176397403Sobrien const char_type* __months1[12]; 176497403Sobrien __tp._M_months_abbreviated(__months1); 1765132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 1766132720Skan __months1, 12, __io, __err); 176797403Sobrien break; 176897403Sobrien case 'B': 176997403Sobrien // Month name [tm_mon]. 177097403Sobrien const char_type* __months2[12]; 177197403Sobrien __tp._M_months(__months2); 1772132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 1773132720Skan __months2, 12, __io, __err); 177497403Sobrien break; 177597403Sobrien case 'c': 177697403Sobrien // Default time and date representation. 177797403Sobrien const char_type* __dt[2]; 177897403Sobrien __tp._M_date_time_formats(__dt); 1779132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 1780132720Skan __tm, __dt[0]); 178197403Sobrien break; 178297403Sobrien case 'd': 178397403Sobrien // Day [01, 31]. [tm_mday] 1784132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 1785132720Skan __io, __err); 178697403Sobrien break; 1787132720Skan case 'e': 1788132720Skan // Day [1, 31], with single digits preceded by 1789132720Skan // space. [tm_mday] 1790132720Skan if (__ctype.is(ctype_base::space, *__beg)) 1791132720Skan __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, 1792132720Skan 1, __io, __err); 1793132720Skan else 1794132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, 1795132720Skan 2, __io, __err); 1796132720Skan break; 179797403Sobrien case 'D': 179897403Sobrien // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 179997403Sobrien __cs = "%m/%d/%y"; 180097403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 1801132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 1802132720Skan __tm, __wcs); 180397403Sobrien break; 180497403Sobrien case 'H': 180597403Sobrien // Hour [00, 23]. [tm_hour] 1806132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 1807132720Skan __io, __err); 180897403Sobrien break; 180997403Sobrien case 'I': 181097403Sobrien // Hour [01, 12]. [tm_hour] 1811132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 1812132720Skan __io, __err); 181397403Sobrien break; 181497403Sobrien case 'm': 181597403Sobrien // Month [01, 12]. [tm_mon] 1816132720Skan __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 1817132720Skan __io, __err); 181897403Sobrien if (!__err) 181997403Sobrien __tm->tm_mon = __mem - 1; 182097403Sobrien break; 182197403Sobrien case 'M': 182297403Sobrien // Minute [00, 59]. [tm_min] 1823132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 1824132720Skan __io, __err); 182597403Sobrien break; 182697403Sobrien case 'n': 182797403Sobrien if (__ctype.narrow(*__beg, 0) == '\n') 182897403Sobrien ++__beg; 182997403Sobrien else 183097403Sobrien __err |= ios_base::failbit; 183197403Sobrien break; 183297403Sobrien case 'R': 183397403Sobrien // Equivalent to (%H:%M). 183497403Sobrien __cs = "%H:%M"; 183597403Sobrien __ctype.widen(__cs, __cs + 6, __wcs); 1836132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 1837132720Skan __tm, __wcs); 183897403Sobrien break; 183997403Sobrien case 'S': 184097403Sobrien // Seconds. 1841132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 1842132720Skan __io, __err); 184397403Sobrien break; 184497403Sobrien case 't': 184597403Sobrien if (__ctype.narrow(*__beg, 0) == '\t') 184697403Sobrien ++__beg; 184797403Sobrien else 1848132720Skan __err |= ios_base::failbit; 184997403Sobrien break; 185097403Sobrien case 'T': 185197403Sobrien // Equivalent to (%H:%M:%S). 185297403Sobrien __cs = "%H:%M:%S"; 185397403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 1854132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 1855132720Skan __tm, __wcs); 185697403Sobrien break; 185797403Sobrien case 'x': 185897403Sobrien // Locale's date. 185997403Sobrien const char_type* __dates[2]; 186097403Sobrien __tp._M_date_formats(__dates); 1861132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 1862132720Skan __tm, __dates[0]); 186397403Sobrien break; 186497403Sobrien case 'X': 186597403Sobrien // Locale's time. 186697403Sobrien const char_type* __times[2]; 186797403Sobrien __tp._M_time_formats(__times); 1868132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 1869132720Skan __tm, __times[0]); 187097403Sobrien break; 187197403Sobrien case 'y': 1872132720Skan case 'C': // C99 187397403Sobrien // Two digit year. [tm_year] 1874132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 1875132720Skan __io, __err); 187697403Sobrien break; 187797403Sobrien case 'Y': 187897403Sobrien // Year [1900). [tm_year] 1879132720Skan __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 1880132720Skan __io, __err); 188197403Sobrien if (!__err) 188297403Sobrien __tm->tm_year = __mem - 1900; 188397403Sobrien break; 188497403Sobrien case 'Z': 188597403Sobrien // Timezone info. 188697403Sobrien if (__ctype.is(ctype_base::upper, *__beg)) 188797403Sobrien { 188897403Sobrien int __tmp; 1889132720Skan __beg = _M_extract_name(__beg, __end, __tmp, 1890132720Skan __timepunct_cache<_CharT>::_S_timezones, 1891132720Skan 14, __io, __err); 1892132720Skan 189397403Sobrien // GMT requires special effort. 1894132720Skan if (__beg != __end && !__err && __tmp == 0 1895132720Skan && (*__beg == __ctype.widen('-') 1896132720Skan || *__beg == __ctype.widen('+'))) 189797403Sobrien { 1898132720Skan __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 1899132720Skan __io, __err); 1900132720Skan __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 1901132720Skan __io, __err); 1902132720Skan } 190397403Sobrien } 190497403Sobrien else 190597403Sobrien __err |= ios_base::failbit; 1906132720Skan break; 1907132720Skan default: 1908132720Skan // Not recognized. 1909132720Skan __err |= ios_base::failbit; 191097403Sobrien } 1911132720Skan } 1912132720Skan else 1913132720Skan { 1914132720Skan // Verify format and input match, extract and discard. 1915132720Skan if (__format[__i] == *__beg) 1916132720Skan ++__beg; 1917132720Skan else 1918132720Skan __err |= ios_base::failbit; 1919132720Skan } 192097403Sobrien } 1921132720Skan return __beg; 192297403Sobrien } 192397403Sobrien 192497403Sobrien template<typename _CharT, typename _InIter> 1925132720Skan _InIter 192697403Sobrien time_get<_CharT, _InIter>:: 1927132720Skan _M_extract_num(iter_type __beg, iter_type __end, int& __member, 1928132720Skan int __min, int __max, size_t __len, 1929132720Skan ios_base& __io, ios_base::iostate& __err) const 193097403Sobrien { 1931132720Skan const locale& __loc = __io._M_getloc(); 1932132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1933132720Skan 1934132720Skan // As-is works for __len = 1, 2, 4, the values actually used. 1935132720Skan int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); 1936132720Skan 1937132720Skan ++__min; 193897403Sobrien size_t __i = 0; 1939132720Skan int __value = 0; 1940132720Skan for (; __beg != __end && __i < __len; ++__beg, ++__i) 194197403Sobrien { 1942132720Skan const char __c = __ctype.narrow(*__beg, '*'); 1943132720Skan if (__c >= '0' && __c <= '9') 1944132720Skan { 1945132720Skan __value = __value * 10 + (__c - '0'); 1946132720Skan const int __valuec = __value * __mult; 1947132720Skan if (__valuec > __max || __valuec + __mult < __min) 1948132720Skan break; 1949132720Skan __mult /= 10; 1950132720Skan } 1951132720Skan else 1952132720Skan break; 195397403Sobrien } 195497403Sobrien if (__i == __len) 1955132720Skan __member = __value; 195697403Sobrien else 195797403Sobrien __err |= ios_base::failbit; 1958132720Skan return __beg; 195997403Sobrien } 196097403Sobrien 196197403Sobrien // Assumptions: 196297403Sobrien // All elements in __names are unique. 196397403Sobrien template<typename _CharT, typename _InIter> 1964132720Skan _InIter 196597403Sobrien time_get<_CharT, _InIter>:: 1966132720Skan _M_extract_name(iter_type __beg, iter_type __end, int& __member, 1967132720Skan const _CharT** __names, size_t __indexlen, 1968132720Skan ios_base& __io, ios_base::iostate& __err) const 196997403Sobrien { 1970132720Skan typedef char_traits<_CharT> __traits_type; 1971132720Skan const locale& __loc = __io._M_getloc(); 1972132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1973132720Skan 1974132720Skan int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 1975117397Skan * __indexlen)); 197697403Sobrien size_t __nmatches = 0; 197797403Sobrien size_t __pos = 0; 197897403Sobrien bool __testvalid = true; 197997403Sobrien const char_type* __name; 198097403Sobrien 198197403Sobrien // Look for initial matches. 1982132720Skan // NB: Some of the locale data is in the form of all lowercase 1983132720Skan // names, and some is in the form of initially-capitalized 1984132720Skan // names. Look for both. 1985132720Skan if (__beg != __end) 1986132720Skan { 1987132720Skan const char_type __c = *__beg; 1988132720Skan for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 1989132720Skan if (__c == __names[__i1][0] 1990132720Skan || __c == __ctype.toupper(__names[__i1][0])) 1991132720Skan __matches[__nmatches++] = __i1; 1992132720Skan } 1993132720Skan 1994117397Skan while (__nmatches > 1) 199597403Sobrien { 199697403Sobrien // Find smallest matching string. 1997132720Skan size_t __minlen = __traits_type::length(__names[__matches[0]]); 1998132720Skan for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) 1999132720Skan __minlen = std::min(__minlen, 2000132720Skan __traits_type::length(__names[__matches[__i2]])); 2001132720Skan ++__pos; 2002132720Skan ++__beg; 200397403Sobrien if (__pos < __minlen && __beg != __end) 2004132720Skan for (size_t __i3 = 0; __i3 < __nmatches;) 2005132720Skan { 2006132720Skan __name = __names[__matches[__i3]]; 2007132720Skan if (__name[__pos] != *__beg) 2008132720Skan __matches[__i3] = __matches[--__nmatches]; 2009132720Skan else 2010132720Skan ++__i3; 2011132720Skan } 201297403Sobrien else 201397403Sobrien break; 201497403Sobrien } 201597403Sobrien 201697403Sobrien if (__nmatches == 1) 201797403Sobrien { 201897403Sobrien // Make sure found name is completely extracted. 2019132720Skan ++__pos; 2020132720Skan ++__beg; 202197403Sobrien __name = __names[__matches[0]]; 202297403Sobrien const size_t __len = __traits_type::length(__name); 202397403Sobrien while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 202497403Sobrien ++__beg, ++__pos; 202597403Sobrien 202697403Sobrien if (__len == __pos) 202797403Sobrien __member = __matches[0]; 202897403Sobrien else 202997403Sobrien __testvalid = false; 203097403Sobrien } 203197403Sobrien else 203297403Sobrien __testvalid = false; 203397403Sobrien if (!__testvalid) 203497403Sobrien __err |= ios_base::failbit; 2035132720Skan return __beg; 203697403Sobrien } 203797403Sobrien 203897403Sobrien template<typename _CharT, typename _InIter> 203997403Sobrien _InIter 204097403Sobrien time_get<_CharT, _InIter>:: 204197403Sobrien do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 204297403Sobrien ios_base::iostate& __err, tm* __tm) const 204397403Sobrien { 2044132720Skan const locale& __loc = __io._M_getloc(); 2045132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2046132720Skan const char_type* __times[2]; 2047132720Skan __tp._M_time_formats(__times); 2048132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 2049132720Skan __tm, __times[0]); 205097403Sobrien if (__beg == __end) 205197403Sobrien __err |= ios_base::eofbit; 205297403Sobrien return __beg; 205397403Sobrien } 205497403Sobrien 205597403Sobrien template<typename _CharT, typename _InIter> 205697403Sobrien _InIter 205797403Sobrien time_get<_CharT, _InIter>:: 205897403Sobrien do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 205997403Sobrien ios_base::iostate& __err, tm* __tm) const 206097403Sobrien { 2061132720Skan const locale& __loc = __io._M_getloc(); 2062132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2063132720Skan const char_type* __dates[2]; 2064132720Skan __tp._M_date_formats(__dates); 2065132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 2066132720Skan __tm, __dates[0]); 206797403Sobrien if (__beg == __end) 206897403Sobrien __err |= ios_base::eofbit; 206997403Sobrien return __beg; 207097403Sobrien } 207197403Sobrien 207297403Sobrien template<typename _CharT, typename _InIter> 207397403Sobrien _InIter 207497403Sobrien time_get<_CharT, _InIter>:: 2075132720Skan do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 207697403Sobrien ios_base::iostate& __err, tm* __tm) const 207797403Sobrien { 2078132720Skan typedef char_traits<_CharT> __traits_type; 2079132720Skan const locale& __loc = __io._M_getloc(); 2080132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2081132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 208297403Sobrien const char_type* __days[7]; 208397403Sobrien __tp._M_days_abbreviated(__days); 208497403Sobrien int __tmpwday; 2085132720Skan __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err); 208697403Sobrien 208797403Sobrien // Check to see if non-abbreviated name exists, and extract. 208897403Sobrien // NB: Assumes both _M_days and _M_days_abbreviated organized in 208997403Sobrien // exact same order, first to last, such that the resulting 209097403Sobrien // __days array with the same index points to a day, and that 209197403Sobrien // day's abbreviated form. 2092132720Skan // NB: Also assumes that an abbreviated name is a subset of the name. 209397403Sobrien if (!__err) 209497403Sobrien { 209597403Sobrien size_t __pos = __traits_type::length(__days[__tmpwday]); 209697403Sobrien __tp._M_days(__days); 209797403Sobrien const char_type* __name = __days[__tmpwday]; 209897403Sobrien if (__name[__pos] == *__beg) 209997403Sobrien { 210097403Sobrien // Extract the rest of it. 210197403Sobrien const size_t __len = __traits_type::length(__name); 2102132720Skan while (__pos < __len && __beg != __end 210397403Sobrien && __name[__pos] == *__beg) 210497403Sobrien ++__beg, ++__pos; 210597403Sobrien if (__len != __pos) 210697403Sobrien __err |= ios_base::failbit; 210797403Sobrien } 210897403Sobrien if (!__err) 210997403Sobrien __tm->tm_wday = __tmpwday; 211097403Sobrien } 211197403Sobrien if (__beg == __end) 211297403Sobrien __err |= ios_base::eofbit; 211397403Sobrien return __beg; 211497403Sobrien } 211597403Sobrien 211697403Sobrien template<typename _CharT, typename _InIter> 211797403Sobrien _InIter 211897403Sobrien time_get<_CharT, _InIter>:: 211997403Sobrien do_get_monthname(iter_type __beg, iter_type __end, 212097403Sobrien ios_base& __io, ios_base::iostate& __err, tm* __tm) const 212197403Sobrien { 2122132720Skan typedef char_traits<_CharT> __traits_type; 2123132720Skan const locale& __loc = __io._M_getloc(); 2124132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2125132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 212697403Sobrien const char_type* __months[12]; 212797403Sobrien __tp._M_months_abbreviated(__months); 212897403Sobrien int __tmpmon; 2129132720Skan __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 2130132720Skan __io, __err); 213197403Sobrien 213297403Sobrien // Check to see if non-abbreviated name exists, and extract. 213397403Sobrien // NB: Assumes both _M_months and _M_months_abbreviated organized in 213497403Sobrien // exact same order, first to last, such that the resulting 213597403Sobrien // __months array with the same index points to a month, and that 213697403Sobrien // month's abbreviated form. 2137132720Skan // NB: Also assumes that an abbreviated name is a subset of the name. 213897403Sobrien if (!__err) 213997403Sobrien { 214097403Sobrien size_t __pos = __traits_type::length(__months[__tmpmon]); 214197403Sobrien __tp._M_months(__months); 214297403Sobrien const char_type* __name = __months[__tmpmon]; 214397403Sobrien if (__name[__pos] == *__beg) 214497403Sobrien { 214597403Sobrien // Extract the rest of it. 214697403Sobrien const size_t __len = __traits_type::length(__name); 2147132720Skan while (__pos < __len && __beg != __end 214897403Sobrien && __name[__pos] == *__beg) 214997403Sobrien ++__beg, ++__pos; 215097403Sobrien if (__len != __pos) 215197403Sobrien __err |= ios_base::failbit; 215297403Sobrien } 215397403Sobrien if (!__err) 215497403Sobrien __tm->tm_mon = __tmpmon; 215597403Sobrien } 2156132720Skan 215797403Sobrien if (__beg == __end) 215897403Sobrien __err |= ios_base::eofbit; 215997403Sobrien return __beg; 216097403Sobrien } 216197403Sobrien 216297403Sobrien template<typename _CharT, typename _InIter> 216397403Sobrien _InIter 216497403Sobrien time_get<_CharT, _InIter>:: 2165132720Skan do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 216697403Sobrien ios_base::iostate& __err, tm* __tm) const 216797403Sobrien { 2168132720Skan const locale& __loc = __io._M_getloc(); 2169132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 217097403Sobrien 217197403Sobrien size_t __i = 0; 2172132720Skan int __value = 0; 2173132720Skan for (; __beg != __end && __i < 4; ++__beg, ++__i) 217497403Sobrien { 2175132720Skan const char __c = __ctype.narrow(*__beg, '*'); 2176132720Skan if (__c >= '0' && __c <= '9') 2177132720Skan __value = __value * 10 + (__c - '0'); 2178132720Skan else 2179132720Skan break; 218097403Sobrien } 218197403Sobrien if (__i == 2 || __i == 4) 2182132720Skan __tm->tm_year = __i == 2 ? __value : __value - 1900; 218397403Sobrien else 218497403Sobrien __err |= ios_base::failbit; 218597403Sobrien if (__beg == __end) 218697403Sobrien __err |= ios_base::eofbit; 218797403Sobrien return __beg; 218897403Sobrien } 218997403Sobrien 219097403Sobrien template<typename _CharT, typename _OutIter> 219197403Sobrien _OutIter 219297403Sobrien time_put<_CharT, _OutIter>:: 2193132720Skan put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 219497403Sobrien const _CharT* __beg, const _CharT* __end) const 219597403Sobrien { 2196132720Skan const locale& __loc = __io._M_getloc(); 219797403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 2198132720Skan for (; __beg != __end; ++__beg) 2199132720Skan if (__ctype.narrow(*__beg, 0) != '%') 2200132720Skan { 2201132720Skan *__s = *__beg; 2202132720Skan ++__s; 2203132720Skan } 2204132720Skan else if (++__beg != __end) 2205132720Skan { 2206132720Skan char __format; 2207132720Skan char __mod = 0; 2208132720Skan const char __c = __ctype.narrow(*__beg, 0); 2209132720Skan if (__c != 'E' && __c != 'O') 2210132720Skan __format = __c; 2211132720Skan else if (++__beg != __end) 2212132720Skan { 2213132720Skan __mod = __c; 2214132720Skan __format = __ctype.narrow(*__beg, 0); 2215132720Skan } 2216132720Skan else 2217132720Skan break; 2218132720Skan __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); 2219132720Skan } 2220132720Skan else 2221132720Skan break; 222297403Sobrien return __s; 222397403Sobrien } 222497403Sobrien 222597403Sobrien template<typename _CharT, typename _OutIter> 222697403Sobrien _OutIter 222797403Sobrien time_put<_CharT, _OutIter>:: 2228132720Skan do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 222997403Sobrien char __format, char __mod) const 2230132720Skan { 2231132720Skan const locale& __loc = __io._M_getloc(); 223297403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 223397403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 223497403Sobrien 223597403Sobrien // NB: This size is arbitrary. Should this be a data member, 223697403Sobrien // initialized at construction? 223797403Sobrien const size_t __maxlen = 64; 2238132720Skan char_type* __res = 2239132720Skan static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 224097403Sobrien 224197403Sobrien // NB: In IEE 1003.1-200x, and perhaps other locale models, it 224297403Sobrien // is possible that the format character will be longer than one 224397403Sobrien // character. Possibilities include 'E' or 'O' followed by a 224497403Sobrien // format character: if __mod is not the default argument, assume 224597403Sobrien // it's a valid modifier. 224697403Sobrien char_type __fmt[4]; 2247132720Skan __fmt[0] = __ctype.widen('%'); 224897403Sobrien if (!__mod) 224997403Sobrien { 225097403Sobrien __fmt[1] = __format; 225197403Sobrien __fmt[2] = char_type(); 225297403Sobrien } 225397403Sobrien else 225497403Sobrien { 225597403Sobrien __fmt[1] = __mod; 225697403Sobrien __fmt[2] = __format; 225797403Sobrien __fmt[3] = char_type(); 225897403Sobrien } 225997403Sobrien 226097403Sobrien __tp._M_put(__res, __maxlen, __fmt, __tm); 226197403Sobrien 226297403Sobrien // Write resulting, fully-formatted string to output iterator. 2263132720Skan return std::__write(__s, __res, char_traits<char_type>::length(__res)); 226497403Sobrien } 226597403Sobrien 226697403Sobrien 226797403Sobrien // Generic version does nothing. 226897403Sobrien template<typename _CharT> 226997403Sobrien int 227097403Sobrien collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 227197403Sobrien { return 0; } 227297403Sobrien 227397403Sobrien // Generic version does nothing. 227497403Sobrien template<typename _CharT> 227597403Sobrien size_t 227697403Sobrien collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 227797403Sobrien { return 0; } 227897403Sobrien 227997403Sobrien template<typename _CharT> 228097403Sobrien int 228197403Sobrien collate<_CharT>:: 2282132720Skan do_compare(const _CharT* __lo1, const _CharT* __hi1, 228397403Sobrien const _CharT* __lo2, const _CharT* __hi2) const 2284132720Skan { 2285117397Skan // strcoll assumes zero-terminated strings so we make a copy 2286117397Skan // and then put a zero at the end. 228797403Sobrien const string_type __one(__lo1, __hi1); 228897403Sobrien const string_type __two(__lo2, __hi2); 2289117397Skan 2290117397Skan const _CharT* __p = __one.c_str(); 2291132720Skan const _CharT* __pend = __one.data() + __one.length(); 2292117397Skan const _CharT* __q = __two.c_str(); 2293132720Skan const _CharT* __qend = __two.data() + __two.length(); 2294117397Skan 2295117397Skan // strcoll stops when it sees a nul character so we break 2296117397Skan // the strings into zero-terminated substrings and pass those 2297117397Skan // to strcoll. 2298117397Skan for (;;) 2299117397Skan { 2300132720Skan const int __res = _M_compare(__p, __q); 2301117397Skan if (__res) 2302117397Skan return __res; 2303117397Skan 2304117397Skan __p += char_traits<_CharT>::length(__p); 2305117397Skan __q += char_traits<_CharT>::length(__q); 2306117397Skan if (__p == __pend && __q == __qend) 2307117397Skan return 0; 2308117397Skan else if (__p == __pend) 2309117397Skan return -1; 2310117397Skan else if (__q == __qend) 2311117397Skan return 1; 2312117397Skan 2313117397Skan __p++; 2314117397Skan __q++; 2315117397Skan } 231697403Sobrien } 231797403Sobrien 2318132720Skan template<typename _CharT> 231997403Sobrien typename collate<_CharT>::string_type 232097403Sobrien collate<_CharT>:: 232197403Sobrien do_transform(const _CharT* __lo, const _CharT* __hi) const 232297403Sobrien { 2323117397Skan // strxfrm assumes zero-terminated strings so we make a copy 2324117397Skan string_type __str(__lo, __hi); 2325117397Skan 2326117397Skan const _CharT* __p = __str.c_str(); 2327132720Skan const _CharT* __pend = __str.data() + __str.length(); 2328117397Skan 232997403Sobrien size_t __len = (__hi - __lo) * 2; 2330117397Skan 2331117397Skan string_type __ret; 2332117397Skan 2333117397Skan // strxfrm stops when it sees a nul character so we break 2334117397Skan // the string into zero-terminated substrings and pass those 2335117397Skan // to strxfrm. 2336117397Skan for (;;) 233797403Sobrien { 2338117397Skan // First try a buffer perhaps big enough. 2339117397Skan _CharT* __c = 2340117397Skan static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 2341117397Skan size_t __res = _M_transform(__c, __p, __len); 2342117397Skan // If the buffer was not large enough, try again with the 2343117397Skan // correct size. 2344117397Skan if (__res >= __len) 2345117397Skan { 2346117397Skan __len = __res + 1; 2347132720Skan __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2348117397Skan * __len)); 2349117397Skan __res = _M_transform(__c, __p, __res + 1); 2350117397Skan } 2351117397Skan 2352117397Skan __ret.append(__c, __res); 2353117397Skan __p += char_traits<_CharT>::length(__p); 2354117397Skan if (__p == __pend) 2355117397Skan return __ret; 2356117397Skan 2357117397Skan __p++; 2358117397Skan __ret.push_back(_CharT()); 235997403Sobrien } 236097403Sobrien } 236197403Sobrien 2362132720Skan template<typename _CharT> 236397403Sobrien long 236497403Sobrien collate<_CharT>:: 236597403Sobrien do_hash(const _CharT* __lo, const _CharT* __hi) const 2366132720Skan { 236797403Sobrien unsigned long __val = 0; 236897403Sobrien for (; __lo < __hi; ++__lo) 2369132720Skan __val = *__lo + ((__val << 7) | 237097403Sobrien (__val >> (numeric_limits<unsigned long>::digits - 7))); 237197403Sobrien return static_cast<long>(__val); 237297403Sobrien } 237397403Sobrien 237497403Sobrien // Construct correctly padded string, as per 22.2.2.2.2 2375132720Skan // Assumes 237697403Sobrien // __newlen > __oldlen 237797403Sobrien // __news is allocated for __newlen size 237897403Sobrien // Used by both num_put and ostream inserters: if __num, 237997403Sobrien // internal-adjusted objects are padded according to the rules below 238097403Sobrien // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 238197403Sobrien // ones are. 2382102782Skan 2383102782Skan // NB: Of the two parameters, _CharT can be deduced from the 2384102782Skan // function arguments. The other (_Traits) has to be explicitly specified. 238597403Sobrien template<typename _CharT, typename _Traits> 2386132720Skan void 2387132720Skan __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2388132720Skan _CharT* __news, const _CharT* __olds, 2389132720Skan const streamsize __newlen, 2390102782Skan const streamsize __oldlen, const bool __num) 2391102782Skan { 2392132720Skan const size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2393132720Skan const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 2394102782Skan 2395132720Skan // Padding last. 239697403Sobrien if (__adjust == ios_base::left) 239797403Sobrien { 2398132720Skan _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen); 2399132720Skan _Traits::assign(__news + __oldlen, __plen, __fill); 2400132720Skan return; 240197403Sobrien } 2402132720Skan 2403132720Skan size_t __mod = 0; 2404132720Skan if (__adjust == ios_base::internal && __num) 240597403Sobrien { 240697403Sobrien // Pad after the sign, if there is one. 240797403Sobrien // Pad after 0[xX], if there is one. 240897403Sobrien // Who came up with these rules, anyway? Jeeze. 2409132720Skan const locale& __loc = __io._M_getloc(); 2410132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2411102782Skan 2412132720Skan const bool __testsign = (__ctype.widen('-') == __olds[0] 2413132720Skan || __ctype.widen('+') == __olds[0]); 2414132720Skan const bool __testhex = (__ctype.widen('0') == __olds[0] 2415132720Skan && __oldlen > 1 2416132720Skan && (__ctype.widen('x') == __olds[1] 2417132720Skan || __ctype.widen('X') == __olds[1])); 241897403Sobrien if (__testhex) 241997403Sobrien { 2420132720Skan __news[0] = __olds[0]; 242197403Sobrien __news[1] = __olds[1]; 2422132720Skan __mod = 2; 242397403Sobrien __news += 2; 242497403Sobrien } 242597403Sobrien else if (__testsign) 242697403Sobrien { 2427132720Skan __news[0] = __olds[0]; 2428132720Skan __mod = 1; 242997403Sobrien ++__news; 243097403Sobrien } 2431132720Skan // else Padding first. 243297403Sobrien } 2433132720Skan _Traits::assign(__news, __plen, __fill); 2434132720Skan _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod), 2435132720Skan __oldlen - __mod); 243697403Sobrien } 243797403Sobrien 2438132720Skan bool 2439132720Skan __verify_grouping(const char* __grouping, size_t __grouping_size, 2440132720Skan const string& __grouping_tmp) 2441132720Skan { 2442132720Skan const size_t __n = __grouping_tmp.size() - 1; 2443132720Skan const size_t __min = std::min(__n, __grouping_size - 1); 2444132720Skan size_t __i = __n; 2445132720Skan bool __test = true; 2446132720Skan 2447132720Skan // Parsed number groupings have to match the 2448132720Skan // numpunct::grouping string exactly, starting at the 2449132720Skan // right-most point of the parsed sequence of elements ... 2450132720Skan for (size_t __j = 0; __j < __min && __test; --__i, ++__j) 2451132720Skan __test = __grouping_tmp[__i] == __grouping[__j]; 2452132720Skan for (; __i && __test; --__i) 2453132720Skan __test = __grouping_tmp[__i] == __grouping[__min]; 2454132720Skan // ... but the last parsed grouping can be <= numpunct 2455132720Skan // grouping. 2456132720Skan __test &= __grouping_tmp[0] <= __grouping[__min]; 2457132720Skan return __test; 2458132720Skan } 245997403Sobrien 246097403Sobrien template<typename _CharT> 246197403Sobrien _CharT* 2462132720Skan __add_grouping(_CharT* __s, _CharT __sep, 2463132720Skan const char* __gbeg, size_t __gsize, 246497403Sobrien const _CharT* __first, const _CharT* __last) 246597403Sobrien { 246697403Sobrien if (__last - __first > *__gbeg) 2467132720Skan { 2468132720Skan const bool __bump = __gsize != 1; 2469132720Skan __s = std::__add_grouping(__s, __sep, __gbeg + __bump, 2470132720Skan __gsize - __bump, __first, 2471132720Skan __last - *__gbeg); 2472132720Skan __first = __last - *__gbeg; 2473132720Skan *__s++ = __sep; 2474132720Skan } 247597403Sobrien do 247697403Sobrien *__s++ = *__first++; 247797403Sobrien while (__first != __last); 247897403Sobrien return __s; 247997403Sobrien } 248097403Sobrien 248197403Sobrien // Inhibit implicit instantiations for required instantiations, 2482132720Skan // which are defined via explicit instantiations elsewhere. 248397403Sobrien // NB: This syntax is a GNU extension. 2484132720Skan#if _GLIBCXX_EXTERN_TEMPLATE 248597403Sobrien extern template class moneypunct<char, false>; 248697403Sobrien extern template class moneypunct<char, true>; 248797403Sobrien extern template class moneypunct_byname<char, false>; 248897403Sobrien extern template class moneypunct_byname<char, true>; 248997403Sobrien extern template class money_get<char>; 249097403Sobrien extern template class money_put<char>; 249197403Sobrien extern template class numpunct<char>; 249297403Sobrien extern template class numpunct_byname<char>; 249397403Sobrien extern template class num_get<char>; 2494132720Skan extern template class num_put<char>; 249597403Sobrien extern template class __timepunct<char>; 249697403Sobrien extern template class time_put<char>; 249797403Sobrien extern template class time_put_byname<char>; 249897403Sobrien extern template class time_get<char>; 249997403Sobrien extern template class time_get_byname<char>; 250097403Sobrien extern template class messages<char>; 250197403Sobrien extern template class messages_byname<char>; 250297403Sobrien extern template class ctype_byname<char>; 250397403Sobrien extern template class codecvt_byname<char, char, mbstate_t>; 250497403Sobrien extern template class collate<char>; 250597403Sobrien extern template class collate_byname<char>; 250697403Sobrien 250797403Sobrien extern template 2508132720Skan const codecvt<char, char, mbstate_t>& 250997403Sobrien use_facet<codecvt<char, char, mbstate_t> >(const locale&); 251097403Sobrien 251197403Sobrien extern template 2512132720Skan const collate<char>& 251397403Sobrien use_facet<collate<char> >(const locale&); 251497403Sobrien 251597403Sobrien extern template 2516132720Skan const numpunct<char>& 251797403Sobrien use_facet<numpunct<char> >(const locale&); 251897403Sobrien 2519132720Skan extern template 2520132720Skan const num_put<char>& 252197403Sobrien use_facet<num_put<char> >(const locale&); 252297403Sobrien 2523132720Skan extern template 2524132720Skan const num_get<char>& 252597403Sobrien use_facet<num_get<char> >(const locale&); 252697403Sobrien 252797403Sobrien extern template 2528132720Skan const moneypunct<char, true>& 252997403Sobrien use_facet<moneypunct<char, true> >(const locale&); 253097403Sobrien 253197403Sobrien extern template 2532132720Skan const moneypunct<char, false>& 253397403Sobrien use_facet<moneypunct<char, false> >(const locale&); 253497403Sobrien 2535132720Skan extern template 2536132720Skan const money_put<char>& 253797403Sobrien use_facet<money_put<char> >(const locale&); 253897403Sobrien 2539132720Skan extern template 2540132720Skan const money_get<char>& 254197403Sobrien use_facet<money_get<char> >(const locale&); 254297403Sobrien 254397403Sobrien extern template 2544132720Skan const __timepunct<char>& 254597403Sobrien use_facet<__timepunct<char> >(const locale&); 254697403Sobrien 2547132720Skan extern template 2548132720Skan const time_put<char>& 254997403Sobrien use_facet<time_put<char> >(const locale&); 255097403Sobrien 2551132720Skan extern template 2552132720Skan const time_get<char>& 255397403Sobrien use_facet<time_get<char> >(const locale&); 255497403Sobrien 2555132720Skan extern template 2556132720Skan const messages<char>& 255797403Sobrien use_facet<messages<char> >(const locale&); 255897403Sobrien 2559132720Skan extern template 2560107606Sobrien bool 2561107606Sobrien has_facet<ctype<char> >(const locale&); 2562107606Sobrien 2563132720Skan extern template 2564107606Sobrien bool 2565107606Sobrien has_facet<codecvt<char, char, mbstate_t> >(const locale&); 2566107606Sobrien 2567132720Skan extern template 2568107606Sobrien bool 2569107606Sobrien has_facet<collate<char> >(const locale&); 2570107606Sobrien 2571132720Skan extern template 2572107606Sobrien bool 2573107606Sobrien has_facet<numpunct<char> >(const locale&); 2574107606Sobrien 2575132720Skan extern template 2576107606Sobrien bool 2577107606Sobrien has_facet<num_put<char> >(const locale&); 2578107606Sobrien 2579132720Skan extern template 2580107606Sobrien bool 2581107606Sobrien has_facet<num_get<char> >(const locale&); 2582107606Sobrien 2583132720Skan extern template 2584107606Sobrien bool 2585107606Sobrien has_facet<moneypunct<char> >(const locale&); 2586107606Sobrien 2587132720Skan extern template 2588107606Sobrien bool 2589107606Sobrien has_facet<money_put<char> >(const locale&); 2590107606Sobrien 2591132720Skan extern template 2592107606Sobrien bool 2593107606Sobrien has_facet<money_get<char> >(const locale&); 2594107606Sobrien 2595132720Skan extern template 2596107606Sobrien bool 2597107606Sobrien has_facet<__timepunct<char> >(const locale&); 2598107606Sobrien 2599132720Skan extern template 2600107606Sobrien bool 2601107606Sobrien has_facet<time_put<char> >(const locale&); 2602107606Sobrien 2603132720Skan extern template 2604107606Sobrien bool 2605107606Sobrien has_facet<time_get<char> >(const locale&); 2606107606Sobrien 2607132720Skan extern template 2608107606Sobrien bool 2609107606Sobrien has_facet<messages<char> >(const locale&); 2610107606Sobrien 2611132720Skan#ifdef _GLIBCXX_USE_WCHAR_T 2612107606Sobrien extern template class moneypunct<wchar_t, false>; 2613107606Sobrien extern template class moneypunct<wchar_t, true>; 2614107606Sobrien extern template class moneypunct_byname<wchar_t, false>; 2615107606Sobrien extern template class moneypunct_byname<wchar_t, true>; 2616107606Sobrien extern template class money_get<wchar_t>; 2617107606Sobrien extern template class money_put<wchar_t>; 2618107606Sobrien extern template class numpunct<wchar_t>; 2619107606Sobrien extern template class numpunct_byname<wchar_t>; 2620107606Sobrien extern template class num_get<wchar_t>; 2621107606Sobrien extern template class num_put<wchar_t>; 2622107606Sobrien extern template class __timepunct<wchar_t>; 2623107606Sobrien extern template class time_put<wchar_t>; 2624107606Sobrien extern template class time_put_byname<wchar_t>; 2625107606Sobrien extern template class time_get<wchar_t>; 2626107606Sobrien extern template class time_get_byname<wchar_t>; 2627107606Sobrien extern template class messages<wchar_t>; 2628107606Sobrien extern template class messages_byname<wchar_t>; 2629107606Sobrien extern template class ctype_byname<wchar_t>; 2630107606Sobrien extern template class codecvt_byname<wchar_t, char, mbstate_t>; 2631107606Sobrien extern template class collate<wchar_t>; 2632107606Sobrien extern template class collate_byname<wchar_t>; 2633107606Sobrien 263497403Sobrien extern template 2635132720Skan const codecvt<wchar_t, char, mbstate_t>& 263697403Sobrien use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 263797403Sobrien 263897403Sobrien extern template 2639132720Skan const collate<wchar_t>& 264097403Sobrien use_facet<collate<wchar_t> >(const locale&); 264197403Sobrien 264297403Sobrien extern template 2643132720Skan const numpunct<wchar_t>& 264497403Sobrien use_facet<numpunct<wchar_t> >(const locale&); 264597403Sobrien 2646132720Skan extern template 2647132720Skan const num_put<wchar_t>& 264897403Sobrien use_facet<num_put<wchar_t> >(const locale&); 264997403Sobrien 2650132720Skan extern template 2651132720Skan const num_get<wchar_t>& 265297403Sobrien use_facet<num_get<wchar_t> >(const locale&); 265397403Sobrien 265497403Sobrien extern template 2655132720Skan const moneypunct<wchar_t, true>& 265697403Sobrien use_facet<moneypunct<wchar_t, true> >(const locale&); 265797403Sobrien 265897403Sobrien extern template 2659132720Skan const moneypunct<wchar_t, false>& 266097403Sobrien use_facet<moneypunct<wchar_t, false> >(const locale&); 2661132720Skan 2662132720Skan extern template 2663132720Skan const money_put<wchar_t>& 266497403Sobrien use_facet<money_put<wchar_t> >(const locale&); 266597403Sobrien 2666132720Skan extern template 2667132720Skan const money_get<wchar_t>& 266897403Sobrien use_facet<money_get<wchar_t> >(const locale&); 266997403Sobrien 267097403Sobrien extern template 2671132720Skan const __timepunct<wchar_t>& 267297403Sobrien use_facet<__timepunct<wchar_t> >(const locale&); 267397403Sobrien 2674132720Skan extern template 2675132720Skan const time_put<wchar_t>& 267697403Sobrien use_facet<time_put<wchar_t> >(const locale&); 267797403Sobrien 2678132720Skan extern template 2679132720Skan const time_get<wchar_t>& 268097403Sobrien use_facet<time_get<wchar_t> >(const locale&); 268197403Sobrien 2682132720Skan extern template 2683132720Skan const messages<wchar_t>& 268497403Sobrien use_facet<messages<wchar_t> >(const locale&); 268597403Sobrien 2686132720Skan extern template 268797403Sobrien bool 268897403Sobrien has_facet<ctype<wchar_t> >(const locale&); 268997403Sobrien 2690132720Skan extern template 269197403Sobrien bool 269297403Sobrien has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 269397403Sobrien 2694132720Skan extern template 269597403Sobrien bool 269697403Sobrien has_facet<collate<wchar_t> >(const locale&); 269797403Sobrien 2698132720Skan extern template 269997403Sobrien bool 270097403Sobrien has_facet<numpunct<wchar_t> >(const locale&); 270197403Sobrien 2702132720Skan extern template 270397403Sobrien bool 270497403Sobrien has_facet<num_put<wchar_t> >(const locale&); 270597403Sobrien 2706132720Skan extern template 270797403Sobrien bool 270897403Sobrien has_facet<num_get<wchar_t> >(const locale&); 270997403Sobrien 2710132720Skan extern template 271197403Sobrien bool 271297403Sobrien has_facet<moneypunct<wchar_t> >(const locale&); 271397403Sobrien 2714132720Skan extern template 271597403Sobrien bool 271697403Sobrien has_facet<money_put<wchar_t> >(const locale&); 271797403Sobrien 2718132720Skan extern template 271997403Sobrien bool 272097403Sobrien has_facet<money_get<wchar_t> >(const locale&); 272197403Sobrien 2722132720Skan extern template 272397403Sobrien bool 272497403Sobrien has_facet<__timepunct<wchar_t> >(const locale&); 272597403Sobrien 2726132720Skan extern template 272797403Sobrien bool 272897403Sobrien has_facet<time_put<wchar_t> >(const locale&); 272997403Sobrien 2730132720Skan extern template 273197403Sobrien bool 273297403Sobrien has_facet<time_get<wchar_t> >(const locale&); 273397403Sobrien 2734132720Skan extern template 273597403Sobrien bool 273697403Sobrien has_facet<messages<wchar_t> >(const locale&); 2737107606Sobrien#endif 2738117397Skan#endif 273997403Sobrien} // namespace std 274097403Sobrien 274197403Sobrien#endif 2742