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