197403Sobrien// Locale support -*- C++ -*- 297403Sobrien 3228780Spfg// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 4228780Spfg// 2006, 2007, 2008 597403Sobrien// Free Software Foundation, Inc. 697403Sobrien// 797403Sobrien// This file is part of the GNU ISO C++ Library. This library is free 897403Sobrien// software; you can redistribute it and/or modify it under the 997403Sobrien// terms of the GNU General Public License as published by the 1097403Sobrien// Free Software Foundation; either version 2, or (at your option) 1197403Sobrien// any later version. 1297403Sobrien 1397403Sobrien// This library is distributed in the hope that it will be useful, 1497403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1597403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1697403Sobrien// GNU General Public License for more details. 1797403Sobrien 1897403Sobrien// You should have received a copy of the GNU General Public License along 1997403Sobrien// with this library; see the file COPYING. If not, write to the Free 20169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 2197403Sobrien// USA. 2297403Sobrien 2397403Sobrien// As a special exception, you may use this file as part of a free software 2497403Sobrien// library without restriction. Specifically, if other files instantiate 2597403Sobrien// templates or use macros or inline functions from this file, or you compile 2697403Sobrien// this file and link it with other files to produce an executable, this 2797403Sobrien// file does not by itself cause the resulting executable to be covered by 2897403Sobrien// the GNU General Public License. This exception does not however 2997403Sobrien// invalidate any other reasons why the executable file might be covered by 3097403Sobrien// the GNU General Public License. 3197403Sobrien 32169691Skan/** @file locale_facets.tcc 33169691Skan * This is an internal header file, included by other library headers. 34169691Skan * You should not attempt to use it directly. 35169691Skan */ 3697403Sobrien 37132720Skan#ifndef _LOCALE_FACETS_TCC 38132720Skan#define _LOCALE_FACETS_TCC 1 3997403Sobrien 4097403Sobrien#pragma GCC system_header 4197403Sobrien 42132720Skan#include <limits> // For numeric_limits 43132720Skan#include <typeinfo> // For bad_cast. 4497403Sobrien#include <bits/streambuf_iterator.h> 45169691Skan#include <ext/type_traits.h> 4697403Sobrien 47169691Skan_GLIBCXX_BEGIN_NAMESPACE(std) 48169691Skan 4997403Sobrien template<typename _Facet> 5097403Sobrien locale 5197403Sobrien locale::combine(const locale& __other) const 5297403Sobrien { 5397403Sobrien _Impl* __tmp = new _Impl(*_M_impl, 1); 54132720Skan try 55132720Skan { 56132720Skan __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 57132720Skan } 58132720Skan catch(...) 59132720Skan { 60132720Skan __tmp->_M_remove_reference(); 61132720Skan __throw_exception_again; 62132720Skan } 6397403Sobrien return locale(__tmp); 6497403Sobrien } 6597403Sobrien 6697403Sobrien template<typename _CharT, typename _Traits, typename _Alloc> 6797403Sobrien bool 6897403Sobrien locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 6997403Sobrien const basic_string<_CharT, _Traits, _Alloc>& __s2) const 7097403Sobrien { 7197403Sobrien typedef std::collate<_CharT> __collate_type; 7297403Sobrien const __collate_type& __collate = use_facet<__collate_type>(*this); 7397403Sobrien return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 7497403Sobrien __s2.data(), __s2.data() + __s2.length()) < 0); 7597403Sobrien } 7697403Sobrien 77132720Skan /** 78132720Skan * @brief Test for the presence of a facet. 79132720Skan * 80132720Skan * has_facet tests the locale argument for the presence of the facet type 81132720Skan * provided as the template parameter. Facets derived from the facet 82132720Skan * parameter will also return true. 83132720Skan * 84132720Skan * @param Facet The facet type to test the presence of. 85132720Skan * @param locale The locale to test. 86132720Skan * @return true if locale contains a facet of type Facet, else false. 87132720Skan */ 8897403Sobrien template<typename _Facet> 89132720Skan inline bool 90132720Skan has_facet(const locale& __loc) throw() 91132720Skan { 92132720Skan const size_t __i = _Facet::id._M_id(); 93132720Skan const locale::facet** __facets = __loc._M_impl->_M_facets; 94132720Skan return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); 95132720Skan } 96132720Skan 97132720Skan /** 98132720Skan * @brief Return a facet. 99132720Skan * 100132720Skan * use_facet looks for and returns a reference to a facet of type Facet 101132720Skan * where Facet is the template parameter. If has_facet(locale) is true, 102132720Skan * there is a suitable facet to return. It throws std::bad_cast if the 103132720Skan * locale doesn't contain a facet of type Facet. 104132720Skan * 105132720Skan * @param Facet The facet type to access. 106132720Skan * @param locale The locale to use. 107132720Skan * @return Reference to facet of type Facet. 108132720Skan * @throw std::bad_cast if locale doesn't contain a facet of type Facet. 109132720Skan */ 110132720Skan template<typename _Facet> 111132720Skan inline const _Facet& 11297403Sobrien use_facet(const locale& __loc) 11397403Sobrien { 114132720Skan const size_t __i = _Facet::id._M_id(); 115132720Skan const locale::facet** __facets = __loc._M_impl->_M_facets; 11697403Sobrien if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) 11797403Sobrien __throw_bad_cast(); 11897403Sobrien return static_cast<const _Facet&>(*__facets[__i]); 11997403Sobrien } 12097403Sobrien 121228780Spfg 122132720Skan // Routine to access a cache for the facet. If the cache didn't 123132720Skan // exist before, it gets constructed on the fly. 12497403Sobrien template<typename _Facet> 125132720Skan struct __use_cache 12697403Sobrien { 127132720Skan const _Facet* 128132720Skan operator() (const locale& __loc) const; 129132720Skan }; 130132720Skan 131132720Skan // Specializations. 132132720Skan template<typename _CharT> 133132720Skan struct __use_cache<__numpunct_cache<_CharT> > 134132720Skan { 135132720Skan const __numpunct_cache<_CharT>* 136132720Skan operator() (const locale& __loc) const 137132720Skan { 138132720Skan const size_t __i = numpunct<_CharT>::id._M_id(); 139132720Skan const locale::facet** __caches = __loc._M_impl->_M_caches; 140132720Skan if (!__caches[__i]) 141132720Skan { 142132720Skan __numpunct_cache<_CharT>* __tmp = NULL; 143132720Skan try 144132720Skan { 145132720Skan __tmp = new __numpunct_cache<_CharT>; 146132720Skan __tmp->_M_cache(__loc); 147132720Skan } 148132720Skan catch(...) 149132720Skan { 150132720Skan delete __tmp; 151132720Skan __throw_exception_again; 152132720Skan } 153132720Skan __loc._M_impl->_M_install_cache(__tmp, __i); 154132720Skan } 155132720Skan return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]); 156132720Skan } 157132720Skan }; 158132720Skan 159132720Skan template<typename _CharT, bool _Intl> 160132720Skan struct __use_cache<__moneypunct_cache<_CharT, _Intl> > 161132720Skan { 162132720Skan const __moneypunct_cache<_CharT, _Intl>* 163132720Skan operator() (const locale& __loc) const 164132720Skan { 165132720Skan const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); 166132720Skan const locale::facet** __caches = __loc._M_impl->_M_caches; 167132720Skan if (!__caches[__i]) 168132720Skan { 169132720Skan __moneypunct_cache<_CharT, _Intl>* __tmp = NULL; 170132720Skan try 171132720Skan { 172132720Skan __tmp = new __moneypunct_cache<_CharT, _Intl>; 173132720Skan __tmp->_M_cache(__loc); 174132720Skan } 175132720Skan catch(...) 176132720Skan { 177132720Skan delete __tmp; 178132720Skan __throw_exception_again; 179132720Skan } 180132720Skan __loc._M_impl->_M_install_cache(__tmp, __i); 181132720Skan } 182132720Skan return static_cast< 183132720Skan const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); 184132720Skan } 185132720Skan }; 186132720Skan 187132720Skan template<typename _CharT> 188132720Skan void 189132720Skan __numpunct_cache<_CharT>::_M_cache(const locale& __loc) 190132720Skan { 191132720Skan _M_allocated = true; 192132720Skan 193132720Skan const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 194132720Skan 195132720Skan _M_grouping_size = __np.grouping().size(); 196132720Skan char* __grouping = new char[_M_grouping_size]; 197132720Skan __np.grouping().copy(__grouping, _M_grouping_size); 198132720Skan _M_grouping = __grouping; 199169691Skan _M_use_grouping = (_M_grouping_size 200169691Skan && static_cast<signed char>(__np.grouping()[0]) > 0); 201132720Skan 202132720Skan _M_truename_size = __np.truename().size(); 203132720Skan _CharT* __truename = new _CharT[_M_truename_size]; 204132720Skan __np.truename().copy(__truename, _M_truename_size); 205132720Skan _M_truename = __truename; 206132720Skan 207132720Skan _M_falsename_size = __np.falsename().size(); 208132720Skan _CharT* __falsename = new _CharT[_M_falsename_size]; 209132720Skan __np.falsename().copy(__falsename, _M_falsename_size); 210132720Skan _M_falsename = __falsename; 211132720Skan 212132720Skan _M_decimal_point = __np.decimal_point(); 213132720Skan _M_thousands_sep = __np.thousands_sep(); 214132720Skan 215132720Skan const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 216132720Skan __ct.widen(__num_base::_S_atoms_out, 217132720Skan __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out); 218132720Skan __ct.widen(__num_base::_S_atoms_in, 219132720Skan __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in); 22097403Sobrien } 22197403Sobrien 222132720Skan template<typename _CharT, bool _Intl> 223132720Skan void 224132720Skan __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) 225117397Skan { 226132720Skan _M_allocated = true; 227132720Skan 228132720Skan const moneypunct<_CharT, _Intl>& __mp = 229132720Skan use_facet<moneypunct<_CharT, _Intl> >(__loc); 230132720Skan 231132720Skan _M_grouping_size = __mp.grouping().size(); 232132720Skan char* __grouping = new char[_M_grouping_size]; 233132720Skan __mp.grouping().copy(__grouping, _M_grouping_size); 234132720Skan _M_grouping = __grouping; 235169691Skan _M_use_grouping = (_M_grouping_size 236169691Skan && static_cast<signed char>(__mp.grouping()[0]) > 0); 237132720Skan 238132720Skan _M_decimal_point = __mp.decimal_point(); 239132720Skan _M_thousands_sep = __mp.thousands_sep(); 240132720Skan _M_frac_digits = __mp.frac_digits(); 241132720Skan 242132720Skan _M_curr_symbol_size = __mp.curr_symbol().size(); 243132720Skan _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size]; 244132720Skan __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size); 245132720Skan _M_curr_symbol = __curr_symbol; 246132720Skan 247132720Skan _M_positive_sign_size = __mp.positive_sign().size(); 248132720Skan _CharT* __positive_sign = new _CharT[_M_positive_sign_size]; 249132720Skan __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size); 250132720Skan _M_positive_sign = __positive_sign; 251132720Skan 252132720Skan _M_negative_sign_size = __mp.negative_sign().size(); 253132720Skan _CharT* __negative_sign = new _CharT[_M_negative_sign_size]; 254132720Skan __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size); 255132720Skan _M_negative_sign = __negative_sign; 256132720Skan 257132720Skan _M_pos_format = __mp.pos_format(); 258132720Skan _M_neg_format = __mp.neg_format(); 259132720Skan 260132720Skan const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 261132720Skan __ct.widen(money_base::_S_atoms, 262132720Skan money_base::_S_atoms + money_base::_S_end, _M_atoms); 263117397Skan } 26497403Sobrien 265132720Skan 266132720Skan // Used by both numeric and monetary facets. 267132720Skan // Check to make sure that the __grouping_tmp string constructed in 268132720Skan // money_get or num_get matches the canonical grouping for a given 269132720Skan // locale. 270132720Skan // __grouping_tmp is parsed L to R 271132720Skan // 1,222,444 == __grouping_tmp of "\1\3\3" 272132720Skan // __grouping is parsed R to L 273132720Skan // 1,222,444 == __grouping of "\3" == "\3\3\3" 274132720Skan static bool 275132720Skan __verify_grouping(const char* __grouping, size_t __grouping_size, 276132720Skan const string& __grouping_tmp); 277132720Skan 278169691Skan_GLIBCXX_BEGIN_LDBL_NAMESPACE 279169691Skan 28097403Sobrien template<typename _CharT, typename _InIter> 28197403Sobrien _InIter 28297403Sobrien num_get<_CharT, _InIter>:: 28397403Sobrien _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 28497403Sobrien ios_base::iostate& __err, string& __xtrc) const 28597403Sobrien { 286132720Skan typedef char_traits<_CharT> __traits_type; 287169691Skan typedef __numpunct_cache<_CharT> __cache_type; 288132720Skan __use_cache<__cache_type> __uc; 289132720Skan const locale& __loc = __io._M_getloc(); 290132720Skan const __cache_type* __lc = __uc(__loc); 291132720Skan const _CharT* __lit = __lc->_M_atoms_in; 292169691Skan char_type __c = char_type(); 29397403Sobrien 294169691Skan // True if __beg becomes equal to __end. 295169691Skan bool __testeof = __beg == __end; 296132720Skan 29797403Sobrien // First check for sign. 298169691Skan if (!__testeof) 29997403Sobrien { 300169691Skan __c = *__beg; 301132720Skan const bool __plus = __c == __lit[__num_base::_S_iplus]; 302132720Skan if ((__plus || __c == __lit[__num_base::_S_iminus]) 303132720Skan && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 304132720Skan && !(__c == __lc->_M_decimal_point)) 305132720Skan { 306132720Skan __xtrc += __plus ? '+' : '-'; 307169691Skan if (++__beg != __end) 308169691Skan __c = *__beg; 309169691Skan else 310169691Skan __testeof = true; 311132720Skan } 31297403Sobrien } 31397403Sobrien 314132720Skan // Next, look for leading zeros. 315169691Skan bool __found_mantissa = false; 316169691Skan int __sep_pos = 0; 317169691Skan while (!__testeof) 31897403Sobrien { 319241957Sdim if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 320132720Skan || __c == __lc->_M_decimal_point) 321132720Skan break; 322132720Skan else if (__c == __lit[__num_base::_S_izero]) 323132720Skan { 324132720Skan if (!__found_mantissa) 325132720Skan { 326132720Skan __xtrc += '0'; 327132720Skan __found_mantissa = true; 328132720Skan } 329169691Skan ++__sep_pos; 330169691Skan 331169691Skan if (++__beg != __end) 332169691Skan __c = *__beg; 333169691Skan else 334169691Skan __testeof = true; 335132720Skan } 336132720Skan else 337132720Skan break; 33897403Sobrien } 33997403Sobrien 34097403Sobrien // Only need acceptable digits for floating point numbers. 34197403Sobrien bool __found_dec = false; 34297403Sobrien bool __found_sci = false; 34397403Sobrien string __found_grouping; 344132720Skan if (__lc->_M_use_grouping) 345132720Skan __found_grouping.reserve(32); 346132720Skan const char_type* __lit_zero = __lit + __num_base::_S_izero; 34797403Sobrien 348169691Skan if (!__lc->_M_allocated) 349169691Skan // "C" locale 350169691Skan while (!__testeof) 351169691Skan { 352169691Skan const int __digit = _M_find(__lit_zero, 10, __c); 353169691Skan if (__digit != -1) 354169691Skan { 355169691Skan __xtrc += '0' + __digit; 356169691Skan __found_mantissa = true; 357169691Skan } 358169691Skan else if (__c == __lc->_M_decimal_point 359169691Skan && !__found_dec && !__found_sci) 360169691Skan { 361169691Skan __xtrc += '.'; 362169691Skan __found_dec = true; 363169691Skan } 364169691Skan else if ((__c == __lit[__num_base::_S_ie] 365169691Skan || __c == __lit[__num_base::_S_iE]) 366169691Skan && !__found_sci && __found_mantissa) 367169691Skan { 368169691Skan // Scientific notation. 369169691Skan __xtrc += 'e'; 370169691Skan __found_sci = true; 371169691Skan 372169691Skan // Remove optional plus or minus sign, if they exist. 373169691Skan if (++__beg != __end) 374169691Skan { 375169691Skan __c = *__beg; 376169691Skan const bool __plus = __c == __lit[__num_base::_S_iplus]; 377169691Skan if (__plus || __c == __lit[__num_base::_S_iminus]) 378132720Skan __xtrc += __plus ? '+' : '-'; 379169691Skan else 380169691Skan continue; 381169691Skan } 382169691Skan else 383169691Skan { 384169691Skan __testeof = true; 385169691Skan break; 386169691Skan } 387169691Skan } 388169691Skan else 389169691Skan break; 39097403Sobrien 391169691Skan if (++__beg != __end) 392169691Skan __c = *__beg; 393169691Skan else 394169691Skan __testeof = true; 395169691Skan } 396169691Skan else 397169691Skan while (!__testeof) 398169691Skan { 399169691Skan // According to 22.2.2.1.2, p8-9, first look for thousands_sep 400169691Skan // and decimal_point. 401169691Skan if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 402169691Skan { 403169691Skan if (!__found_dec && !__found_sci) 404169691Skan { 405169691Skan // NB: Thousands separator at the beginning of a string 406169691Skan // is a no-no, as is two consecutive thousands separators. 407169691Skan if (__sep_pos) 408169691Skan { 409169691Skan __found_grouping += static_cast<char>(__sep_pos); 410169691Skan __sep_pos = 0; 411169691Skan } 412169691Skan else 413169691Skan { 414169691Skan // NB: __convert_to_v will not assign __v and will 415169691Skan // set the failbit. 416169691Skan __xtrc.clear(); 417169691Skan break; 418169691Skan } 419169691Skan } 420169691Skan else 421169691Skan break; 422169691Skan } 423169691Skan else if (__c == __lc->_M_decimal_point) 424169691Skan { 425169691Skan if (!__found_dec && !__found_sci) 426169691Skan { 427169691Skan // If no grouping chars are seen, no grouping check 428169691Skan // is applied. Therefore __found_grouping is adjusted 429169691Skan // only if decimal_point comes after some thousands_sep. 430169691Skan if (__found_grouping.size()) 431169691Skan __found_grouping += static_cast<char>(__sep_pos); 432169691Skan __xtrc += '.'; 433169691Skan __found_dec = true; 434169691Skan } 435169691Skan else 436169691Skan break; 437169691Skan } 438169691Skan else 439169691Skan { 440169691Skan const char_type* __q = 441169691Skan __traits_type::find(__lit_zero, 10, __c); 442169691Skan if (__q) 443169691Skan { 444169691Skan __xtrc += '0' + (__q - __lit_zero); 445169691Skan __found_mantissa = true; 446169691Skan ++__sep_pos; 447169691Skan } 448169691Skan else if ((__c == __lit[__num_base::_S_ie] 449169691Skan || __c == __lit[__num_base::_S_iE]) 450169691Skan && !__found_sci && __found_mantissa) 451169691Skan { 452169691Skan // Scientific notation. 453169691Skan if (__found_grouping.size() && !__found_dec) 454169691Skan __found_grouping += static_cast<char>(__sep_pos); 455169691Skan __xtrc += 'e'; 456169691Skan __found_sci = true; 457169691Skan 458169691Skan // Remove optional plus or minus sign, if they exist. 459169691Skan if (++__beg != __end) 460169691Skan { 461169691Skan __c = *__beg; 462169691Skan const bool __plus = __c == __lit[__num_base::_S_iplus]; 463169691Skan if ((__plus || __c == __lit[__num_base::_S_iminus]) 464169691Skan && !(__lc->_M_use_grouping 465169691Skan && __c == __lc->_M_thousands_sep) 466169691Skan && !(__c == __lc->_M_decimal_point)) 467169691Skan __xtrc += __plus ? '+' : '-'; 468169691Skan else 469169691Skan continue; 470169691Skan } 471169691Skan else 472169691Skan { 473169691Skan __testeof = true; 474169691Skan break; 475169691Skan } 476169691Skan } 477169691Skan else 478169691Skan break; 479169691Skan } 480169691Skan 481169691Skan if (++__beg != __end) 482169691Skan __c = *__beg; 483169691Skan else 484169691Skan __testeof = true; 485169691Skan } 486169691Skan 48797403Sobrien // Digit grouping is checked. If grouping and found_grouping don't 48897403Sobrien // match, then get very very upset, and set failbit. 489169691Skan if (__found_grouping.size()) 49097403Sobrien { 491132720Skan // Add the ending grouping if a decimal or 'e'/'E' wasn't found. 492132720Skan if (!__found_dec && !__found_sci) 49397403Sobrien __found_grouping += static_cast<char>(__sep_pos); 494132720Skan 495132720Skan if (!std::__verify_grouping(__lc->_M_grouping, 496132720Skan __lc->_M_grouping_size, 497132720Skan __found_grouping)) 49897403Sobrien __err |= ios_base::failbit; 49997403Sobrien } 50097403Sobrien 501132720Skan // Finish up. 502169691Skan if (__testeof) 50397403Sobrien __err |= ios_base::eofbit; 50497403Sobrien return __beg; 50597403Sobrien } 50697403Sobrien 507169691Skan_GLIBCXX_END_LDBL_NAMESPACE 508169691Skan 509169691Skan_GLIBCXX_BEGIN_LDBL_NAMESPACE 510169691Skan 51197403Sobrien template<typename _CharT, typename _InIter> 512132720Skan template<typename _ValueT> 513132720Skan _InIter 514132720Skan num_get<_CharT, _InIter>:: 515132720Skan _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 516132720Skan ios_base::iostate& __err, _ValueT& __v) const 517132720Skan { 518169691Skan typedef char_traits<_CharT> __traits_type; 519169691Skan using __gnu_cxx::__add_unsigned; 520169691Skan typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; 521169691Skan typedef __numpunct_cache<_CharT> __cache_type; 522132720Skan __use_cache<__cache_type> __uc; 523132720Skan const locale& __loc = __io._M_getloc(); 524132720Skan const __cache_type* __lc = __uc(__loc); 525132720Skan const _CharT* __lit = __lc->_M_atoms_in; 526169691Skan char_type __c = char_type(); 52797403Sobrien 528132720Skan // NB: Iff __basefield == 0, __base can change based on contents. 529132720Skan const ios_base::fmtflags __basefield = __io.flags() 530132720Skan & ios_base::basefield; 531132720Skan const bool __oct = __basefield == ios_base::oct; 532132720Skan int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); 533102782Skan 534169691Skan // True if __beg becomes equal to __end. 535169691Skan bool __testeof = __beg == __end; 53697403Sobrien 537132720Skan // First check for sign. 538132720Skan bool __negative = false; 539169691Skan if (!__testeof) 540132720Skan { 541169691Skan __c = *__beg; 542132720Skan if (numeric_limits<_ValueT>::is_signed) 543132720Skan __negative = __c == __lit[__num_base::_S_iminus]; 544132720Skan if ((__negative || __c == __lit[__num_base::_S_iplus]) 545132720Skan && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 546132720Skan && !(__c == __lc->_M_decimal_point)) 547169691Skan { 548169691Skan if (++__beg != __end) 549169691Skan __c = *__beg; 550169691Skan else 551169691Skan __testeof = true; 552169691Skan } 553132720Skan } 554132720Skan 555132720Skan // Next, look for leading zeros and check required digits 556132720Skan // for base formats. 557169691Skan bool __found_zero = false; 558169691Skan int __sep_pos = 0; 559169691Skan while (!__testeof) 560132720Skan { 561241957Sdim if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 562132720Skan || __c == __lc->_M_decimal_point) 563132720Skan break; 564132720Skan else if (__c == __lit[__num_base::_S_izero] 565169691Skan && (!__found_zero || __base == 10)) 566132720Skan { 567169691Skan __found_zero = true; 568169691Skan ++__sep_pos; 569169691Skan if (__basefield == 0) 570169691Skan __base = 8; 571169691Skan if (__base == 8) 572169691Skan __sep_pos = 0; 573132720Skan } 574169691Skan else if (__found_zero 575169691Skan && (__c == __lit[__num_base::_S_ix] 576169691Skan || __c == __lit[__num_base::_S_iX])) 577132720Skan { 578169691Skan if (__basefield == 0) 579169691Skan __base = 16; 580169691Skan if (__base == 16) 581132720Skan { 582169691Skan __found_zero = false; 583169691Skan __sep_pos = 0; 584132720Skan } 585169691Skan else 586169691Skan break; 587132720Skan } 588132720Skan else 589132720Skan break; 590169691Skan 591169691Skan if (++__beg != __end) 592169691Skan { 593169691Skan __c = *__beg; 594169691Skan if (!__found_zero) 595169691Skan break; 596169691Skan } 597169691Skan else 598169691Skan __testeof = true; 599132720Skan } 600169691Skan 601132720Skan // At this point, base is determined. If not hex, only allow 602132720Skan // base digits as valid input. 603169691Skan const size_t __len = (__base == 16 ? __num_base::_S_iend 604169691Skan - __num_base::_S_izero : __base); 60597403Sobrien 606132720Skan // Extract. 607132720Skan string __found_grouping; 608132720Skan if (__lc->_M_use_grouping) 609132720Skan __found_grouping.reserve(32); 610169691Skan bool __testfail = false; 611169691Skan const __unsigned_type __max = __negative ? 612169691Skan -numeric_limits<_ValueT>::min() : numeric_limits<_ValueT>::max(); 613169691Skan const __unsigned_type __smax = __max / __base; 614169691Skan __unsigned_type __result = 0; 615169691Skan int __digit = 0; 616132720Skan const char_type* __lit_zero = __lit + __num_base::_S_izero; 617169691Skan 618169691Skan if (!__lc->_M_allocated) 619169691Skan // "C" locale 620169691Skan while (!__testeof) 621169691Skan { 622169691Skan __digit = _M_find(__lit_zero, __len, __c); 623169691Skan if (__digit == -1) 624169691Skan break; 625169691Skan 626169691Skan if (__result > __smax) 627169691Skan __testfail = true; 628169691Skan else 629169691Skan { 630169691Skan __result *= __base; 631169691Skan __testfail |= __result > __max - __digit; 632169691Skan __result += __digit; 633169691Skan ++__sep_pos; 634169691Skan } 635169691Skan 636169691Skan if (++__beg != __end) 637169691Skan __c = *__beg; 638169691Skan else 639169691Skan __testeof = true; 640169691Skan } 641132720Skan else 642169691Skan while (!__testeof) 643169691Skan { 644169691Skan // According to 22.2.2.1.2, p8-9, first look for thousands_sep 645169691Skan // and decimal_point. 646169691Skan if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 647169691Skan { 648169691Skan // NB: Thousands separator at the beginning of a string 649169691Skan // is a no-no, as is two consecutive thousands separators. 650169691Skan if (__sep_pos) 651169691Skan { 652169691Skan __found_grouping += static_cast<char>(__sep_pos); 653169691Skan __sep_pos = 0; 654169691Skan } 655169691Skan else 656169691Skan { 657169691Skan __testfail = true; 658169691Skan break; 659169691Skan } 660169691Skan } 661169691Skan else if (__c == __lc->_M_decimal_point) 662169691Skan break; 663169691Skan else 664169691Skan { 665169691Skan const char_type* __q = 666169691Skan __traits_type::find(__lit_zero, __len, __c); 667169691Skan if (!__q) 668169691Skan break; 669169691Skan 670169691Skan __digit = __q - __lit_zero; 671169691Skan if (__digit > 15) 672169691Skan __digit -= 6; 673169691Skan if (__result > __smax) 674169691Skan __testfail = true; 675169691Skan else 676169691Skan { 677169691Skan __result *= __base; 678169691Skan __testfail |= __result > __max - __digit; 679169691Skan __result += __digit; 680169691Skan ++__sep_pos; 681169691Skan } 682169691Skan } 683169691Skan 684169691Skan if (++__beg != __end) 685169691Skan __c = *__beg; 686169691Skan else 687169691Skan __testeof = true; 688169691Skan } 689169691Skan 690132720Skan // Digit grouping is checked. If grouping and found_grouping don't 691132720Skan // match, then get very very upset, and set failbit. 692169691Skan if (__found_grouping.size()) 693132720Skan { 694132720Skan // Add the ending grouping. 695132720Skan __found_grouping += static_cast<char>(__sep_pos); 69697403Sobrien 697132720Skan if (!std::__verify_grouping(__lc->_M_grouping, 698132720Skan __lc->_M_grouping_size, 699132720Skan __found_grouping)) 700132720Skan __err |= ios_base::failbit; 701132720Skan } 70297403Sobrien 703169691Skan if (!__testfail && (__sep_pos || __found_zero 704169691Skan || __found_grouping.size())) 705169691Skan __v = __negative ? -__result : __result; 706132720Skan else 707132720Skan __err |= ios_base::failbit; 708132720Skan 709169691Skan if (__testeof) 710132720Skan __err |= ios_base::eofbit; 711132720Skan return __beg; 712132720Skan } 713132720Skan 714132720Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 715132720Skan // 17. Bad bool parsing 71697403Sobrien template<typename _CharT, typename _InIter> 71797403Sobrien _InIter 71897403Sobrien num_get<_CharT, _InIter>:: 71997403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 72097403Sobrien ios_base::iostate& __err, bool& __v) const 72197403Sobrien { 72297403Sobrien if (!(__io.flags() & ios_base::boolalpha)) 72397403Sobrien { 724132720Skan // Parse bool values as long. 72597403Sobrien // NB: We can't just call do_get(long) here, as it might 72697403Sobrien // refer to a derived class. 727132720Skan long __l = -1; 728132720Skan __beg = _M_extract_int(__beg, __end, __io, __err, __l); 729132720Skan if (__l == 0 || __l == 1) 730132720Skan __v = __l; 731132720Skan else 73297403Sobrien __err |= ios_base::failbit; 73397403Sobrien } 73497403Sobrien else 73597403Sobrien { 736132720Skan // Parse bool values as alphanumeric. 737169691Skan typedef __numpunct_cache<_CharT> __cache_type; 738132720Skan __use_cache<__cache_type> __uc; 739132720Skan const locale& __loc = __io._M_getloc(); 740132720Skan const __cache_type* __lc = __uc(__loc); 741102782Skan 742132720Skan bool __testf = true; 743132720Skan bool __testt = true; 744132720Skan size_t __n; 745169691Skan bool __testeof = __beg == __end; 746169691Skan for (__n = 0; !__testeof; ++__n) 747132720Skan { 748169691Skan const char_type __c = *__beg; 749169691Skan 750132720Skan if (__testf) 751241957Sdim { 752241957Sdim if (__n < __lc->_M_falsename_size) 753241957Sdim __testf = __c == __lc->_M_falsename[__n]; 754241957Sdim else 755241957Sdim break; 756241957Sdim } 75797403Sobrien 758132720Skan if (__testt) 759241957Sdim { 760241957Sdim if (__n < __lc->_M_truename_size) 761241957Sdim __testt = __c == __lc->_M_truename[__n]; 762241957Sdim else 763241957Sdim break; 764241957Sdim } 765132720Skan 766132720Skan if (!__testf && !__testt) 767132720Skan break; 768169691Skan 769169691Skan if (++__beg == __end) 770169691Skan __testeof = true; 77197403Sobrien } 772132720Skan if (__testf && __n == __lc->_M_falsename_size) 773132720Skan __v = 0; 774132720Skan else if (__testt && __n == __lc->_M_truename_size) 775132720Skan __v = 1; 776132720Skan else 777132720Skan __err |= ios_base::failbit; 778132720Skan 779169691Skan if (__testeof) 78097403Sobrien __err |= ios_base::eofbit; 78197403Sobrien } 78297403Sobrien return __beg; 78397403Sobrien } 78497403Sobrien 78597403Sobrien template<typename _CharT, typename _InIter> 78697403Sobrien _InIter 78797403Sobrien num_get<_CharT, _InIter>:: 78897403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 78997403Sobrien ios_base::iostate& __err, long& __v) const 790132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 79197403Sobrien 79297403Sobrien template<typename _CharT, typename _InIter> 79397403Sobrien _InIter 79497403Sobrien num_get<_CharT, _InIter>:: 79597403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 79697403Sobrien ios_base::iostate& __err, unsigned short& __v) const 797132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 79897403Sobrien 79997403Sobrien template<typename _CharT, typename _InIter> 80097403Sobrien _InIter 80197403Sobrien num_get<_CharT, _InIter>:: 80297403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 80397403Sobrien ios_base::iostate& __err, unsigned int& __v) const 804132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 80597403Sobrien 80697403Sobrien template<typename _CharT, typename _InIter> 80797403Sobrien _InIter 80897403Sobrien num_get<_CharT, _InIter>:: 80997403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 81097403Sobrien ios_base::iostate& __err, unsigned long& __v) const 811132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 81297403Sobrien 813132720Skan#ifdef _GLIBCXX_USE_LONG_LONG 81497403Sobrien template<typename _CharT, typename _InIter> 81597403Sobrien _InIter 81697403Sobrien num_get<_CharT, _InIter>:: 81797403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 81897403Sobrien ios_base::iostate& __err, long long& __v) const 819132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 82097403Sobrien 82197403Sobrien template<typename _CharT, typename _InIter> 82297403Sobrien _InIter 82397403Sobrien num_get<_CharT, _InIter>:: 82497403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 82597403Sobrien ios_base::iostate& __err, unsigned long long& __v) const 826132720Skan { return _M_extract_int(__beg, __end, __io, __err, __v); } 82797403Sobrien#endif 82897403Sobrien 82997403Sobrien template<typename _CharT, typename _InIter> 83097403Sobrien _InIter 83197403Sobrien num_get<_CharT, _InIter>:: 832132720Skan do_get(iter_type __beg, iter_type __end, ios_base& __io, 83397403Sobrien ios_base::iostate& __err, float& __v) const 83497403Sobrien { 83597403Sobrien string __xtrc; 83697403Sobrien __xtrc.reserve(32); 83797403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 838132720Skan std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 83997403Sobrien return __beg; 84097403Sobrien } 84197403Sobrien 84297403Sobrien template<typename _CharT, typename _InIter> 84397403Sobrien _InIter 84497403Sobrien num_get<_CharT, _InIter>:: 84597403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 84697403Sobrien ios_base::iostate& __err, double& __v) const 84797403Sobrien { 84897403Sobrien string __xtrc; 84997403Sobrien __xtrc.reserve(32); 85097403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 851132720Skan std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 85297403Sobrien return __beg; 85397403Sobrien } 85497403Sobrien 855169691Skan#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 85697403Sobrien template<typename _CharT, typename _InIter> 85797403Sobrien _InIter 85897403Sobrien num_get<_CharT, _InIter>:: 859169691Skan __do_get(iter_type __beg, iter_type __end, ios_base& __io, 860169691Skan ios_base::iostate& __err, double& __v) const 861169691Skan { 862169691Skan string __xtrc; 863169691Skan __xtrc.reserve(32); 864169691Skan __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 865169691Skan std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 866169691Skan return __beg; 867169691Skan } 868169691Skan#endif 869169691Skan 870169691Skan template<typename _CharT, typename _InIter> 871169691Skan _InIter 872169691Skan num_get<_CharT, _InIter>:: 87397403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 87497403Sobrien ios_base::iostate& __err, long double& __v) const 87597403Sobrien { 87697403Sobrien string __xtrc; 87797403Sobrien __xtrc.reserve(32); 87897403Sobrien __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 879132720Skan std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 88097403Sobrien return __beg; 88197403Sobrien } 88297403Sobrien 88397403Sobrien template<typename _CharT, typename _InIter> 88497403Sobrien _InIter 88597403Sobrien num_get<_CharT, _InIter>:: 88697403Sobrien do_get(iter_type __beg, iter_type __end, ios_base& __io, 88797403Sobrien ios_base::iostate& __err, void*& __v) const 88897403Sobrien { 889132720Skan // Prepare for hex formatted input. 89097403Sobrien typedef ios_base::fmtflags fmtflags; 891132720Skan const fmtflags __fmt = __io.flags(); 892132720Skan __io.flags(__fmt & ~ios_base::basefield | ios_base::hex); 89397403Sobrien 894236829Spfg typedef __gnu_cxx::__conditional_type<(sizeof(void*) 895236829Spfg <= sizeof(unsigned long)), 896236829Spfg unsigned long, unsigned long long>::__type _UIntPtrType; 897236829Spfg 898236829Spfg _UIntPtrType __ul; 899132720Skan __beg = _M_extract_int(__beg, __end, __io, __err, __ul); 90097403Sobrien 901132720Skan // Reset from hex formatted input. 90297403Sobrien __io.flags(__fmt); 90397403Sobrien 90497403Sobrien if (!(__err & ios_base::failbit)) 90597403Sobrien __v = reinterpret_cast<void*>(__ul); 90697403Sobrien return __beg; 90797403Sobrien } 90897403Sobrien 909117397Skan // For use by integer and floating-point types after they have been 910117397Skan // converted into a char_type string. 911117397Skan template<typename _CharT, typename _OutIter> 912117397Skan void 913117397Skan num_put<_CharT, _OutIter>:: 914132720Skan _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 915117397Skan _CharT* __new, const _CharT* __cs, int& __len) const 916117397Skan { 917117397Skan // [22.2.2.2.2] Stage 3. 918117397Skan // If necessary, pad. 919132720Skan __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 920117397Skan __w, __len, true); 921117397Skan __len = static_cast<int>(__w); 922117397Skan } 923117397Skan 924169691Skan_GLIBCXX_END_LDBL_NAMESPACE 925117397Skan 926117397Skan template<typename _CharT, typename _ValueT> 927117397Skan int 928132720Skan __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, 929169691Skan ios_base::fmtflags __flags, bool __dec) 930117397Skan { 931169691Skan _CharT* __buf = __bufend; 932169691Skan if (__builtin_expect(__dec, true)) 933117397Skan { 934117397Skan // Decimal. 935132720Skan do 936117397Skan { 937169691Skan *--__buf = __lit[(__v % 10) + __num_base::_S_odigits]; 938117397Skan __v /= 10; 939132720Skan } 940117397Skan while (__v != 0); 941117397Skan } 942169691Skan else if ((__flags & ios_base::basefield) == ios_base::oct) 943117397Skan { 944117397Skan // Octal. 945132720Skan do 946117397Skan { 947169691Skan *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits]; 948117397Skan __v >>= 3; 949132720Skan } 950117397Skan while (__v != 0); 951117397Skan } 952117397Skan else 953117397Skan { 954117397Skan // Hex. 955117397Skan const bool __uppercase = __flags & ios_base::uppercase; 956132720Skan const int __case_offset = __uppercase ? __num_base::_S_oudigits 957132720Skan : __num_base::_S_odigits; 958132720Skan do 959117397Skan { 960169691Skan *--__buf = __lit[(__v & 0xf) + __case_offset]; 961117397Skan __v >>= 4; 962132720Skan } 963117397Skan while (__v != 0); 964117397Skan } 965169691Skan return __bufend - __buf; 966117397Skan } 967117397Skan 968169691Skan_GLIBCXX_BEGIN_LDBL_NAMESPACE 969169691Skan 970117397Skan template<typename _CharT, typename _OutIter> 971117397Skan void 972117397Skan num_put<_CharT, _OutIter>:: 973132720Skan _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, 974169691Skan ios_base&, _CharT* __new, _CharT* __cs, int& __len) const 975117397Skan { 976169691Skan _CharT* __p = std::__add_grouping(__new, __sep, __grouping, 977169691Skan __grouping_size, __cs, __cs + __len); 978117397Skan __len = __p - __new; 979117397Skan } 980169691Skan 981117397Skan template<typename _CharT, typename _OutIter> 982117397Skan template<typename _ValueT> 983117397Skan _OutIter 984117397Skan num_put<_CharT, _OutIter>:: 985132720Skan _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, 986132720Skan _ValueT __v) const 987117397Skan { 988169691Skan using __gnu_cxx::__add_unsigned; 989169691Skan typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; 990169691Skan typedef __numpunct_cache<_CharT> __cache_type; 991132720Skan __use_cache<__cache_type> __uc; 992132720Skan const locale& __loc = __io._M_getloc(); 993132720Skan const __cache_type* __lc = __uc(__loc); 994132720Skan const _CharT* __lit = __lc->_M_atoms_out; 995169691Skan const ios_base::fmtflags __flags = __io.flags(); 996117397Skan 997117397Skan // Long enough to hold hex, dec, and octal representations. 998169691Skan const int __ilen = 5 * sizeof(_ValueT); 999132720Skan _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1000117397Skan * __ilen)); 1001132720Skan 1002117397Skan // [22.2.2.2.2] Stage 1, numeric conversion to character. 1003117397Skan // Result is returned right-justified in the buffer. 1004169691Skan const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 1005169691Skan const bool __dec = (__basefield != ios_base::oct 1006169691Skan && __basefield != ios_base::hex); 1007169691Skan const __unsigned_type __u = (__v > 0 || !__dec) ? __v : -__v; 1008169691Skan int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec); 1009132720Skan __cs += __ilen - __len; 1010132720Skan 1011132720Skan // Add grouping, if necessary. 1012132720Skan if (__lc->_M_use_grouping) 1013117397Skan { 1014169691Skan // Grouping can add (almost) as many separators as the number 1015169691Skan // of digits + space is reserved for numeric base or sign. 1016132720Skan _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1017169691Skan * (__len + 1) 1018169691Skan * 2)); 1019132720Skan _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, 1020169691Skan __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len); 1021169691Skan __cs = __cs2 + 2; 1022117397Skan } 1023132720Skan 1024169691Skan // Complete Stage 1, prepend numeric base or sign. 1025169691Skan if (__builtin_expect(__dec, true)) 1026169691Skan { 1027169691Skan // Decimal. 1028228780Spfg if (__v >= 0) 1029169691Skan { 1030169691Skan if (__flags & ios_base::showpos 1031169691Skan && numeric_limits<_ValueT>::is_signed) 1032169691Skan *--__cs = __lit[__num_base::_S_oplus], ++__len; 1033169691Skan } 1034228780Spfg else 1035169691Skan *--__cs = __lit[__num_base::_S_ominus], ++__len; 1036169691Skan } 1037169691Skan else if (__flags & ios_base::showbase && __v) 1038169691Skan { 1039169691Skan if (__basefield == ios_base::oct) 1040169691Skan *--__cs = __lit[__num_base::_S_odigits], ++__len; 1041169691Skan else 1042169691Skan { 1043169691Skan // 'x' or 'X' 1044169691Skan const bool __uppercase = __flags & ios_base::uppercase; 1045169691Skan *--__cs = __lit[__num_base::_S_ox + __uppercase]; 1046169691Skan // '0' 1047169691Skan *--__cs = __lit[__num_base::_S_odigits]; 1048169691Skan __len += 2; 1049169691Skan } 1050169691Skan } 1051169691Skan 1052117397Skan // Pad. 1053132720Skan const streamsize __w = __io.width(); 1054117397Skan if (__w > static_cast<streamsize>(__len)) 1055117397Skan { 1056132720Skan _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1057132720Skan * __w)); 1058117397Skan _M_pad(__fill, __w, __io, __cs3, __cs, __len); 1059117397Skan __cs = __cs3; 1060117397Skan } 1061117397Skan __io.width(0); 1062117397Skan 1063117397Skan // [22.2.2.2.2] Stage 4. 1064117397Skan // Write resulting, fully-formatted string to output iterator. 1065132720Skan return std::__write(__s, __cs, __len); 1066132720Skan } 1067117397Skan 1068117397Skan template<typename _CharT, typename _OutIter> 1069117397Skan void 1070117397Skan num_put<_CharT, _OutIter>:: 1071132720Skan _M_group_float(const char* __grouping, size_t __grouping_size, 1072132720Skan _CharT __sep, const _CharT* __p, _CharT* __new, 1073132720Skan _CharT* __cs, int& __len) const 1074117397Skan { 1075132720Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 1076132720Skan // 282. What types does numpunct grouping refer to? 1077132720Skan // Add grouping, if necessary. 1078132720Skan const int __declen = __p ? __p - __cs : __len; 1079169691Skan _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping, 1080169691Skan __grouping_size, 1081169691Skan __cs, __cs + __declen); 1082132720Skan 1083117397Skan // Tack on decimal part. 1084117397Skan int __newlen = __p2 - __new; 1085117397Skan if (__p) 1086117397Skan { 1087117397Skan char_traits<_CharT>::copy(__p2, __p, __len - __declen); 1088117397Skan __newlen += __len - __declen; 1089132720Skan } 1090117397Skan __len = __newlen; 1091117397Skan } 1092117397Skan 1093169691Skan // The following code uses vsnprintf (or vsprintf(), when 1094132720Skan // _GLIBCXX_USE_C99 is not defined) to convert floating point values 1095117397Skan // for insertion into a stream. An optimization would be to replace 1096117397Skan // them with code that works directly on a wide buffer and then use 1097117397Skan // __pad to do the padding. It would be good to replace them anyway 1098117397Skan // to gain back the efficiency that C++ provides by knowing up front 1099117397Skan // the type of the values to insert. Also, sprintf is dangerous 1100117397Skan // since may lead to accidental buffer overruns. This 1101117397Skan // implementation follows the C++ standard fairly directly as 110297403Sobrien // outlined in 22.2.2.2 [lib.locale.num.put] 110397403Sobrien template<typename _CharT, typename _OutIter> 110497403Sobrien template<typename _ValueT> 110597403Sobrien _OutIter 110697403Sobrien num_put<_CharT, _OutIter>:: 1107132720Skan _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 110897403Sobrien _ValueT __v) const 110997403Sobrien { 1110169691Skan typedef __numpunct_cache<_CharT> __cache_type; 1111132720Skan __use_cache<__cache_type> __uc; 1112132720Skan const locale& __loc = __io._M_getloc(); 1113132720Skan const __cache_type* __lc = __uc(__loc); 1114117397Skan 1115117397Skan // Use default precision if out of range. 1116169691Skan const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision(); 111797403Sobrien 1118132720Skan const int __max_digits = numeric_limits<_ValueT>::digits10; 1119117397Skan 1120117397Skan // [22.2.2.2.2] Stage 1, numeric conversion to character. 1121117397Skan int __len; 112297403Sobrien // Long enough for the max format spec. 112397403Sobrien char __fbuf[16]; 1124169691Skan __num_base::_S_format_float(__io, __fbuf, __mod); 112597403Sobrien 1126132720Skan#ifdef _GLIBCXX_USE_C99 1127132720Skan // First try a buffer perhaps big enough (most probably sufficient 1128117397Skan // for non-ios_base::fixed outputs) 112997403Sobrien int __cs_size = __max_digits * 3; 113097403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1131169691Skan __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 1132169691Skan __fbuf, __prec, __v); 113397403Sobrien 113497403Sobrien // If the buffer was not large enough, try again with the correct size. 113597403Sobrien if (__len >= __cs_size) 113697403Sobrien { 1137132720Skan __cs_size = __len + 1; 113897403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1139169691Skan __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 1140169691Skan __fbuf, __prec, __v); 114197403Sobrien } 114297403Sobrien#else 114397403Sobrien // Consider the possibility of long ios_base::fixed outputs 114497403Sobrien const bool __fixed = __io.flags() & ios_base::fixed; 114597403Sobrien const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 1146117397Skan 1147132720Skan // The size of the output string is computed as follows. 1148132720Skan // ios_base::fixed outputs may need up to __max_exp + 1 chars 1149132720Skan // for the integer part + __prec chars for the fractional part 1150132720Skan // + 3 chars for sign, decimal point, '\0'. On the other hand, 1151132720Skan // for non-fixed outputs __max_digits * 2 + __prec chars are 1152132720Skan // largely sufficient. 1153132720Skan const int __cs_size = __fixed ? __max_exp + __prec + 4 1154132720Skan : __max_digits * 2 + __prec; 115597403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1156169691Skan __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, 1157169691Skan __prec, __v); 115897403Sobrien#endif 115997403Sobrien 1160169691Skan // [22.2.2.2.2] Stage 2, convert to char_type, using correct 1161169691Skan // numpunct.decimal_point() values for '.' and adding grouping. 1162169691Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1163169691Skan 1164169691Skan _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1165169691Skan * __len)); 1166169691Skan __ctype.widen(__cs, __cs + __len, __ws); 1167169691Skan 1168169691Skan // Replace decimal point. 1169169691Skan _CharT* __wp = 0; 1170169691Skan const char* __p = char_traits<char>::find(__cs, __len, '.'); 1171169691Skan if (__p) 1172169691Skan { 1173169691Skan __wp = __ws + (__p - __cs); 1174169691Skan *__wp = __lc->_M_decimal_point; 1175169691Skan } 1176169691Skan 1177169691Skan // Add grouping, if necessary. 1178169691Skan // N.B. Make sure to not group things like 2e20, i.e., no decimal 1179169691Skan // point, scientific notation. 1180169691Skan if (__lc->_M_use_grouping 1181169691Skan && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9' 1182169691Skan && __cs[1] >= '0' && __cs[2] >= '0'))) 1183169691Skan { 1184169691Skan // Grouping can add (almost) as many separators as the 1185169691Skan // number of digits, but no more. 1186169691Skan _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1187169691Skan * __len * 2)); 1188169691Skan 1189169691Skan streamsize __off = 0; 1190169691Skan if (__cs[0] == '-' || __cs[0] == '+') 1191169691Skan { 1192169691Skan __off = 1; 1193169691Skan __ws2[0] = __ws[0]; 1194169691Skan __len -= 1; 1195169691Skan } 1196169691Skan 1197169691Skan _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, 1198169691Skan __lc->_M_thousands_sep, __wp, __ws2 + __off, 1199169691Skan __ws + __off, __len); 1200169691Skan __len += __off; 1201169691Skan 1202169691Skan __ws = __ws2; 1203169691Skan } 1204117397Skan 1205169691Skan // Pad. 1206169691Skan const streamsize __w = __io.width(); 1207169691Skan if (__w > static_cast<streamsize>(__len)) 1208169691Skan { 1209169691Skan _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1210169691Skan * __w)); 1211169691Skan _M_pad(__fill, __w, __io, __ws3, __ws, __len); 1212169691Skan __ws = __ws3; 1213169691Skan } 1214169691Skan __io.width(0); 1215169691Skan 1216169691Skan // [22.2.2.2.2] Stage 4. 1217169691Skan // Write resulting, fully-formatted string to output iterator. 1218169691Skan return std::__write(__s, __ws, __len); 1219117397Skan } 1220169691Skan 122197403Sobrien template<typename _CharT, typename _OutIter> 122297403Sobrien _OutIter 122397403Sobrien num_put<_CharT, _OutIter>:: 122497403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 122597403Sobrien { 1226132720Skan const ios_base::fmtflags __flags = __io.flags(); 122797403Sobrien if ((__flags & ios_base::boolalpha) == 0) 122897403Sobrien { 1229146897Skan const long __l = __v; 1230146897Skan __s = _M_insert_int(__s, __io, __fill, __l); 123197403Sobrien } 123297403Sobrien else 123397403Sobrien { 1234169691Skan typedef __numpunct_cache<_CharT> __cache_type; 1235132720Skan __use_cache<__cache_type> __uc; 1236132720Skan const locale& __loc = __io._M_getloc(); 1237132720Skan const __cache_type* __lc = __uc(__loc); 1238117397Skan 1239132720Skan const _CharT* __name = __v ? __lc->_M_truename 1240132720Skan : __lc->_M_falsename; 1241132720Skan int __len = __v ? __lc->_M_truename_size 1242132720Skan : __lc->_M_falsename_size; 1243117397Skan 1244132720Skan const streamsize __w = __io.width(); 1245117397Skan if (__w > static_cast<streamsize>(__len)) 1246117397Skan { 1247132720Skan _CharT* __cs 1248132720Skan = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1249132720Skan * __w)); 1250132720Skan _M_pad(__fill, __w, __io, __cs, __name, __len); 1251132720Skan __name = __cs; 1252117397Skan } 1253117397Skan __io.width(0); 1254132720Skan __s = std::__write(__s, __name, __len); 125597403Sobrien } 125697403Sobrien return __s; 125797403Sobrien } 125897403Sobrien 125997403Sobrien template<typename _CharT, typename _OutIter> 126097403Sobrien _OutIter 126197403Sobrien num_put<_CharT, _OutIter>:: 126297403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 1263132720Skan { return _M_insert_int(__s, __io, __fill, __v); } 126497403Sobrien 126597403Sobrien template<typename _CharT, typename _OutIter> 126697403Sobrien _OutIter 126797403Sobrien num_put<_CharT, _OutIter>:: 126897403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 126997403Sobrien unsigned long __v) const 1270132720Skan { return _M_insert_int(__s, __io, __fill, __v); } 127197403Sobrien 1272132720Skan#ifdef _GLIBCXX_USE_LONG_LONG 127397403Sobrien template<typename _CharT, typename _OutIter> 127497403Sobrien _OutIter 127597403Sobrien num_put<_CharT, _OutIter>:: 1276169691Skan do_put(iter_type __s, ios_base& __io, char_type __fill, long long __v) const 1277169691Skan { return _M_insert_int(__s, __io, __fill, __v); } 127897403Sobrien 127997403Sobrien template<typename _CharT, typename _OutIter> 128097403Sobrien _OutIter 128197403Sobrien num_put<_CharT, _OutIter>:: 128297403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 128397403Sobrien unsigned long long __v) const 1284132720Skan { return _M_insert_int(__s, __io, __fill, __v); } 128597403Sobrien#endif 128697403Sobrien 128797403Sobrien template<typename _CharT, typename _OutIter> 128897403Sobrien _OutIter 128997403Sobrien num_put<_CharT, _OutIter>:: 129097403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 1291132720Skan { return _M_insert_float(__s, __io, __fill, char(), __v); } 129297403Sobrien 1293169691Skan#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 129497403Sobrien template<typename _CharT, typename _OutIter> 129597403Sobrien _OutIter 129697403Sobrien num_put<_CharT, _OutIter>:: 1297169691Skan __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 1298169691Skan { return _M_insert_float(__s, __io, __fill, char(), __v); } 1299169691Skan#endif 1300169691Skan 1301169691Skan template<typename _CharT, typename _OutIter> 1302169691Skan _OutIter 1303169691Skan num_put<_CharT, _OutIter>:: 1304132720Skan do_put(iter_type __s, ios_base& __io, char_type __fill, 130597403Sobrien long double __v) const 1306132720Skan { return _M_insert_float(__s, __io, __fill, 'L', __v); } 130797403Sobrien 130897403Sobrien template<typename _CharT, typename _OutIter> 130997403Sobrien _OutIter 131097403Sobrien num_put<_CharT, _OutIter>:: 131197403Sobrien do_put(iter_type __s, ios_base& __io, char_type __fill, 131297403Sobrien const void* __v) const 131397403Sobrien { 1314132720Skan const ios_base::fmtflags __flags = __io.flags(); 1315146897Skan const ios_base::fmtflags __fmt = ~(ios_base::basefield 1316132720Skan | ios_base::uppercase 1317132720Skan | ios_base::internal); 131897403Sobrien __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 1319132720Skan 1320236829Spfg typedef __gnu_cxx::__conditional_type<(sizeof(const void*) 1321236829Spfg <= sizeof(unsigned long)), 1322236829Spfg unsigned long, unsigned long long>::__type _UIntPtrType; 1323236829Spfg 1324132720Skan __s = _M_insert_int(__s, __io, __fill, 1325236829Spfg reinterpret_cast<_UIntPtrType>(__v)); 1326132720Skan __io.flags(__flags); 132797403Sobrien return __s; 132897403Sobrien } 132997403Sobrien 133097403Sobrien template<typename _CharT, typename _InIter> 1331132720Skan template<bool _Intl> 1332132720Skan _InIter 1333132720Skan money_get<_CharT, _InIter>:: 1334132720Skan _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 1335132720Skan ios_base::iostate& __err, string& __units) const 1336132720Skan { 1337132720Skan typedef char_traits<_CharT> __traits_type; 1338132720Skan typedef typename string_type::size_type size_type; 1339132720Skan typedef money_base::part part; 1340169691Skan typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 1341132720Skan 1342132720Skan const locale& __loc = __io._M_getloc(); 1343132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 134497403Sobrien 1345132720Skan __use_cache<__cache_type> __uc; 1346132720Skan const __cache_type* __lc = __uc(__loc); 1347132720Skan const char_type* __lit = __lc->_M_atoms; 134897403Sobrien 1349132720Skan // Deduced sign. 1350132720Skan bool __negative = false; 1351132720Skan // Sign size. 1352132720Skan size_type __sign_size = 0; 1353132720Skan // True if sign is mandatory. 1354132720Skan const bool __mandatory_sign = (__lc->_M_positive_sign_size 1355132720Skan && __lc->_M_negative_sign_size); 1356132720Skan // String of grouping info from thousands_sep plucked from __units. 1357132720Skan string __grouping_tmp; 1358132720Skan if (__lc->_M_use_grouping) 1359132720Skan __grouping_tmp.reserve(32); 1360132720Skan // Last position before the decimal point. 1361132720Skan int __last_pos = 0; 1362132720Skan // Separator positions, then, possibly, fractional digits. 1363132720Skan int __n = 0; 1364132720Skan // If input iterator is in a valid state. 1365132720Skan bool __testvalid = true; 1366132720Skan // Flag marking when a decimal point is found. 1367132720Skan bool __testdecfound = false; 136897403Sobrien 1369132720Skan // The tentative returned string is stored here. 1370132720Skan string __res; 1371132720Skan __res.reserve(32); 137297403Sobrien 1373132720Skan const char_type* __lit_zero = __lit + money_base::_S_zero; 1374169691Skan const money_base::pattern __p = __lc->_M_neg_format; 1375132720Skan for (int __i = 0; __i < 4 && __testvalid; ++__i) 1376132720Skan { 1377132720Skan const part __which = static_cast<part>(__p.field[__i]); 1378132720Skan switch (__which) 1379132720Skan { 1380132720Skan case money_base::symbol: 1381132720Skan // According to 22.2.6.1.2, p2, symbol is required 1382132720Skan // if (__io.flags() & ios_base::showbase), otherwise 1383132720Skan // is optional and consumed only if other characters 1384132720Skan // are needed to complete the format. 1385132720Skan if (__io.flags() & ios_base::showbase || __sign_size > 1 1386132720Skan || __i == 0 1387132720Skan || (__i == 1 && (__mandatory_sign 1388132720Skan || (static_cast<part>(__p.field[0]) 1389132720Skan == money_base::sign) 1390132720Skan || (static_cast<part>(__p.field[2]) 1391132720Skan == money_base::space))) 1392132720Skan || (__i == 2 && ((static_cast<part>(__p.field[3]) 1393132720Skan == money_base::value) 1394241957Sdim || (__mandatory_sign 1395132720Skan && (static_cast<part>(__p.field[3]) 1396241957Sdim == money_base::sign))))) 139797403Sobrien { 1398132720Skan const size_type __len = __lc->_M_curr_symbol_size; 1399132720Skan size_type __j = 0; 1400132720Skan for (; __beg != __end && __j < __len 1401132720Skan && *__beg == __lc->_M_curr_symbol[__j]; 1402132720Skan ++__beg, ++__j); 1403132720Skan if (__j != __len 1404132720Skan && (__j || __io.flags() & ios_base::showbase)) 140597403Sobrien __testvalid = false; 140697403Sobrien } 1407132720Skan break; 1408132720Skan case money_base::sign: 1409132720Skan // Sign might not exist, or be more than one character long. 1410132720Skan if (__lc->_M_positive_sign_size && __beg != __end 1411132720Skan && *__beg == __lc->_M_positive_sign[0]) 1412132720Skan { 1413132720Skan __sign_size = __lc->_M_positive_sign_size; 1414132720Skan ++__beg; 1415132720Skan } 1416132720Skan else if (__lc->_M_negative_sign_size && __beg != __end 1417132720Skan && *__beg == __lc->_M_negative_sign[0]) 1418132720Skan { 1419132720Skan __negative = true; 1420132720Skan __sign_size = __lc->_M_negative_sign_size; 1421132720Skan ++__beg; 1422132720Skan } 1423132720Skan else if (__lc->_M_positive_sign_size 1424132720Skan && !__lc->_M_negative_sign_size) 1425132720Skan // "... if no sign is detected, the result is given the sign 1426132720Skan // that corresponds to the source of the empty string" 1427132720Skan __negative = true; 1428132720Skan else if (__mandatory_sign) 1429132720Skan __testvalid = false; 1430132720Skan break; 1431132720Skan case money_base::value: 1432132720Skan // Extract digits, remove and stash away the 1433132720Skan // grouping of found thousands separators. 1434132720Skan for (; __beg != __end; ++__beg) 1435169691Skan { 1436169691Skan const char_type __c = *__beg; 1437169691Skan const char_type* __q = __traits_type::find(__lit_zero, 1438169691Skan 10, __c); 1439169691Skan if (__q != 0) 1440169691Skan { 1441169691Skan __res += money_base::_S_atoms[__q - __lit]; 1442169691Skan ++__n; 1443169691Skan } 1444169691Skan else if (__c == __lc->_M_decimal_point 1445169691Skan && !__testdecfound) 1446169691Skan { 1447169691Skan __last_pos = __n; 1448169691Skan __n = 0; 1449169691Skan __testdecfound = true; 1450169691Skan } 1451169691Skan else if (__lc->_M_use_grouping 1452169691Skan && __c == __lc->_M_thousands_sep 1453169691Skan && !__testdecfound) 1454169691Skan { 1455169691Skan if (__n) 1456169691Skan { 1457169691Skan // Mark position for later analysis. 1458169691Skan __grouping_tmp += static_cast<char>(__n); 1459169691Skan __n = 0; 1460169691Skan } 1461169691Skan else 1462169691Skan { 1463169691Skan __testvalid = false; 1464169691Skan break; 1465169691Skan } 1466169691Skan } 1467169691Skan else 1468169691Skan break; 1469169691Skan } 1470132720Skan if (__res.empty()) 1471132720Skan __testvalid = false; 1472132720Skan break; 1473132720Skan case money_base::space: 1474132720Skan // At least one space is required. 1475132720Skan if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) 1476132720Skan ++__beg; 1477132720Skan else 1478132720Skan __testvalid = false; 1479132720Skan case money_base::none: 1480132720Skan // Only if not at the end of the pattern. 1481132720Skan if (__i != 3) 1482132720Skan for (; __beg != __end 1483132720Skan && __ctype.is(ctype_base::space, *__beg); ++__beg); 1484132720Skan break; 1485132720Skan } 1486132720Skan } 148797403Sobrien 1488132720Skan // Need to get the rest of the sign characters, if they exist. 1489132720Skan if (__sign_size > 1 && __testvalid) 1490132720Skan { 1491132720Skan const char_type* __sign = __negative ? __lc->_M_negative_sign 1492132720Skan : __lc->_M_positive_sign; 1493132720Skan size_type __i = 1; 1494132720Skan for (; __beg != __end && __i < __sign_size 1495132720Skan && *__beg == __sign[__i]; ++__beg, ++__i); 1496132720Skan 1497132720Skan if (__i != __sign_size) 1498132720Skan __testvalid = false; 1499132720Skan } 150097403Sobrien 1501132720Skan if (__testvalid) 1502132720Skan { 1503132720Skan // Strip leading zeros. 1504132720Skan if (__res.size() > 1) 1505132720Skan { 1506132720Skan const size_type __first = __res.find_first_not_of('0'); 1507132720Skan const bool __only_zeros = __first == string::npos; 1508132720Skan if (__first) 1509132720Skan __res.erase(0, __only_zeros ? __res.size() - 1 : __first); 1510132720Skan } 151197403Sobrien 1512132720Skan // 22.2.6.1.2, p4 1513132720Skan if (__negative && __res[0] != '0') 1514132720Skan __res.insert(__res.begin(), '-'); 1515132720Skan 1516132720Skan // Test for grouping fidelity. 1517132720Skan if (__grouping_tmp.size()) 1518132720Skan { 1519132720Skan // Add the ending grouping. 1520132720Skan __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos 1521132720Skan : __n); 1522132720Skan if (!std::__verify_grouping(__lc->_M_grouping, 1523132720Skan __lc->_M_grouping_size, 1524132720Skan __grouping_tmp)) 1525169691Skan __err |= ios_base::failbit; 1526132720Skan } 1527132720Skan 1528132720Skan // Iff not enough digits were supplied after the decimal-point. 1529132720Skan if (__testdecfound && __lc->_M_frac_digits > 0 1530132720Skan && __n != __lc->_M_frac_digits) 1531132720Skan __testvalid = false; 1532132720Skan } 1533132720Skan 1534132720Skan // Iff valid sequence is not recognized. 1535132720Skan if (!__testvalid) 1536132720Skan __err |= ios_base::failbit; 1537132720Skan else 1538132720Skan __units.swap(__res); 1539132720Skan 1540169691Skan // Iff no more characters are available. 1541169691Skan if (__beg == __end) 1542169691Skan __err |= ios_base::eofbit; 1543132720Skan return __beg; 1544132720Skan } 154597403Sobrien 1546169691Skan#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 1547132720Skan template<typename _CharT, typename _InIter> 1548132720Skan _InIter 1549132720Skan money_get<_CharT, _InIter>:: 1550169691Skan __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1551169691Skan ios_base::iostate& __err, double& __units) const 1552169691Skan { 1553169691Skan string __str; 1554169691Skan __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 1555169691Skan : _M_extract<false>(__beg, __end, __io, __err, __str); 1556169691Skan std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 1557169691Skan return __beg; 1558169691Skan } 1559169691Skan#endif 1560169691Skan 1561169691Skan template<typename _CharT, typename _InIter> 1562169691Skan _InIter 1563169691Skan money_get<_CharT, _InIter>:: 1564132720Skan do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1565132720Skan ios_base::iostate& __err, long double& __units) const 1566132720Skan { 1567132720Skan string __str; 1568169691Skan __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 1569169691Skan : _M_extract<false>(__beg, __end, __io, __err, __str); 1570132720Skan std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 1571132720Skan return __beg; 1572132720Skan } 1573132720Skan 1574132720Skan template<typename _CharT, typename _InIter> 1575132720Skan _InIter 1576132720Skan money_get<_CharT, _InIter>:: 1577132720Skan do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1578169691Skan ios_base::iostate& __err, string_type& __digits) const 1579132720Skan { 1580132720Skan typedef typename string::size_type size_type; 1581132720Skan 1582132720Skan const locale& __loc = __io._M_getloc(); 1583132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1584132720Skan 1585132720Skan string __str; 1586169691Skan __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 1587169691Skan : _M_extract<false>(__beg, __end, __io, __err, __str); 1588132720Skan const size_type __len = __str.size(); 1589132720Skan if (__len) 159097403Sobrien { 1591169691Skan __digits.resize(__len); 1592169691Skan __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]); 159397403Sobrien } 1594169691Skan return __beg; 1595132720Skan } 159697403Sobrien 1597132720Skan template<typename _CharT, typename _OutIter> 1598132720Skan template<bool _Intl> 1599132720Skan _OutIter 1600132720Skan money_put<_CharT, _OutIter>:: 1601132720Skan _M_insert(iter_type __s, ios_base& __io, char_type __fill, 1602132720Skan const string_type& __digits) const 1603132720Skan { 1604132720Skan typedef typename string_type::size_type size_type; 1605132720Skan typedef money_base::part part; 1606169691Skan typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 1607132720Skan 1608132720Skan const locale& __loc = __io._M_getloc(); 1609132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 161097403Sobrien 1611132720Skan __use_cache<__cache_type> __uc; 1612132720Skan const __cache_type* __lc = __uc(__loc); 1613132720Skan const char_type* __lit = __lc->_M_atoms; 161497403Sobrien 1615132720Skan // Determine if negative or positive formats are to be used, and 1616132720Skan // discard leading negative_sign if it is present. 1617132720Skan const char_type* __beg = __digits.data(); 1618132720Skan 1619132720Skan money_base::pattern __p; 1620132720Skan const char_type* __sign; 1621132720Skan size_type __sign_size; 1622169691Skan if (!(*__beg == __lit[money_base::_S_minus])) 1623132720Skan { 1624132720Skan __p = __lc->_M_pos_format; 1625132720Skan __sign = __lc->_M_positive_sign; 1626132720Skan __sign_size = __lc->_M_positive_sign_size; 1627132720Skan } 1628132720Skan else 1629132720Skan { 1630132720Skan __p = __lc->_M_neg_format; 1631132720Skan __sign = __lc->_M_negative_sign; 1632132720Skan __sign_size = __lc->_M_negative_sign_size; 1633132720Skan if (__digits.size()) 1634132720Skan ++__beg; 1635132720Skan } 1636132720Skan 1637132720Skan // Look for valid numbers in the ctype facet within input digits. 1638132720Skan size_type __len = __ctype.scan_not(ctype_base::digit, __beg, 1639132720Skan __beg + __digits.size()) - __beg; 1640132720Skan if (__len) 1641132720Skan { 1642132720Skan // Assume valid input, and attempt to format. 1643132720Skan // Break down input numbers into base components, as follows: 1644132720Skan // final_value = grouped units + (decimal point) + (digits) 1645132720Skan string_type __value; 1646132720Skan __value.reserve(2 * __len); 1647132720Skan 1648132720Skan // Add thousands separators to non-decimal digits, per 1649132720Skan // grouping rules. 1650169691Skan long __paddec = __len - __lc->_M_frac_digits; 1651132720Skan if (__paddec > 0) 1652132720Skan { 1653132720Skan if (__lc->_M_frac_digits < 0) 1654132720Skan __paddec = __len; 1655132720Skan if (__lc->_M_grouping_size) 1656132720Skan { 1657169691Skan __value.assign(2 * __paddec, char_type()); 1658169691Skan _CharT* __vend = 1659169691Skan std::__add_grouping(&__value[0], __lc->_M_thousands_sep, 1660132720Skan __lc->_M_grouping, 1661132720Skan __lc->_M_grouping_size, 1662132720Skan __beg, __beg + __paddec); 1663169691Skan __value.erase(__vend - &__value[0]); 1664132720Skan } 1665132720Skan else 1666132720Skan __value.assign(__beg, __paddec); 1667132720Skan } 1668132720Skan 1669132720Skan // Deal with decimal point, decimal digits. 1670132720Skan if (__lc->_M_frac_digits > 0) 1671132720Skan { 1672132720Skan __value += __lc->_M_decimal_point; 1673132720Skan if (__paddec >= 0) 1674132720Skan __value.append(__beg + __paddec, __lc->_M_frac_digits); 1675132720Skan else 1676132720Skan { 1677132720Skan // Have to pad zeros in the decimal position. 1678132720Skan __value.append(-__paddec, __lit[money_base::_S_zero]); 1679132720Skan __value.append(__beg, __len); 1680132720Skan } 1681132720Skan } 1682132720Skan 1683132720Skan // Calculate length of resulting string. 1684132720Skan const ios_base::fmtflags __f = __io.flags() 1685132720Skan & ios_base::adjustfield; 1686132720Skan __len = __value.size() + __sign_size; 1687132720Skan __len += ((__io.flags() & ios_base::showbase) 1688132720Skan ? __lc->_M_curr_symbol_size : 0); 1689132720Skan 1690132720Skan string_type __res; 1691132720Skan __res.reserve(2 * __len); 1692132720Skan 1693132720Skan const size_type __width = static_cast<size_type>(__io.width()); 1694132720Skan const bool __testipad = (__f == ios_base::internal 1695132720Skan && __len < __width); 1696132720Skan // Fit formatted digits into the required pattern. 1697132720Skan for (int __i = 0; __i < 4; ++__i) 1698132720Skan { 1699132720Skan const part __which = static_cast<part>(__p.field[__i]); 1700132720Skan switch (__which) 1701132720Skan { 1702132720Skan case money_base::symbol: 1703132720Skan if (__io.flags() & ios_base::showbase) 1704132720Skan __res.append(__lc->_M_curr_symbol, 1705132720Skan __lc->_M_curr_symbol_size); 1706132720Skan break; 1707132720Skan case money_base::sign: 1708132720Skan // Sign might not exist, or be more than one 1709132720Skan // charater long. In that case, add in the rest 1710132720Skan // below. 1711132720Skan if (__sign_size) 1712132720Skan __res += __sign[0]; 1713132720Skan break; 1714132720Skan case money_base::value: 1715132720Skan __res += __value; 1716132720Skan break; 1717132720Skan case money_base::space: 1718132720Skan // At least one space is required, but if internal 1719132720Skan // formatting is required, an arbitrary number of 1720132720Skan // fill spaces will be necessary. 1721132720Skan if (__testipad) 1722132720Skan __res.append(__width - __len, __fill); 1723132720Skan else 1724132720Skan __res += __fill; 1725132720Skan break; 1726132720Skan case money_base::none: 1727132720Skan if (__testipad) 1728132720Skan __res.append(__width - __len, __fill); 1729132720Skan break; 1730132720Skan } 1731132720Skan } 1732132720Skan 1733132720Skan // Special case of multi-part sign parts. 1734132720Skan if (__sign_size > 1) 1735132720Skan __res.append(__sign + 1, __sign_size - 1); 1736132720Skan 1737132720Skan // Pad, if still necessary. 1738132720Skan __len = __res.size(); 1739132720Skan if (__width > __len) 1740132720Skan { 1741132720Skan if (__f == ios_base::left) 1742132720Skan // After. 1743132720Skan __res.append(__width - __len, __fill); 1744132720Skan else 1745132720Skan // Before. 1746132720Skan __res.insert(0, __width - __len, __fill); 1747132720Skan __len = __width; 1748132720Skan } 1749132720Skan 1750132720Skan // Write resulting, fully-formatted string to output iterator. 1751132720Skan __s = std::__write(__s, __res.data(), __len); 1752132720Skan } 1753132720Skan __io.width(0); 1754132720Skan return __s; 1755132720Skan } 1756169691Skan 1757169691Skan#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 175897403Sobrien template<typename _CharT, typename _OutIter> 175997403Sobrien _OutIter 176097403Sobrien money_put<_CharT, _OutIter>:: 1761169691Skan __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 1762169691Skan double __units) const 1763169691Skan { return this->do_put(__s, __intl, __io, __fill, (long double) __units); } 1764169691Skan#endif 1765169691Skan 1766169691Skan template<typename _CharT, typename _OutIter> 1767169691Skan _OutIter 1768169691Skan money_put<_CharT, _OutIter>:: 176997403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 177097403Sobrien long double __units) const 1771132720Skan { 177297403Sobrien const locale __loc = __io.getloc(); 177397403Sobrien const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1774132720Skan#ifdef _GLIBCXX_USE_C99 177597403Sobrien // First try a buffer perhaps big enough. 177697403Sobrien int __cs_size = 64; 177797403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1778132720Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 1779132720Skan // 328. Bad sprintf format modifier in money_put<>::do_put() 1780169691Skan int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 1781169691Skan "%.*Lf", 0, __units); 178297403Sobrien // If the buffer was not large enough, try again with the correct size. 178397403Sobrien if (__len >= __cs_size) 178497403Sobrien { 178597403Sobrien __cs_size = __len + 1; 178697403Sobrien __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1787169691Skan __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 1788169691Skan "%.*Lf", 0, __units); 178997403Sobrien } 179097403Sobrien#else 1791132720Skan // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 1792132720Skan const int __cs_size = numeric_limits<long double>::max_exponent10 + 3; 179397403Sobrien char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1794169691Skan int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 1795169691Skan 0, __units); 179697403Sobrien#endif 1797169691Skan string_type __digits(__len, char_type()); 1798169691Skan __ctype.widen(__cs, __cs + __len, &__digits[0]); 1799132720Skan return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 1800132720Skan : _M_insert<false>(__s, __io, __fill, __digits); 180197403Sobrien } 180297403Sobrien 180397403Sobrien template<typename _CharT, typename _OutIter> 180497403Sobrien _OutIter 180597403Sobrien money_put<_CharT, _OutIter>:: 180697403Sobrien do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 180797403Sobrien const string_type& __digits) const 1808132720Skan { return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 1809132720Skan : _M_insert<false>(__s, __io, __fill, __digits); } 181097403Sobrien 1811169691Skan_GLIBCXX_END_LDBL_NAMESPACE 181297403Sobrien 181397403Sobrien // NB: Not especially useful. Without an ios_base object or some 181497403Sobrien // kind of locale reference, we are left clawing at the air where 181597403Sobrien // the side of the mountain used to be... 181697403Sobrien template<typename _CharT, typename _InIter> 181797403Sobrien time_base::dateorder 181897403Sobrien time_get<_CharT, _InIter>::do_date_order() const 181997403Sobrien { return time_base::no_order; } 182097403Sobrien 1821132720Skan // Expand a strftime format string and parse it. E.g., do_get_date() may 1822132720Skan // pass %m/%d/%Y => extracted characters. 182397403Sobrien template<typename _CharT, typename _InIter> 1824132720Skan _InIter 182597403Sobrien time_get<_CharT, _InIter>:: 1826132720Skan _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 1827132720Skan ios_base::iostate& __err, tm* __tm, 182897403Sobrien const _CharT* __format) const 1829132720Skan { 1830132720Skan const locale& __loc = __io._M_getloc(); 1831132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1832132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1833132720Skan const size_t __len = char_traits<_CharT>::length(__format); 183497403Sobrien 1835169691Skan ios_base::iostate __tmperr = ios_base::goodbit; 1836169691Skan for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i) 183797403Sobrien { 1838132720Skan if (__ctype.narrow(__format[__i], 0) == '%') 183997403Sobrien { 184097403Sobrien // Verify valid formatting code, attempt to extract. 1841132720Skan char __c = __ctype.narrow(__format[++__i], 0); 1842132720Skan int __mem = 0; 184397403Sobrien if (__c == 'E' || __c == 'O') 1844132720Skan __c = __ctype.narrow(__format[++__i], 0); 184597403Sobrien switch (__c) 184697403Sobrien { 184797403Sobrien const char* __cs; 184897403Sobrien _CharT __wcs[10]; 184997403Sobrien case 'a': 185097403Sobrien // Abbreviated weekday name [tm_wday] 185197403Sobrien const char_type* __days1[7]; 185297403Sobrien __tp._M_days_abbreviated(__days1); 1853132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 1854169691Skan 7, __io, __tmperr); 185597403Sobrien break; 185697403Sobrien case 'A': 185797403Sobrien // Weekday name [tm_wday]. 185897403Sobrien const char_type* __days2[7]; 185997403Sobrien __tp._M_days(__days2); 1860132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 1861169691Skan 7, __io, __tmperr); 186297403Sobrien break; 186397403Sobrien case 'h': 186497403Sobrien case 'b': 186597403Sobrien // Abbreviated month name [tm_mon] 186697403Sobrien const char_type* __months1[12]; 186797403Sobrien __tp._M_months_abbreviated(__months1); 1868132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 1869169691Skan __months1, 12, __io, __tmperr); 187097403Sobrien break; 187197403Sobrien case 'B': 187297403Sobrien // Month name [tm_mon]. 187397403Sobrien const char_type* __months2[12]; 187497403Sobrien __tp._M_months(__months2); 1875132720Skan __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 1876169691Skan __months2, 12, __io, __tmperr); 187797403Sobrien break; 187897403Sobrien case 'c': 187997403Sobrien // Default time and date representation. 188097403Sobrien const char_type* __dt[2]; 188197403Sobrien __tp._M_date_time_formats(__dt); 1882169691Skan __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 1883132720Skan __tm, __dt[0]); 188497403Sobrien break; 188597403Sobrien case 'd': 188697403Sobrien // Day [01, 31]. [tm_mday] 1887132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 1888169691Skan __io, __tmperr); 188997403Sobrien break; 1890132720Skan case 'e': 1891132720Skan // Day [1, 31], with single digits preceded by 1892132720Skan // space. [tm_mday] 1893132720Skan if (__ctype.is(ctype_base::space, *__beg)) 1894132720Skan __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, 1895169691Skan 1, __io, __tmperr); 1896132720Skan else 1897132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, 1898169691Skan 2, __io, __tmperr); 1899132720Skan break; 190097403Sobrien case 'D': 190197403Sobrien // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 190297403Sobrien __cs = "%m/%d/%y"; 190397403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 1904169691Skan __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 1905132720Skan __tm, __wcs); 190697403Sobrien break; 190797403Sobrien case 'H': 190897403Sobrien // Hour [00, 23]. [tm_hour] 1909132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 1910169691Skan __io, __tmperr); 191197403Sobrien break; 191297403Sobrien case 'I': 191397403Sobrien // Hour [01, 12]. [tm_hour] 1914132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 1915169691Skan __io, __tmperr); 191697403Sobrien break; 191797403Sobrien case 'm': 191897403Sobrien // Month [01, 12]. [tm_mon] 1919132720Skan __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 1920169691Skan __io, __tmperr); 1921169691Skan if (!__tmperr) 192297403Sobrien __tm->tm_mon = __mem - 1; 192397403Sobrien break; 192497403Sobrien case 'M': 192597403Sobrien // Minute [00, 59]. [tm_min] 1926132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 1927169691Skan __io, __tmperr); 192897403Sobrien break; 192997403Sobrien case 'n': 193097403Sobrien if (__ctype.narrow(*__beg, 0) == '\n') 193197403Sobrien ++__beg; 193297403Sobrien else 1933169691Skan __tmperr |= ios_base::failbit; 193497403Sobrien break; 193597403Sobrien case 'R': 193697403Sobrien // Equivalent to (%H:%M). 193797403Sobrien __cs = "%H:%M"; 193897403Sobrien __ctype.widen(__cs, __cs + 6, __wcs); 1939169691Skan __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 1940132720Skan __tm, __wcs); 194197403Sobrien break; 194297403Sobrien case 'S': 1943146897Skan // Seconds. [tm_sec] 1944146897Skan // [00, 60] in C99 (one leap-second), [00, 61] in C89. 1945146897Skan#ifdef _GLIBCXX_USE_C99 1946146897Skan __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2, 1947146897Skan#else 1948146897Skan __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2, 1949146897Skan#endif 1950169691Skan __io, __tmperr); 195197403Sobrien break; 195297403Sobrien case 't': 195397403Sobrien if (__ctype.narrow(*__beg, 0) == '\t') 195497403Sobrien ++__beg; 195597403Sobrien else 1956169691Skan __tmperr |= ios_base::failbit; 195797403Sobrien break; 195897403Sobrien case 'T': 195997403Sobrien // Equivalent to (%H:%M:%S). 196097403Sobrien __cs = "%H:%M:%S"; 196197403Sobrien __ctype.widen(__cs, __cs + 9, __wcs); 1962169691Skan __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 1963132720Skan __tm, __wcs); 196497403Sobrien break; 196597403Sobrien case 'x': 196697403Sobrien // Locale's date. 196797403Sobrien const char_type* __dates[2]; 196897403Sobrien __tp._M_date_formats(__dates); 1969169691Skan __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 1970132720Skan __tm, __dates[0]); 197197403Sobrien break; 197297403Sobrien case 'X': 197397403Sobrien // Locale's time. 197497403Sobrien const char_type* __times[2]; 197597403Sobrien __tp._M_time_formats(__times); 1976169691Skan __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 1977132720Skan __tm, __times[0]); 197897403Sobrien break; 197997403Sobrien case 'y': 1980132720Skan case 'C': // C99 198197403Sobrien // Two digit year. [tm_year] 1982132720Skan __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 1983169691Skan __io, __tmperr); 198497403Sobrien break; 198597403Sobrien case 'Y': 198697403Sobrien // Year [1900). [tm_year] 1987132720Skan __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 1988169691Skan __io, __tmperr); 1989169691Skan if (!__tmperr) 199097403Sobrien __tm->tm_year = __mem - 1900; 199197403Sobrien break; 199297403Sobrien case 'Z': 199397403Sobrien // Timezone info. 199497403Sobrien if (__ctype.is(ctype_base::upper, *__beg)) 199597403Sobrien { 199697403Sobrien int __tmp; 1997132720Skan __beg = _M_extract_name(__beg, __end, __tmp, 1998132720Skan __timepunct_cache<_CharT>::_S_timezones, 1999169691Skan 14, __io, __tmperr); 2000132720Skan 200197403Sobrien // GMT requires special effort. 2002169691Skan if (__beg != __end && !__tmperr && __tmp == 0 2003132720Skan && (*__beg == __ctype.widen('-') 2004132720Skan || *__beg == __ctype.widen('+'))) 200597403Sobrien { 2006132720Skan __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 2007169691Skan __io, __tmperr); 2008132720Skan __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 2009169691Skan __io, __tmperr); 2010132720Skan } 201197403Sobrien } 201297403Sobrien else 2013169691Skan __tmperr |= ios_base::failbit; 2014132720Skan break; 2015132720Skan default: 2016132720Skan // Not recognized. 2017169691Skan __tmperr |= ios_base::failbit; 201897403Sobrien } 2019132720Skan } 2020132720Skan else 2021132720Skan { 2022132720Skan // Verify format and input match, extract and discard. 2023132720Skan if (__format[__i] == *__beg) 2024132720Skan ++__beg; 2025132720Skan else 2026169691Skan __tmperr |= ios_base::failbit; 2027132720Skan } 202897403Sobrien } 2029169691Skan 2030169691Skan if (__tmperr) 2031169691Skan __err |= ios_base::failbit; 2032169691Skan 2033132720Skan return __beg; 203497403Sobrien } 203597403Sobrien 203697403Sobrien template<typename _CharT, typename _InIter> 2037132720Skan _InIter 203897403Sobrien time_get<_CharT, _InIter>:: 2039132720Skan _M_extract_num(iter_type __beg, iter_type __end, int& __member, 2040132720Skan int __min, int __max, size_t __len, 2041132720Skan ios_base& __io, ios_base::iostate& __err) const 204297403Sobrien { 2043132720Skan const locale& __loc = __io._M_getloc(); 2044132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2045132720Skan 2046132720Skan // As-is works for __len = 1, 2, 4, the values actually used. 2047132720Skan int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); 2048132720Skan 2049132720Skan ++__min; 205097403Sobrien size_t __i = 0; 2051132720Skan int __value = 0; 2052132720Skan for (; __beg != __end && __i < __len; ++__beg, ++__i) 205397403Sobrien { 2054132720Skan const char __c = __ctype.narrow(*__beg, '*'); 2055132720Skan if (__c >= '0' && __c <= '9') 2056132720Skan { 2057132720Skan __value = __value * 10 + (__c - '0'); 2058132720Skan const int __valuec = __value * __mult; 2059132720Skan if (__valuec > __max || __valuec + __mult < __min) 2060132720Skan break; 2061132720Skan __mult /= 10; 2062132720Skan } 2063132720Skan else 2064132720Skan break; 206597403Sobrien } 206697403Sobrien if (__i == __len) 2067132720Skan __member = __value; 206897403Sobrien else 206997403Sobrien __err |= ios_base::failbit; 2070169691Skan 2071132720Skan return __beg; 207297403Sobrien } 207397403Sobrien 207497403Sobrien // Assumptions: 207597403Sobrien // All elements in __names are unique. 207697403Sobrien template<typename _CharT, typename _InIter> 2077132720Skan _InIter 207897403Sobrien time_get<_CharT, _InIter>:: 2079132720Skan _M_extract_name(iter_type __beg, iter_type __end, int& __member, 2080132720Skan const _CharT** __names, size_t __indexlen, 2081132720Skan ios_base& __io, ios_base::iostate& __err) const 208297403Sobrien { 2083132720Skan typedef char_traits<_CharT> __traits_type; 2084132720Skan const locale& __loc = __io._M_getloc(); 2085132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2086132720Skan 2087132720Skan int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 2088117397Skan * __indexlen)); 208997403Sobrien size_t __nmatches = 0; 209097403Sobrien size_t __pos = 0; 209197403Sobrien bool __testvalid = true; 209297403Sobrien const char_type* __name; 209397403Sobrien 209497403Sobrien // Look for initial matches. 2095132720Skan // NB: Some of the locale data is in the form of all lowercase 2096132720Skan // names, and some is in the form of initially-capitalized 2097132720Skan // names. Look for both. 2098132720Skan if (__beg != __end) 2099132720Skan { 2100132720Skan const char_type __c = *__beg; 2101132720Skan for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 2102132720Skan if (__c == __names[__i1][0] 2103132720Skan || __c == __ctype.toupper(__names[__i1][0])) 2104132720Skan __matches[__nmatches++] = __i1; 2105132720Skan } 2106132720Skan 2107117397Skan while (__nmatches > 1) 210897403Sobrien { 210997403Sobrien // Find smallest matching string. 2110132720Skan size_t __minlen = __traits_type::length(__names[__matches[0]]); 2111132720Skan for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) 2112132720Skan __minlen = std::min(__minlen, 2113132720Skan __traits_type::length(__names[__matches[__i2]])); 2114146897Skan ++__beg, ++__pos; 211597403Sobrien if (__pos < __minlen && __beg != __end) 2116132720Skan for (size_t __i3 = 0; __i3 < __nmatches;) 2117132720Skan { 2118132720Skan __name = __names[__matches[__i3]]; 2119169691Skan if (!(__name[__pos] == *__beg)) 2120132720Skan __matches[__i3] = __matches[--__nmatches]; 2121132720Skan else 2122132720Skan ++__i3; 2123132720Skan } 212497403Sobrien else 212597403Sobrien break; 212697403Sobrien } 212797403Sobrien 212897403Sobrien if (__nmatches == 1) 212997403Sobrien { 213097403Sobrien // Make sure found name is completely extracted. 2131146897Skan ++__beg, ++__pos; 213297403Sobrien __name = __names[__matches[0]]; 213397403Sobrien const size_t __len = __traits_type::length(__name); 213497403Sobrien while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 213597403Sobrien ++__beg, ++__pos; 213697403Sobrien 213797403Sobrien if (__len == __pos) 213897403Sobrien __member = __matches[0]; 213997403Sobrien else 214097403Sobrien __testvalid = false; 214197403Sobrien } 214297403Sobrien else 214397403Sobrien __testvalid = false; 214497403Sobrien if (!__testvalid) 214597403Sobrien __err |= ios_base::failbit; 2146169691Skan 2147132720Skan return __beg; 214897403Sobrien } 214997403Sobrien 215097403Sobrien template<typename _CharT, typename _InIter> 215197403Sobrien _InIter 215297403Sobrien time_get<_CharT, _InIter>:: 215397403Sobrien do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 215497403Sobrien ios_base::iostate& __err, tm* __tm) const 215597403Sobrien { 2156132720Skan const locale& __loc = __io._M_getloc(); 2157132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2158132720Skan const char_type* __times[2]; 2159132720Skan __tp._M_time_formats(__times); 2160132720Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 2161132720Skan __tm, __times[0]); 216297403Sobrien if (__beg == __end) 216397403Sobrien __err |= ios_base::eofbit; 216497403Sobrien return __beg; 216597403Sobrien } 216697403Sobrien 216797403Sobrien template<typename _CharT, typename _InIter> 216897403Sobrien _InIter 216997403Sobrien time_get<_CharT, _InIter>:: 217097403Sobrien do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 217197403Sobrien ios_base::iostate& __err, tm* __tm) const 217297403Sobrien { 2173132720Skan const locale& __loc = __io._M_getloc(); 2174132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2175132720Skan const char_type* __dates[2]; 2176132720Skan __tp._M_date_formats(__dates); 2177169691Skan __beg = _M_extract_via_format(__beg, __end, __io, __err, 2178132720Skan __tm, __dates[0]); 217997403Sobrien if (__beg == __end) 218097403Sobrien __err |= ios_base::eofbit; 218197403Sobrien return __beg; 218297403Sobrien } 218397403Sobrien 218497403Sobrien template<typename _CharT, typename _InIter> 218597403Sobrien _InIter 218697403Sobrien time_get<_CharT, _InIter>:: 2187132720Skan do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 218897403Sobrien ios_base::iostate& __err, tm* __tm) const 218997403Sobrien { 2190132720Skan typedef char_traits<_CharT> __traits_type; 2191132720Skan const locale& __loc = __io._M_getloc(); 2192132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2193132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 219497403Sobrien const char_type* __days[7]; 219597403Sobrien __tp._M_days_abbreviated(__days); 219697403Sobrien int __tmpwday; 2197169691Skan ios_base::iostate __tmperr = ios_base::goodbit; 2198169691Skan __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, 2199169691Skan __io, __tmperr); 220097403Sobrien 220197403Sobrien // Check to see if non-abbreviated name exists, and extract. 220297403Sobrien // NB: Assumes both _M_days and _M_days_abbreviated organized in 220397403Sobrien // exact same order, first to last, such that the resulting 220497403Sobrien // __days array with the same index points to a day, and that 220597403Sobrien // day's abbreviated form. 2206132720Skan // NB: Also assumes that an abbreviated name is a subset of the name. 2207169691Skan if (!__tmperr && __beg != __end) 220897403Sobrien { 220997403Sobrien size_t __pos = __traits_type::length(__days[__tmpwday]); 221097403Sobrien __tp._M_days(__days); 221197403Sobrien const char_type* __name = __days[__tmpwday]; 221297403Sobrien if (__name[__pos] == *__beg) 221397403Sobrien { 221497403Sobrien // Extract the rest of it. 221597403Sobrien const size_t __len = __traits_type::length(__name); 2216132720Skan while (__pos < __len && __beg != __end 221797403Sobrien && __name[__pos] == *__beg) 221897403Sobrien ++__beg, ++__pos; 221997403Sobrien if (__len != __pos) 2220169691Skan __tmperr |= ios_base::failbit; 222197403Sobrien } 222297403Sobrien } 2223169691Skan if (!__tmperr) 2224146897Skan __tm->tm_wday = __tmpwday; 2225169691Skan else 2226169691Skan __err |= ios_base::failbit; 2227169691Skan 222897403Sobrien if (__beg == __end) 222997403Sobrien __err |= ios_base::eofbit; 223097403Sobrien return __beg; 223197403Sobrien } 223297403Sobrien 223397403Sobrien template<typename _CharT, typename _InIter> 223497403Sobrien _InIter 223597403Sobrien time_get<_CharT, _InIter>:: 223697403Sobrien do_get_monthname(iter_type __beg, iter_type __end, 223797403Sobrien ios_base& __io, ios_base::iostate& __err, tm* __tm) const 223897403Sobrien { 2239132720Skan typedef char_traits<_CharT> __traits_type; 2240132720Skan const locale& __loc = __io._M_getloc(); 2241132720Skan const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 2242132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 224397403Sobrien const char_type* __months[12]; 224497403Sobrien __tp._M_months_abbreviated(__months); 224597403Sobrien int __tmpmon; 2246169691Skan ios_base::iostate __tmperr = ios_base::goodbit; 2247132720Skan __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 2248169691Skan __io, __tmperr); 224997403Sobrien 225097403Sobrien // Check to see if non-abbreviated name exists, and extract. 225197403Sobrien // NB: Assumes both _M_months and _M_months_abbreviated organized in 225297403Sobrien // exact same order, first to last, such that the resulting 225397403Sobrien // __months array with the same index points to a month, and that 225497403Sobrien // month's abbreviated form. 2255132720Skan // NB: Also assumes that an abbreviated name is a subset of the name. 2256169691Skan if (!__tmperr && __beg != __end) 225797403Sobrien { 225897403Sobrien size_t __pos = __traits_type::length(__months[__tmpmon]); 225997403Sobrien __tp._M_months(__months); 226097403Sobrien const char_type* __name = __months[__tmpmon]; 226197403Sobrien if (__name[__pos] == *__beg) 226297403Sobrien { 226397403Sobrien // Extract the rest of it. 226497403Sobrien const size_t __len = __traits_type::length(__name); 2265132720Skan while (__pos < __len && __beg != __end 226697403Sobrien && __name[__pos] == *__beg) 226797403Sobrien ++__beg, ++__pos; 226897403Sobrien if (__len != __pos) 2269169691Skan __tmperr |= ios_base::failbit; 227097403Sobrien } 227197403Sobrien } 2272169691Skan if (!__tmperr) 2273146897Skan __tm->tm_mon = __tmpmon; 2274169691Skan else 2275169691Skan __err |= ios_base::failbit; 2276132720Skan 227797403Sobrien if (__beg == __end) 227897403Sobrien __err |= ios_base::eofbit; 227997403Sobrien return __beg; 228097403Sobrien } 228197403Sobrien 228297403Sobrien template<typename _CharT, typename _InIter> 228397403Sobrien _InIter 228497403Sobrien time_get<_CharT, _InIter>:: 2285132720Skan do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 228697403Sobrien ios_base::iostate& __err, tm* __tm) const 228797403Sobrien { 2288132720Skan const locale& __loc = __io._M_getloc(); 2289132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 229097403Sobrien 229197403Sobrien size_t __i = 0; 2292132720Skan int __value = 0; 2293132720Skan for (; __beg != __end && __i < 4; ++__beg, ++__i) 229497403Sobrien { 2295132720Skan const char __c = __ctype.narrow(*__beg, '*'); 2296132720Skan if (__c >= '0' && __c <= '9') 2297132720Skan __value = __value * 10 + (__c - '0'); 2298132720Skan else 2299132720Skan break; 230097403Sobrien } 230197403Sobrien if (__i == 2 || __i == 4) 2302132720Skan __tm->tm_year = __i == 2 ? __value : __value - 1900; 230397403Sobrien else 230497403Sobrien __err |= ios_base::failbit; 2305169691Skan 230697403Sobrien if (__beg == __end) 230797403Sobrien __err |= ios_base::eofbit; 230897403Sobrien return __beg; 230997403Sobrien } 231097403Sobrien 231197403Sobrien template<typename _CharT, typename _OutIter> 231297403Sobrien _OutIter 231397403Sobrien time_put<_CharT, _OutIter>:: 2314132720Skan put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 231597403Sobrien const _CharT* __beg, const _CharT* __end) const 231697403Sobrien { 2317132720Skan const locale& __loc = __io._M_getloc(); 231897403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 2319132720Skan for (; __beg != __end; ++__beg) 2320132720Skan if (__ctype.narrow(*__beg, 0) != '%') 2321132720Skan { 2322132720Skan *__s = *__beg; 2323132720Skan ++__s; 2324132720Skan } 2325132720Skan else if (++__beg != __end) 2326132720Skan { 2327132720Skan char __format; 2328132720Skan char __mod = 0; 2329132720Skan const char __c = __ctype.narrow(*__beg, 0); 2330132720Skan if (__c != 'E' && __c != 'O') 2331132720Skan __format = __c; 2332132720Skan else if (++__beg != __end) 2333132720Skan { 2334132720Skan __mod = __c; 2335132720Skan __format = __ctype.narrow(*__beg, 0); 2336132720Skan } 2337132720Skan else 2338132720Skan break; 2339132720Skan __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); 2340132720Skan } 2341132720Skan else 2342132720Skan break; 234397403Sobrien return __s; 234497403Sobrien } 234597403Sobrien 234697403Sobrien template<typename _CharT, typename _OutIter> 234797403Sobrien _OutIter 234897403Sobrien time_put<_CharT, _OutIter>:: 2349132720Skan do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 235097403Sobrien char __format, char __mod) const 2351132720Skan { 2352132720Skan const locale& __loc = __io._M_getloc(); 235397403Sobrien ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 235497403Sobrien __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 235597403Sobrien 235697403Sobrien // NB: This size is arbitrary. Should this be a data member, 235797403Sobrien // initialized at construction? 2358146897Skan const size_t __maxlen = 128; 2359132720Skan char_type* __res = 2360132720Skan static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 236197403Sobrien 236297403Sobrien // NB: In IEE 1003.1-200x, and perhaps other locale models, it 236397403Sobrien // is possible that the format character will be longer than one 236497403Sobrien // character. Possibilities include 'E' or 'O' followed by a 236597403Sobrien // format character: if __mod is not the default argument, assume 236697403Sobrien // it's a valid modifier. 236797403Sobrien char_type __fmt[4]; 2368132720Skan __fmt[0] = __ctype.widen('%'); 236997403Sobrien if (!__mod) 237097403Sobrien { 237197403Sobrien __fmt[1] = __format; 237297403Sobrien __fmt[2] = char_type(); 237397403Sobrien } 237497403Sobrien else 237597403Sobrien { 237697403Sobrien __fmt[1] = __mod; 237797403Sobrien __fmt[2] = __format; 237897403Sobrien __fmt[3] = char_type(); 237997403Sobrien } 238097403Sobrien 238197403Sobrien __tp._M_put(__res, __maxlen, __fmt, __tm); 238297403Sobrien 238397403Sobrien // Write resulting, fully-formatted string to output iterator. 2384132720Skan return std::__write(__s, __res, char_traits<char_type>::length(__res)); 238597403Sobrien } 238697403Sobrien 238797403Sobrien // Generic version does nothing. 238897403Sobrien template<typename _CharT> 238997403Sobrien int 239097403Sobrien collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 239197403Sobrien { return 0; } 239297403Sobrien 239397403Sobrien // Generic version does nothing. 239497403Sobrien template<typename _CharT> 239597403Sobrien size_t 239697403Sobrien collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 239797403Sobrien { return 0; } 239897403Sobrien 239997403Sobrien template<typename _CharT> 240097403Sobrien int 240197403Sobrien collate<_CharT>:: 2402132720Skan do_compare(const _CharT* __lo1, const _CharT* __hi1, 240397403Sobrien const _CharT* __lo2, const _CharT* __hi2) const 2404132720Skan { 2405117397Skan // strcoll assumes zero-terminated strings so we make a copy 2406117397Skan // and then put a zero at the end. 240797403Sobrien const string_type __one(__lo1, __hi1); 240897403Sobrien const string_type __two(__lo2, __hi2); 2409117397Skan 2410117397Skan const _CharT* __p = __one.c_str(); 2411132720Skan const _CharT* __pend = __one.data() + __one.length(); 2412117397Skan const _CharT* __q = __two.c_str(); 2413132720Skan const _CharT* __qend = __two.data() + __two.length(); 2414117397Skan 2415117397Skan // strcoll stops when it sees a nul character so we break 2416117397Skan // the strings into zero-terminated substrings and pass those 2417117397Skan // to strcoll. 2418117397Skan for (;;) 2419117397Skan { 2420132720Skan const int __res = _M_compare(__p, __q); 2421117397Skan if (__res) 2422117397Skan return __res; 2423117397Skan 2424117397Skan __p += char_traits<_CharT>::length(__p); 2425117397Skan __q += char_traits<_CharT>::length(__q); 2426117397Skan if (__p == __pend && __q == __qend) 2427117397Skan return 0; 2428117397Skan else if (__p == __pend) 2429117397Skan return -1; 2430117397Skan else if (__q == __qend) 2431117397Skan return 1; 2432117397Skan 2433117397Skan __p++; 2434117397Skan __q++; 2435117397Skan } 243697403Sobrien } 243797403Sobrien 2438132720Skan template<typename _CharT> 243997403Sobrien typename collate<_CharT>::string_type 244097403Sobrien collate<_CharT>:: 244197403Sobrien do_transform(const _CharT* __lo, const _CharT* __hi) const 244297403Sobrien { 2443169691Skan string_type __ret; 2444169691Skan 2445117397Skan // strxfrm assumes zero-terminated strings so we make a copy 2446169691Skan const string_type __str(__lo, __hi); 2447117397Skan 2448117397Skan const _CharT* __p = __str.c_str(); 2449132720Skan const _CharT* __pend = __str.data() + __str.length(); 2450117397Skan 245197403Sobrien size_t __len = (__hi - __lo) * 2; 2452117397Skan 2453169691Skan _CharT* __c = new _CharT[__len]; 2454117397Skan 2455169691Skan try 245697403Sobrien { 2457169691Skan // strxfrm stops when it sees a nul character so we break 2458169691Skan // the string into zero-terminated substrings and pass those 2459169691Skan // to strxfrm. 2460169691Skan for (;;) 2461117397Skan { 2462169691Skan // First try a buffer perhaps big enough. 2463169691Skan size_t __res = _M_transform(__c, __p, __len); 2464169691Skan // If the buffer was not large enough, try again with the 2465169691Skan // correct size. 2466169691Skan if (__res >= __len) 2467169691Skan { 2468169691Skan __len = __res + 1; 2469169691Skan delete [] __c, __c = 0; 2470169691Skan __c = new _CharT[__len]; 2471169691Skan __res = _M_transform(__c, __p, __len); 2472169691Skan } 2473169691Skan 2474169691Skan __ret.append(__c, __res); 2475169691Skan __p += char_traits<_CharT>::length(__p); 2476169691Skan if (__p == __pend) 2477169691Skan break; 2478169691Skan 2479169691Skan __p++; 2480169691Skan __ret.push_back(_CharT()); 2481117397Skan } 2482169691Skan } 2483169691Skan catch(...) 2484169691Skan { 2485169691Skan delete [] __c; 2486169691Skan __throw_exception_again; 2487169691Skan } 2488117397Skan 2489169691Skan delete [] __c; 2490117397Skan 2491169691Skan return __ret; 249297403Sobrien } 249397403Sobrien 2494132720Skan template<typename _CharT> 249597403Sobrien long 249697403Sobrien collate<_CharT>:: 249797403Sobrien do_hash(const _CharT* __lo, const _CharT* __hi) const 2498132720Skan { 249997403Sobrien unsigned long __val = 0; 250097403Sobrien for (; __lo < __hi; ++__lo) 2501132720Skan __val = *__lo + ((__val << 7) | 250297403Sobrien (__val >> (numeric_limits<unsigned long>::digits - 7))); 250397403Sobrien return static_cast<long>(__val); 250497403Sobrien } 250597403Sobrien 250697403Sobrien // Construct correctly padded string, as per 22.2.2.2.2 2507132720Skan // Assumes 250897403Sobrien // __newlen > __oldlen 250997403Sobrien // __news is allocated for __newlen size 251097403Sobrien // Used by both num_put and ostream inserters: if __num, 251197403Sobrien // internal-adjusted objects are padded according to the rules below 251297403Sobrien // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 251397403Sobrien // ones are. 2514102782Skan 2515102782Skan // NB: Of the two parameters, _CharT can be deduced from the 2516102782Skan // function arguments. The other (_Traits) has to be explicitly specified. 251797403Sobrien template<typename _CharT, typename _Traits> 2518132720Skan void 2519132720Skan __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2520132720Skan _CharT* __news, const _CharT* __olds, 2521132720Skan const streamsize __newlen, 2522102782Skan const streamsize __oldlen, const bool __num) 2523102782Skan { 2524132720Skan const size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2525132720Skan const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 2526102782Skan 2527132720Skan // Padding last. 252897403Sobrien if (__adjust == ios_base::left) 252997403Sobrien { 2530132720Skan _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen); 2531132720Skan _Traits::assign(__news + __oldlen, __plen, __fill); 2532132720Skan return; 253397403Sobrien } 2534132720Skan 2535132720Skan size_t __mod = 0; 2536132720Skan if (__adjust == ios_base::internal && __num) 253797403Sobrien { 253897403Sobrien // Pad after the sign, if there is one. 253997403Sobrien // Pad after 0[xX], if there is one. 254097403Sobrien // Who came up with these rules, anyway? Jeeze. 2541132720Skan const locale& __loc = __io._M_getloc(); 2542132720Skan const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2543102782Skan 2544132720Skan const bool __testsign = (__ctype.widen('-') == __olds[0] 2545132720Skan || __ctype.widen('+') == __olds[0]); 2546132720Skan const bool __testhex = (__ctype.widen('0') == __olds[0] 2547132720Skan && __oldlen > 1 2548132720Skan && (__ctype.widen('x') == __olds[1] 2549132720Skan || __ctype.widen('X') == __olds[1])); 255097403Sobrien if (__testhex) 255197403Sobrien { 2552132720Skan __news[0] = __olds[0]; 255397403Sobrien __news[1] = __olds[1]; 2554132720Skan __mod = 2; 255597403Sobrien __news += 2; 255697403Sobrien } 255797403Sobrien else if (__testsign) 255897403Sobrien { 2559132720Skan __news[0] = __olds[0]; 2560132720Skan __mod = 1; 256197403Sobrien ++__news; 256297403Sobrien } 2563132720Skan // else Padding first. 256497403Sobrien } 2565132720Skan _Traits::assign(__news, __plen, __fill); 2566132720Skan _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod), 2567132720Skan __oldlen - __mod); 256897403Sobrien } 256997403Sobrien 2570132720Skan bool 2571132720Skan __verify_grouping(const char* __grouping, size_t __grouping_size, 2572132720Skan const string& __grouping_tmp) 2573132720Skan { 2574132720Skan const size_t __n = __grouping_tmp.size() - 1; 2575169691Skan const size_t __min = std::min(__n, size_t(__grouping_size - 1)); 2576132720Skan size_t __i = __n; 2577132720Skan bool __test = true; 2578132720Skan 2579132720Skan // Parsed number groupings have to match the 2580132720Skan // numpunct::grouping string exactly, starting at the 2581132720Skan // right-most point of the parsed sequence of elements ... 2582132720Skan for (size_t __j = 0; __j < __min && __test; --__i, ++__j) 2583132720Skan __test = __grouping_tmp[__i] == __grouping[__j]; 2584132720Skan for (; __i && __test; --__i) 2585132720Skan __test = __grouping_tmp[__i] == __grouping[__min]; 2586169691Skan // ... but the first parsed grouping can be <= numpunct 2587169691Skan // grouping (only do the check if the numpunct char is > 0 2588169691Skan // because <= 0 means any size is ok). 2589169691Skan if (static_cast<signed char>(__grouping[__min]) > 0) 2590169691Skan __test &= __grouping_tmp[0] <= __grouping[__min]; 2591132720Skan return __test; 2592132720Skan } 259397403Sobrien 259497403Sobrien template<typename _CharT> 259597403Sobrien _CharT* 2596132720Skan __add_grouping(_CharT* __s, _CharT __sep, 2597132720Skan const char* __gbeg, size_t __gsize, 259897403Sobrien const _CharT* __first, const _CharT* __last) 259997403Sobrien { 2600169691Skan size_t __idx = 0; 2601169691Skan size_t __ctr = 0; 2602169691Skan 2603169691Skan while (__last - __first > __gbeg[__idx] 2604169691Skan && static_cast<signed char>(__gbeg[__idx]) > 0) 2605132720Skan { 2606169691Skan __last -= __gbeg[__idx]; 2607169691Skan __idx < __gsize - 1 ? ++__idx : ++__ctr; 2608132720Skan } 2609169691Skan 2610169691Skan while (__first != __last) 261197403Sobrien *__s++ = *__first++; 2612169691Skan 2613169691Skan while (__ctr--) 2614169691Skan { 2615169691Skan *__s++ = __sep; 2616169691Skan for (char __i = __gbeg[__idx]; __i > 0; --__i) 2617169691Skan *__s++ = *__first++; 2618169691Skan } 2619169691Skan 2620169691Skan while (__idx--) 2621169691Skan { 2622169691Skan *__s++ = __sep; 2623169691Skan for (char __i = __gbeg[__idx]; __i > 0; --__i) 2624169691Skan *__s++ = *__first++; 2625169691Skan } 2626169691Skan 262797403Sobrien return __s; 262897403Sobrien } 262997403Sobrien 263097403Sobrien // Inhibit implicit instantiations for required instantiations, 2631132720Skan // which are defined via explicit instantiations elsewhere. 263297403Sobrien // NB: This syntax is a GNU extension. 2633132720Skan#if _GLIBCXX_EXTERN_TEMPLATE 263497403Sobrien extern template class moneypunct<char, false>; 263597403Sobrien extern template class moneypunct<char, true>; 263697403Sobrien extern template class moneypunct_byname<char, false>; 263797403Sobrien extern template class moneypunct_byname<char, true>; 2638169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>; 2639169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>; 264097403Sobrien extern template class numpunct<char>; 264197403Sobrien extern template class numpunct_byname<char>; 2642169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE num_get<char>; 2643169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE num_put<char>; 264497403Sobrien extern template class __timepunct<char>; 264597403Sobrien extern template class time_put<char>; 264697403Sobrien extern template class time_put_byname<char>; 264797403Sobrien extern template class time_get<char>; 264897403Sobrien extern template class time_get_byname<char>; 264997403Sobrien extern template class messages<char>; 265097403Sobrien extern template class messages_byname<char>; 265197403Sobrien extern template class ctype_byname<char>; 265297403Sobrien extern template class codecvt_byname<char, char, mbstate_t>; 265397403Sobrien extern template class collate<char>; 265497403Sobrien extern template class collate_byname<char>; 265597403Sobrien 265697403Sobrien extern template 2657132720Skan const codecvt<char, char, mbstate_t>& 265897403Sobrien use_facet<codecvt<char, char, mbstate_t> >(const locale&); 265997403Sobrien 266097403Sobrien extern template 2661132720Skan const collate<char>& 266297403Sobrien use_facet<collate<char> >(const locale&); 266397403Sobrien 266497403Sobrien extern template 2665132720Skan const numpunct<char>& 266697403Sobrien use_facet<numpunct<char> >(const locale&); 266797403Sobrien 2668132720Skan extern template 2669132720Skan const num_put<char>& 267097403Sobrien use_facet<num_put<char> >(const locale&); 267197403Sobrien 2672132720Skan extern template 2673132720Skan const num_get<char>& 267497403Sobrien use_facet<num_get<char> >(const locale&); 267597403Sobrien 267697403Sobrien extern template 2677132720Skan const moneypunct<char, true>& 267897403Sobrien use_facet<moneypunct<char, true> >(const locale&); 267997403Sobrien 268097403Sobrien extern template 2681132720Skan const moneypunct<char, false>& 268297403Sobrien use_facet<moneypunct<char, false> >(const locale&); 268397403Sobrien 2684132720Skan extern template 2685132720Skan const money_put<char>& 268697403Sobrien use_facet<money_put<char> >(const locale&); 268797403Sobrien 2688132720Skan extern template 2689132720Skan const money_get<char>& 269097403Sobrien use_facet<money_get<char> >(const locale&); 269197403Sobrien 269297403Sobrien extern template 2693132720Skan const __timepunct<char>& 269497403Sobrien use_facet<__timepunct<char> >(const locale&); 269597403Sobrien 2696132720Skan extern template 2697132720Skan const time_put<char>& 269897403Sobrien use_facet<time_put<char> >(const locale&); 269997403Sobrien 2700132720Skan extern template 2701132720Skan const time_get<char>& 270297403Sobrien use_facet<time_get<char> >(const locale&); 270397403Sobrien 2704132720Skan extern template 2705132720Skan const messages<char>& 270697403Sobrien use_facet<messages<char> >(const locale&); 270797403Sobrien 2708132720Skan extern template 2709107606Sobrien bool 2710107606Sobrien has_facet<ctype<char> >(const locale&); 2711107606Sobrien 2712132720Skan extern template 2713107606Sobrien bool 2714107606Sobrien has_facet<codecvt<char, char, mbstate_t> >(const locale&); 2715107606Sobrien 2716132720Skan extern template 2717107606Sobrien bool 2718107606Sobrien has_facet<collate<char> >(const locale&); 2719107606Sobrien 2720132720Skan extern template 2721107606Sobrien bool 2722107606Sobrien has_facet<numpunct<char> >(const locale&); 2723107606Sobrien 2724132720Skan extern template 2725107606Sobrien bool 2726107606Sobrien has_facet<num_put<char> >(const locale&); 2727107606Sobrien 2728132720Skan extern template 2729107606Sobrien bool 2730107606Sobrien has_facet<num_get<char> >(const locale&); 2731107606Sobrien 2732132720Skan extern template 2733107606Sobrien bool 2734107606Sobrien has_facet<moneypunct<char> >(const locale&); 2735107606Sobrien 2736132720Skan extern template 2737107606Sobrien bool 2738107606Sobrien has_facet<money_put<char> >(const locale&); 2739107606Sobrien 2740132720Skan extern template 2741107606Sobrien bool 2742107606Sobrien has_facet<money_get<char> >(const locale&); 2743107606Sobrien 2744132720Skan extern template 2745107606Sobrien bool 2746107606Sobrien has_facet<__timepunct<char> >(const locale&); 2747107606Sobrien 2748132720Skan extern template 2749107606Sobrien bool 2750107606Sobrien has_facet<time_put<char> >(const locale&); 2751107606Sobrien 2752132720Skan extern template 2753107606Sobrien bool 2754107606Sobrien has_facet<time_get<char> >(const locale&); 2755107606Sobrien 2756132720Skan extern template 2757107606Sobrien bool 2758107606Sobrien has_facet<messages<char> >(const locale&); 2759107606Sobrien 2760132720Skan#ifdef _GLIBCXX_USE_WCHAR_T 2761107606Sobrien extern template class moneypunct<wchar_t, false>; 2762107606Sobrien extern template class moneypunct<wchar_t, true>; 2763107606Sobrien extern template class moneypunct_byname<wchar_t, false>; 2764107606Sobrien extern template class moneypunct_byname<wchar_t, true>; 2765169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>; 2766169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>; 2767107606Sobrien extern template class numpunct<wchar_t>; 2768107606Sobrien extern template class numpunct_byname<wchar_t>; 2769169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE num_get<wchar_t>; 2770169691Skan extern template class _GLIBCXX_LDBL_NAMESPACE num_put<wchar_t>; 2771107606Sobrien extern template class __timepunct<wchar_t>; 2772107606Sobrien extern template class time_put<wchar_t>; 2773107606Sobrien extern template class time_put_byname<wchar_t>; 2774107606Sobrien extern template class time_get<wchar_t>; 2775107606Sobrien extern template class time_get_byname<wchar_t>; 2776107606Sobrien extern template class messages<wchar_t>; 2777107606Sobrien extern template class messages_byname<wchar_t>; 2778107606Sobrien extern template class ctype_byname<wchar_t>; 2779107606Sobrien extern template class codecvt_byname<wchar_t, char, mbstate_t>; 2780107606Sobrien extern template class collate<wchar_t>; 2781107606Sobrien extern template class collate_byname<wchar_t>; 2782107606Sobrien 278397403Sobrien extern template 2784132720Skan const codecvt<wchar_t, char, mbstate_t>& 278597403Sobrien use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 278697403Sobrien 278797403Sobrien extern template 2788132720Skan const collate<wchar_t>& 278997403Sobrien use_facet<collate<wchar_t> >(const locale&); 279097403Sobrien 279197403Sobrien extern template 2792132720Skan const numpunct<wchar_t>& 279397403Sobrien use_facet<numpunct<wchar_t> >(const locale&); 279497403Sobrien 2795132720Skan extern template 2796132720Skan const num_put<wchar_t>& 279797403Sobrien use_facet<num_put<wchar_t> >(const locale&); 279897403Sobrien 2799132720Skan extern template 2800132720Skan const num_get<wchar_t>& 280197403Sobrien use_facet<num_get<wchar_t> >(const locale&); 280297403Sobrien 280397403Sobrien extern template 2804132720Skan const moneypunct<wchar_t, true>& 280597403Sobrien use_facet<moneypunct<wchar_t, true> >(const locale&); 280697403Sobrien 280797403Sobrien extern template 2808132720Skan const moneypunct<wchar_t, false>& 280997403Sobrien use_facet<moneypunct<wchar_t, false> >(const locale&); 2810132720Skan 2811132720Skan extern template 2812132720Skan const money_put<wchar_t>& 281397403Sobrien use_facet<money_put<wchar_t> >(const locale&); 281497403Sobrien 2815132720Skan extern template 2816132720Skan const money_get<wchar_t>& 281797403Sobrien use_facet<money_get<wchar_t> >(const locale&); 281897403Sobrien 281997403Sobrien extern template 2820132720Skan const __timepunct<wchar_t>& 282197403Sobrien use_facet<__timepunct<wchar_t> >(const locale&); 282297403Sobrien 2823132720Skan extern template 2824132720Skan const time_put<wchar_t>& 282597403Sobrien use_facet<time_put<wchar_t> >(const locale&); 282697403Sobrien 2827132720Skan extern template 2828132720Skan const time_get<wchar_t>& 282997403Sobrien use_facet<time_get<wchar_t> >(const locale&); 283097403Sobrien 2831132720Skan extern template 2832132720Skan const messages<wchar_t>& 283397403Sobrien use_facet<messages<wchar_t> >(const locale&); 283497403Sobrien 2835132720Skan extern template 283697403Sobrien bool 283797403Sobrien has_facet<ctype<wchar_t> >(const locale&); 283897403Sobrien 2839132720Skan extern template 284097403Sobrien bool 284197403Sobrien has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 284297403Sobrien 2843132720Skan extern template 284497403Sobrien bool 284597403Sobrien has_facet<collate<wchar_t> >(const locale&); 284697403Sobrien 2847132720Skan extern template 284897403Sobrien bool 284997403Sobrien has_facet<numpunct<wchar_t> >(const locale&); 285097403Sobrien 2851132720Skan extern template 285297403Sobrien bool 285397403Sobrien has_facet<num_put<wchar_t> >(const locale&); 285497403Sobrien 2855132720Skan extern template 285697403Sobrien bool 285797403Sobrien has_facet<num_get<wchar_t> >(const locale&); 285897403Sobrien 2859132720Skan extern template 286097403Sobrien bool 286197403Sobrien has_facet<moneypunct<wchar_t> >(const locale&); 286297403Sobrien 2863132720Skan extern template 286497403Sobrien bool 286597403Sobrien has_facet<money_put<wchar_t> >(const locale&); 286697403Sobrien 2867132720Skan extern template 286897403Sobrien bool 286997403Sobrien has_facet<money_get<wchar_t> >(const locale&); 287097403Sobrien 2871132720Skan extern template 287297403Sobrien bool 287397403Sobrien has_facet<__timepunct<wchar_t> >(const locale&); 287497403Sobrien 2875132720Skan extern template 287697403Sobrien bool 287797403Sobrien has_facet<time_put<wchar_t> >(const locale&); 287897403Sobrien 2879132720Skan extern template 288097403Sobrien bool 288197403Sobrien has_facet<time_get<wchar_t> >(const locale&); 288297403Sobrien 2883132720Skan extern template 288497403Sobrien bool 288597403Sobrien has_facet<messages<wchar_t> >(const locale&); 2886107606Sobrien#endif 2887117397Skan#endif 288897403Sobrien 2889169691Skan_GLIBCXX_END_NAMESPACE 2890169691Skan 289197403Sobrien#endif 2892