locale_facets.tcc revision 102782
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 const int __max_digits = numeric_limits<_ValueT>::digits10 + 1; 628 streamsize __prec = __io.precision(); 629 630 if (__prec > static_cast<streamsize>(__max_digits)) 631 __prec = static_cast<streamsize>(__max_digits); 632 633 // Long enough for the max format spec. 634 char __fbuf[16]; 635 636 // [22.2.2.2.2] Stage 1, numeric conversion to character. 637 int __len; 638#ifdef _GLIBCPP_USE_C99 639 // First try a buffer perhaps big enough (for sure sufficient for 640 // non-ios_base::fixed outputs) 641 int __cs_size = __max_digits * 3; 642 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 643 644 const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); 645 if (__fp) 646 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 647 _S_c_locale, __prec); 648 else 649 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); 650 651 // If the buffer was not large enough, try again with the correct size. 652 if (__len >= __cs_size) 653 { 654 __cs_size = __len + 1; 655 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 656 if (__fp) 657 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 658 _S_c_locale, __prec); 659 else 660 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 661 _S_c_locale); 662 } 663#else 664 // Consider the possibility of long ios_base::fixed outputs 665 const bool __fixed = __io.flags() & ios_base::fixed; 666 const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 667 // ios_base::fixed outputs may need up to __max_exp+1 chars 668 // for the integer part + up to __max_digits chars for the 669 // fractional part + 3 chars for sign, decimal point, '\0'. On 670 // the other hand, for non-fixed outputs __max_digits*3 chars 671 // are largely sufficient. 672 const int __cs_size = __fixed ? __max_exp + __max_digits + 4 673 : __max_digits * 3; 674 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 675 676 if (_S_format_float(__io, __fbuf, __mod, __prec)) 677 __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); 678 else 679 __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 680#endif 681 return _M_widen_float(__s, __io, __fill, __cs, __len); 682 } 683 684 template<typename _CharT, typename _OutIter> 685 template<typename _ValueT> 686 _OutIter 687 num_put<_CharT, _OutIter>:: 688 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 689 char __modl, _ValueT __v) const 690 { 691 // [22.2.2.2.2] Stage 1, numeric conversion to character. 692 693 // Long enough for the max format spec. 694 char __fbuf[16]; 695 _S_format_int(__io, __fbuf, __mod, __modl); 696#ifdef _GLIBCPP_USE_C99 697 // First try a buffer perhaps big enough. 698 int __cs_size = 64; 699 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 700 int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 701 _S_c_locale); 702 // If the buffer was not large enough, try again with the correct size. 703 if (__len >= __cs_size) 704 { 705 __cs_size = __len + 1; 706 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 707 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 708 _S_c_locale); 709 } 710#else 711 // Leave room for "+/-," "0x," and commas. This size is 712 // arbitrary, but should be largely sufficient. 713 char __cs[128]; 714 int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 715#endif 716 return _M_widen_int(__s, __io, __fill, __cs, __len); 717 } 718 719 template<typename _CharT, typename _OutIter> 720 _OutIter 721 num_put<_CharT, _OutIter>:: 722 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 723 int __len) const 724 { 725 typedef char_traits<_CharT> __traits_type; 726 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 727 // numpunct.decimal_point() values for '.' and adding grouping. 728 const locale __loc = __io.getloc(); 729 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 730 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 731 * __len)); 732 // Grouping can add (almost) as many separators as the number of 733 // digits, but no more. 734 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 735 * __len * 2)); 736 __ctype.widen(__cs, __cs + __len, __ws); 737 738 // Replace decimal point. 739 const _CharT* __p; 740 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 741 if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) 742 __ws[__p - __ws] = __np.decimal_point(); 743 744#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 745//282. What types does numpunct grouping refer to? 746 // Add grouping, if necessary. 747 const string __grouping = __np.grouping(); 748 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 749 if (__grouping.size()) 750 { 751 _CharT* __p2; 752 int __declen = __p ? __p - __ws : __len; 753 __p2 = __add_grouping(__ws2, __np.thousands_sep(), 754 __grouping.c_str(), 755 __grouping.c_str() + __grouping.size(), 756 __ws, __ws + __declen); 757 int __newlen = __p2 - __ws2; 758 759 // Tack on decimal part. 760 if (__p) 761 { 762 __traits_type::copy(__p2, __p, __len - __declen); 763 __newlen += __len - __declen; 764 } 765 766 // Switch strings, establish correct new length. 767 __ws = __ws2; 768 __len = __newlen; 769 } 770#endif 771 return _M_insert(__s, __io, __fill, __ws, __len); 772 } 773 774 template<typename _CharT, typename _OutIter> 775 _OutIter 776 num_put<_CharT, _OutIter>:: 777 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 778 int __len) const 779 { 780 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 781 // numpunct.decimal_point() values for '.' and adding grouping. 782 const locale __loc = __io.getloc(); 783 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 784 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 785 * __len)); 786 // Grouping can add (almost) as many separators as the number of 787 // digits, but no more. 788 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 789 * __len * 2)); 790 __ctype.widen(__cs, __cs + __len, __ws); 791 792 // Add grouping, if necessary. 793 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 794 const string __grouping = __np.grouping(); 795 const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 796 if (__grouping.size()) 797 { 798 // By itself __add_grouping cannot deal correctly with __ws when 799 // ios::showbase is set and ios_base::oct || ios_base::hex. 800 // Therefore we take care "by hand" of the initial 0, 0x or 0X. 801 streamsize __off = 0; 802 if (__io.flags() & ios_base::showbase) 803 if (__basefield == ios_base::oct) 804 { 805 __off = 1; 806 *__ws2 = *__ws; 807 } 808 else if (__basefield == ios_base::hex) 809 { 810 __off = 2; 811 *__ws2 = *__ws; 812 *(__ws2 + 1) = *(__ws + 1); 813 } 814 _CharT* __p; 815 __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 816 __grouping.c_str(), 817 __grouping.c_str() + __grouping.size(), 818 __ws + __off, __ws + __len); 819 __len = __p - __ws2; 820 // Switch strings. 821 __ws = __ws2; 822 } 823 return _M_insert(__s, __io, __fill, __ws, __len); 824 } 825 826 // For use by integer and floating-point types after they have been 827 // converted into a char_type string. 828 template<typename _CharT, typename _OutIter> 829 _OutIter 830 num_put<_CharT, _OutIter>:: 831 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 832 int __len) const 833 { 834 typedef char_traits<_CharT> __traits_type; 835 // [22.2.2.2.2] Stage 3. 836 streamsize __w = __io.width(); 837 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 838 * __w)); 839 if (__w > static_cast<streamsize>(__len)) 840 { 841 __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 842 __w, __len, true); 843 __len = static_cast<int>(__w); 844 // Switch strings. 845 __ws = __ws2; 846 } 847 __io.width(0); 848 849 // [22.2.2.2.2] Stage 4. 850 // Write resulting, fully-formatted string to output iterator. 851 for (int __j = 0; __j < __len; ++__j, ++__s) 852 *__s = __ws[__j]; 853 return __s; 854 } 855 856 template<typename _CharT, typename _OutIter> 857 _OutIter 858 num_put<_CharT, _OutIter>:: 859 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 860 { 861 ios_base::fmtflags __flags = __io.flags(); 862 if ((__flags & ios_base::boolalpha) == 0) 863 { 864 unsigned long __uv = __v; 865 __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv); 866 } 867 else 868 { 869 typedef basic_string<_CharT> __string_type; 870 locale __loc = __io.getloc(); 871 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 872 __string_type __name; 873 if (__v) 874 __name = __np.truename(); 875 else 876 __name = __np.falsename(); 877 __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 878 } 879 return __s; 880 } 881 882 template<typename _CharT, typename _OutIter> 883 _OutIter 884 num_put<_CharT, _OutIter>:: 885 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 886 { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); } 887 888 template<typename _CharT, typename _OutIter> 889 _OutIter 890 num_put<_CharT, _OutIter>:: 891 do_put(iter_type __s, ios_base& __io, char_type __fill, 892 unsigned long __v) const 893 { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); } 894 895#ifdef _GLIBCPP_USE_LONG_LONG 896 template<typename _CharT, typename _OutIter> 897 _OutIter 898 num_put<_CharT, _OutIter>:: 899 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 900 { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); } 901 902 template<typename _CharT, typename _OutIter> 903 _OutIter 904 num_put<_CharT, _OutIter>:: 905 do_put(iter_type __s, ios_base& __io, char_type __fill, 906 unsigned long long __v) const 907 { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } 908#endif 909 910 template<typename _CharT, typename _OutIter> 911 _OutIter 912 num_put<_CharT, _OutIter>:: 913 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 914 { return _M_convert_float(__s, __io, __fill, char(), __v); } 915 916 template<typename _CharT, typename _OutIter> 917 _OutIter 918 num_put<_CharT, _OutIter>:: 919 do_put(iter_type __s, ios_base& __io, char_type __fill, 920 long double __v) const 921 { return _M_convert_float(__s, __io, __fill, 'L', __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 const void* __v) const 928 { 929 ios_base::fmtflags __flags = __io.flags(); 930 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield 931 | ios_base::uppercase | ios_base::internal); 932 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 933 try 934 { 935 __s = _M_convert_int(__s, __io, __fill, 'u', char(), 936 reinterpret_cast<unsigned long>(__v)); 937 __io.flags(__flags); 938 } 939 catch (...) 940 { 941 __io.flags(__flags); 942 __throw_exception_again; 943 } 944 return __s; 945 } 946 947 948 template<typename _CharT, typename _InIter> 949 _InIter 950 money_get<_CharT, _InIter>:: 951 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 952 ios_base::iostate& __err, long double& __units) const 953 { 954 string_type __str; 955 __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 956 957 const int __n = numeric_limits<long double>::digits10; 958 char* __cs = static_cast<char*>(__builtin_alloca(__n)); 959 const locale __loc = __io.getloc(); 960 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 961 const _CharT* __wcs = __str.c_str(); 962 __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); 963 __convert_to_v(__cs, __units, __err, _S_c_locale); 964 return __beg; 965 } 966 967 template<typename _CharT, typename _InIter> 968 _InIter 969 money_get<_CharT, _InIter>:: 970 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 971 ios_base::iostate& __err, string_type& __units) const 972 { 973 // These contortions are quite unfortunate. 974 typedef moneypunct<_CharT, true> __money_true; 975 typedef moneypunct<_CharT, false> __money_false; 976 typedef money_base::part part; 977 typedef typename string_type::size_type size_type; 978 979 const locale __loc = __io.getloc(); 980 const __money_true& __mpt = use_facet<__money_true>(__loc); 981 const __money_false& __mpf = use_facet<__money_false>(__loc); 982 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 983 984 const money_base::pattern __p = __intl ? __mpt.neg_format() 985 : __mpf.neg_format(); 986 987 const string_type __pos_sign =__intl ? __mpt.positive_sign() 988 : __mpf.positive_sign(); 989 const string_type __neg_sign =__intl ? __mpt.negative_sign() 990 : __mpf.negative_sign(); 991 const char_type __d = __intl ? __mpt.decimal_point() 992 : __mpf.decimal_point(); 993 const char_type __sep = __intl ? __mpt.thousands_sep() 994 : __mpf.thousands_sep(); 995 996 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); 997 998 // Set to deduced positive or negative sign, depending. 999 string_type __sign; 1000 // String of grouping info from thousands_sep plucked from __units. 1001 string __grouping_tmp; 1002 // Marker for thousands_sep position. 1003 int __sep_pos = 0; 1004 // If input iterator is in a valid state. 1005 bool __testvalid = true; 1006 // Flag marking when a decimal point is found. 1007 bool __testdecfound = false; 1008 1009 // The tentative returned string is stored here. 1010 string_type __temp_units; 1011 1012 char_type __c = *__beg; 1013 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); 1014 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) 1015 { 1016 part __which = static_cast<part>(__p.field[__i]); 1017 switch (__which) 1018 { 1019 case money_base::symbol: 1020 if (__io.flags() & ios_base::showbase 1021 || __i < 2 || __sign.size() > 1 1022 || ((static_cast<part>(__p.field[3]) != money_base::none) 1023 && __i == 2)) 1024 { 1025 // According to 22.2.6.1.2.2, symbol is required 1026 // if (__io.flags() & ios_base::showbase), 1027 // otherwise is optional and consumed only if 1028 // other characters are needed to complete the 1029 // format. 1030 const string_type __symbol = __intl ? __mpt.curr_symbol() 1031 : __mpf.curr_symbol(); 1032 size_type __len = __symbol.size(); 1033 size_type __j = 0; 1034 while (__beg != __end 1035 && __j < __len && __symbol[__j] == __c) 1036 { 1037 __c = *(++__beg); 1038 ++__j; 1039 } 1040 // When (__io.flags() & ios_base::showbase) 1041 // symbol is required. 1042 if (__j != __len && (__io.flags() & ios_base::showbase)) 1043 __testvalid = false; 1044 } 1045 break; 1046 case money_base::sign: 1047 // Sign might not exist, or be more than one character long. 1048 if (__pos_sign.size() && __neg_sign.size()) 1049 { 1050 // Sign is mandatory. 1051 if (__c == __pos_sign[0]) 1052 { 1053 __sign = __pos_sign; 1054 __c = *(++__beg); 1055 } 1056 else if (__c == __neg_sign[0]) 1057 { 1058 __sign = __neg_sign; 1059 __c = *(++__beg); 1060 } 1061 else 1062 __testvalid = false; 1063 } 1064 else if (__pos_sign.size() && __c == __pos_sign[0]) 1065 { 1066 __sign = __pos_sign; 1067 __c = *(++__beg); 1068 } 1069 else if (__neg_sign.size() && __c == __neg_sign[0]) 1070 { 1071 __sign = __neg_sign; 1072 __c = *(++__beg); 1073 } 1074 break; 1075 case money_base::value: 1076 // Extract digits, remove and stash away the 1077 // grouping of found thousands separators. 1078 while (__beg != __end 1079 && (__ctype.is(ctype_base::digit, __c) 1080 || (__c == __d && !__testdecfound) 1081 || __c == __sep)) 1082 { 1083 if (__c == __d) 1084 { 1085 __grouping_tmp += static_cast<char>(__sep_pos); 1086 __sep_pos = 0; 1087 __testdecfound = true; 1088 } 1089 else if (__c == __sep) 1090 { 1091 if (__grouping.size()) 1092 { 1093 // Mark position for later analysis. 1094 __grouping_tmp += static_cast<char>(__sep_pos); 1095 __sep_pos = 0; 1096 } 1097 else 1098 { 1099 __testvalid = false; 1100 break; 1101 } 1102 } 1103 else 1104 { 1105 __temp_units += __c; 1106 ++__sep_pos; 1107 } 1108 __c = *(++__beg); 1109 } 1110 break; 1111 case money_base::space: 1112 case money_base::none: 1113 // Only if not at the end of the pattern. 1114 if (__i != 3) 1115 while (__beg != __end 1116 && __ctype.is(ctype_base::space, __c)) 1117 __c = *(++__beg); 1118 break; 1119 } 1120 } 1121 1122 // Need to get the rest of the sign characters, if they exist. 1123 if (__sign.size() > 1) 1124 { 1125 size_type __len = __sign.size(); 1126 size_type __i = 1; 1127 for (; __c != __eof && __i < __len; ++__i) 1128 while (__beg != __end && __c != __sign[__i]) 1129 __c = *(++__beg); 1130 1131 if (__i != __len) 1132 __testvalid = false; 1133 } 1134 1135 // Strip leading zeros. 1136 while (__temp_units[0] == __ctype.widen('0')) 1137 __temp_units.erase(__temp_units.begin()); 1138 1139 if (__sign.size() && __sign == __neg_sign) 1140 __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); 1141 1142 // Test for grouping fidelity. 1143 if (__grouping.size() && __grouping_tmp.size()) 1144 { 1145 if (!__verify_grouping(__grouping, __grouping_tmp)) 1146 __testvalid = false; 1147 } 1148 1149 // Iff no more characters are available. 1150 if (__c == __eof) 1151 __err |= ios_base::eofbit; 1152 1153 // Iff valid sequence is not recognized. 1154 if (!__testvalid || !__temp_units.size()) 1155 __err |= ios_base::failbit; 1156 else 1157 // Use the "swap trick" to copy __temp_units into __units. 1158 __temp_units.swap(__units); 1159 1160 return __beg; 1161 } 1162 1163 template<typename _CharT, typename _OutIter> 1164 _OutIter 1165 money_put<_CharT, _OutIter>:: 1166 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 1167 long double __units) const 1168 { 1169 const locale __loc = __io.getloc(); 1170 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1171#ifdef _GLIBCPP_USE_C99 1172 // First try a buffer perhaps big enough. 1173 int __cs_size = 64; 1174 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1175 int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 1176 _S_c_locale); 1177 // If the buffer was not large enough, try again with the correct size. 1178 if (__len >= __cs_size) 1179 { 1180 __cs_size = __len + 1; 1181 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1182 __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 1183 _S_c_locale); 1184 } 1185#else 1186 // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, 1187 // decimal digit, '\0'. 1188 const int __cs_size = numeric_limits<long double>::max_exponent10 + 5; 1189 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1190 int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); 1191#endif 1192 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); 1193 __ctype.widen(__cs, __cs + __len, __ws); 1194 string_type __digits(__ws); 1195 return this->do_put(__s, __intl, __io, __fill, __digits); 1196 } 1197 1198 template<typename _CharT, typename _OutIter> 1199 _OutIter 1200 money_put<_CharT, _OutIter>:: 1201 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 1202 const string_type& __digits) const 1203 { 1204 typedef typename string_type::size_type size_type; 1205 typedef money_base::part part; 1206 1207 const locale __loc = __io.getloc(); 1208 const size_type __width = static_cast<size_type>(__io.width()); 1209 1210 // These contortions are quite unfortunate. 1211 typedef moneypunct<_CharT, true> __money_true; 1212 typedef moneypunct<_CharT, false> __money_false; 1213 const __money_true& __mpt = use_facet<__money_true>(__loc); 1214 const __money_false& __mpf = use_facet<__money_false>(__loc); 1215 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1216 1217 // Determine if negative or positive formats are to be used, and 1218 // discard leading negative_sign if it is present. 1219 const char_type* __beg = __digits.data(); 1220 const char_type* __end = __beg + __digits.size(); 1221 money_base::pattern __p; 1222 string_type __sign; 1223 if (*__beg != __ctype.widen('-')) 1224 { 1225 __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); 1226 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); 1227 } 1228 else 1229 { 1230 __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); 1231 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); 1232 ++__beg; 1233 } 1234 1235 // Look for valid numbers in the current ctype facet within input digits. 1236 __end = __ctype.scan_not(ctype_base::digit, __beg, __end); 1237 if (__beg != __end) 1238 { 1239 // Assume valid input, and attempt to format. 1240 // Break down input numbers into base components, as follows: 1241 // final_value = grouped units + (decimal point) + (digits) 1242 string_type __res; 1243 string_type __value; 1244 const string_type __symbol = __intl ? __mpt.curr_symbol() 1245 : __mpf.curr_symbol(); 1246 1247 // Deal with decimal point, decimal digits. 1248 const int __frac = __intl ? __mpt.frac_digits() 1249 : __mpf.frac_digits(); 1250 if (__frac > 0) 1251 { 1252 const char_type __d = __intl ? __mpt.decimal_point() 1253 : __mpf.decimal_point(); 1254 if (__end - __beg >= __frac) 1255 { 1256 __value = string_type(__end - __frac, __end); 1257 __value.insert(__value.begin(), __d); 1258 __end -= __frac; 1259 } 1260 else 1261 { 1262 // Have to pad zeros in the decimal position. 1263 __value = string_type(__beg, __end); 1264 int __paddec = __frac - (__end - __beg); 1265 char_type __zero = __ctype.widen('0'); 1266 __value.insert(__value.begin(), __paddec, __zero); 1267 __value.insert(__value.begin(), __d); 1268 __beg = __end; 1269 } 1270 } 1271 1272 // Add thousands separators to non-decimal digits, per 1273 // grouping rules. 1274 if (__beg != __end) 1275 { 1276 const string __grouping = __intl ? __mpt.grouping() 1277 : __mpf.grouping(); 1278 if (__grouping.size()) 1279 { 1280 const char_type __sep = __intl ? __mpt.thousands_sep() 1281 : __mpf.thousands_sep(); 1282 const char* __gbeg = __grouping.c_str(); 1283 const char* __gend = __gbeg + __grouping.size(); 1284 const int __n = (__end - __beg) * 2; 1285 _CharT* __ws2 = 1286 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); 1287 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 1288 __gend, __beg, __end); 1289 __value.insert(0, __ws2, __ws_end - __ws2); 1290 } 1291 else 1292 __value.insert(0, string_type(__beg, __end)); 1293 } 1294 1295 // Calculate length of resulting string. 1296 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; 1297 size_type __len = __value.size() + __sign.size(); 1298 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; 1299 bool __testipad = __f == ios_base::internal && __len < __width; 1300 1301 // Fit formatted digits into the required pattern. 1302 for (int __i = 0; __i < 4; ++__i) 1303 { 1304 part __which = static_cast<part>(__p.field[__i]); 1305 switch (__which) 1306 { 1307 case money_base::symbol: 1308 if (__io.flags() & ios_base::showbase) 1309 __res += __symbol; 1310 break; 1311 case money_base::sign: 1312 // Sign might not exist, or be more than one 1313 // charater long. In that case, add in the rest 1314 // below. 1315 if (__sign.size()) 1316 __res += __sign[0]; 1317 break; 1318 case money_base::value: 1319 __res += __value; 1320 break; 1321 case money_base::space: 1322 // At least one space is required, but if internal 1323 // formatting is required, an arbitrary number of 1324 // fill spaces will be necessary. 1325 if (__testipad) 1326 __res += string_type(__width - __len, __fill); 1327 else 1328 __res += __ctype.widen(__fill); 1329 break; 1330 case money_base::none: 1331 if (__testipad) 1332 __res += string_type(__width - __len, __fill); 1333 break; 1334 } 1335 } 1336 1337 // Special case of multi-part sign parts. 1338 if (__sign.size() > 1) 1339 __res += string_type(__sign.begin() + 1, __sign.end()); 1340 1341 // Pad, if still necessary. 1342 __len = __res.size(); 1343 if (__width > __len) 1344 { 1345 if (__f == ios_base::left) 1346 // After. 1347 __res.append(__width - __len, __fill); 1348 else 1349 // Before. 1350 __res.insert(0, string_type(__width - __len, __fill)); 1351 __len = __width; 1352 } 1353 1354 // Write resulting, fully-formatted string to output iterator. 1355 for (size_type __j = 0; __j < __len; ++__j, ++__s) 1356 *__s = __res[__j]; 1357 } 1358 __io.width(0); 1359 return __s; 1360 } 1361 1362 1363 // NB: Not especially useful. Without an ios_base object or some 1364 // kind of locale reference, we are left clawing at the air where 1365 // the side of the mountain used to be... 1366 template<typename _CharT, typename _InIter> 1367 time_base::dateorder 1368 time_get<_CharT, _InIter>::do_date_order() const 1369 { return time_base::no_order; } 1370 1371 template<typename _CharT, typename _InIter> 1372 void 1373 time_get<_CharT, _InIter>:: 1374 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, 1375 ios_base::iostate& __err, tm* __tm, 1376 const _CharT* __format) const 1377 { 1378 locale __loc = __io.getloc(); 1379 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1380 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1381 size_t __len = char_traits<_CharT>::length(__format); 1382 1383 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 1384 { 1385 char __c = __format[__i]; 1386 if (__c == '%') 1387 { 1388 // Verify valid formatting code, attempt to extract. 1389 __c = __format[++__i]; 1390 char __mod = 0; 1391 int __mem = 0; 1392 if (__c == 'E' || __c == 'O') 1393 { 1394 __mod = __c; 1395 __c = __format[++__i]; 1396 } 1397 switch (__c) 1398 { 1399 const char* __cs; 1400 _CharT __wcs[10]; 1401 case 'a': 1402 // Abbreviated weekday name [tm_wday] 1403 const char_type* __days1[7]; 1404 __tp._M_days_abbreviated(__days1); 1405 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 1406 __err); 1407 break; 1408 case 'A': 1409 // Weekday name [tm_wday]. 1410 const char_type* __days2[7]; 1411 __tp._M_days(__days2); 1412 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 1413 __err); 1414 break; 1415 case 'h': 1416 case 'b': 1417 // Abbreviated month name [tm_mon] 1418 const char_type* __months1[12]; 1419 __tp._M_months_abbreviated(__months1); 1420 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 1421 __err); 1422 break; 1423 case 'B': 1424 // Month name [tm_mon]. 1425 const char_type* __months2[12]; 1426 __tp._M_months(__months2); 1427 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 1428 __err); 1429 break; 1430 case 'c': 1431 // Default time and date representation. 1432 const char_type* __dt[2]; 1433 __tp._M_date_time_formats(__dt); 1434 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1435 __dt[0]); 1436 break; 1437 case 'd': 1438 // Day [01, 31]. [tm_mday] 1439 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 1440 __ctype, __err); 1441 break; 1442 case 'D': 1443 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 1444 __cs = "%m/%d/%y"; 1445 __ctype.widen(__cs, __cs + 9, __wcs); 1446 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1447 __wcs); 1448 break; 1449 case 'H': 1450 // Hour [00, 23]. [tm_hour] 1451 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 1452 __ctype, __err); 1453 break; 1454 case 'I': 1455 // Hour [01, 12]. [tm_hour] 1456 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 1457 __ctype, __err); 1458 break; 1459 case 'm': 1460 // Month [01, 12]. [tm_mon] 1461 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 1462 __err); 1463 if (!__err) 1464 __tm->tm_mon = __mem - 1; 1465 break; 1466 case 'M': 1467 // Minute [00, 59]. [tm_min] 1468 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 1469 __ctype, __err); 1470 break; 1471 case 'n': 1472 if (__ctype.narrow(*__beg, 0) == '\n') 1473 ++__beg; 1474 else 1475 __err |= ios_base::failbit; 1476 break; 1477 case 'R': 1478 // Equivalent to (%H:%M). 1479 __cs = "%H:%M"; 1480 __ctype.widen(__cs, __cs + 6, __wcs); 1481 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1482 __wcs); 1483 break; 1484 case 'S': 1485 // Seconds. 1486 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 1487 __ctype, __err); 1488 break; 1489 case 't': 1490 if (__ctype.narrow(*__beg, 0) == '\t') 1491 ++__beg; 1492 else 1493 __err |= ios_base::failbit; 1494 break; 1495 case 'T': 1496 // Equivalent to (%H:%M:%S). 1497 __cs = "%H:%M:%S"; 1498 __ctype.widen(__cs, __cs + 9, __wcs); 1499 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1500 __wcs); 1501 break; 1502 case 'x': 1503 // Locale's date. 1504 const char_type* __dates[2]; 1505 __tp._M_date_formats(__dates); 1506 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1507 __dates[0]); 1508 break; 1509 case 'X': 1510 // Locale's time. 1511 const char_type* __times[2]; 1512 __tp._M_time_formats(__times); 1513 _M_extract_via_format(__beg, __end, __io, __err, __tm, 1514 __times[0]); 1515 break; 1516 case 'y': 1517 // Two digit year. [tm_year] 1518 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 1519 __ctype, __err); 1520 break; 1521 case 'Y': 1522 // Year [1900). [tm_year] 1523 _M_extract_num(__beg, __end, __mem, 0, 1524 numeric_limits<int>::max(), 4, 1525 __ctype, __err); 1526 if (!__err) 1527 __tm->tm_year = __mem - 1900; 1528 break; 1529 case 'Z': 1530 // Timezone info. 1531 if (__ctype.is(ctype_base::upper, *__beg)) 1532 { 1533 int __tmp; 1534 _M_extract_name(__beg, __end, __tmp, 1535 __timepunct<_CharT>::_S_timezones, 1536 14, __err); 1537 1538 // GMT requires special effort. 1539 char_type __c = *__beg; 1540 if (!__err && __tmp == 0 1541 && (__c == __ctype.widen('-') 1542 || __c == __ctype.widen('+'))) 1543 { 1544 _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 1545 __ctype, __err); 1546 _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 1547 __ctype, __err); 1548 } 1549 } 1550 else 1551 __err |= ios_base::failbit; 1552 break; 1553 default: 1554 // Not recognized. 1555 __err |= ios_base::failbit; 1556 } 1557 } 1558 else 1559 { 1560 // Verify format and input match, extract and discard. 1561 if (__c == __ctype.narrow(*__beg, 0)) 1562 ++__beg; 1563 else 1564 __err |= ios_base::failbit; 1565 } 1566 } 1567 } 1568 1569 template<typename _CharT, typename _InIter> 1570 void 1571 time_get<_CharT, _InIter>:: 1572 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, 1573 int __min, int __max, size_t __len, 1574 const ctype<_CharT>& __ctype, 1575 ios_base::iostate& __err) const 1576 { 1577 size_t __i = 0; 1578 string __digits; 1579 bool __testvalid = true; 1580 char_type __c = *__beg; 1581 while (__beg != __end && __i < __len 1582 && __ctype.is(ctype_base::digit, __c)) 1583 { 1584 __digits += __ctype.narrow(__c, 0); 1585 __c = *(++__beg); 1586 ++__i; 1587 } 1588 if (__i == __len) 1589 { 1590 int __value = atoi(__digits.c_str()); 1591 if (__min <= __value && __value <= __max) 1592 __member = __value; 1593 else 1594 __testvalid = false; 1595 } 1596 else 1597 __testvalid = false; 1598 if (!__testvalid) 1599 __err |= ios_base::failbit; 1600 } 1601 1602 // Assumptions: 1603 // All elements in __names are unique. 1604 template<typename _CharT, typename _InIter> 1605 void 1606 time_get<_CharT, _InIter>:: 1607 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, 1608 const _CharT** __names, size_t __indexlen, 1609 ios_base::iostate& __err) const 1610 { 1611 typedef char_traits<_CharT> __traits_type; 1612 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen)); 1613 size_t __nmatches = 0; 1614 size_t __pos = 0; 1615 bool __testvalid = true; 1616 const char_type* __name; 1617 1618 char_type __c = *__beg; 1619 // Look for initial matches. 1620 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 1621 if (__c == __names[__i1][0]) 1622 __matches[__nmatches++] = __i1; 1623 1624 while(__nmatches > 1) 1625 { 1626 // Find smallest matching string. 1627 size_t __minlen = 10; 1628 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 1629 __minlen = min(__minlen, 1630 __traits_type::length(__names[__matches[__i2]])); 1631 1632 if (__pos < __minlen && __beg != __end) 1633 { 1634 ++__pos; 1635 __c = *(++__beg); 1636 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 1637 { 1638 __name = __names[__matches[__i3]]; 1639 if (__name[__pos] != __c) 1640 __matches[__i3] = __matches[--__nmatches]; 1641 } 1642 } 1643 else 1644 break; 1645 } 1646 1647 if (__nmatches == 1) 1648 { 1649 // Make sure found name is completely extracted. 1650 __name = __names[__matches[0]]; 1651 const size_t __len = __traits_type::length(__name); 1652 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 1653 ++__beg, ++__pos; 1654 1655 if (__len == __pos) 1656 __member = __matches[0]; 1657 else 1658 __testvalid = false; 1659 } 1660 else 1661 __testvalid = false; 1662 if (!__testvalid) 1663 __err |= ios_base::failbit; 1664 } 1665 1666 template<typename _CharT, typename _InIter> 1667 _InIter 1668 time_get<_CharT, _InIter>:: 1669 do_get_time(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_date(iter_type __beg, iter_type __end, ios_base& __io, 1687 ios_base::iostate& __err, tm* __tm) const 1688 { 1689 _CharT __wcs[3]; 1690 const char* __cs = "%x"; 1691 locale __loc = __io.getloc(); 1692 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1693 __ctype.widen(__cs, __cs + 3, __wcs); 1694 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 1695 if (__beg == __end) 1696 __err |= ios_base::eofbit; 1697 return __beg; 1698 } 1699 1700 template<typename _CharT, typename _InIter> 1701 _InIter 1702 time_get<_CharT, _InIter>:: 1703 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 1704 ios_base::iostate& __err, tm* __tm) const 1705 { 1706 typedef char_traits<_CharT> __traits_type; 1707 locale __loc = __io.getloc(); 1708 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1709 const char_type* __days[7]; 1710 __tp._M_days_abbreviated(__days); 1711 int __tmpwday; 1712 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); 1713 1714 // Check to see if non-abbreviated name exists, and extract. 1715 // NB: Assumes both _M_days and _M_days_abbreviated organized in 1716 // exact same order, first to last, such that the resulting 1717 // __days array with the same index points to a day, and that 1718 // day's abbreviated form. 1719 // NB: Also assumes that an abbreviated name is a subset of the name. 1720 if (!__err) 1721 { 1722 size_t __pos = __traits_type::length(__days[__tmpwday]); 1723 __tp._M_days(__days); 1724 const char_type* __name = __days[__tmpwday]; 1725 if (__name[__pos] == *__beg) 1726 { 1727 // Extract the rest of it. 1728 const size_t __len = __traits_type::length(__name); 1729 while (__pos < __len && __beg != __end 1730 && __name[__pos] == *__beg) 1731 ++__beg, ++__pos; 1732 if (__len != __pos) 1733 __err |= ios_base::failbit; 1734 } 1735 if (!__err) 1736 __tm->tm_wday = __tmpwday; 1737 } 1738 if (__beg == __end) 1739 __err |= ios_base::eofbit; 1740 return __beg; 1741 } 1742 1743 template<typename _CharT, typename _InIter> 1744 _InIter 1745 time_get<_CharT, _InIter>:: 1746 do_get_monthname(iter_type __beg, iter_type __end, 1747 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 1748 { 1749 typedef char_traits<_CharT> __traits_type; 1750 locale __loc = __io.getloc(); 1751 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1752 const char_type* __months[12]; 1753 __tp._M_months_abbreviated(__months); 1754 int __tmpmon; 1755 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); 1756 1757 // Check to see if non-abbreviated name exists, and extract. 1758 // NB: Assumes both _M_months and _M_months_abbreviated organized in 1759 // exact same order, first to last, such that the resulting 1760 // __months array with the same index points to a month, and that 1761 // month's abbreviated form. 1762 // NB: Also assumes that an abbreviated name is a subset of the name. 1763 if (!__err) 1764 { 1765 size_t __pos = __traits_type::length(__months[__tmpmon]); 1766 __tp._M_months(__months); 1767 const char_type* __name = __months[__tmpmon]; 1768 if (__name[__pos] == *__beg) 1769 { 1770 // Extract the rest of it. 1771 const size_t __len = __traits_type::length(__name); 1772 while (__pos < __len && __beg != __end 1773 && __name[__pos] == *__beg) 1774 ++__beg, ++__pos; 1775 if (__len != __pos) 1776 __err |= ios_base::failbit; 1777 } 1778 if (!__err) 1779 __tm->tm_mon = __tmpmon; 1780 } 1781 1782 if (__beg == __end) 1783 __err |= ios_base::eofbit; 1784 return __beg; 1785 } 1786 1787 template<typename _CharT, typename _InIter> 1788 _InIter 1789 time_get<_CharT, _InIter>:: 1790 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 1791 ios_base::iostate& __err, tm* __tm) const 1792 { 1793 locale __loc = __io.getloc(); 1794 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1795 1796 char_type __c = *__beg; 1797 size_t __i = 0; 1798 string __digits; 1799 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) 1800 { 1801 __digits += __ctype.narrow(__c, 0); 1802 __c = *(++__beg); 1803 ++__i; 1804 } 1805 if (__i == 2 || __i == 4) 1806 { 1807 long __l; 1808 __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); 1809 if (!(__err & ios_base::failbit) && __l <= INT_MAX) 1810 { 1811 __l = __i == 2 ? __l : __l - 1900; 1812 __tm->tm_year = static_cast<int>(__l); 1813 } 1814 } 1815 else 1816 __err |= ios_base::failbit; 1817 if (__beg == __end) 1818 __err |= ios_base::eofbit; 1819 return __beg; 1820 } 1821 1822 template<typename _CharT, typename _OutIter> 1823 _OutIter 1824 time_put<_CharT, _OutIter>:: 1825 put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 1826 const _CharT* __beg, const _CharT* __end) const 1827 { 1828 locale __loc = __io.getloc(); 1829 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1830 while (__beg != __end) 1831 { 1832 char __c = __ctype.narrow(*__beg, 0); 1833 ++__beg; 1834 if (__c == '%') 1835 { 1836 char __format; 1837 char __mod = 0; 1838 size_t __len = 1; 1839 __c = __ctype.narrow(*__beg, 0); 1840 ++__beg; 1841 if (__c == 'E' || __c == 'O') 1842 { 1843 __mod = __c; 1844 __format = __ctype.narrow(*__beg, 0); 1845 ++__beg; 1846 } 1847 else 1848 __format = __c; 1849 __s = this->do_put(__s, __io, char_type(), __tm, __format, 1850 __mod); 1851 } 1852 else 1853 { 1854 *__s = __c; 1855 ++__s; 1856 } 1857 } 1858 return __s; 1859 } 1860 1861 template<typename _CharT, typename _OutIter> 1862 _OutIter 1863 time_put<_CharT, _OutIter>:: 1864 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 1865 char __format, char __mod) const 1866 { 1867 locale __loc = __io.getloc(); 1868 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1869 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1870 1871 // NB: This size is arbitrary. Should this be a data member, 1872 // initialized at construction? 1873 const size_t __maxlen = 64; 1874 char_type* __res = 1875 static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 1876 1877 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 1878 // is possible that the format character will be longer than one 1879 // character. Possibilities include 'E' or 'O' followed by a 1880 // format character: if __mod is not the default argument, assume 1881 // it's a valid modifier. 1882 char_type __fmt[4]; 1883 __fmt[0] = __ctype.widen('%'); 1884 if (!__mod) 1885 { 1886 __fmt[1] = __format; 1887 __fmt[2] = char_type(); 1888 } 1889 else 1890 { 1891 __fmt[1] = __mod; 1892 __fmt[2] = __format; 1893 __fmt[3] = char_type(); 1894 } 1895 1896 __tp._M_put(__res, __maxlen, __fmt, __tm); 1897 1898 // Write resulting, fully-formatted string to output iterator. 1899 size_t __len = char_traits<char_type>::length(__res); 1900 for (size_t __i = 0; __i < __len; ++__i, ++__s) 1901 *__s = __res[__i]; 1902 return __s; 1903 } 1904 1905 1906 // Generic version does nothing. 1907 template<typename _CharT> 1908 int 1909 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 1910 { return 0; } 1911 1912 // Generic version does nothing. 1913 template<typename _CharT> 1914 size_t 1915 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 1916 { return 0; } 1917 1918 template<typename _CharT> 1919 int 1920 collate<_CharT>:: 1921 do_compare(const _CharT* __lo1, const _CharT* __hi1, 1922 const _CharT* __lo2, const _CharT* __hi2) const 1923 { 1924 const string_type __one(__lo1, __hi1); 1925 const string_type __two(__lo2, __hi2); 1926 return _M_compare(__one.c_str(), __two.c_str()); 1927 } 1928 1929 template<typename _CharT> 1930 typename collate<_CharT>::string_type 1931 collate<_CharT>:: 1932 do_transform(const _CharT* __lo, const _CharT* __hi) const 1933 { 1934 size_t __len = (__hi - __lo) * 2; 1935 // First try a buffer perhaps big enough. 1936 _CharT* __c = 1937 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 1938 size_t __res = _M_transform(__c, __lo, __len); 1939 // If the buffer was not large enough, try again with the correct size. 1940 if (__res >= __len) 1941 { 1942 __c = 1943 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); 1944 _M_transform(__c, __lo, __res + 1); 1945 } 1946 return string_type(__c); 1947 } 1948 1949 template<typename _CharT> 1950 long 1951 collate<_CharT>:: 1952 do_hash(const _CharT* __lo, const _CharT* __hi) const 1953 { 1954 unsigned long __val = 0; 1955 for (; __lo < __hi; ++__lo) 1956 __val = *__lo + ((__val << 7) | 1957 (__val >> (numeric_limits<unsigned long>::digits - 7))); 1958 return static_cast<long>(__val); 1959 } 1960 1961 // Convert string to numeric value of type _Tv and store results. 1962 // NB: This is specialized for all required types, there is no 1963 // generic definition. 1964 template<typename _Tv> 1965 void 1966 __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, 1967 const __c_locale& __cloc, int __base = 10); 1968 1969 // Convert numeric value of type _Tv to string and return length of string. 1970 // If snprintf is available use it, otherwise fall back to the unsafe sprintf 1971 // which, in general, can be dangerous and should be avoided. 1972#ifdef _GLIBCPP_USE_C99 1973 template<typename _Tv> 1974 int 1975 __convert_from_v(char* __out, const int __size, const char* __fmt, 1976 _Tv __v, const __c_locale&, int __prec = -1) 1977 { 1978 int __ret; 1979 char* __old = strdup(setlocale(LC_ALL, NULL)); 1980 setlocale(LC_ALL, "C"); 1981 if (__prec >= 0) 1982 __ret = snprintf(__out, __size, __fmt, __prec, __v); 1983 else 1984 __ret = snprintf(__out, __size, __fmt, __v); 1985 setlocale(LC_ALL, __old); 1986 free(__old); 1987 return __ret; 1988 } 1989#else 1990 template<typename _Tv> 1991 int 1992 __convert_from_v(char* __out, const int, const char* __fmt, _Tv __v, 1993 const __c_locale&, int __prec = -1) 1994 { 1995 int __ret; 1996 char* __old = strdup(setlocale(LC_ALL, NULL)); 1997 setlocale(LC_ALL, "C"); 1998 if (__prec >= 0) 1999 __ret = sprintf(__out, __fmt, __prec, __v); 2000 else 2001 __ret = sprintf(__out, __fmt, __v); 2002 setlocale(LC_ALL, __old); 2003 free(__old); 2004 return __ret; 2005 } 2006#endif 2007 2008 // Construct correctly padded string, as per 22.2.2.2.2 2009 // Assumes 2010 // __newlen > __oldlen 2011 // __news is allocated for __newlen size 2012 // Used by both num_put and ostream inserters: if __num, 2013 // internal-adjusted objects are padded according to the rules below 2014 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 2015 // ones are. 2016 2017 // NB: Of the two parameters, _CharT can be deduced from the 2018 // function arguments. The other (_Traits) has to be explicitly specified. 2019 template<typename _CharT, typename _Traits> 2020 struct __pad 2021 { 2022 static void 2023 _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, 2024 const _CharT* __olds, const streamsize __newlen, 2025 const streamsize __oldlen, const bool __num); 2026 }; 2027 2028 template<typename _CharT, typename _Traits> 2029 void 2030 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 2031 _CharT* __news, const _CharT* __olds, 2032 const streamsize __newlen, 2033 const streamsize __oldlen, const bool __num) 2034 { 2035 size_t __plen = static_cast<size_t>(__newlen - __oldlen); 2036 _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen)); 2037 _Traits::assign(__pads, __plen, __fill); 2038 2039 _CharT* __beg; 2040 _CharT* __end; 2041 size_t __mod = 0; 2042 size_t __beglen; //either __plen or __oldlen 2043 ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 2044 2045 if (__adjust == ios_base::left) 2046 { 2047 // Padding last. 2048 __beg = const_cast<_CharT*>(__olds); 2049 __beglen = __oldlen; 2050 __end = __pads; 2051 } 2052 else if (__adjust == ios_base::internal && __num) 2053 { 2054 // Pad after the sign, if there is one. 2055 // Pad after 0[xX], if there is one. 2056 // Who came up with these rules, anyway? Jeeze. 2057 locale __loc = __io.getloc(); 2058 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 2059 const _CharT __minus = __ctype.widen('-'); 2060 const _CharT __plus = __ctype.widen('+'); 2061 bool __testsign = _Traits::eq(__olds[0], __minus) 2062 || _Traits::eq(__olds[0], __plus); 2063 2064 bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 2065 && (_Traits::eq(__ctype.widen('x'), __olds[1]) 2066 || _Traits::eq(__ctype.widen('X'), __olds[1])); 2067 if (__testhex) 2068 { 2069 __news[0] = __olds[0]; 2070 __news[1] = __olds[1]; 2071 __mod += 2; 2072 __news += 2; 2073 __beg = __pads; 2074 __beglen = __plen; 2075 __end = const_cast<_CharT*>(__olds + __mod); 2076 } 2077 else if (__testsign) 2078 { 2079 _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; 2080 ++__mod; 2081 ++__news; 2082 __beg = __pads; 2083 __beglen = __plen; 2084 __end = const_cast<_CharT*>(__olds + __mod); 2085 } 2086 else 2087 { 2088 // Padding first. 2089 __beg = __pads; 2090 __beglen = __plen; 2091 __end = const_cast<_CharT*>(__olds); 2092 } 2093 } 2094 else 2095 { 2096 // Padding first. 2097 __beg = __pads; 2098 __beglen = __plen; 2099 __end = const_cast<_CharT*>(__olds); 2100 } 2101 _Traits::copy(__news, __beg, __beglen); 2102 _Traits::copy(__news + __beglen, __end, 2103 __newlen - __beglen - __mod); 2104 } 2105 2106 // Used by both numeric and monetary facets. 2107 // Check to make sure that the __grouping_tmp string constructed in 2108 // money_get or num_get matches the canonical grouping for a given 2109 // locale. 2110 // __grouping_tmp is parsed L to R 2111 // 1,222,444 == __grouping_tmp of "/1/3/3" 2112 // __grouping is parsed R to L 2113 // 1,222,444 == __grouping of "/3" == "/3/3/3" 2114 template<typename _CharT> 2115 bool 2116 __verify_grouping(const basic_string<_CharT>& __grouping, 2117 basic_string<_CharT>& __grouping_tmp) 2118 { 2119 int __i = 0; 2120 int __j = 0; 2121 const int __len = __grouping.size(); 2122 const int __n = __grouping_tmp.size(); 2123 bool __test = true; 2124 2125 // Parsed number groupings have to match the 2126 // numpunct::grouping string exactly, starting at the 2127 // right-most point of the parsed sequence of elements ... 2128 while (__test && __i < __n - 1) 2129 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) 2130 __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; 2131 // ... but the last parsed grouping can be <= numpunct 2132 // grouping. 2133 __j == __len ? __j = 0 : __j; 2134 __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; 2135 return __test; 2136 } 2137 2138 // Used by both numeric and monetary facets. 2139 // Inserts "group separator" characters into an array of characters. 2140 // It's recursive, one iteration per group. It moves the characters 2141 // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this 2142 // only with __gbeg != __gend. 2143 template<typename _CharT> 2144 _CharT* 2145 __add_grouping(_CharT* __s, _CharT __sep, 2146 const char* __gbeg, const char* __gend, 2147 const _CharT* __first, const _CharT* __last) 2148 { 2149 if (__last - __first > *__gbeg) 2150 { 2151 __s = __add_grouping(__s, __sep, 2152 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), 2153 __gend, __first, __last - *__gbeg); 2154 __first = __last - *__gbeg; 2155 *__s++ = __sep; 2156 } 2157 do 2158 *__s++ = *__first++; 2159 while (__first != __last); 2160 return __s; 2161 } 2162 2163 // Inhibit implicit instantiations for required instantiations, 2164 // which are defined via explicit instantiations elsewhere. 2165 // NB: This syntax is a GNU extension. 2166 extern template class moneypunct<char, false>; 2167 extern template class moneypunct<char, true>; 2168 extern template class moneypunct_byname<char, false>; 2169 extern template class moneypunct_byname<char, true>; 2170 extern template class money_get<char>; 2171 extern template class money_put<char>; 2172 extern template class moneypunct<wchar_t, false>; 2173 extern template class moneypunct<wchar_t, true>; 2174 extern template class moneypunct_byname<wchar_t, false>; 2175 extern template class moneypunct_byname<wchar_t, true>; 2176 extern template class money_get<wchar_t>; 2177 extern template class money_put<wchar_t>; 2178 extern template class numpunct<char>; 2179 extern template class numpunct_byname<char>; 2180 extern template class num_get<char>; 2181 extern template class num_put<char>; 2182 extern template class numpunct<wchar_t>; 2183 extern template class numpunct_byname<wchar_t>; 2184 extern template class num_get<wchar_t>; 2185 extern template class num_put<wchar_t>; 2186 extern template class __timepunct<char>; 2187 extern template class time_put<char>; 2188 extern template class time_put_byname<char>; 2189 extern template class time_get<char>; 2190 extern template class time_get_byname<char>; 2191 extern template class __timepunct<wchar_t>; 2192 extern template class time_put<wchar_t>; 2193 extern template class time_put_byname<wchar_t>; 2194 extern template class time_get<wchar_t>; 2195 extern template class time_get_byname<wchar_t>; 2196 extern template class messages<char>; 2197 extern template class messages_byname<char>; 2198 extern template class messages<wchar_t>; 2199 extern template class messages_byname<wchar_t>; 2200 extern template class ctype_byname<char>; 2201 extern template class ctype_byname<wchar_t>; 2202 extern template class codecvt_byname<char, char, mbstate_t>; 2203 extern template class codecvt_byname<wchar_t, char, mbstate_t>; 2204 extern template class collate<char>; 2205 extern template class collate_byname<char>; 2206 extern template class collate<wchar_t>; 2207 extern template class collate_byname<wchar_t>; 2208 2209 extern template 2210 const codecvt<char, char, mbstate_t>& 2211 use_facet<codecvt<char, char, mbstate_t> >(const locale&); 2212 2213 extern template 2214 const collate<char>& 2215 use_facet<collate<char> >(const locale&); 2216 2217 extern template 2218 const numpunct<char>& 2219 use_facet<numpunct<char> >(const locale&); 2220 2221 extern template 2222 const num_put<char>& 2223 use_facet<num_put<char> >(const locale&); 2224 2225 extern template 2226 const num_get<char>& 2227 use_facet<num_get<char> >(const locale&); 2228 2229 extern template 2230 const moneypunct<char, true>& 2231 use_facet<moneypunct<char, true> >(const locale&); 2232 2233 extern template 2234 const moneypunct<char, false>& 2235 use_facet<moneypunct<char, false> >(const locale&); 2236 2237 extern template 2238 const money_put<char>& 2239 use_facet<money_put<char> >(const locale&); 2240 2241 extern template 2242 const money_get<char>& 2243 use_facet<money_get<char> >(const locale&); 2244 2245 extern template 2246 const __timepunct<char>& 2247 use_facet<__timepunct<char> >(const locale&); 2248 2249 extern template 2250 const time_put<char>& 2251 use_facet<time_put<char> >(const locale&); 2252 2253 extern template 2254 const time_get<char>& 2255 use_facet<time_get<char> >(const locale&); 2256 2257 extern template 2258 const messages<char>& 2259 use_facet<messages<char> >(const locale&); 2260 2261 extern template 2262 const codecvt<wchar_t, char, mbstate_t>& 2263 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 2264 2265 extern template 2266 const collate<wchar_t>& 2267 use_facet<collate<wchar_t> >(const locale&); 2268 2269 extern template 2270 const numpunct<wchar_t>& 2271 use_facet<numpunct<wchar_t> >(const locale&); 2272 2273 extern template 2274 const num_put<wchar_t>& 2275 use_facet<num_put<wchar_t> >(const locale&); 2276 2277 extern template 2278 const num_get<wchar_t>& 2279 use_facet<num_get<wchar_t> >(const locale&); 2280 2281 extern template 2282 const moneypunct<wchar_t, true>& 2283 use_facet<moneypunct<wchar_t, true> >(const locale&); 2284 2285 extern template 2286 const moneypunct<wchar_t, false>& 2287 use_facet<moneypunct<wchar_t, false> >(const locale&); 2288 2289 extern template 2290 const money_put<wchar_t>& 2291 use_facet<money_put<wchar_t> >(const locale&); 2292 2293 extern template 2294 const money_get<wchar_t>& 2295 use_facet<money_get<wchar_t> >(const locale&); 2296 2297 extern template 2298 const __timepunct<wchar_t>& 2299 use_facet<__timepunct<wchar_t> >(const locale&); 2300 2301 extern template 2302 const time_put<wchar_t>& 2303 use_facet<time_put<wchar_t> >(const locale&); 2304 2305 extern template 2306 const time_get<wchar_t>& 2307 use_facet<time_get<wchar_t> >(const locale&); 2308 2309 extern template 2310 const messages<wchar_t>& 2311 use_facet<messages<wchar_t> >(const locale&); 2312 2313 2314 extern template 2315 bool 2316 has_facet<ctype<char> >(const locale&); 2317 2318 extern template 2319 bool 2320 has_facet<codecvt<char, char, mbstate_t> >(const locale&); 2321 2322 extern template 2323 bool 2324 has_facet<collate<char> >(const locale&); 2325 2326 extern template 2327 bool 2328 has_facet<numpunct<char> >(const locale&); 2329 2330 extern template 2331 bool 2332 has_facet<num_put<char> >(const locale&); 2333 2334 extern template 2335 bool 2336 has_facet<num_get<char> >(const locale&); 2337 2338 extern template 2339 bool 2340 has_facet<moneypunct<char> >(const locale&); 2341 2342 extern template 2343 bool 2344 has_facet<money_put<char> >(const locale&); 2345 2346 extern template 2347 bool 2348 has_facet<money_get<char> >(const locale&); 2349 2350 extern template 2351 bool 2352 has_facet<__timepunct<char> >(const locale&); 2353 2354 extern template 2355 bool 2356 has_facet<time_put<char> >(const locale&); 2357 2358 extern template 2359 bool 2360 has_facet<time_get<char> >(const locale&); 2361 2362 extern template 2363 bool 2364 has_facet<messages<char> >(const locale&); 2365 2366 extern template 2367 bool 2368 has_facet<ctype<wchar_t> >(const locale&); 2369 2370 extern template 2371 bool 2372 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 2373 2374 extern template 2375 bool 2376 has_facet<collate<wchar_t> >(const locale&); 2377 2378 extern template 2379 bool 2380 has_facet<numpunct<wchar_t> >(const locale&); 2381 2382 extern template 2383 bool 2384 has_facet<num_put<wchar_t> >(const locale&); 2385 2386 extern template 2387 bool 2388 has_facet<num_get<wchar_t> >(const locale&); 2389 2390 extern template 2391 bool 2392 has_facet<moneypunct<wchar_t> >(const locale&); 2393 2394 extern template 2395 bool 2396 has_facet<money_put<wchar_t> >(const locale&); 2397 2398 extern template 2399 bool 2400 has_facet<money_get<wchar_t> >(const locale&); 2401 2402 extern template 2403 bool 2404 has_facet<__timepunct<wchar_t> >(const locale&); 2405 2406 extern template 2407 bool 2408 has_facet<time_put<wchar_t> >(const locale&); 2409 2410 extern template 2411 bool 2412 has_facet<time_get<wchar_t> >(const locale&); 2413 2414 extern template 2415 bool 2416 has_facet<messages<wchar_t> >(const locale&); 2417} // namespace std 2418 2419#endif 2420