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