1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 2, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // You should have received a copy of the GNU General Public License along 18 // with this library; see the file COPYING. If not, write to the Free 19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 // USA. 21 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 // Warning: this file is not meant for user inclusion. Use <locale>. 32 33 #ifndef _CPP_BITS_LOCFACETS_TCC 34 #define _CPP_BITS_LOCFACETS_TCC 1 35 36 #pragma GCC system_header 37 38 #include <cerrno> 39 #include <clocale> // For localeconv 40 #include <cstdlib> // For strof, strtold 41 #include <cctype> // For isspace 42 #include <limits> // For numeric_limits 43 #include <typeinfo> // For bad_cast. 44 #include <bits/streambuf_iterator.h> 45 46 namespace std 47 { 48 template<typename _Facet> 49 locale combine(const locale & __other) const50 locale::combine(const locale& __other) const 51 { 52 _Impl* __tmp = new _Impl(*_M_impl, 1); 53 try 54 { 55 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 56 } 57 catch(...) 58 { 59 __tmp->_M_remove_reference(); 60 __throw_exception_again; 61 } 62 return locale(__tmp); 63 } 64 65 template<typename _CharT, typename _Traits, typename _Alloc> 66 bool operator ()(const basic_string<_CharT,_Traits,_Alloc> & __s1,const basic_string<_CharT,_Traits,_Alloc> & __s2) const67 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 68 const basic_string<_CharT, _Traits, _Alloc>& __s2) const 69 { 70 typedef std::collate<_CharT> __collate_type; 71 const __collate_type& __collate = use_facet<__collate_type>(*this); 72 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 73 __s2.data(), __s2.data() + __s2.length()) < 0); 74 } 75 76 template<typename _Facet> 77 const _Facet& use_facet(const locale & __loc)78 use_facet(const locale& __loc) 79 { 80 size_t __i = _Facet::id._M_id(); 81 locale::facet** __facets = __loc._M_impl->_M_facets; 82 if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) 83 __throw_bad_cast(); 84 return static_cast<const _Facet&>(*__facets[__i]); 85 } 86 87 template<typename _Facet> 88 bool has_facet(const locale & __loc)89 has_facet(const locale& __loc) throw() 90 { 91 size_t __i = _Facet::id._M_id(); 92 locale::facet** __facets = __loc._M_impl->_M_facets; 93 return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); 94 } 95 96 // Routine to access a cache for the locale. If the cache didn't 97 // exist before, it gets constructed on the fly. 98 template<typename _Facet> 99 inline const __locale_cache<_Facet>& __use_cache(const locale & __loc)100 __use_cache(const locale& __loc) 101 { 102 size_t __i = _Facet::id._M_id(); 103 if (__builtin_expect(__i >= __loc._M_impl->_M_facets_size,false)) 104 __throw_bad_cast(); 105 __locale_cache_base* __cache = __loc._M_impl->_M_get_cache(__i); 106 if (__builtin_expect(!__cache, false)) 107 { 108 __cache = new __locale_cache<_Facet>(__loc); 109 __loc._M_impl->_M_install_cache(__cache, __i); 110 } 111 return static_cast<const __locale_cache<_Facet>&>(*__cache); 112 } 113 114 // Stage 1: Determine a conversion specifier. 115 template<typename _CharT, typename _InIter> 116 _InIter 117 num_get<_CharT, _InIter>:: _M_extract_float(_InIter __beg,_InIter __end,ios_base & __io,ios_base::iostate & __err,string & __xtrc) const118 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 119 ios_base::iostate& __err, string& __xtrc) const 120 { 121 typedef char_traits<_CharT> __traits_type; 122 const locale __loc = __io.getloc(); 123 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 124 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 125 126 // First check for sign. 127 const char_type __plus = __ctype.widen('+'); 128 const char_type __minus = __ctype.widen('-'); 129 int __pos = 0; 130 char_type __c = *__beg; 131 if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 132 && __beg != __end) 133 { 134 __xtrc += __ctype.narrow(__c, char()); 135 ++__pos; 136 __c = *(++__beg); 137 } 138 139 // Next, strip leading zeros. 140 const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); 141 bool __found_zero = false; 142 while (__traits_type::eq(__c, __zero) && __beg != __end) 143 { 144 __c = *(++__beg); 145 __found_zero = true; 146 } 147 if (__found_zero) 148 { 149 __xtrc += _S_atoms_in[_M_zero]; 150 ++__pos; 151 } 152 153 // Only need acceptable digits for floating point numbers. 154 const size_t __len = _M_E - _M_zero + 1; 155 char_type __watoms[__len]; 156 __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); 157 bool __found_dec = false; 158 bool __found_sci = false; 159 const char_type __dec = __np.decimal_point(); 160 161 string __found_grouping; 162 const string __grouping = __np.grouping(); 163 bool __check_grouping = __grouping.size(); 164 int __sep_pos = 0; 165 const char_type __sep = __np.thousands_sep(); 166 167 while (__beg != __end) 168 { 169 // Only look in digits. 170 const char_type* __p = __traits_type::find(__watoms, 10, __c); 171 172 // NB: strchr returns true for __c == 0x0 173 if (__p && !__traits_type::eq(__c, char_type())) 174 { 175 // Try first for acceptable digit; record it if found. 176 ++__pos; 177 __xtrc += _S_atoms_in[__p - __watoms]; 178 ++__sep_pos; 179 __c = *(++__beg); 180 } 181 else if (__traits_type::eq(__c, __sep) 182 && __check_grouping && !__found_dec) 183 { 184 // NB: Thousands separator at the beginning of a string 185 // is a no-no, as is two consecutive thousands separators. 186 if (__sep_pos) 187 { 188 __found_grouping += static_cast<char>(__sep_pos); 189 __sep_pos = 0; 190 __c = *(++__beg); 191 } 192 else 193 { 194 __err |= ios_base::failbit; 195 break; 196 } 197 } 198 else if (__traits_type::eq(__c, __dec) && !__found_dec) 199 { 200 // According to the standard, if no grouping chars are seen, 201 // no grouping check is applied. Therefore __found_grouping 202 // must be adjusted only if __dec comes after some __sep. 203 if (__found_grouping.size()) 204 __found_grouping += static_cast<char>(__sep_pos); 205 ++__pos; 206 __xtrc += '.'; 207 __c = *(++__beg); 208 __found_dec = true; 209 } 210 else if ((__traits_type::eq(__c, __watoms[_M_e]) 211 || __traits_type::eq(__c, __watoms[_M_E])) 212 && !__found_sci && __pos) 213 { 214 // Scientific notation. 215 ++__pos; 216 __xtrc += __ctype.narrow(__c, char()); 217 __c = *(++__beg); 218 219 // Remove optional plus or minus sign, if they exist. 220 if (__traits_type::eq(__c, __plus) 221 || __traits_type::eq(__c, __minus)) 222 { 223 ++__pos; 224 __xtrc += __ctype.narrow(__c, char()); 225 __c = *(++__beg); 226 } 227 __found_sci = true; 228 } 229 else 230 // Not a valid input item. 231 break; 232 } 233 234 // Digit grouping is checked. If grouping and found_grouping don't 235 // match, then get very very upset, and set failbit. 236 if (__check_grouping && __found_grouping.size()) 237 { 238 // Add the ending grouping if a decimal wasn't found. 239 if (!__found_dec) 240 __found_grouping += static_cast<char>(__sep_pos); 241 if (!__verify_grouping(__grouping, __found_grouping)) 242 __err |= ios_base::failbit; 243 } 244 245 // Finish up 246 __xtrc += char(); 247 if (__beg == __end) 248 __err |= ios_base::eofbit; 249 return __beg; 250 } 251 252 // Stage 1: Determine a conversion specifier. 253 template<typename _CharT, typename _InIter> 254 _InIter 255 num_get<_CharT, _InIter>:: _M_extract_int(_InIter __beg,_InIter __end,ios_base & __io,ios_base::iostate & __err,string & __xtrc,int & __base) const256 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 257 ios_base::iostate& __err, string& __xtrc, int& __base) const 258 { 259 typedef char_traits<_CharT> __traits_type; 260 const locale __loc = __io.getloc(); 261 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 262 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 263 264 // NB: Iff __basefield == 0, this can change based on contents. 265 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 266 if (__basefield == ios_base::oct) 267 __base = 8; 268 else if (__basefield == ios_base::hex) 269 __base = 16; 270 else 271 __base = 10; 272 273 // First check for sign. 274 int __pos = 0; 275 char_type __c = *__beg; 276 const char_type __plus = __ctype.widen('+'); 277 const char_type __minus = __ctype.widen('-'); 278 279 if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 280 && __beg != __end) 281 { 282 __xtrc += __ctype.narrow(__c, char()); 283 ++__pos; 284 __c = *(++__beg); 285 } 286 287 // Next, strip leading zeros and check required digits for base formats. 288 const char_type __zero = __ctype.widen(_S_atoms_in[_M_zero]); 289 const char_type __x = __ctype.widen('x'); 290 const char_type __X = __ctype.widen('X'); 291 if (__base == 10) 292 { 293 bool __found_zero = false; 294 while (__traits_type::eq(__c, __zero) && __beg != __end) 295 { 296 __c = *(++__beg); 297 __found_zero = true; 298 } 299 if (__found_zero) 300 { 301 __xtrc += _S_atoms_in[_M_zero]; 302 ++__pos; 303 if (__basefield == 0) 304 { 305 if ((__traits_type::eq(__c, __x) 306 || __traits_type::eq(__c, __X)) 307 && __beg != __end) 308 { 309 __xtrc += __ctype.narrow(__c, char()); 310 ++__pos; 311 __c = *(++__beg); 312 __base = 16; 313 } 314 else 315 __base = 8; 316 } 317 } 318 } 319 else if (__base == 16) 320 { 321 if (__traits_type::eq(__c, __zero) && __beg != __end) 322 { 323 __xtrc += _S_atoms_in[_M_zero]; 324 ++__pos; 325 __c = *(++__beg); 326 if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) 327 && __beg != __end) 328 { 329 __xtrc += __ctype.narrow(__c, char()); 330 ++__pos; 331 __c = *(++__beg); 332 } 333 } 334 } 335 336 // At this point, base is determined. If not hex, only allow 337 // base digits as valid input. 338 size_t __len; 339 if (__base == 16) 340 __len = _M_size; 341 else 342 __len = __base; 343 344 // Extract. 345 char_type __watoms[_M_size]; 346 __ctype.widen(_S_atoms_in, _S_atoms_in + __len, __watoms); 347 string __found_grouping; 348 const string __grouping = __np.grouping(); 349 bool __check_grouping = __grouping.size(); 350 int __sep_pos = 0; 351 const char_type __sep = __np.thousands_sep(); 352 while (__beg != __end) 353 { 354 const char_type* __p = __traits_type::find(__watoms, __len, __c); 355 356 // NB: strchr returns true for __c == 0x0 357 if (__p && !__traits_type::eq(__c, char_type())) 358 { 359 // Try first for acceptable digit; record it if found. 360 __xtrc += _S_atoms_in[__p - __watoms]; 361 ++__pos; 362 ++__sep_pos; 363 __c = *(++__beg); 364 } 365 else if (__traits_type::eq(__c, __sep) && __check_grouping) 366 { 367 // NB: Thousands separator at the beginning of a string 368 // is a no-no, as is two consecutive thousands separators. 369 if (__sep_pos) 370 { 371 __found_grouping += static_cast<char>(__sep_pos); 372 __sep_pos = 0; 373 __c = *(++__beg); 374 } 375 else 376 { 377 __err |= ios_base::failbit; 378 break; 379 } 380 } 381 else 382 // Not a valid input item. 383 break; 384 } 385 386 // Digit grouping is checked. If grouping and found_grouping don't 387 // match, then get very very upset, and set failbit. 388 if (__check_grouping && __found_grouping.size()) 389 { 390 // Add the ending grouping. 391 __found_grouping += static_cast<char>(__sep_pos); 392 if (!__verify_grouping(__grouping, __found_grouping)) 393 __err |= ios_base::failbit; 394 } 395 396 // Finish up. 397 __xtrc += char(); 398 if (__beg == __end) 399 __err |= ios_base::eofbit; 400 return __beg; 401 } 402 403 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 404 //17. Bad bool parsing 405 template<typename _CharT, typename _InIter> 406 _InIter 407 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,bool & __v) const408 do_get(iter_type __beg, iter_type __end, ios_base& __io, 409 ios_base::iostate& __err, bool& __v) const 410 { 411 // Parse bool values as unsigned long 412 if (!(__io.flags() & ios_base::boolalpha)) 413 { 414 // NB: We can't just call do_get(long) here, as it might 415 // refer to a derived class. 416 string __xtrc; 417 int __base; 418 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 419 420 unsigned long __ul; 421 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 422 if (!(__err & ios_base::failbit) && __ul <= 1) 423 __v = __ul; 424 else 425 __err |= ios_base::failbit; 426 } 427 428 // Parse bool values as alphanumeric 429 else 430 { 431 typedef char_traits<_CharT> __traits_type; 432 typedef basic_string<_CharT> __string_type; 433 434 locale __loc = __io.getloc(); 435 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 436 const __string_type __true = __np.truename(); 437 const __string_type __false = __np.falsename(); 438 const char_type* __trues = __true.c_str(); 439 const char_type* __falses = __false.c_str(); 440 const size_t __truen = __true.size() - 1; 441 const size_t __falsen = __false.size() - 1; 442 443 for (size_t __n = 0; __beg != __end; ++__n) 444 { 445 char_type __c = *__beg++; 446 bool __testf = __n <= __falsen 447 ? __traits_type::eq(__c, __falses[__n]) : false; 448 bool __testt = __n <= __truen 449 ? __traits_type::eq(__c, __trues[__n]) : false; 450 if (!(__testf || __testt)) 451 { 452 __err |= ios_base::failbit; 453 break; 454 } 455 else if (__testf && __n == __falsen) 456 { 457 __v = 0; 458 break; 459 } 460 else if (__testt && __n == __truen) 461 { 462 __v = 1; 463 break; 464 } 465 } 466 if (__beg == __end) 467 __err |= ios_base::eofbit; 468 } 469 return __beg; 470 } 471 #endif 472 473 template<typename _CharT, typename _InIter> 474 _InIter 475 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,long & __v) const476 do_get(iter_type __beg, iter_type __end, ios_base& __io, 477 ios_base::iostate& __err, long& __v) const 478 { 479 string __xtrc; 480 int __base; 481 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 482 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 483 return __beg; 484 } 485 486 template<typename _CharT, typename _InIter> 487 _InIter 488 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,unsigned short & __v) const489 do_get(iter_type __beg, iter_type __end, ios_base& __io, 490 ios_base::iostate& __err, unsigned short& __v) const 491 { 492 string __xtrc; 493 int __base; 494 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 495 unsigned long __ul; 496 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 497 if (!(__err & ios_base::failbit) 498 && __ul <= numeric_limits<unsigned short>::max()) 499 __v = static_cast<unsigned short>(__ul); 500 else 501 __err |= ios_base::failbit; 502 return __beg; 503 } 504 505 template<typename _CharT, typename _InIter> 506 _InIter 507 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,unsigned int & __v) const508 do_get(iter_type __beg, iter_type __end, ios_base& __io, 509 ios_base::iostate& __err, unsigned int& __v) const 510 { 511 string __xtrc; 512 int __base; 513 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 514 unsigned long __ul; 515 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 516 if (!(__err & ios_base::failbit) 517 && __ul <= numeric_limits<unsigned int>::max()) 518 __v = static_cast<unsigned int>(__ul); 519 else 520 __err |= ios_base::failbit; 521 return __beg; 522 } 523 524 template<typename _CharT, typename _InIter> 525 _InIter 526 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,unsigned long & __v) const527 do_get(iter_type __beg, iter_type __end, ios_base& __io, 528 ios_base::iostate& __err, unsigned long& __v) const 529 { 530 string __xtrc; 531 int __base; 532 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 533 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 534 return __beg; 535 } 536 537 #ifdef _GLIBCPP_USE_LONG_LONG 538 template<typename _CharT, typename _InIter> 539 _InIter 540 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,long long & __v) const541 do_get(iter_type __beg, iter_type __end, ios_base& __io, 542 ios_base::iostate& __err, long long& __v) const 543 { 544 string __xtrc; 545 int __base; 546 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 547 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 548 return __beg; 549 } 550 551 template<typename _CharT, typename _InIter> 552 _InIter 553 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,unsigned long long & __v) const554 do_get(iter_type __beg, iter_type __end, ios_base& __io, 555 ios_base::iostate& __err, unsigned long long& __v) const 556 { 557 string __xtrc; 558 int __base; 559 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 560 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 561 return __beg; 562 } 563 #endif 564 565 template<typename _CharT, typename _InIter> 566 _InIter 567 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,float & __v) const568 do_get(iter_type __beg, iter_type __end, ios_base& __io, 569 ios_base::iostate& __err, float& __v) const 570 { 571 string __xtrc; 572 __xtrc.reserve(32); 573 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 574 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 575 return __beg; 576 } 577 578 template<typename _CharT, typename _InIter> 579 _InIter 580 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,double & __v) const581 do_get(iter_type __beg, iter_type __end, ios_base& __io, 582 ios_base::iostate& __err, double& __v) const 583 { 584 string __xtrc; 585 __xtrc.reserve(32); 586 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 587 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 588 return __beg; 589 } 590 591 template<typename _CharT, typename _InIter> 592 _InIter 593 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,long double & __v) const594 do_get(iter_type __beg, iter_type __end, ios_base& __io, 595 ios_base::iostate& __err, long double& __v) const 596 { 597 string __xtrc; 598 __xtrc.reserve(32); 599 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 600 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 601 return __beg; 602 } 603 604 template<typename _CharT, typename _InIter> 605 _InIter 606 num_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,void * & __v) const607 do_get(iter_type __beg, iter_type __end, ios_base& __io, 608 ios_base::iostate& __err, void*& __v) const 609 { 610 // Prepare for hex formatted input 611 typedef ios_base::fmtflags fmtflags; 612 fmtflags __fmt = __io.flags(); 613 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield 614 | ios_base::uppercase | ios_base::internal); 615 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); 616 617 string __xtrc; 618 int __base; 619 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 620 621 // Reset from hex formatted input 622 __io.flags(__fmt); 623 624 unsigned long __ul; 625 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 626 if (!(__err & ios_base::failbit)) 627 __v = reinterpret_cast<void*>(__ul); 628 else 629 __err |= ios_base::failbit; 630 return __beg; 631 } 632 633 // For use by integer and floating-point types after they have been 634 // converted into a char_type string. 635 template<typename _CharT, typename _OutIter> 636 void 637 num_put<_CharT, _OutIter>:: _M_pad(_CharT __fill,streamsize __w,ios_base & __io,_CharT * __new,const _CharT * __cs,int & __len) const638 _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 639 _CharT* __new, const _CharT* __cs, int& __len) const 640 { 641 // [22.2.2.2.2] Stage 3. 642 // If necessary, pad. 643 __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 644 __w, __len, true); 645 __len = static_cast<int>(__w); 646 } 647 648 // Forwarding functions to peel signed from unsigned integer types. 649 template<typename _CharT> 650 inline int __int_to_char(_CharT * __out,const int __size,long __v,const _CharT * __lit,ios_base::fmtflags __flags)651 __int_to_char(_CharT* __out, const int __size, long __v, 652 const _CharT* __lit, ios_base::fmtflags __flags) 653 { 654 unsigned long __ul = static_cast<unsigned long>(__v); 655 bool __neg = false; 656 if (__v < 0) 657 { 658 __ul = -__ul; 659 __neg = true; 660 } 661 return __int_to_char(__out, __size, __ul, __lit, __flags, __neg); 662 } 663 664 template<typename _CharT> 665 inline int __int_to_char(_CharT * __out,const int __size,unsigned long __v,const _CharT * __lit,ios_base::fmtflags __flags)666 __int_to_char(_CharT* __out, const int __size, unsigned long __v, 667 const _CharT* __lit, ios_base::fmtflags __flags) 668 { return __int_to_char(__out, __size, __v, __lit, __flags, false); } 669 670 #ifdef _GLIBCPP_USE_LONG_LONG 671 template<typename _CharT> 672 inline int __int_to_char(_CharT * __out,const int __size,long long __v,const _CharT * __lit,ios_base::fmtflags __flags)673 __int_to_char(_CharT* __out, const int __size, long long __v, 674 const _CharT* __lit, ios_base::fmtflags __flags) 675 { 676 unsigned long long __ull = static_cast<unsigned long long>(__v); 677 bool __neg = false; 678 if (__v < 0) 679 { 680 __ull = -__ull; 681 __neg = true; 682 } 683 return __int_to_char(__out, __size, __ull, __lit, __flags, __neg); 684 } 685 686 template<typename _CharT> 687 inline int __int_to_char(_CharT * __out,const int __size,unsigned long long __v,const _CharT * __lit,ios_base::fmtflags __flags)688 __int_to_char(_CharT* __out, const int __size, unsigned long long __v, 689 const _CharT* __lit, ios_base::fmtflags __flags) 690 { return __int_to_char(__out, __size, __v, __lit, __flags, false); } 691 #endif 692 693 template<typename _CharT, typename _ValueT> 694 int __int_to_char(_CharT * __out,const int __size,_ValueT __v,const _CharT * __lit,ios_base::fmtflags __flags,bool __neg)695 __int_to_char(_CharT* __out, const int __size, _ValueT __v, 696 const _CharT* __lit, ios_base::fmtflags __flags, bool __neg) 697 { 698 // Don't write base if already 0. 699 const bool __showbase = (__flags & ios_base::showbase) && __v; 700 const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 701 _CharT* __buf = __out + __size - 1; 702 _CharT* __bufend = __out + __size; 703 704 if (__builtin_expect(__basefield != ios_base::oct && 705 __basefield != ios_base::hex, true)) 706 { 707 // Decimal. 708 do 709 { 710 *__buf-- = __lit[(__v % 10) + __num_base::_S_digits]; 711 __v /= 10; 712 } 713 while (__v != 0); 714 if (__neg) 715 *__buf-- = __lit[__num_base::_S_minus]; 716 else if (__flags & ios_base::showpos) 717 *__buf-- = __lit[__num_base::_S_plus]; 718 } 719 else if (__basefield == ios_base::oct) 720 { 721 // Octal. 722 do 723 { 724 *__buf-- = __lit[(__v & 0x7) + __num_base::_S_digits]; 725 __v >>= 3; 726 } 727 while (__v != 0); 728 if (__showbase) 729 *__buf-- = __lit[__num_base::_S_digits]; 730 } 731 else 732 { 733 // Hex. 734 const bool __uppercase = __flags & ios_base::uppercase; 735 int __case_offset = __uppercase 736 ? __num_base::_S_udigits : __num_base::_S_digits; 737 do 738 { 739 *__buf-- = __lit[(__v & 0xf) + __case_offset]; 740 __v >>= 4; 741 } 742 while (__v != 0); 743 if (__showbase) 744 { 745 // 'x' or 'X' 746 *__buf-- = __lit[__num_base::_S_x + __uppercase]; 747 // '0' 748 *__buf-- = __lit[__num_base::_S_digits]; 749 } 750 } 751 int __ret = __bufend - __buf - 1; 752 return __ret; 753 } 754 755 template<typename _CharT, typename _OutIter> 756 void 757 num_put<_CharT, _OutIter>:: _M_group_int(const string & __grouping,_CharT __sep,ios_base & __io,_CharT * __new,_CharT * __cs,int & __len) const758 _M_group_int(const string& __grouping, _CharT __sep, ios_base& __io, 759 _CharT* __new, _CharT* __cs, int& __len) const 760 { 761 // By itself __add_grouping cannot deal correctly with __ws when 762 // ios::showbase is set and ios_base::oct || ios_base::hex. 763 // Therefore we take care "by hand" of the initial 0, 0x or 0X. 764 // However, remember that the latter do not occur if the number 765 // printed is '0' (__len == 1). 766 streamsize __off = 0; 767 const ios_base::fmtflags __basefield = __io.flags() 768 & ios_base::basefield; 769 if ((__io.flags() & ios_base::showbase) && __len > 1) 770 if (__basefield == ios_base::oct) 771 { 772 __off = 1; 773 *__new = *__cs; 774 } 775 else if (__basefield == ios_base::hex) 776 { 777 __off = 2; 778 *__new = *__cs; 779 *(__new + 1) = *(__cs + 1); 780 } 781 _CharT* __p; 782 __p = __add_grouping(__new + __off, __sep, 783 __grouping.c_str(), 784 __grouping.c_str() + __grouping.size(), 785 __cs + __off, __cs + __len); 786 __len = __p - __new; 787 } 788 789 template<typename _CharT, typename _OutIter> 790 template<typename _ValueT> 791 _OutIter 792 num_put<_CharT, _OutIter>:: _M_convert_int(_OutIter __s,ios_base & __io,_CharT __fill,_ValueT __v) const793 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, 794 _ValueT __v) const 795 { 796 typedef numpunct<_CharT> __facet_type; 797 typedef __locale_cache<numpunct<_CharT> > __cache_type; 798 const locale& __loc = __io._M_getloc(); 799 const __cache_type& __lc = __use_cache<__facet_type>(__loc); 800 const _CharT* __lit = __lc._M_atoms_out; 801 802 // Long enough to hold hex, dec, and octal representations. 803 int __ilen = 4 * sizeof(_ValueT); 804 _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 805 * __ilen)); 806 // [22.2.2.2.2] Stage 1, numeric conversion to character. 807 // Result is returned right-justified in the buffer. 808 int __len; 809 __len = __int_to_char(&__cs[0], __ilen, __v, __lit, __io.flags()); 810 __cs = __cs + __ilen - __len; 811 812 // Add grouping, if necessary. 813 _CharT* __cs2; 814 if (__lc._M_use_grouping) 815 { 816 // Grouping can add (almost) as many separators as the 817 // number of digits, but no more. 818 __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 819 * __len * 2)); 820 _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, 821 __cs2, __cs, __len); 822 __cs = __cs2; 823 } 824 825 // Pad. 826 _CharT* __cs3; 827 streamsize __w = __io.width(); 828 if (__w > static_cast<streamsize>(__len)) 829 { 830 __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 831 * __w)); 832 _M_pad(__fill, __w, __io, __cs3, __cs, __len); 833 __cs = __cs3; 834 } 835 __io.width(0); 836 837 // [22.2.2.2.2] Stage 4. 838 // Write resulting, fully-formatted string to output iterator. 839 return __write(__s, __cs, __len); 840 } 841 842 template<typename _CharT, typename _OutIter> 843 void 844 num_put<_CharT, _OutIter>:: _M_group_float(const string & __grouping,_CharT __sep,const _CharT * __p,_CharT * __new,_CharT * __cs,int & __len) const845 _M_group_float(const string& __grouping, _CharT __sep, const _CharT* __p, 846 _CharT* __new, _CharT* __cs, int& __len) const 847 { 848 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 849 //282. What types does numpunct grouping refer to? 850 // Add grouping, if necessary. 851 _CharT* __p2; 852 int __declen = __p ? __p - __cs : __len; 853 __p2 = __add_grouping(__new, __sep, 854 __grouping.c_str(), 855 __grouping.c_str() + __grouping.size(), 856 __cs, __cs + __declen); 857 858 // Tack on decimal part. 859 int __newlen = __p2 - __new; 860 if (__p) 861 { 862 char_traits<_CharT>::copy(__p2, __p, __len - __declen); 863 __newlen += __len - __declen; 864 } 865 __len = __newlen; 866 #endif 867 } 868 869 // The following code uses snprintf (or sprintf(), when 870 // _GLIBCPP_USE_C99 is not defined) to convert floating point values 871 // for insertion into a stream. An optimization would be to replace 872 // them with code that works directly on a wide buffer and then use 873 // __pad to do the padding. It would be good to replace them anyway 874 // to gain back the efficiency that C++ provides by knowing up front 875 // the type of the values to insert. Also, sprintf is dangerous 876 // since may lead to accidental buffer overruns. This 877 // implementation follows the C++ standard fairly directly as 878 // outlined in 22.2.2.2 [lib.locale.num.put] 879 template<typename _CharT, typename _OutIter> 880 template<typename _ValueT> 881 _OutIter 882 num_put<_CharT, _OutIter>:: _M_convert_float(_OutIter __s,ios_base & __io,_CharT __fill,char __mod,_ValueT __v) const883 _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 884 _ValueT __v) const 885 { 886 // Use default precision if out of range. 887 streamsize __prec = __io.precision(); 888 if (__prec < static_cast<streamsize>(0)) 889 __prec = static_cast<streamsize>(6); 890 891 const int __max_digits = numeric_limits<_ValueT>::digits10; 892 893 typedef numpunct<_CharT> __facet_type; 894 typedef __locale_cache<numpunct<_CharT> > __cache_type; 895 const locale __loc = __io._M_getloc(); 896 const __cache_type& __lc = __use_cache<__facet_type>(__loc); 897 898 // [22.2.2.2.2] Stage 1, numeric conversion to character. 899 int __len; 900 // Long enough for the max format spec. 901 char __fbuf[16]; 902 903 #if defined _GLIBCPP_USE_C99 || defined _GLIBCPP_USE_C99_SNPRINTF 904 // First try a buffer perhaps big enough (most probably sufficient 905 // for non-ios_base::fixed outputs) 906 int __cs_size = __max_digits * 3; 907 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 908 909 _S_format_float(__io, __fbuf, __mod, __prec); 910 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 911 _S_c_locale, __prec); 912 913 // If the buffer was not large enough, try again with the correct size. 914 if (__len >= __cs_size) 915 { 916 __cs_size = __len + 1; 917 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 918 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 919 _S_c_locale, __prec); 920 } 921 #else 922 // Consider the possibility of long ios_base::fixed outputs 923 const bool __fixed = __io.flags() & ios_base::fixed; 924 const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 925 926 // ios_base::fixed outputs may need up to __max_exp + 1 chars 927 // for the integer part + __prec chars for the fractional part 928 // + 3 chars for sign, decimal point, '\0'. On the other hand, 929 // for non-fixed outputs __max_digits * 2 chars + __prec are 930 // largely sufficient. 931 const int __cs_size = __fixed ? __max_exp + __prec + 4 932 : __max_digits * 2 + __prec; 933 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 934 935 _S_format_float(__io, __fbuf, __mod, __prec); 936 __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); 937 #endif 938 939 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 940 // numpunct.decimal_point() values for '.' and adding grouping. 941 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 942 943 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 944 * __len)); 945 __ctype.widen(__cs, __cs + __len, __ws); 946 947 // Replace decimal point. 948 const _CharT __cdec = __ctype.widen('.'); 949 const _CharT __dec = __lc._M_decimal_point; 950 const _CharT* __p; 951 if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) 952 __ws[__p - __ws] = __dec; 953 954 // Add grouping, if necessary. 955 _CharT* __ws2; 956 if (__lc._M_use_grouping) 957 { 958 // Grouping can add (almost) as many separators as the 959 // number of digits, but no more. 960 __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 961 * __len * 2)); 962 _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p, 963 __ws2, __ws, __len); 964 __ws = __ws2; 965 } 966 967 // Pad. 968 _CharT* __ws3; 969 streamsize __w = __io.width(); 970 if (__w > static_cast<streamsize>(__len)) 971 { 972 __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)); 973 _M_pad(__fill, __w, __io, __ws3, __ws, __len); 974 __ws = __ws3; 975 } 976 __io.width(0); 977 978 // [22.2.2.2.2] Stage 4. 979 // Write resulting, fully-formatted string to output iterator. 980 return __write(__s, __ws, __len); 981 } 982 983 template<typename _CharT, typename _OutIter> 984 _OutIter 985 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type __fill,bool __v) const986 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 987 { 988 ios_base::fmtflags __flags = __io.flags(); 989 if ((__flags & ios_base::boolalpha) == 0) 990 { 991 unsigned long __uv = __v; 992 __s = _M_convert_int(__s, __io, __fill, __uv); 993 } 994 else 995 { 996 typedef numpunct<_CharT> __facet_type; 997 typedef __locale_cache<numpunct<_CharT> > __cache_type; 998 const locale __loc = __io._M_getloc(); 999 const __cache_type& __lc = __use_cache<__facet_type>(__loc); 1000 1001 typedef basic_string<_CharT> __string_type; 1002 __string_type __name; 1003 if (__v) 1004 __name = __lc._M_truename; 1005 else 1006 __name = __lc._M_falsename; 1007 1008 const _CharT* __cs = __name.c_str(); 1009 int __len = __name.size(); 1010 _CharT* __cs3; 1011 streamsize __w = __io.width(); 1012 if (__w > static_cast<streamsize>(__len)) 1013 { 1014 __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1015 * __w)); 1016 _M_pad(__fill, __w, __io, __cs3, __cs, __len); 1017 __cs = __cs3; 1018 } 1019 __io.width(0); 1020 __s = __write(__s, __cs, __len); 1021 } 1022 return __s; 1023 } 1024 1025 template<typename _CharT, typename _OutIter> 1026 _OutIter 1027 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type __fill,long __v) const1028 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 1029 { return _M_convert_int(__s, __io, __fill, __v); } 1030 1031 template<typename _CharT, typename _OutIter> 1032 _OutIter 1033 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type __fill,unsigned long __v) const1034 do_put(iter_type __s, ios_base& __io, char_type __fill, 1035 unsigned long __v) const 1036 { return _M_convert_int(__s, __io, __fill, __v); } 1037 1038 #ifdef _GLIBCPP_USE_LONG_LONG 1039 template<typename _CharT, typename _OutIter> 1040 _OutIter 1041 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __b,char_type __fill,long long __v) const1042 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 1043 { return _M_convert_int(__s, __b, __fill, __v); } 1044 1045 template<typename _CharT, typename _OutIter> 1046 _OutIter 1047 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type __fill,unsigned long long __v) const1048 do_put(iter_type __s, ios_base& __io, char_type __fill, 1049 unsigned long long __v) const 1050 { return _M_convert_int(__s, __io, __fill, __v); } 1051 #endif 1052 1053 template<typename _CharT, typename _OutIter> 1054 _OutIter 1055 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type __fill,double __v) const1056 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 1057 { return _M_convert_float(__s, __io, __fill, char(), __v); } 1058 1059 template<typename _CharT, typename _OutIter> 1060 _OutIter 1061 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type __fill,long double __v) const1062 do_put(iter_type __s, ios_base& __io, char_type __fill, 1063 long double __v) const 1064 { return _M_convert_float(__s, __io, __fill, 'L', __v); } 1065 1066 template<typename _CharT, typename _OutIter> 1067 _OutIter 1068 num_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type __fill,const void * __v) const1069 do_put(iter_type __s, ios_base& __io, char_type __fill, 1070 const void* __v) const 1071 { 1072 ios_base::fmtflags __flags = __io.flags(); 1073 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield 1074 | ios_base::uppercase | ios_base::internal); 1075 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 1076 try 1077 { 1078 __s = _M_convert_int(__s, __io, __fill, 1079 reinterpret_cast<unsigned long>(__v)); 1080 __io.flags(__flags); 1081 } 1082 catch (...) 1083 { 1084 __io.flags(__flags); 1085 __throw_exception_again; 1086 } 1087 return __s; 1088 } 1089 1090 1091 template<typename _CharT, typename _InIter> 1092 _InIter 1093 money_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,long double & __units) const1094 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1095 ios_base::iostate& __err, long double& __units) const 1096 { 1097 string_type __str; 1098 __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 1099 1100 const int __cs_size = __str.size() + 1; 1101 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1102 const locale __loc = __io.getloc(); 1103 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1104 const _CharT* __wcs = __str.c_str(); 1105 __ctype.narrow(__wcs, __wcs + __cs_size, char(), __cs); 1106 __convert_to_v(__cs, __units, __err, _S_c_locale); 1107 return __beg; 1108 } 1109 1110 template<typename _CharT, typename _InIter> 1111 _InIter 1112 money_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,string_type & __units) const1113 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 1114 ios_base::iostate& __err, string_type& __units) const 1115 { 1116 // These contortions are quite unfortunate. 1117 typedef moneypunct<_CharT, true> __money_true; 1118 typedef moneypunct<_CharT, false> __money_false; 1119 typedef money_base::part part; 1120 typedef typename string_type::size_type size_type; 1121 1122 const locale __loc = __io.getloc(); 1123 const __money_true& __mpt = use_facet<__money_true>(__loc); 1124 const __money_false& __mpf = use_facet<__money_false>(__loc); 1125 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1126 1127 const money_base::pattern __p = __intl ? __mpt.neg_format() 1128 : __mpf.neg_format(); 1129 1130 const string_type __pos_sign =__intl ? __mpt.positive_sign() 1131 : __mpf.positive_sign(); 1132 const string_type __neg_sign =__intl ? __mpt.negative_sign() 1133 : __mpf.negative_sign(); 1134 const char_type __d = __intl ? __mpt.decimal_point() 1135 : __mpf.decimal_point(); 1136 const char_type __sep = __intl ? __mpt.thousands_sep() 1137 : __mpf.thousands_sep(); 1138 1139 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); 1140 1141 // Set to deduced positive or negative sign, depending. 1142 string_type __sign; 1143 // String of grouping info from thousands_sep plucked from __units. 1144 string __grouping_tmp; 1145 // Marker for thousands_sep position. 1146 int __sep_pos = 0; 1147 // If input iterator is in a valid state. 1148 bool __testvalid = true; 1149 // Flag marking when a decimal point is found. 1150 bool __testdecfound = false; 1151 1152 // The tentative returned string is stored here. 1153 string_type __temp_units; 1154 1155 char_type __c = *__beg; 1156 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); 1157 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) 1158 { 1159 part __which = static_cast<part>(__p.field[__i]); 1160 switch (__which) 1161 { 1162 case money_base::symbol: 1163 if (__io.flags() & ios_base::showbase 1164 || __i < 2 || __sign.size() > 1 1165 || ((static_cast<part>(__p.field[3]) != money_base::none) 1166 && __i == 2)) 1167 { 1168 // According to 22.2.6.1.2.2, symbol is required 1169 // if (__io.flags() & ios_base::showbase), 1170 // otherwise is optional and consumed only if 1171 // other characters are needed to complete the 1172 // format. 1173 const string_type __symbol = __intl ? __mpt.curr_symbol() 1174 : __mpf.curr_symbol(); 1175 size_type __len = __symbol.size(); 1176 size_type __j = 0; 1177 while (__beg != __end 1178 && __j < __len && __symbol[__j] == __c) 1179 { 1180 __c = *(++__beg); 1181 ++__j; 1182 } 1183 // When (__io.flags() & ios_base::showbase) 1184 // symbol is required. 1185 if (__j != __len && (__io.flags() & ios_base::showbase)) 1186 __testvalid = false; 1187 } 1188 break; 1189 case money_base::sign: 1190 // Sign might not exist, or be more than one character long. 1191 if (__pos_sign.size() && __neg_sign.size()) 1192 { 1193 // Sign is mandatory. 1194 if (__c == __pos_sign[0]) 1195 { 1196 __sign = __pos_sign; 1197 __c = *(++__beg); 1198 } 1199 else if (__c == __neg_sign[0]) 1200 { 1201 __sign = __neg_sign; 1202 __c = *(++__beg); 1203 } 1204 else 1205 __testvalid = false; 1206 } 1207 else if (__pos_sign.size() && __c == __pos_sign[0]) 1208 { 1209 __sign = __pos_sign; 1210 __c = *(++__beg); 1211 } 1212 else if (__neg_sign.size() && __c == __neg_sign[0]) 1213 { 1214 __sign = __neg_sign; 1215 __c = *(++__beg); 1216 } 1217 break; 1218 case money_base::value: 1219 // Extract digits, remove and stash away the 1220 // grouping of found thousands separators. 1221 while (__beg != __end 1222 && (__ctype.is(ctype_base::digit, __c) 1223 || (__c == __d && !__testdecfound) 1224 || __c == __sep)) 1225 { 1226 if (__c == __d) 1227 { 1228 __grouping_tmp += static_cast<char>(__sep_pos); 1229 __sep_pos = 0; 1230 __testdecfound = true; 1231 } 1232 else if (__c == __sep) 1233 { 1234 if (__grouping.size()) 1235 { 1236 // Mark position for later analysis. 1237 __grouping_tmp += static_cast<char>(__sep_pos); 1238 __sep_pos = 0; 1239 } 1240 else 1241 { 1242 __testvalid = false; 1243 break; 1244 } 1245 } 1246 else 1247 { 1248 __temp_units += __c; 1249 ++__sep_pos; 1250 } 1251 __c = *(++__beg); 1252 } 1253 break; 1254 case money_base::space: 1255 case money_base::none: 1256 // Only if not at the end of the pattern. 1257 if (__i != 3) 1258 while (__beg != __end 1259 && __ctype.is(ctype_base::space, __c)) 1260 __c = *(++__beg); 1261 break; 1262 } 1263 } 1264 1265 // Need to get the rest of the sign characters, if they exist. 1266 if (__sign.size() > 1) 1267 { 1268 size_type __len = __sign.size(); 1269 size_type __i = 1; 1270 for (; __c != __eof && __i < __len; ++__i) 1271 while (__beg != __end && __c != __sign[__i]) 1272 __c = *(++__beg); 1273 1274 if (__i != __len) 1275 __testvalid = false; 1276 } 1277 1278 // Strip leading zeros. 1279 while (__temp_units.size() > 1 && __temp_units[0] == __ctype.widen('0')) 1280 __temp_units.erase(__temp_units.begin()); 1281 1282 if (__sign.size() && __sign == __neg_sign) 1283 __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); 1284 1285 // Test for grouping fidelity. 1286 if (__grouping.size() && __grouping_tmp.size()) 1287 { 1288 if (!__verify_grouping(__grouping, __grouping_tmp)) 1289 __testvalid = false; 1290 } 1291 1292 // Iff no more characters are available. 1293 if (__c == __eof) 1294 __err |= ios_base::eofbit; 1295 1296 // Iff valid sequence is not recognized. 1297 if (!__testvalid || !__temp_units.size()) 1298 __err |= ios_base::failbit; 1299 else 1300 // Use the "swap trick" to copy __temp_units into __units. 1301 __temp_units.swap(__units); 1302 1303 return __beg; 1304 } 1305 1306 template<typename _CharT, typename _OutIter> 1307 _OutIter 1308 money_put<_CharT, _OutIter>:: do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,long double __units) const1309 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 1310 long double __units) const 1311 { 1312 const locale __loc = __io.getloc(); 1313 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1314 #if defined _GLIBCPP_USE_C99 || defined _GLIBCPP_USE_C99_SNPRINTF 1315 // First try a buffer perhaps big enough. 1316 int __cs_size = 64; 1317 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1318 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1319 // 328. Bad sprintf format modifier in money_put<>::do_put() 1320 int __len = __convert_from_v(__cs, __cs_size, "%.0Lf", __units, 1321 _S_c_locale); 1322 // If the buffer was not large enough, try again with the correct size. 1323 if (__len >= __cs_size) 1324 { 1325 __cs_size = __len + 1; 1326 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1327 __len = __convert_from_v(__cs, __cs_size, "%.0Lf", __units, 1328 _S_c_locale); 1329 } 1330 #else 1331 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 1332 const int __cs_size = numeric_limits<long double>::max_exponent10 + 3; 1333 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1334 int __len = __convert_from_v(__cs, 0, "%.0Lf", __units, _S_c_locale); 1335 #endif 1336 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1337 * __cs_size)); 1338 __ctype.widen(__cs, __cs + __len, __ws); 1339 const string_type __digits(__ws, __len); 1340 return this->do_put(__s, __intl, __io, __fill, __digits); 1341 } 1342 1343 template<typename _CharT, typename _OutIter> 1344 _OutIter 1345 money_put<_CharT, _OutIter>:: do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,const string_type & __digits) const1346 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 1347 const string_type& __digits) const 1348 { 1349 typedef typename string_type::size_type size_type; 1350 typedef money_base::part part; 1351 1352 const locale __loc = __io.getloc(); 1353 const size_type __width = static_cast<size_type>(__io.width()); 1354 1355 // These contortions are quite unfortunate. 1356 typedef moneypunct<_CharT, true> __money_true; 1357 typedef moneypunct<_CharT, false> __money_false; 1358 const __money_true& __mpt = use_facet<__money_true>(__loc); 1359 const __money_false& __mpf = use_facet<__money_false>(__loc); 1360 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1361 1362 // Determine if negative or positive formats are to be used, and 1363 // discard leading negative_sign if it is present. 1364 const char_type* __beg = __digits.data(); 1365 const char_type* __end = __beg + __digits.size(); 1366 money_base::pattern __p; 1367 string_type __sign; 1368 if (*__beg != __ctype.widen('-')) 1369 { 1370 __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); 1371 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); 1372 } 1373 else 1374 { 1375 __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); 1376 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); 1377 ++__beg; 1378 } 1379 1380 // Look for valid numbers in the current ctype facet within input digits. 1381 __end = __ctype.scan_not(ctype_base::digit, __beg, __end); 1382 if (__beg != __end) 1383 { 1384 // Assume valid input, and attempt to format. 1385 // Break down input numbers into base components, as follows: 1386 // final_value = grouped units + (decimal point) + (digits) 1387 string_type __res; 1388 string_type __value; 1389 const string_type __symbol = __intl ? __mpt.curr_symbol() 1390 : __mpf.curr_symbol(); 1391 1392 // Deal with decimal point, decimal digits. 1393 const int __frac = __intl ? __mpt.frac_digits() 1394 : __mpf.frac_digits(); 1395 if (__frac > 0) 1396 { 1397 const char_type __d = __intl ? __mpt.decimal_point() 1398 : __mpf.decimal_point(); 1399 if (__end - __beg >= __frac) 1400 { 1401 __value = string_type(__end - __frac, __end); 1402 __value.insert(__value.begin(), __d); 1403 __end -= __frac; 1404 } 1405 else 1406 { 1407 // Have to pad zeros in the decimal position. 1408 __value = string_type(__beg, __end); 1409 int __paddec = __frac - (__end - __beg); 1410 char_type __zero = __ctype.widen('0'); 1411 __value.insert(__value.begin(), __paddec, __zero); 1412 __value.insert(__value.begin(), __d); 1413 __beg = __end; 1414 } 1415 } 1416 1417 // Add thousands separators to non-decimal digits, per 1418 // grouping rules. 1419 if (__beg != __end) 1420 { 1421 const string __grouping = __intl ? __mpt.grouping() 1422 : __mpf.grouping(); 1423 if (__grouping.size()) 1424 { 1425 const char_type __sep = __intl ? __mpt.thousands_sep() 1426 : __mpf.thousands_sep(); 1427 const char* __gbeg = __grouping.c_str(); 1428 const char* __gend = __gbeg + __grouping.size(); 1429 const int __n = (__end - __beg) * 2; 1430 _CharT* __ws2 = 1431 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); 1432 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 1433 __gend, __beg, __end); 1434 __value.insert(0, __ws2, __ws_end - __ws2); 1435 } 1436 else 1437 __value.insert(0, string_type(__beg, __end)); 1438 } 1439 1440 // Calculate length of resulting string. 1441 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; 1442 size_type __len = __value.size() + __sign.size(); 1443 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; 1444 bool __testipad = __f == ios_base::internal && __len < __width; 1445 1446 // Fit formatted digits into the required pattern. 1447 for (int __i = 0; __i < 4; ++__i) 1448 { 1449 part __which = static_cast<part>(__p.field[__i]); 1450 switch (__which) 1451 { 1452 case money_base::symbol: 1453 if (__io.flags() & ios_base::showbase) 1454 __res += __symbol; 1455 break; 1456 case money_base::sign: 1457 // Sign might not exist, or be more than one 1458 // charater long. In that case, add in the rest 1459 // below. 1460 if (__sign.size()) 1461 __res += __sign[0]; 1462 break; 1463 case money_base::value: 1464 __res += __value; 1465 break; 1466 case money_base::space: 1467 // At least one space is required, but if internal 1468 // formatting is required, an arbitrary number of 1469 // fill spaces will be necessary. 1470 if (__testipad) 1471 __res += string_type(__width - __len, __fill); 1472 else 1473 __res += __ctype.widen(__fill); 1474 break; 1475 case money_base::none: 1476 if (__testipad) 1477 __res += string_type(__width - __len, __fill); 1478 break; 1479 } 1480 } 1481 1482 // Special case of multi-part sign parts. 1483 if (__sign.size() > 1) 1484 __res += string_type(__sign.begin() + 1, __sign.end()); 1485 1486 // Pad, if still necessary. 1487 __len = __res.size(); 1488 if (__width > __len) 1489 { 1490 if (__f == ios_base::left) 1491 // After. 1492 __res.append(__width - __len, __fill); 1493 else 1494 // Before. 1495 __res.insert(0, string_type(__width - __len, __fill)); 1496 __len = __width; 1497 } 1498 1499 // Write resulting, fully-formatted string to output iterator. 1500 __s = __write(__s, __res.c_str(), __len); 1501 } 1502 __io.width(0); 1503 return __s; 1504 } 1505 1506 1507 // NB: Not especially useful. Without an ios_base object or some 1508 // kind of locale reference, we are left clawing at the air where 1509 // the side of the mountain used to be... 1510 template<typename _CharT, typename _InIter> 1511 time_base::dateorder do_date_order() const1512 time_get<_CharT, _InIter>::do_date_order() const 1513 { return time_base::no_order; } 1514 1515 template<typename _CharT, typename _InIter> 1516 void 1517 time_get<_CharT, _InIter>:: _M_extract_via_format(iter_type & __beg,iter_type & __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,const _CharT * __format) const1518 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, 1519 ios_base::iostate& __err, tm* __tm, 1520 const _CharT* __format) const 1521 { 1522 locale __loc = __io.getloc(); 1523 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1524 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1525 size_t __len = char_traits<_CharT>::length(__format); 1526 1527 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 1528 { 1529 char __c = __format[__i]; 1530 if (__c == '%') 1531 { 1532 // Verify valid formatting code, attempt to extract. 1533 __c = __format[++__i]; 1534 char __mod = 0; 1535 int __mem = 0; 1536 if (__c == 'E' || __c == 'O') 1537 { 1538 __mod = __c; 1539 __c = __format[++__i]; 1540 } 1541 switch (__c) 1542 { 1543 const char* __cs; 1544 _CharT __wcs[10]; 1545 case 'a': 1546 // Abbreviated weekday name [tm_wday] 1547 const char_type* __days1[7]; 1548 __tp._M_days_abbreviated(__days1); 1549 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 1550 __err); 1551 break; 1552 case 'A': 1553 // Weekday name [tm_wday]. 1554 const char_type* __days2[7]; 1555 __tp._M_days(__days2); 1556 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 1557 __err); 1558 break; 1559 case 'h': 1560 case 'b': 1561 // Abbreviated month name [tm_mon] 1562 const char_type* __months1[12]; 1563 __tp._M_months_abbreviated(__months1); 1564 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 1565 __err); 1566 break; 1567 case 'B': 1568 // Month name [tm_mon]. 1569 const char_type* __months2[12]; 1570 __tp._M_months(__months2); 1571 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 1572 __err); 1573 break; 1574 case 'c': 1575 // Default time and date representation. 1576 const char_type* __dt[2]; 1577 __tp._M_date_time_formats(__dt); 1578 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1579 __dt[0]); 1580 break; 1581 case 'd': 1582 // Day [01, 31]. [tm_mday] 1583 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 1584 __ctype, __err); 1585 break; 1586 case 'D': 1587 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 1588 __cs = "%m/%d/%y"; 1589 __ctype.widen(__cs, __cs + 9, __wcs); 1590 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1591 __wcs); 1592 break; 1593 case 'H': 1594 // Hour [00, 23]. [tm_hour] 1595 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 1596 __ctype, __err); 1597 break; 1598 case 'I': 1599 // Hour [01, 12]. [tm_hour] 1600 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 1601 __ctype, __err); 1602 break; 1603 case 'm': 1604 // Month [01, 12]. [tm_mon] 1605 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 1606 __err); 1607 if (!__err) 1608 __tm->tm_mon = __mem - 1; 1609 break; 1610 case 'M': 1611 // Minute [00, 59]. [tm_min] 1612 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 1613 __ctype, __err); 1614 break; 1615 case 'n': 1616 if (__ctype.narrow(*__beg, 0) == '\n') 1617 ++__beg; 1618 else 1619 __err |= ios_base::failbit; 1620 break; 1621 case 'R': 1622 // Equivalent to (%H:%M). 1623 __cs = "%H:%M"; 1624 __ctype.widen(__cs, __cs + 6, __wcs); 1625 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1626 __wcs); 1627 break; 1628 case 'S': 1629 // Seconds. 1630 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 1631 __ctype, __err); 1632 break; 1633 case 't': 1634 if (__ctype.narrow(*__beg, 0) == '\t') 1635 ++__beg; 1636 else 1637 __err |= ios_base::failbit; 1638 break; 1639 case 'T': 1640 // Equivalent to (%H:%M:%S). 1641 __cs = "%H:%M:%S"; 1642 __ctype.widen(__cs, __cs + 9, __wcs); 1643 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1644 __wcs); 1645 break; 1646 case 'x': 1647 // Locale's date. 1648 const char_type* __dates[2]; 1649 __tp._M_date_formats(__dates); 1650 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1651 __dates[0]); 1652 break; 1653 case 'X': 1654 // Locale's time. 1655 const char_type* __times[2]; 1656 __tp._M_time_formats(__times); 1657 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1658 __times[0]); 1659 break; 1660 case 'y': 1661 // Two digit year. [tm_year] 1662 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 1663 __ctype, __err); 1664 break; 1665 case 'Y': 1666 // Year [1900). [tm_year] 1667 _M_extract_num(__beg, __end, __mem, 0, 1668 numeric_limits<int>::max(), 4, 1669 __ctype, __err); 1670 if (!__err) 1671 __tm->tm_year = __mem - 1900; 1672 break; 1673 case 'Z': 1674 // Timezone info. 1675 if (__ctype.is(ctype_base::upper, *__beg)) 1676 { 1677 int __tmp; 1678 _M_extract_name(__beg, __end, __tmp, 1679 __timepunct<_CharT>::_S_timezones, 1680 14, __err); 1681 1682 // GMT requires special effort. 1683 char_type __c = *__beg; 1684 if (!__err && __tmp == 0 1685 && (__c == __ctype.widen('-') 1686 || __c == __ctype.widen('+'))) 1687 { 1688 _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 1689 __ctype, __err); 1690 _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 1691 __ctype, __err); 1692 } 1693 } 1694 else 1695 __err |= ios_base::failbit; 1696 break; 1697 default: 1698 // Not recognized. 1699 __err |= ios_base::failbit; 1700 } 1701 } 1702 else 1703 { 1704 // Verify format and input match, extract and discard. 1705 if (__c == __ctype.narrow(*__beg, 0)) 1706 ++__beg; 1707 else 1708 __err |= ios_base::failbit; 1709 } 1710 } 1711 } 1712 1713 template<typename _CharT, typename _InIter> 1714 void 1715 time_get<_CharT, _InIter>:: _M_extract_num(iter_type & __beg,iter_type & __end,int & __member,int __min,int __max,size_t __len,const ctype<_CharT> & __ctype,ios_base::iostate & __err) const1716 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, 1717 int __min, int __max, size_t __len, 1718 const ctype<_CharT>& __ctype, 1719 ios_base::iostate& __err) const 1720 { 1721 size_t __i = 0; 1722 string __digits; 1723 bool __testvalid = true; 1724 char_type __c = *__beg; 1725 while (__beg != __end && __i < __len 1726 && __ctype.is(ctype_base::digit, __c)) 1727 { 1728 __digits += __ctype.narrow(__c, 0); 1729 __c = *(++__beg); 1730 ++__i; 1731 } 1732 if (__i == __len) 1733 { 1734 int __value = atoi(__digits.c_str()); 1735 if (__min <= __value && __value <= __max) 1736 __member = __value; 1737 else 1738 __testvalid = false; 1739 } 1740 else 1741 __testvalid = false; 1742 if (!__testvalid) 1743 __err |= ios_base::failbit; 1744 } 1745 1746 // Assumptions: 1747 // All elements in __names are unique. 1748 template<typename _CharT, typename _InIter> 1749 void 1750 time_get<_CharT, _InIter>:: _M_extract_name(iter_type & __beg,iter_type & __end,int & __member,const _CharT ** __names,size_t __indexlen,ios_base::iostate & __err) const1751 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, 1752 const _CharT** __names, size_t __indexlen, 1753 ios_base::iostate& __err) const 1754 { 1755 typedef char_traits<_CharT> __traits_type; 1756 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 1757 * __indexlen)); 1758 size_t __nmatches = 0; 1759 size_t __pos = 0; 1760 bool __testvalid = true; 1761 const char_type* __name; 1762 1763 char_type __c = *__beg; 1764 // Look for initial matches. 1765 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 1766 if (__c == __names[__i1][0]) 1767 __matches[__nmatches++] = __i1; 1768 1769 while (__nmatches > 1) 1770 { 1771 // Find smallest matching string. 1772 size_t __minlen = 10; 1773 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 1774 __minlen = min(__minlen, 1775 __traits_type::length(__names[__matches[__i2]])); 1776 1777 if (__pos < __minlen && __beg != __end) 1778 { 1779 ++__pos; 1780 __c = *(++__beg); 1781 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 1782 { 1783 __name = __names[__matches[__i3]]; 1784 if (__name[__pos] != __c) 1785 __matches[__i3] = __matches[--__nmatches]; 1786 } 1787 } 1788 else 1789 break; 1790 } 1791 1792 if (__nmatches == 1) 1793 { 1794 // Make sure found name is completely extracted. 1795 __name = __names[__matches[0]]; 1796 const size_t __len = __traits_type::length(__name); 1797 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 1798 ++__beg, ++__pos; 1799 1800 if (__len == __pos) 1801 __member = __matches[0]; 1802 else 1803 __testvalid = false; 1804 } 1805 else 1806 __testvalid = false; 1807 if (!__testvalid) 1808 __err |= ios_base::failbit; 1809 } 1810 1811 template<typename _CharT, typename _InIter> 1812 _InIter 1813 time_get<_CharT, _InIter>:: do_get_time(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1814 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 1815 ios_base::iostate& __err, tm* __tm) const 1816 { 1817 _CharT __wcs[3]; 1818 const char* __cs = "%X"; 1819 locale __loc = __io.getloc(); 1820 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1821 __ctype.widen(__cs, __cs + 3, __wcs); 1822 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 1823 if (__beg == __end) 1824 __err |= ios_base::eofbit; 1825 return __beg; 1826 } 1827 1828 template<typename _CharT, typename _InIter> 1829 _InIter 1830 time_get<_CharT, _InIter>:: do_get_date(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1831 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 1832 ios_base::iostate& __err, tm* __tm) const 1833 { 1834 _CharT __wcs[3]; 1835 const char* __cs = "%x"; 1836 locale __loc = __io.getloc(); 1837 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1838 __ctype.widen(__cs, __cs + 3, __wcs); 1839 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 1840 if (__beg == __end) 1841 __err |= ios_base::eofbit; 1842 return __beg; 1843 } 1844 1845 template<typename _CharT, typename _InIter> 1846 _InIter 1847 time_get<_CharT, _InIter>:: do_get_weekday(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1848 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 1849 ios_base::iostate& __err, tm* __tm) const 1850 { 1851 typedef char_traits<_CharT> __traits_type; 1852 locale __loc = __io.getloc(); 1853 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1854 const char_type* __days[7]; 1855 __tp._M_days_abbreviated(__days); 1856 int __tmpwday; 1857 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); 1858 1859 // Check to see if non-abbreviated name exists, and extract. 1860 // NB: Assumes both _M_days and _M_days_abbreviated organized in 1861 // exact same order, first to last, such that the resulting 1862 // __days array with the same index points to a day, and that 1863 // day's abbreviated form. 1864 // NB: Also assumes that an abbreviated name is a subset of the name. 1865 if (!__err) 1866 { 1867 size_t __pos = __traits_type::length(__days[__tmpwday]); 1868 __tp._M_days(__days); 1869 const char_type* __name = __days[__tmpwday]; 1870 if (__name[__pos] == *__beg) 1871 { 1872 // Extract the rest of it. 1873 const size_t __len = __traits_type::length(__name); 1874 while (__pos < __len && __beg != __end 1875 && __name[__pos] == *__beg) 1876 ++__beg, ++__pos; 1877 if (__len != __pos) 1878 __err |= ios_base::failbit; 1879 } 1880 if (!__err) 1881 __tm->tm_wday = __tmpwday; 1882 } 1883 if (__beg == __end) 1884 __err |= ios_base::eofbit; 1885 return __beg; 1886 } 1887 1888 template<typename _CharT, typename _InIter> 1889 _InIter 1890 time_get<_CharT, _InIter>:: do_get_monthname(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1891 do_get_monthname(iter_type __beg, iter_type __end, 1892 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 1893 { 1894 typedef char_traits<_CharT> __traits_type; 1895 locale __loc = __io.getloc(); 1896 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1897 const char_type* __months[12]; 1898 __tp._M_months_abbreviated(__months); 1899 int __tmpmon; 1900 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); 1901 1902 // Check to see if non-abbreviated name exists, and extract. 1903 // NB: Assumes both _M_months and _M_months_abbreviated organized in 1904 // exact same order, first to last, such that the resulting 1905 // __months array with the same index points to a month, and that 1906 // month's abbreviated form. 1907 // NB: Also assumes that an abbreviated name is a subset of the name. 1908 if (!__err) 1909 { 1910 size_t __pos = __traits_type::length(__months[__tmpmon]); 1911 __tp._M_months(__months); 1912 const char_type* __name = __months[__tmpmon]; 1913 if (__name[__pos] == *__beg) 1914 { 1915 // Extract the rest of it. 1916 const size_t __len = __traits_type::length(__name); 1917 while (__pos < __len && __beg != __end 1918 && __name[__pos] == *__beg) 1919 ++__beg, ++__pos; 1920 if (__len != __pos) 1921 __err |= ios_base::failbit; 1922 } 1923 if (!__err) 1924 __tm->tm_mon = __tmpmon; 1925 } 1926 1927 if (__beg == __end) 1928 __err |= ios_base::eofbit; 1929 return __beg; 1930 } 1931 1932 template<typename _CharT, typename _InIter> 1933 _InIter 1934 time_get<_CharT, _InIter>:: do_get_year(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1935 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 1936 ios_base::iostate& __err, tm* __tm) const 1937 { 1938 locale __loc = __io.getloc(); 1939 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1940 1941 char_type __c = *__beg; 1942 size_t __i = 0; 1943 string __digits; 1944 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) 1945 { 1946 __digits += __ctype.narrow(__c, 0); 1947 __c = *(++__beg); 1948 ++__i; 1949 } 1950 if (__i == 2 || __i == 4) 1951 { 1952 long __l; 1953 __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); 1954 if (!(__err & ios_base::failbit) && __l <= INT_MAX) 1955 { 1956 __l = __i == 2 ? __l : __l - 1900; 1957 __tm->tm_year = static_cast<int>(__l); 1958 } 1959 } 1960 else 1961 __err |= ios_base::failbit; 1962 if (__beg == __end) 1963 __err |= ios_base::eofbit; 1964 return __beg; 1965 } 1966 1967 template<typename _CharT, typename _OutIter> 1968 _OutIter 1969 time_put<_CharT, _OutIter>:: put(iter_type __s,ios_base & __io,char_type,const tm * __tm,const _CharT * __beg,const _CharT * __end) const1970 put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 1971 const _CharT* __beg, const _CharT* __end) const 1972 { 1973 locale __loc = __io.getloc(); 1974 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1975 while (__beg != __end) 1976 { 1977 char __c = __ctype.narrow(*__beg, 0); 1978 ++__beg; 1979 if (__c == '%') 1980 { 1981 char __format; 1982 char __mod = 0; 1983 size_t __len = 1; 1984 __c = __ctype.narrow(*__beg, 0); 1985 ++__beg; 1986 if (__c == 'E' || __c == 'O') 1987 { 1988 __mod = __c; 1989 __format = __ctype.narrow(*__beg, 0); 1990 ++__beg; 1991 } 1992 else 1993 __format = __c; 1994 __s = this->do_put(__s, __io, _CharT(), __tm, __format, __mod); 1995 } 1996 else 1997 { 1998 *__s = __c; 1999 ++__s; 2000 } 2001 } 2002 return __s; 2003 } 2004 2005 template<typename _CharT, typename _OutIter> 2006 _OutIter 2007 time_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type,const tm * __tm,char __format,char __mod) const2008 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 2009 char __format, char __mod) const 2010 { 2011 locale __loc = __io.getloc(); 2012 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 2013 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 2014 2015 // NB: This size is arbitrary. Should this be a data member, 2016 // initialized at construction? 2017 const size_t __maxlen = 64; 2018 char_type* __res = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 2019 2020 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 2021 // is possible that the format character will be longer than one 2022 // character. Possibilities include 'E' or 'O' followed by a 2023 // format character: if __mod is not the default argument, assume 2024 // it's a valid modifier. 2025 char_type __fmt[4]; 2026 __fmt[0] = __ctype.widen('%'); 2027 if (!__mod) 2028 { 2029 __fmt[1] = __format; 2030 __fmt[2] = char_type(); 2031 } 2032 else 2033 { 2034 __fmt[1] = __mod; 2035 __fmt[2] = __format; 2036 __fmt[3] = char_type(); 2037 } 2038 2039 __tp._M_put(__res, __maxlen, __fmt, __tm); 2040 2041 // Write resulting, fully-formatted string to output iterator. 2042 return __write(__s, __res, char_traits<char_type>::length(__res)); 2043 } 2044 2045 2046 // Generic version does nothing. 2047 template<typename _CharT> 2048 int _M_compare(const _CharT *,const _CharT *) const2049 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 2050 { return 0; } 2051 2052 // Generic version does nothing. 2053 template<typename _CharT> 2054 size_t _M_transform(_CharT *,const _CharT *,size_t) const2055 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 2056 { return 0; } 2057 2058 template<typename _CharT> 2059 int 2060 collate<_CharT>:: do_compare(const _CharT * __lo1,const _CharT * __hi1,const _CharT * __lo2,const _CharT * __hi2) const2061 do_compare(const _CharT* __lo1, const _CharT* __hi1, 2062 const _CharT* __lo2, const _CharT* __hi2) const 2063 { 2064 // strcoll assumes zero-terminated strings so we make a copy 2065 // and then put a zero at the end. 2066 const string_type __one(__lo1, __hi1); 2067 const string_type __two(__lo2, __hi2); 2068 2069 const _CharT* __p = __one.c_str(); 2070 const _CharT* __pend = __one.c_str() + __one.length(); 2071 const _CharT* __q = __two.c_str(); 2072 const _CharT* __qend = __two.c_str() + __two.length(); 2073 2074 // strcoll stops when it sees a nul character so we break 2075 // the strings into zero-terminated substrings and pass those 2076 // to strcoll. 2077 for (;;) 2078 { 2079 int __res = _M_compare(__p, __q); 2080 if (__res) 2081 return __res; 2082 2083 __p += char_traits<_CharT>::length(__p); 2084 __q += char_traits<_CharT>::length(__q); 2085 if (__p == __pend && __q == __qend) 2086 return 0; 2087 else if (__p == __pend) 2088 return -1; 2089 else if (__q == __qend) 2090 return 1; 2091 2092 __p++; 2093 __q++; 2094 } 2095 } 2096 2097 template<typename _CharT> 2098 typename collate<_CharT>::string_type 2099 collate<_CharT>:: do_transform(const _CharT * __lo,const _CharT * __hi) const2100 do_transform(const _CharT* __lo, const _CharT* __hi) const 2101 { 2102 // strxfrm assumes zero-terminated strings so we make a copy 2103 string_type __str(__lo, __hi); 2104 2105 const _CharT* __p = __str.c_str(); 2106 const _CharT* __pend = __str.c_str() + __str.length(); 2107 2108 size_t __len = (__hi - __lo) * 2; 2109 2110 string_type __ret; 2111 2112 // strxfrm stops when it sees a nul character so we break 2113 // the string into zero-terminated substrings and pass those 2114 // to strxfrm. 2115 for (;;) 2116 { 2117 // First try a buffer perhaps big enough. 2118 _CharT* __c = 2119 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 2120 size_t __res = _M_transform(__c, __p, __len); 2121 // If the buffer was not large enough, try again with the 2122 // correct size. 2123 if (__res >= __len) 2124 { 2125 __len = __res + 1; 2126 __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2127 * __len)); 2128 __res = _M_transform(__c, __p, __res + 1); 2129 } 2130 2131 __ret.append(__c, __res); 2132 __p += char_traits<_CharT>::length(__p); 2133 if (__p == __pend) 2134 return __ret; 2135 2136 __p++; 2137 __ret.push_back(_CharT()); 2138 } 2139 } 2140 2141 template<typename _CharT> 2142 long 2143 collate<_CharT>:: do_hash(const _CharT * __lo,const _CharT * __hi) const2144 do_hash(const _CharT* __lo, const _CharT* __hi) const 2145 { 2146 unsigned long __val = 0; 2147 for (; __lo < __hi; ++__lo) 2148 __val = *__lo + ((__val << 7) | 2149 (__val >> (numeric_limits<unsigned long>::digits - 7))); 2150 return static_cast<long>(__val); 2151 } 2152 2153 // Construct correctly padded string, as per 22.2.2.2.2 2154 // Assumes 2155 // __newlen > __oldlen 2156 // __news is allocated for __newlen size 2157 // Used by both num_put and ostream inserters: if __num, 2158 // internal-adjusted objects are padded according to the rules below 2159 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 2160 // ones are. 2161 2162 // NB: Of the two parameters, _CharT can be deduced from the 2163 // function arguments. The other (_Traits) has to be explicitly specified. 2164 template<typename _CharT, typename _Traits> 2165 void _S_pad(ios_base & __io,_CharT __fill,_CharT * __news,const _CharT * __olds,const streamsize __newlen,const streamsize __oldlen,const bool __num)2166 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2167 _CharT* __news, const _CharT* __olds, 2168 const streamsize __newlen, 2169 const streamsize __oldlen, const bool __num) 2170 { 2171 const size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2172 const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 2173 2174 // Padding last. 2175 if (__adjust == ios_base::left) 2176 { 2177 _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen); 2178 _Traits::assign(__news + __oldlen, __plen, __fill); 2179 return; 2180 } 2181 2182 size_t __mod = 0; 2183 if (__adjust == ios_base::internal && __num) 2184 { 2185 // Pad after the sign, if there is one. 2186 // Pad after 0[xX], if there is one. 2187 // Who came up with these rules, anyway? Jeeze. 2188 const locale& __loc = __io.getloc(); 2189 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2190 const _CharT __minus = __ctype.widen('-'); 2191 const _CharT __plus = __ctype.widen('+'); 2192 const bool __testsign = _Traits::eq(__olds[0], __minus) 2193 || _Traits::eq(__olds[0], __plus); 2194 2195 const bool __testhex = (_Traits::eq(__ctype.widen('0'), __olds[0]) 2196 && __oldlen > 1 2197 && (_Traits::eq(__ctype.widen('x'), __olds[1]) 2198 || _Traits::eq(__ctype.widen('X'), 2199 __olds[1]))); 2200 if (__testhex) 2201 { 2202 __news[0] = __olds[0]; 2203 __news[1] = __olds[1]; 2204 __mod = 2; 2205 __news += 2; 2206 } 2207 else if (__testsign) 2208 { 2209 __news[0] = __olds[0]; 2210 __mod = 1; 2211 ++__news; 2212 } 2213 // else Padding first. 2214 } 2215 _Traits::assign(__news, __plen, __fill); 2216 _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod), 2217 __oldlen - __mod); 2218 } 2219 2220 template<typename _CharT> 2221 bool __verify_grouping(const basic_string<_CharT> & __grouping,basic_string<_CharT> & __grouping_tmp)2222 __verify_grouping(const basic_string<_CharT>& __grouping, 2223 basic_string<_CharT>& __grouping_tmp) 2224 { 2225 const size_t __n = __grouping_tmp.size() - 1; 2226 const size_t __min = std::min(__n, __grouping.size() - 1); 2227 size_t __i = __n; 2228 bool __test = true; 2229 2230 // Parsed number groupings have to match the 2231 // numpunct::grouping string exactly, starting at the 2232 // right-most point of the parsed sequence of elements ... 2233 for (size_t __j = 0; __j < __min && __test; --__i, ++__j) 2234 __test = __grouping_tmp[__i] == __grouping[__j]; 2235 for (; __i && __test; --__i) 2236 __test = __grouping_tmp[__i] == __grouping[__min]; 2237 // ... but the last parsed grouping can be <= numpunct 2238 // grouping. 2239 __test &= __grouping_tmp[0] <= __grouping[__min]; 2240 return __test; 2241 } 2242 2243 template<typename _CharT> 2244 _CharT* __add_grouping(_CharT * __s,_CharT __sep,const char * __gbeg,const char * __gend,const _CharT * __first,const _CharT * __last)2245 __add_grouping(_CharT* __s, _CharT __sep, 2246 const char* __gbeg, const char* __gend, 2247 const _CharT* __first, const _CharT* __last) 2248 { 2249 if (__last - __first > *__gbeg) 2250 { 2251 __s = __add_grouping(__s, __sep, 2252 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), 2253 __gend, __first, __last - *__gbeg); 2254 __first = __last - *__gbeg; 2255 *__s++ = __sep; 2256 } 2257 do 2258 *__s++ = *__first++; 2259 while (__first != __last); 2260 return __s; 2261 } 2262 2263 #if 1 2264 // XXX GLIBCXX_ABI Deprecated, compatibility only. 2265 template<typename _CharT, typename _OutIter> 2266 template<typename _ValueT> 2267 _OutIter 2268 num_put<_CharT, _OutIter>:: _M_convert_int(_OutIter __s,ios_base & __io,_CharT __fill,char __mod,char __modl,_ValueT __v) const2269 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 2270 char __modl, _ValueT __v) const 2271 { 2272 // [22.2.2.2.2] Stage 1, numeric conversion to character. 2273 2274 // Long enough for the max format spec. 2275 char __fbuf[16]; 2276 _S_format_int(__io, __fbuf, __mod, __modl); 2277 #if defined _GLIBCPP_USE_C99 || defined _GLIBCPP_USE_C99_SNPRINTF 2278 // First try a buffer perhaps big enough. 2279 int __cs_size = 64; 2280 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 2281 int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 2282 _S_c_locale); 2283 // If the buffer was not large enough, try again with the correct size. 2284 if (__len >= __cs_size) 2285 { 2286 __cs_size = __len + 1; 2287 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 2288 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 2289 _S_c_locale); 2290 } 2291 #else 2292 // Leave room for "+/-," "0x," and commas. This size is 2293 // arbitrary, but should be largely sufficient. 2294 char __cs[128]; 2295 int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 2296 #endif 2297 return _M_widen_int(__s, __io, __fill, __cs, __len); 2298 } 2299 2300 template<typename _CharT, typename _OutIter> 2301 _OutIter 2302 num_put<_CharT, _OutIter>:: _M_widen_float(_OutIter __s,ios_base & __io,_CharT __fill,char * __cs,int __len) const2303 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 2304 int __len) const 2305 { 2306 typedef char_traits<_CharT> __traits_type; 2307 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 2308 // numpunct.decimal_point() values for '.' and adding grouping. 2309 const locale __loc = __io.getloc(); 2310 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2311 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2312 * __len)); 2313 // Grouping can add (almost) as many separators as the number of 2314 // digits, but no more. 2315 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2316 * __len * 2)); 2317 __ctype.widen(__cs, __cs + __len, __ws); 2318 2319 // Replace decimal point. 2320 const _CharT* __p; 2321 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2322 if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) 2323 __ws[__p - __ws] = __np.decimal_point(); 2324 2325 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 2326 //282. What types does numpunct grouping refer to? 2327 // Add grouping, if necessary. 2328 const string __grouping = __np.grouping(); 2329 if (__grouping.size()) 2330 { 2331 _CharT* __p2; 2332 int __declen = __p ? __p - __ws : __len; 2333 __p2 = __add_grouping(__ws2, __np.thousands_sep(), 2334 __grouping.c_str(), 2335 __grouping.c_str() + __grouping.size(), 2336 __ws, __ws + __declen); 2337 int __newlen = __p2 - __ws2; 2338 2339 // Tack on decimal part. 2340 if (__p) 2341 { 2342 __traits_type::copy(__p2, __p, __len - __declen); 2343 __newlen += __len - __declen; 2344 } 2345 2346 // Switch strings, establish correct new length. 2347 __ws = __ws2; 2348 __len = __newlen; 2349 } 2350 #endif 2351 return _M_insert(__s, __io, __fill, __ws, __len); 2352 } 2353 2354 template<typename _CharT, typename _OutIter> 2355 _OutIter 2356 num_put<_CharT, _OutIter>:: _M_widen_int(_OutIter __s,ios_base & __io,_CharT __fill,char * __cs,int __len) const2357 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 2358 int __len) const 2359 { 2360 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 2361 // numpunct.decimal_point() values for '.' and adding grouping. 2362 const locale __loc = __io.getloc(); 2363 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2364 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2365 * __len)); 2366 // Grouping can add (almost) as many separators as the number of 2367 // digits, but no more. 2368 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2369 * __len * 2)); 2370 __ctype.widen(__cs, __cs + __len, __ws); 2371 2372 // Add grouping, if necessary. 2373 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2374 const string __grouping = __np.grouping(); 2375 if (__grouping.size()) 2376 { 2377 // By itself __add_grouping cannot deal correctly with __ws when 2378 // ios::showbase is set and ios_base::oct || ios_base::hex. 2379 // Therefore we take care "by hand" of the initial 0, 0x or 0X. 2380 // However, remember that the latter do not occur if the number 2381 // printed is '0' (__len == 1). 2382 streamsize __off = 0; 2383 const ios_base::fmtflags __basefield = __io.flags() 2384 & ios_base::basefield; 2385 if ((__io.flags() & ios_base::showbase) && __len > 1) 2386 if (__basefield == ios_base::oct) 2387 { 2388 __off = 1; 2389 *__ws2 = *__ws; 2390 } 2391 else if (__basefield == ios_base::hex) 2392 { 2393 __off = 2; 2394 *__ws2 = *__ws; 2395 *(__ws2 + 1) = *(__ws + 1); 2396 } 2397 _CharT* __p; 2398 __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 2399 __grouping.c_str(), 2400 __grouping.c_str() + __grouping.size(), 2401 __ws + __off, __ws + __len); 2402 __len = __p - __ws2; 2403 // Switch strings. 2404 __ws = __ws2; 2405 } 2406 return _M_insert(__s, __io, __fill, __ws, __len); 2407 } 2408 2409 // For use by integer and floating-point types after they have been 2410 // converted into a char_type string. 2411 template<typename _CharT, typename _OutIter> 2412 _OutIter 2413 num_put<_CharT, _OutIter>:: _M_insert(_OutIter __s,ios_base & __io,_CharT __fill,const _CharT * __ws,int __len) const2414 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 2415 int __len) const 2416 { 2417 typedef char_traits<_CharT> __traits_type; 2418 // [22.2.2.2.2] Stage 3. 2419 // If necessary, pad. 2420 streamsize __w = __io.width(); 2421 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 2422 * __w)); 2423 if (__w > static_cast<streamsize>(__len)) 2424 { 2425 __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 2426 __w, __len, true); 2427 __len = static_cast<int>(__w); 2428 // Switch strings. 2429 __ws = __ws2; 2430 } 2431 __io.width(0); 2432 2433 // [22.2.2.2.2] Stage 4. 2434 // Write resulting, fully-formatted string to output iterator. 2435 return __write(__s, __ws, __len); 2436 } 2437 #endif 2438 2439 template<typename _CharT> __locale_cache(const locale & __loc)2440 __locale_cache<numpunct<_CharT> >::__locale_cache(const locale& __loc) 2441 : _M_truename(0), _M_falsename(0), _M_use_grouping(false), 2442 _M_grouping(0) 2443 { 2444 if (has_facet<numpunct<_CharT> >(__loc)) 2445 { 2446 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2447 _M_decimal_point = __np.decimal_point(); 2448 _M_thousands_sep = __np.thousands_sep(); 2449 2450 string_type __false = __np.falsename(); 2451 _CharT* __falsename = new _CharT[__false.length() + 1]; 2452 __false.copy(__falsename, __false.length()); 2453 __falsename[__false.length()] = _CharT(); 2454 _M_falsename = __falsename; 2455 2456 string_type __true = __np.truename(); 2457 _CharT* __truename = new _CharT[__true.length() + 1]; 2458 __true.copy(__truename, __true.length()); 2459 __truename[__true.length()] = _CharT(); 2460 _M_truename = __truename; 2461 2462 string __grouping = __np.grouping(); 2463 char* __group = new char[__grouping.length() + 1]; 2464 __grouping.copy(__group, __grouping.length()); 2465 __group[__grouping.length()] = 0; 2466 _M_grouping = __group; 2467 2468 _M_use_grouping = __grouping.length() != 0 2469 && __grouping.data()[0] != 0; 2470 } 2471 2472 if (has_facet<ctype<_CharT> >(__loc)) 2473 { 2474 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 2475 __ct.widen(__num_base::_S_atoms_out, 2476 __num_base::_S_atoms_out + __num_base::_S_end, 2477 _M_atoms_out); 2478 } 2479 } 2480 2481 // Static locale cache initialization. Only instantiated with char 2482 // and wchar_t, so no need to check has_facet. 2483 template<typename _CharT> 2484 __locale_cache<numpunct<_CharT> >:: __locale_cache(const locale & __loc,bool)2485 __locale_cache(const locale& __loc, bool) 2486 { 2487 // Grab pointers to numpunct static strings 2488 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 2489 _M_thousands_sep = __np._M_thousands_sep; 2490 _M_decimal_point = __np._M_decimal_point; 2491 _M_falsename = __np._M_falsename; 2492 _M_truename = __np._M_truename; 2493 _M_grouping = __np._M_grouping; 2494 _M_use_grouping = false; 2495 2496 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 2497 __ct.widen(__num_base::_S_atoms_out, 2498 __num_base::_S_atoms_out + __num_base::_S_end, 2499 _M_atoms_out); 2500 } 2501 2502 // Inhibit implicit instantiations for required instantiations, 2503 // which are defined via explicit instantiations elsewhere. 2504 // NB: This syntax is a GNU extension. 2505 #if _GLIBCPP_EXTERN_TEMPLATE 2506 extern template class moneypunct<char, false>; 2507 extern template class moneypunct<char, true>; 2508 extern template class moneypunct_byname<char, false>; 2509 extern template class moneypunct_byname<char, true>; 2510 extern template class money_get<char>; 2511 extern template class money_put<char>; 2512 extern template class numpunct<char>; 2513 extern template class numpunct_byname<char>; 2514 extern template class num_get<char>; 2515 extern template class num_put<char>; 2516 extern template class __timepunct<char>; 2517 extern template class time_put<char>; 2518 extern template class time_put_byname<char>; 2519 extern template class time_get<char>; 2520 extern template class time_get_byname<char>; 2521 extern template class messages<char>; 2522 extern template class messages_byname<char>; 2523 extern template class ctype_byname<char>; 2524 extern template class codecvt_byname<char, char, mbstate_t>; 2525 extern template class collate<char>; 2526 extern template class collate_byname<char>; 2527 2528 extern template 2529 const codecvt<char, char, mbstate_t>& 2530 use_facet<codecvt<char, char, mbstate_t> >(const locale&); 2531 2532 extern template 2533 const collate<char>& 2534 use_facet<collate<char> >(const locale&); 2535 2536 extern template 2537 const numpunct<char>& 2538 use_facet<numpunct<char> >(const locale&); 2539 2540 extern template 2541 const num_put<char>& 2542 use_facet<num_put<char> >(const locale&); 2543 2544 extern template 2545 const num_get<char>& 2546 use_facet<num_get<char> >(const locale&); 2547 2548 extern template 2549 const moneypunct<char, true>& 2550 use_facet<moneypunct<char, true> >(const locale&); 2551 2552 extern template 2553 const moneypunct<char, false>& 2554 use_facet<moneypunct<char, false> >(const locale&); 2555 2556 extern template 2557 const money_put<char>& 2558 use_facet<money_put<char> >(const locale&); 2559 2560 extern template 2561 const money_get<char>& 2562 use_facet<money_get<char> >(const locale&); 2563 2564 extern template 2565 const __timepunct<char>& 2566 use_facet<__timepunct<char> >(const locale&); 2567 2568 extern template 2569 const time_put<char>& 2570 use_facet<time_put<char> >(const locale&); 2571 2572 extern template 2573 const time_get<char>& 2574 use_facet<time_get<char> >(const locale&); 2575 2576 extern template 2577 const messages<char>& 2578 use_facet<messages<char> >(const locale&); 2579 2580 extern template 2581 bool 2582 has_facet<ctype<char> >(const locale&); 2583 2584 extern template 2585 bool 2586 has_facet<codecvt<char, char, mbstate_t> >(const locale&); 2587 2588 extern template 2589 bool 2590 has_facet<collate<char> >(const locale&); 2591 2592 extern template 2593 bool 2594 has_facet<numpunct<char> >(const locale&); 2595 2596 extern template 2597 bool 2598 has_facet<num_put<char> >(const locale&); 2599 2600 extern template 2601 bool 2602 has_facet<num_get<char> >(const locale&); 2603 2604 extern template 2605 bool 2606 has_facet<moneypunct<char> >(const locale&); 2607 2608 extern template 2609 bool 2610 has_facet<money_put<char> >(const locale&); 2611 2612 extern template 2613 bool 2614 has_facet<money_get<char> >(const locale&); 2615 2616 extern template 2617 bool 2618 has_facet<__timepunct<char> >(const locale&); 2619 2620 extern template 2621 bool 2622 has_facet<time_put<char> >(const locale&); 2623 2624 extern template 2625 bool 2626 has_facet<time_get<char> >(const locale&); 2627 2628 extern template 2629 bool 2630 has_facet<messages<char> >(const locale&); 2631 2632 #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T) 2633 extern template class moneypunct<wchar_t, false>; 2634 extern template class moneypunct<wchar_t, true>; 2635 extern template class moneypunct_byname<wchar_t, false>; 2636 extern template class moneypunct_byname<wchar_t, true>; 2637 extern template class money_get<wchar_t>; 2638 extern template class money_put<wchar_t>; 2639 extern template class numpunct<wchar_t>; 2640 extern template class numpunct_byname<wchar_t>; 2641 extern template class num_get<wchar_t>; 2642 extern template class num_put<wchar_t>; 2643 extern template class __timepunct<wchar_t>; 2644 extern template class time_put<wchar_t>; 2645 extern template class time_put_byname<wchar_t>; 2646 extern template class time_get<wchar_t>; 2647 extern template class time_get_byname<wchar_t>; 2648 extern template class messages<wchar_t>; 2649 extern template class messages_byname<wchar_t>; 2650 extern template class ctype_byname<wchar_t>; 2651 extern template class codecvt_byname<wchar_t, char, mbstate_t>; 2652 extern template class collate<wchar_t>; 2653 extern template class collate_byname<wchar_t>; 2654 2655 extern template 2656 const codecvt<wchar_t, char, mbstate_t>& 2657 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 2658 2659 extern template 2660 const collate<wchar_t>& 2661 use_facet<collate<wchar_t> >(const locale&); 2662 2663 extern template 2664 const numpunct<wchar_t>& 2665 use_facet<numpunct<wchar_t> >(const locale&); 2666 2667 extern template 2668 const num_put<wchar_t>& 2669 use_facet<num_put<wchar_t> >(const locale&); 2670 2671 extern template 2672 const num_get<wchar_t>& 2673 use_facet<num_get<wchar_t> >(const locale&); 2674 2675 extern template 2676 const moneypunct<wchar_t, true>& 2677 use_facet<moneypunct<wchar_t, true> >(const locale&); 2678 2679 extern template 2680 const moneypunct<wchar_t, false>& 2681 use_facet<moneypunct<wchar_t, false> >(const locale&); 2682 2683 extern template 2684 const money_put<wchar_t>& 2685 use_facet<money_put<wchar_t> >(const locale&); 2686 2687 extern template 2688 const money_get<wchar_t>& 2689 use_facet<money_get<wchar_t> >(const locale&); 2690 2691 extern template 2692 const __timepunct<wchar_t>& 2693 use_facet<__timepunct<wchar_t> >(const locale&); 2694 2695 extern template 2696 const time_put<wchar_t>& 2697 use_facet<time_put<wchar_t> >(const locale&); 2698 2699 extern template 2700 const time_get<wchar_t>& 2701 use_facet<time_get<wchar_t> >(const locale&); 2702 2703 extern template 2704 const messages<wchar_t>& 2705 use_facet<messages<wchar_t> >(const locale&); 2706 2707 extern template 2708 bool 2709 has_facet<ctype<wchar_t> >(const locale&); 2710 2711 extern template 2712 bool 2713 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 2714 2715 extern template 2716 bool 2717 has_facet<collate<wchar_t> >(const locale&); 2718 2719 extern template 2720 bool 2721 has_facet<numpunct<wchar_t> >(const locale&); 2722 2723 extern template 2724 bool 2725 has_facet<num_put<wchar_t> >(const locale&); 2726 2727 extern template 2728 bool 2729 has_facet<num_get<wchar_t> >(const locale&); 2730 2731 extern template 2732 bool 2733 has_facet<moneypunct<wchar_t> >(const locale&); 2734 2735 extern template 2736 bool 2737 has_facet<money_put<wchar_t> >(const locale&); 2738 2739 extern template 2740 bool 2741 has_facet<money_get<wchar_t> >(const locale&); 2742 2743 extern template 2744 bool 2745 has_facet<__timepunct<wchar_t> >(const locale&); 2746 2747 extern template 2748 bool 2749 has_facet<time_put<wchar_t> >(const locale&); 2750 2751 extern template 2752 bool 2753 has_facet<time_get<wchar_t> >(const locale&); 2754 2755 extern template 2756 bool 2757 has_facet<messages<wchar_t> >(const locale&); 2758 #endif 2759 #endif 2760 } // namespace std 2761 2762 #endif 2763