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