1// -*- C++ -*- 2//===-------------------------- locale ------------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10 11#ifndef _LIBCPP_LOCALE 12#define _LIBCPP_LOCALE 13 14/* 15 locale synopsis 16 17namespace std 18{ 19 20class locale 21{ 22public: 23 // types: 24 class facet; 25 class id; 26 27 typedef int category; 28 static const category // values assigned here are for exposition only 29 none = 0x000, 30 collate = 0x010, 31 ctype = 0x020, 32 monetary = 0x040, 33 numeric = 0x080, 34 time = 0x100, 35 messages = 0x200, 36 all = collate | ctype | monetary | numeric | time | messages; 37 38 // construct/copy/destroy: 39 locale() noexcept; 40 locale(const locale& other) noexcept; 41 explicit locale(const char* std_name); 42 explicit locale(const string& std_name); 43 locale(const locale& other, const char* std_name, category); 44 locale(const locale& other, const string& std_name, category); 45 template <class Facet> locale(const locale& other, Facet* f); 46 locale(const locale& other, const locale& one, category); 47 48 ~locale(); // not virtual 49 50 const locale& operator=(const locale& other) noexcept; 51 52 template <class Facet> locale combine(const locale& other) const; 53 54 // locale operations: 55 basic_string<char> name() const; 56 bool operator==(const locale& other) const; 57 bool operator!=(const locale& other) const; 58 template <class charT, class Traits, class Allocator> 59 bool operator()(const basic_string<charT,Traits,Allocator>& s1, 60 const basic_string<charT,Traits,Allocator>& s2) const; 61 62 // global locale objects: 63 static locale global(const locale&); 64 static const locale& classic(); 65}; 66 67template <class Facet> const Facet& use_facet(const locale&); 68template <class Facet> bool has_facet(const locale&) noexcept; 69 70// 22.3.3, convenience interfaces: 71template <class charT> bool isspace (charT c, const locale& loc); 72template <class charT> bool isprint (charT c, const locale& loc); 73template <class charT> bool iscntrl (charT c, const locale& loc); 74template <class charT> bool isupper (charT c, const locale& loc); 75template <class charT> bool islower (charT c, const locale& loc); 76template <class charT> bool isalpha (charT c, const locale& loc); 77template <class charT> bool isdigit (charT c, const locale& loc); 78template <class charT> bool ispunct (charT c, const locale& loc); 79template <class charT> bool isxdigit(charT c, const locale& loc); 80template <class charT> bool isalnum (charT c, const locale& loc); 81template <class charT> bool isgraph (charT c, const locale& loc); 82template <class charT> charT toupper(charT c, const locale& loc); 83template <class charT> charT tolower(charT c, const locale& loc); 84 85template<class Codecvt, class Elem = wchar_t, 86 class Wide_alloc = allocator<Elem>, 87 class Byte_alloc = allocator<char>> 88class wstring_convert 89{ 90public: 91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string; 92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string; 93 typedef typename Codecvt::state_type state_type; 94 typedef typename wide_string::traits_type::int_type int_type; 95 96 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // explicit in C++14 97 wstring_convert(Codecvt* pcvt, state_type state); 98 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14 99 const wide_string& wide_err = wide_string()); 100 wstring_convert(const wstring_convert&) = delete; // C++14 101 wstring_convert & operator=(const wstring_convert &) = delete; // C++14 102 ~wstring_convert(); 103 104 wide_string from_bytes(char byte); 105 wide_string from_bytes(const char* ptr); 106 wide_string from_bytes(const byte_string& str); 107 wide_string from_bytes(const char* first, const char* last); 108 109 byte_string to_bytes(Elem wchar); 110 byte_string to_bytes(const Elem* wptr); 111 byte_string to_bytes(const wide_string& wstr); 112 byte_string to_bytes(const Elem* first, const Elem* last); 113 114 size_t converted() const; // noexcept in C++14 115 state_type state() const; 116}; 117 118template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>> 119class wbuffer_convert 120 : public basic_streambuf<Elem, Tr> 121{ 122public: 123 typedef typename Tr::state_type state_type; 124 125 explicit wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt, 126 state_type state = state_type()); // explicit in C++14 127 wbuffer_convert(const wbuffer_convert&) = delete; // C++14 128 wbuffer_convert & operator=(const wbuffer_convert &) = delete; // C++14 129 ~wbuffer_convert(); // C++14 130 131 streambuf* rdbuf() const; 132 streambuf* rdbuf(streambuf* bytebuf); 133 134 state_type state() const; 135}; 136 137// 22.4.1 and 22.4.1.3, ctype: 138class ctype_base; 139template <class charT> class ctype; 140template <> class ctype<char>; // specialization 141template <class charT> class ctype_byname; 142template <> class ctype_byname<char>; // specialization 143 144class codecvt_base; 145template <class internT, class externT, class stateT> class codecvt; 146template <class internT, class externT, class stateT> class codecvt_byname; 147 148// 22.4.2 and 22.4.3, numeric: 149template <class charT, class InputIterator> class num_get; 150template <class charT, class OutputIterator> class num_put; 151template <class charT> class numpunct; 152template <class charT> class numpunct_byname; 153 154// 22.4.4, col lation: 155template <class charT> class collate; 156template <class charT> class collate_byname; 157 158// 22.4.5, date and time: 159class time_base; 160template <class charT, class InputIterator> class time_get; 161template <class charT, class InputIterator> class time_get_byname; 162template <class charT, class OutputIterator> class time_put; 163template <class charT, class OutputIterator> class time_put_byname; 164 165// 22.4.6, money: 166class money_base; 167template <class charT, class InputIterator> class money_get; 168template <class charT, class OutputIterator> class money_put; 169template <class charT, bool Intl> class moneypunct; 170template <class charT, bool Intl> class moneypunct_byname; 171 172// 22.4.7, message retrieval: 173class messages_base; 174template <class charT> class messages; 175template <class charT> class messages_byname; 176 177} // std 178 179*/ 180 181#include <__config> 182#include <__locale> 183#include <__debug> 184#include <algorithm> 185#include <memory> 186#include <ios> 187#include <streambuf> 188#include <iterator> 189#include <limits> 190#ifndef __APPLE__ 191#include <cstdarg> 192#endif 193#include <cstdlib> 194#include <ctime> 195#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 196#include <support/win32/locale_win32.h> 197#elif defined(_NEWLIB_VERSION) 198// FIXME: replace all the uses of _NEWLIB_VERSION with __NEWLIB__ preceded by an 199// include of <sys/cdefs.h> once https://sourceware.org/ml/newlib-cvs/2014-q3/msg00038.html 200// has had a chance to bake for a bit 201#include <support/newlib/xlocale.h> 202#endif 203#ifdef _LIBCPP_HAS_CATOPEN 204#include <nl_types.h> 205#endif 206 207#ifdef __APPLE__ 208#include <Availability.h> 209#endif 210 211#include <__undef_min_max> 212 213#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 214#pragma GCC system_header 215#endif 216 217#ifdef _LIBCPP_LOCALE__L_EXTENSIONS 218#include <__bsd_locale_defaults.h> 219#else 220#include <__bsd_locale_fallbacks.h> 221#endif 222 223_LIBCPP_BEGIN_NAMESPACE_STD 224 225#if defined(__APPLE__) || defined(__FreeBSD__) 226# define _LIBCPP_GET_C_LOCALE 0 227#elif defined(__CloudABI__) || defined(__NetBSD__) 228# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE 229#else 230# define _LIBCPP_GET_C_LOCALE __cloc() 231 // Get the C locale object 232 _LIBCPP_FUNC_VIS locale_t __cloc(); 233#define __cloc_defined 234#endif 235 236typedef _VSTD::remove_pointer<locale_t>::type __locale_struct; 237typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr; 238 239// __scan_keyword 240// Scans [__b, __e) until a match is found in the basic_strings range 241// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke). 242// __b will be incremented (visibly), consuming CharT until a match is found 243// or proved to not exist. A keyword may be "", in which will match anything. 244// If one keyword is a prefix of another, and the next CharT in the input 245// might match another keyword, the algorithm will attempt to find the longest 246// matching keyword. If the longer matching keyword ends up not matching, then 247// no keyword match is found. If no keyword match is found, __ke is returned 248// and failbit is set in __err. 249// Else an iterator pointing to the matching keyword is found. If more than 250// one keyword matches, an iterator to the first matching keyword is returned. 251// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false, 252// __ct is used to force to lower case before comparing characters. 253// Examples: 254// Keywords: "a", "abb" 255// If the input is "a", the first keyword matches and eofbit is set. 256// If the input is "abc", no match is found and "ab" are consumed. 257template <class _InputIterator, class _ForwardIterator, class _Ctype> 258_LIBCPP_HIDDEN 259_ForwardIterator 260__scan_keyword(_InputIterator& __b, _InputIterator __e, 261 _ForwardIterator __kb, _ForwardIterator __ke, 262 const _Ctype& __ct, ios_base::iostate& __err, 263 bool __case_sensitive = true) 264{ 265 typedef typename iterator_traits<_InputIterator>::value_type _CharT; 266 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke)); 267 const unsigned char __doesnt_match = '\0'; 268 const unsigned char __might_match = '\1'; 269 const unsigned char __does_match = '\2'; 270 unsigned char __statbuf[100]; 271 unsigned char* __status = __statbuf; 272 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free); 273 if (__nkw > sizeof(__statbuf)) 274 { 275 __status = (unsigned char*)malloc(__nkw); 276 if (__status == 0) 277 __throw_bad_alloc(); 278 __stat_hold.reset(__status); 279 } 280 size_t __n_might_match = __nkw; // At this point, any keyword might match 281 size_t __n_does_match = 0; // but none of them definitely do 282 // Initialize all statuses to __might_match, except for "" keywords are __does_match 283 unsigned char* __st = __status; 284 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st) 285 { 286 if (!__ky->empty()) 287 *__st = __might_match; 288 else 289 { 290 *__st = __does_match; 291 --__n_might_match; 292 ++__n_does_match; 293 } 294 } 295 // While there might be a match, test keywords against the next CharT 296 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx) 297 { 298 // Peek at the next CharT but don't consume it 299 _CharT __c = *__b; 300 if (!__case_sensitive) 301 __c = __ct.toupper(__c); 302 bool __consume = false; 303 // For each keyword which might match, see if the __indx character is __c 304 // If a match if found, consume __c 305 // If a match is found, and that is the last character in the keyword, 306 // then that keyword matches. 307 // If the keyword doesn't match this character, then change the keyword 308 // to doesn't match 309 __st = __status; 310 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st) 311 { 312 if (*__st == __might_match) 313 { 314 _CharT __kc = (*__ky)[__indx]; 315 if (!__case_sensitive) 316 __kc = __ct.toupper(__kc); 317 if (__c == __kc) 318 { 319 __consume = true; 320 if (__ky->size() == __indx+1) 321 { 322 *__st = __does_match; 323 --__n_might_match; 324 ++__n_does_match; 325 } 326 } 327 else 328 { 329 *__st = __doesnt_match; 330 --__n_might_match; 331 } 332 } 333 } 334 // consume if we matched a character 335 if (__consume) 336 { 337 ++__b; 338 // If we consumed a character and there might be a matched keyword that 339 // was marked matched on a previous iteration, then such keywords 340 // which are now marked as not matching. 341 if (__n_might_match + __n_does_match > 1) 342 { 343 __st = __status; 344 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st) 345 { 346 if (*__st == __does_match && __ky->size() != __indx+1) 347 { 348 *__st = __doesnt_match; 349 --__n_does_match; 350 } 351 } 352 } 353 } 354 } 355 // We've exited the loop because we hit eof and/or we have no more "might matches". 356 if (__b == __e) 357 __err |= ios_base::eofbit; 358 // Return the first matching result 359 for (__st = __status; __kb != __ke; ++__kb, (void) ++__st) 360 if (*__st == __does_match) 361 break; 362 if (__kb == __ke) 363 __err |= ios_base::failbit; 364 return __kb; 365} 366 367struct _LIBCPP_TYPE_VIS __num_get_base 368{ 369 static const int __num_get_buf_sz = 40; 370 371 static int __get_base(ios_base&); 372 static const char __src[33]; 373}; 374 375_LIBCPP_FUNC_VIS 376void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, 377 ios_base::iostate& __err); 378 379template <class _CharT> 380struct __num_get 381 : protected __num_get_base 382{ 383 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); 384 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, 385 _CharT& __thousands_sep); 386 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, 387 unsigned& __dc, _CharT __thousands_sep, const string& __grouping, 388 unsigned* __g, unsigned*& __g_end, _CharT* __atoms); 389 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, 390 char* __a, char*& __a_end, 391 _CharT __decimal_point, _CharT __thousands_sep, 392 const string& __grouping, unsigned* __g, 393 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms); 394}; 395 396template <class _CharT> 397string 398__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) 399{ 400 locale __loc = __iob.getloc(); 401 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms); 402 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 403 __thousands_sep = __np.thousands_sep(); 404 return __np.grouping(); 405} 406 407template <class _CharT> 408string 409__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, 410 _CharT& __thousands_sep) 411{ 412 locale __loc = __iob.getloc(); 413 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms); 414 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 415 __decimal_point = __np.decimal_point(); 416 __thousands_sep = __np.thousands_sep(); 417 return __np.grouping(); 418} 419 420template <class _CharT> 421int 422__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, 423 unsigned& __dc, _CharT __thousands_sep, const string& __grouping, 424 unsigned* __g, unsigned*& __g_end, _CharT* __atoms) 425{ 426 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) 427 { 428 *__a_end++ = __ct == __atoms[24] ? '+' : '-'; 429 __dc = 0; 430 return 0; 431 } 432 if (__grouping.size() != 0 && __ct == __thousands_sep) 433 { 434 if (__g_end-__g < __num_get_buf_sz) 435 { 436 *__g_end++ = __dc; 437 __dc = 0; 438 } 439 return 0; 440 } 441 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms; 442 if (__f >= 24) 443 return -1; 444 switch (__base) 445 { 446 case 8: 447 case 10: 448 if (__f >= __base) 449 return -1; 450 break; 451 case 16: 452 if (__f < 22) 453 break; 454 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0') 455 { 456 __dc = 0; 457 *__a_end++ = __src[__f]; 458 return 0; 459 } 460 return -1; 461 } 462 *__a_end++ = __src[__f]; 463 ++__dc; 464 return 0; 465} 466 467template <class _CharT> 468int 469__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end, 470 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping, 471 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms) 472{ 473 if (__ct == __decimal_point) 474 { 475 if (!__in_units) 476 return -1; 477 __in_units = false; 478 *__a_end++ = '.'; 479 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz) 480 *__g_end++ = __dc; 481 return 0; 482 } 483 if (__ct == __thousands_sep && __grouping.size() != 0) 484 { 485 if (!__in_units) 486 return -1; 487 if (__g_end-__g < __num_get_buf_sz) 488 { 489 *__g_end++ = __dc; 490 __dc = 0; 491 } 492 return 0; 493 } 494 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms; 495 if (__f >= 32) 496 return -1; 497 char __x = __src[__f]; 498 if (__x == '-' || __x == '+') 499 { 500 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F)) 501 { 502 *__a_end++ = __x; 503 return 0; 504 } 505 return -1; 506 } 507 if (__x == 'x' || __x == 'X') 508 __exp = 'P'; 509 else if ((__x & 0x5F) == __exp) 510 { 511 __exp |= 0x80; 512 if (__in_units) 513 { 514 __in_units = false; 515 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz) 516 *__g_end++ = __dc; 517 } 518 } 519 *__a_end++ = __x; 520 if (__f >= 22) 521 return 0; 522 ++__dc; 523 return 0; 524} 525 526_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>) 527_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>) 528 529template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> > 530class _LIBCPP_TEMPLATE_VIS num_get 531 : public locale::facet, 532 private __num_get<_CharT> 533{ 534public: 535 typedef _CharT char_type; 536 typedef _InputIterator iter_type; 537 538 _LIBCPP_ALWAYS_INLINE 539 explicit num_get(size_t __refs = 0) 540 : locale::facet(__refs) {} 541 542 _LIBCPP_ALWAYS_INLINE 543 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 544 ios_base::iostate& __err, bool& __v) const 545 { 546 return do_get(__b, __e, __iob, __err, __v); 547 } 548 549 _LIBCPP_ALWAYS_INLINE 550 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 551 ios_base::iostate& __err, long& __v) const 552 { 553 return do_get(__b, __e, __iob, __err, __v); 554 } 555 556 _LIBCPP_ALWAYS_INLINE 557 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 558 ios_base::iostate& __err, long long& __v) const 559 { 560 return do_get(__b, __e, __iob, __err, __v); 561 } 562 563 _LIBCPP_ALWAYS_INLINE 564 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 565 ios_base::iostate& __err, unsigned short& __v) const 566 { 567 return do_get(__b, __e, __iob, __err, __v); 568 } 569 570 _LIBCPP_ALWAYS_INLINE 571 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 572 ios_base::iostate& __err, unsigned int& __v) const 573 { 574 return do_get(__b, __e, __iob, __err, __v); 575 } 576 577 _LIBCPP_ALWAYS_INLINE 578 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 579 ios_base::iostate& __err, unsigned long& __v) const 580 { 581 return do_get(__b, __e, __iob, __err, __v); 582 } 583 584 _LIBCPP_ALWAYS_INLINE 585 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 586 ios_base::iostate& __err, unsigned long long& __v) const 587 { 588 return do_get(__b, __e, __iob, __err, __v); 589 } 590 591 _LIBCPP_ALWAYS_INLINE 592 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 593 ios_base::iostate& __err, float& __v) const 594 { 595 return do_get(__b, __e, __iob, __err, __v); 596 } 597 598 _LIBCPP_ALWAYS_INLINE 599 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 600 ios_base::iostate& __err, double& __v) const 601 { 602 return do_get(__b, __e, __iob, __err, __v); 603 } 604 605 _LIBCPP_ALWAYS_INLINE 606 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 607 ios_base::iostate& __err, long double& __v) const 608 { 609 return do_get(__b, __e, __iob, __err, __v); 610 } 611 612 _LIBCPP_ALWAYS_INLINE 613 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 614 ios_base::iostate& __err, void*& __v) const 615 { 616 return do_get(__b, __e, __iob, __err, __v); 617 } 618 619 static locale::id id; 620 621protected: 622 _LIBCPP_ALWAYS_INLINE 623 ~num_get() {} 624 625 template <class _Fp> 626 iter_type __do_get_floating_point 627 (iter_type __b, iter_type __e, ios_base& __iob, 628 ios_base::iostate& __err, _Fp& __v) const; 629 630 template <class _Signed> 631 iter_type __do_get_signed 632 (iter_type __b, iter_type __e, ios_base& __iob, 633 ios_base::iostate& __err, _Signed& __v) const; 634 635 template <class _Unsigned> 636 iter_type __do_get_unsigned 637 (iter_type __b, iter_type __e, ios_base& __iob, 638 ios_base::iostate& __err, _Unsigned& __v) const; 639 640 641 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 642 ios_base::iostate& __err, bool& __v) const; 643 644 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 645 ios_base::iostate& __err, long& __v) const 646 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); } 647 648 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 649 ios_base::iostate& __err, long long& __v) const 650 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); } 651 652 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 653 ios_base::iostate& __err, unsigned short& __v) const 654 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); } 655 656 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 657 ios_base::iostate& __err, unsigned int& __v) const 658 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); } 659 660 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 661 ios_base::iostate& __err, unsigned long& __v) const 662 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); } 663 664 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 665 ios_base::iostate& __err, unsigned long long& __v) const 666 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); } 667 668 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 669 ios_base::iostate& __err, float& __v) const 670 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); } 671 672 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 673 ios_base::iostate& __err, double& __v) const 674 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); } 675 676 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 677 ios_base::iostate& __err, long double& __v) const 678 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); } 679 680 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 681 ios_base::iostate& __err, void*& __v) const; 682}; 683 684template <class _CharT, class _InputIterator> 685locale::id 686num_get<_CharT, _InputIterator>::id; 687 688template <class _Tp> 689_Tp 690__num_get_signed_integral(const char* __a, const char* __a_end, 691 ios_base::iostate& __err, int __base) 692{ 693 if (__a != __a_end) 694 { 695 typename remove_reference<decltype(errno)>::type __save_errno = errno; 696 errno = 0; 697 char *__p2; 698 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); 699 typename remove_reference<decltype(errno)>::type __current_errno = errno; 700 if (__current_errno == 0) 701 errno = __save_errno; 702 if (__p2 != __a_end) 703 { 704 __err = ios_base::failbit; 705 return 0; 706 } 707 else if (__current_errno == ERANGE || 708 __ll < numeric_limits<_Tp>::min() || 709 numeric_limits<_Tp>::max() < __ll) 710 { 711 __err = ios_base::failbit; 712 if (__ll > 0) 713 return numeric_limits<_Tp>::max(); 714 else 715 return numeric_limits<_Tp>::min(); 716 } 717 return static_cast<_Tp>(__ll); 718 } 719 __err = ios_base::failbit; 720 return 0; 721} 722 723template <class _Tp> 724_Tp 725__num_get_unsigned_integral(const char* __a, const char* __a_end, 726 ios_base::iostate& __err, int __base) 727{ 728 if (__a != __a_end) 729 { 730 if (*__a == '-') 731 { 732 __err = ios_base::failbit; 733 return 0; 734 } 735 typename remove_reference<decltype(errno)>::type __save_errno = errno; 736 errno = 0; 737 char *__p2; 738 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); 739 typename remove_reference<decltype(errno)>::type __current_errno = errno; 740 if (__current_errno == 0) 741 errno = __save_errno; 742 if (__p2 != __a_end) 743 { 744 __err = ios_base::failbit; 745 return 0; 746 } 747 else if (__current_errno == ERANGE || 748 numeric_limits<_Tp>::max() < __ll) 749 { 750 __err = ios_base::failbit; 751 return numeric_limits<_Tp>::max(); 752 } 753 return static_cast<_Tp>(__ll); 754 } 755 __err = ios_base::failbit; 756 return 0; 757} 758 759template <class _Tp> 760_LIBCPP_INLINE_VISIBILITY 761_Tp __do_strtod(const char* __a, char** __p2); 762 763template <> 764inline _LIBCPP_INLINE_VISIBILITY 765float __do_strtod<float>(const char* __a, char** __p2) { 766 return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE); 767} 768 769template <> 770inline _LIBCPP_INLINE_VISIBILITY 771double __do_strtod<double>(const char* __a, char** __p2) { 772 return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE); 773} 774 775template <> 776inline _LIBCPP_INLINE_VISIBILITY 777long double __do_strtod<long double>(const char* __a, char** __p2) { 778 return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE); 779} 780 781template <class _Tp> 782_LIBCPP_HIDDEN 783_Tp 784__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) 785{ 786 if (__a != __a_end) 787 { 788 typename remove_reference<decltype(errno)>::type __save_errno = errno; 789 errno = 0; 790 char *__p2; 791 _Tp __ld = __do_strtod<_Tp>(__a, &__p2); 792 typename remove_reference<decltype(errno)>::type __current_errno = errno; 793 if (__current_errno == 0) 794 errno = __save_errno; 795 if (__p2 != __a_end) 796 { 797 __err = ios_base::failbit; 798 return 0; 799 } 800 else if (__current_errno == ERANGE) 801 __err = ios_base::failbit; 802 return __ld; 803 } 804 __err = ios_base::failbit; 805 return 0; 806} 807 808template <class _CharT, class _InputIterator> 809_InputIterator 810num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, 811 ios_base& __iob, 812 ios_base::iostate& __err, 813 bool& __v) const 814{ 815 if ((__iob.flags() & ios_base::boolalpha) == 0) 816 { 817 long __lv = -1; 818 __b = do_get(__b, __e, __iob, __err, __lv); 819 switch (__lv) 820 { 821 case 0: 822 __v = false; 823 break; 824 case 1: 825 __v = true; 826 break; 827 default: 828 __v = true; 829 __err = ios_base::failbit; 830 break; 831 } 832 return __b; 833 } 834 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc()); 835 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc()); 836 typedef typename numpunct<_CharT>::string_type string_type; 837 const string_type __names[2] = {__np.truename(), __np.falsename()}; 838 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2, 839 __ct, __err); 840 __v = __i == __names; 841 return __b; 842} 843 844// signed 845 846template <class _CharT, class _InputIterator> 847template <class _Signed> 848_InputIterator 849num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e, 850 ios_base& __iob, 851 ios_base::iostate& __err, 852 _Signed& __v) const 853{ 854 // Stage 1 855 int __base = this->__get_base(__iob); 856 // Stage 2 857 char_type __atoms[26]; 858 char_type __thousands_sep; 859 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); 860 string __buf; 861 __buf.resize(__buf.capacity()); 862 char* __a = &__buf[0]; 863 char* __a_end = __a; 864 unsigned __g[__num_get_base::__num_get_buf_sz]; 865 unsigned* __g_end = __g; 866 unsigned __dc = 0; 867 for (; __b != __e; ++__b) 868 { 869 if (__a_end == __a + __buf.size()) 870 { 871 size_t __tmp = __buf.size(); 872 __buf.resize(2*__buf.size()); 873 __buf.resize(__buf.capacity()); 874 __a = &__buf[0]; 875 __a_end = __a + __tmp; 876 } 877 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, 878 __thousands_sep, __grouping, __g, __g_end, 879 __atoms)) 880 break; 881 } 882 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz) 883 *__g_end++ = __dc; 884 // Stage 3 885 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); 886 // Digit grouping checked 887 __check_grouping(__grouping, __g, __g_end, __err); 888 // EOF checked 889 if (__b == __e) 890 __err |= ios_base::eofbit; 891 return __b; 892} 893 894// unsigned 895 896template <class _CharT, class _InputIterator> 897template <class _Unsigned> 898_InputIterator 899num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e, 900 ios_base& __iob, 901 ios_base::iostate& __err, 902 _Unsigned& __v) const 903{ 904 // Stage 1 905 int __base = this->__get_base(__iob); 906 // Stage 2 907 char_type __atoms[26]; 908 char_type __thousands_sep; 909 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); 910 string __buf; 911 __buf.resize(__buf.capacity()); 912 char* __a = &__buf[0]; 913 char* __a_end = __a; 914 unsigned __g[__num_get_base::__num_get_buf_sz]; 915 unsigned* __g_end = __g; 916 unsigned __dc = 0; 917 for (; __b != __e; ++__b) 918 { 919 if (__a_end == __a + __buf.size()) 920 { 921 size_t __tmp = __buf.size(); 922 __buf.resize(2*__buf.size()); 923 __buf.resize(__buf.capacity()); 924 __a = &__buf[0]; 925 __a_end = __a + __tmp; 926 } 927 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, 928 __thousands_sep, __grouping, __g, __g_end, 929 __atoms)) 930 break; 931 } 932 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz) 933 *__g_end++ = __dc; 934 // Stage 3 935 __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); 936 // Digit grouping checked 937 __check_grouping(__grouping, __g, __g_end, __err); 938 // EOF checked 939 if (__b == __e) 940 __err |= ios_base::eofbit; 941 return __b; 942} 943 944// floating point 945 946template <class _CharT, class _InputIterator> 947template <class _Fp> 948_InputIterator 949num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e, 950 ios_base& __iob, 951 ios_base::iostate& __err, 952 _Fp& __v) const 953{ 954 // Stage 1, nothing to do 955 // Stage 2 956 char_type __atoms[32]; 957 char_type __decimal_point; 958 char_type __thousands_sep; 959 string __grouping = this->__stage2_float_prep(__iob, __atoms, 960 __decimal_point, 961 __thousands_sep); 962 string __buf; 963 __buf.resize(__buf.capacity()); 964 char* __a = &__buf[0]; 965 char* __a_end = __a; 966 unsigned __g[__num_get_base::__num_get_buf_sz]; 967 unsigned* __g_end = __g; 968 unsigned __dc = 0; 969 bool __in_units = true; 970 char __exp = 'E'; 971 for (; __b != __e; ++__b) 972 { 973 if (__a_end == __a + __buf.size()) 974 { 975 size_t __tmp = __buf.size(); 976 __buf.resize(2*__buf.size()); 977 __buf.resize(__buf.capacity()); 978 __a = &__buf[0]; 979 __a_end = __a + __tmp; 980 } 981 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end, 982 __decimal_point, __thousands_sep, 983 __grouping, __g, __g_end, 984 __dc, __atoms)) 985 break; 986 } 987 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz) 988 *__g_end++ = __dc; 989 // Stage 3 990 __v = __num_get_float<_Fp>(__a, __a_end, __err); 991 // Digit grouping checked 992 __check_grouping(__grouping, __g, __g_end, __err); 993 // EOF checked 994 if (__b == __e) 995 __err |= ios_base::eofbit; 996 return __b; 997} 998 999template <class _CharT, class _InputIterator> 1000_InputIterator 1001num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, 1002 ios_base& __iob, 1003 ios_base::iostate& __err, 1004 void*& __v) const 1005{ 1006 // Stage 1 1007 int __base = 16; 1008 // Stage 2 1009 char_type __atoms[26]; 1010 char_type __thousands_sep = 0; 1011 string __grouping; 1012 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src, 1013 __num_get_base::__src + 26, __atoms); 1014 string __buf; 1015 __buf.resize(__buf.capacity()); 1016 char* __a = &__buf[0]; 1017 char* __a_end = __a; 1018 unsigned __g[__num_get_base::__num_get_buf_sz]; 1019 unsigned* __g_end = __g; 1020 unsigned __dc = 0; 1021 for (; __b != __e; ++__b) 1022 { 1023 if (__a_end == __a + __buf.size()) 1024 { 1025 size_t __tmp = __buf.size(); 1026 __buf.resize(2*__buf.size()); 1027 __buf.resize(__buf.capacity()); 1028 __a = &__buf[0]; 1029 __a_end = __a + __tmp; 1030 } 1031 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, 1032 __thousands_sep, __grouping, 1033 __g, __g_end, __atoms)) 1034 break; 1035 } 1036 // Stage 3 1037 __buf.resize(__a_end - __a); 1038 if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1) 1039 __err = ios_base::failbit; 1040 // EOF checked 1041 if (__b == __e) 1042 __err |= ios_base::eofbit; 1043 return __b; 1044} 1045 1046_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>) 1047_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>) 1048 1049struct _LIBCPP_TYPE_VIS __num_put_base 1050{ 1051protected: 1052 static void __format_int(char* __fmt, const char* __len, bool __signd, 1053 ios_base::fmtflags __flags); 1054 static bool __format_float(char* __fmt, const char* __len, 1055 ios_base::fmtflags __flags); 1056 static char* __identify_padding(char* __nb, char* __ne, 1057 const ios_base& __iob); 1058}; 1059 1060template <class _CharT> 1061struct __num_put 1062 : protected __num_put_base 1063{ 1064 static void __widen_and_group_int(char* __nb, char* __np, char* __ne, 1065 _CharT* __ob, _CharT*& __op, _CharT*& __oe, 1066 const locale& __loc); 1067 static void __widen_and_group_float(char* __nb, char* __np, char* __ne, 1068 _CharT* __ob, _CharT*& __op, _CharT*& __oe, 1069 const locale& __loc); 1070}; 1071 1072template <class _CharT> 1073void 1074__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne, 1075 _CharT* __ob, _CharT*& __op, _CharT*& __oe, 1076 const locale& __loc) 1077{ 1078 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc); 1079 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc); 1080 string __grouping = __npt.grouping(); 1081 if (__grouping.empty()) 1082 { 1083 __ct.widen(__nb, __ne, __ob); 1084 __oe = __ob + (__ne - __nb); 1085 } 1086 else 1087 { 1088 __oe = __ob; 1089 char* __nf = __nb; 1090 if (*__nf == '-' || *__nf == '+') 1091 *__oe++ = __ct.widen(*__nf++); 1092 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || 1093 __nf[1] == 'X')) 1094 { 1095 *__oe++ = __ct.widen(*__nf++); 1096 *__oe++ = __ct.widen(*__nf++); 1097 } 1098 reverse(__nf, __ne); 1099 _CharT __thousands_sep = __npt.thousands_sep(); 1100 unsigned __dc = 0; 1101 unsigned __dg = 0; 1102 for (char* __p = __nf; __p < __ne; ++__p) 1103 { 1104 if (static_cast<unsigned>(__grouping[__dg]) > 0 && 1105 __dc == static_cast<unsigned>(__grouping[__dg])) 1106 { 1107 *__oe++ = __thousands_sep; 1108 __dc = 0; 1109 if (__dg < __grouping.size()-1) 1110 ++__dg; 1111 } 1112 *__oe++ = __ct.widen(*__p); 1113 ++__dc; 1114 } 1115 reverse(__ob + (__nf - __nb), __oe); 1116 } 1117 if (__np == __ne) 1118 __op = __oe; 1119 else 1120 __op = __ob + (__np - __nb); 1121} 1122 1123template <class _CharT> 1124void 1125__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne, 1126 _CharT* __ob, _CharT*& __op, _CharT*& __oe, 1127 const locale& __loc) 1128{ 1129 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc); 1130 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc); 1131 string __grouping = __npt.grouping(); 1132 __oe = __ob; 1133 char* __nf = __nb; 1134 if (*__nf == '-' || *__nf == '+') 1135 *__oe++ = __ct.widen(*__nf++); 1136 char* __ns; 1137 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || 1138 __nf[1] == 'X')) 1139 { 1140 *__oe++ = __ct.widen(*__nf++); 1141 *__oe++ = __ct.widen(*__nf++); 1142 for (__ns = __nf; __ns < __ne; ++__ns) 1143 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE)) 1144 break; 1145 } 1146 else 1147 { 1148 for (__ns = __nf; __ns < __ne; ++__ns) 1149 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE)) 1150 break; 1151 } 1152 if (__grouping.empty()) 1153 { 1154 __ct.widen(__nf, __ns, __oe); 1155 __oe += __ns - __nf; 1156 } 1157 else 1158 { 1159 reverse(__nf, __ns); 1160 _CharT __thousands_sep = __npt.thousands_sep(); 1161 unsigned __dc = 0; 1162 unsigned __dg = 0; 1163 for (char* __p = __nf; __p < __ns; ++__p) 1164 { 1165 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg])) 1166 { 1167 *__oe++ = __thousands_sep; 1168 __dc = 0; 1169 if (__dg < __grouping.size()-1) 1170 ++__dg; 1171 } 1172 *__oe++ = __ct.widen(*__p); 1173 ++__dc; 1174 } 1175 reverse(__ob + (__nf - __nb), __oe); 1176 } 1177 for (__nf = __ns; __nf < __ne; ++__nf) 1178 { 1179 if (*__nf == '.') 1180 { 1181 *__oe++ = __npt.decimal_point(); 1182 ++__nf; 1183 break; 1184 } 1185 else 1186 *__oe++ = __ct.widen(*__nf); 1187 } 1188 __ct.widen(__nf, __ne, __oe); 1189 __oe += __ne - __nf; 1190 if (__np == __ne) 1191 __op = __oe; 1192 else 1193 __op = __ob + (__np - __nb); 1194} 1195 1196_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>) 1197_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>) 1198 1199template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> > 1200class _LIBCPP_TEMPLATE_VIS num_put 1201 : public locale::facet, 1202 private __num_put<_CharT> 1203{ 1204public: 1205 typedef _CharT char_type; 1206 typedef _OutputIterator iter_type; 1207 1208 _LIBCPP_ALWAYS_INLINE 1209 explicit num_put(size_t __refs = 0) 1210 : locale::facet(__refs) {} 1211 1212 _LIBCPP_ALWAYS_INLINE 1213 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1214 bool __v) const 1215 { 1216 return do_put(__s, __iob, __fl, __v); 1217 } 1218 1219 _LIBCPP_ALWAYS_INLINE 1220 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1221 long __v) const 1222 { 1223 return do_put(__s, __iob, __fl, __v); 1224 } 1225 1226 _LIBCPP_ALWAYS_INLINE 1227 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1228 long long __v) const 1229 { 1230 return do_put(__s, __iob, __fl, __v); 1231 } 1232 1233 _LIBCPP_ALWAYS_INLINE 1234 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1235 unsigned long __v) const 1236 { 1237 return do_put(__s, __iob, __fl, __v); 1238 } 1239 1240 _LIBCPP_ALWAYS_INLINE 1241 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1242 unsigned long long __v) const 1243 { 1244 return do_put(__s, __iob, __fl, __v); 1245 } 1246 1247 _LIBCPP_ALWAYS_INLINE 1248 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1249 double __v) const 1250 { 1251 return do_put(__s, __iob, __fl, __v); 1252 } 1253 1254 _LIBCPP_ALWAYS_INLINE 1255 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1256 long double __v) const 1257 { 1258 return do_put(__s, __iob, __fl, __v); 1259 } 1260 1261 _LIBCPP_ALWAYS_INLINE 1262 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 1263 const void* __v) const 1264 { 1265 return do_put(__s, __iob, __fl, __v); 1266 } 1267 1268 static locale::id id; 1269 1270protected: 1271 _LIBCPP_ALWAYS_INLINE 1272 ~num_put() {} 1273 1274 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1275 bool __v) const; 1276 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1277 long __v) const; 1278 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1279 long long __v) const; 1280 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1281 unsigned long) const; 1282 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1283 unsigned long long) const; 1284 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1285 double __v) const; 1286 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1287 long double __v) const; 1288 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, 1289 const void* __v) const; 1290}; 1291 1292template <class _CharT, class _OutputIterator> 1293locale::id 1294num_put<_CharT, _OutputIterator>::id; 1295 1296template <class _CharT, class _OutputIterator> 1297_LIBCPP_HIDDEN 1298_OutputIterator 1299__pad_and_output(_OutputIterator __s, 1300 const _CharT* __ob, const _CharT* __op, const _CharT* __oe, 1301 ios_base& __iob, _CharT __fl) 1302{ 1303 streamsize __sz = __oe - __ob; 1304 streamsize __ns = __iob.width(); 1305 if (__ns > __sz) 1306 __ns -= __sz; 1307 else 1308 __ns = 0; 1309 for (;__ob < __op; ++__ob, ++__s) 1310 *__s = *__ob; 1311 for (; __ns; --__ns, ++__s) 1312 *__s = __fl; 1313 for (; __ob < __oe; ++__ob, ++__s) 1314 *__s = *__ob; 1315 __iob.width(0); 1316 return __s; 1317} 1318 1319#if !defined(__APPLE__) || \ 1320 (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \ 1321 (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0) 1322 1323template <class _CharT, class _Traits> 1324_LIBCPP_HIDDEN 1325ostreambuf_iterator<_CharT, _Traits> 1326__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s, 1327 const _CharT* __ob, const _CharT* __op, const _CharT* __oe, 1328 ios_base& __iob, _CharT __fl) 1329{ 1330 if (__s.__sbuf_ == nullptr) 1331 return __s; 1332 streamsize __sz = __oe - __ob; 1333 streamsize __ns = __iob.width(); 1334 if (__ns > __sz) 1335 __ns -= __sz; 1336 else 1337 __ns = 0; 1338 streamsize __np = __op - __ob; 1339 if (__np > 0) 1340 { 1341 if (__s.__sbuf_->sputn(__ob, __np) != __np) 1342 { 1343 __s.__sbuf_ = nullptr; 1344 return __s; 1345 } 1346 } 1347 if (__ns > 0) 1348 { 1349 basic_string<_CharT, _Traits> __sp(__ns, __fl); 1350 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns) 1351 { 1352 __s.__sbuf_ = nullptr; 1353 return __s; 1354 } 1355 } 1356 __np = __oe - __op; 1357 if (__np > 0) 1358 { 1359 if (__s.__sbuf_->sputn(__op, __np) != __np) 1360 { 1361 __s.__sbuf_ = nullptr; 1362 return __s; 1363 } 1364 } 1365 __iob.width(0); 1366 return __s; 1367} 1368 1369#endif 1370 1371template <class _CharT, class _OutputIterator> 1372_OutputIterator 1373num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1374 char_type __fl, bool __v) const 1375{ 1376 if ((__iob.flags() & ios_base::boolalpha) == 0) 1377 return do_put(__s, __iob, __fl, (unsigned long)__v); 1378 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc()); 1379 typedef typename numpunct<char_type>::string_type string_type; 1380#if _LIBCPP_DEBUG_LEVEL >= 2 1381 string_type __tmp(__v ? __np.truename() : __np.falsename()); 1382 string_type __nm = _VSTD::move(__tmp); 1383#else 1384 string_type __nm = __v ? __np.truename() : __np.falsename(); 1385#endif 1386 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s) 1387 *__s = *__i; 1388 return __s; 1389} 1390 1391template <class _CharT, class _OutputIterator> 1392_OutputIterator 1393num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1394 char_type __fl, long __v) const 1395{ 1396 // Stage 1 - Get number in narrow char 1397 char __fmt[6] = {'%', 0}; 1398 const char* __len = "l"; 1399 this->__format_int(__fmt+1, __len, true, __iob.flags()); 1400 const unsigned __nbuf = (numeric_limits<long>::digits / 3) 1401 + ((numeric_limits<long>::digits % 3) != 0) 1402 + 2; 1403 char __nar[__nbuf]; 1404 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); 1405 char* __ne = __nar + __nc; 1406 char* __np = this->__identify_padding(__nar, __ne, __iob); 1407 // Stage 2 - Widen __nar while adding thousands separators 1408 char_type __o[2*(__nbuf-1) - 1]; 1409 char_type* __op; // pad here 1410 char_type* __oe; // end of output 1411 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); 1412 // [__o, __oe) contains thousands_sep'd wide number 1413 // Stage 3 & 4 1414 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); 1415} 1416 1417template <class _CharT, class _OutputIterator> 1418_OutputIterator 1419num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1420 char_type __fl, long long __v) const 1421{ 1422 // Stage 1 - Get number in narrow char 1423 char __fmt[8] = {'%', 0}; 1424 const char* __len = "ll"; 1425 this->__format_int(__fmt+1, __len, true, __iob.flags()); 1426 const unsigned __nbuf = (numeric_limits<long long>::digits / 3) 1427 + ((numeric_limits<long long>::digits % 3) != 0) 1428 + 2; 1429 char __nar[__nbuf]; 1430 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); 1431 char* __ne = __nar + __nc; 1432 char* __np = this->__identify_padding(__nar, __ne, __iob); 1433 // Stage 2 - Widen __nar while adding thousands separators 1434 char_type __o[2*(__nbuf-1) - 1]; 1435 char_type* __op; // pad here 1436 char_type* __oe; // end of output 1437 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); 1438 // [__o, __oe) contains thousands_sep'd wide number 1439 // Stage 3 & 4 1440 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); 1441} 1442 1443template <class _CharT, class _OutputIterator> 1444_OutputIterator 1445num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1446 char_type __fl, unsigned long __v) const 1447{ 1448 // Stage 1 - Get number in narrow char 1449 char __fmt[6] = {'%', 0}; 1450 const char* __len = "l"; 1451 this->__format_int(__fmt+1, __len, false, __iob.flags()); 1452 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3) 1453 + ((numeric_limits<unsigned long>::digits % 3) != 0) 1454 + 1; 1455 char __nar[__nbuf]; 1456 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); 1457 char* __ne = __nar + __nc; 1458 char* __np = this->__identify_padding(__nar, __ne, __iob); 1459 // Stage 2 - Widen __nar while adding thousands separators 1460 char_type __o[2*(__nbuf-1) - 1]; 1461 char_type* __op; // pad here 1462 char_type* __oe; // end of output 1463 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); 1464 // [__o, __oe) contains thousands_sep'd wide number 1465 // Stage 3 & 4 1466 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); 1467} 1468 1469template <class _CharT, class _OutputIterator> 1470_OutputIterator 1471num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1472 char_type __fl, unsigned long long __v) const 1473{ 1474 // Stage 1 - Get number in narrow char 1475 char __fmt[8] = {'%', 0}; 1476 const char* __len = "ll"; 1477 this->__format_int(__fmt+1, __len, false, __iob.flags()); 1478 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3) 1479 + ((numeric_limits<unsigned long long>::digits % 3) != 0) 1480 + 1; 1481 char __nar[__nbuf]; 1482 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); 1483 char* __ne = __nar + __nc; 1484 char* __np = this->__identify_padding(__nar, __ne, __iob); 1485 // Stage 2 - Widen __nar while adding thousands separators 1486 char_type __o[2*(__nbuf-1) - 1]; 1487 char_type* __op; // pad here 1488 char_type* __oe; // end of output 1489 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc()); 1490 // [__o, __oe) contains thousands_sep'd wide number 1491 // Stage 3 & 4 1492 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); 1493} 1494 1495template <class _CharT, class _OutputIterator> 1496_OutputIterator 1497num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1498 char_type __fl, double __v) const 1499{ 1500 // Stage 1 - Get number in narrow char 1501 char __fmt[8] = {'%', 0}; 1502 const char* __len = ""; 1503 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags()); 1504 const unsigned __nbuf = 30; 1505 char __nar[__nbuf]; 1506 char* __nb = __nar; 1507 int __nc; 1508 if (__specify_precision) 1509 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, 1510 (int)__iob.precision(), __v); 1511 else 1512 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v); 1513 unique_ptr<char, void(*)(void*)> __nbh(0, free); 1514 if (__nc > static_cast<int>(__nbuf-1)) 1515 { 1516 if (__specify_precision) 1517 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); 1518 else 1519 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v); 1520 if (__nb == 0) 1521 __throw_bad_alloc(); 1522 __nbh.reset(__nb); 1523 } 1524 char* __ne = __nb + __nc; 1525 char* __np = this->__identify_padding(__nb, __ne, __iob); 1526 // Stage 2 - Widen __nar while adding thousands separators 1527 char_type __o[2*(__nbuf-1) - 1]; 1528 char_type* __ob = __o; 1529 unique_ptr<char_type, void(*)(void*)> __obh(0, free); 1530 if (__nb != __nar) 1531 { 1532 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type)); 1533 if (__ob == 0) 1534 __throw_bad_alloc(); 1535 __obh.reset(__ob); 1536 } 1537 char_type* __op; // pad here 1538 char_type* __oe; // end of output 1539 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); 1540 // [__o, __oe) contains thousands_sep'd wide number 1541 // Stage 3 & 4 1542 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl); 1543 return __s; 1544} 1545 1546template <class _CharT, class _OutputIterator> 1547_OutputIterator 1548num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1549 char_type __fl, long double __v) const 1550{ 1551 // Stage 1 - Get number in narrow char 1552 char __fmt[8] = {'%', 0}; 1553 const char* __len = "L"; 1554 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags()); 1555 const unsigned __nbuf = 30; 1556 char __nar[__nbuf]; 1557 char* __nb = __nar; 1558 int __nc; 1559 if (__specify_precision) 1560 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, 1561 (int)__iob.precision(), __v); 1562 else 1563 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v); 1564 unique_ptr<char, void(*)(void*)> __nbh(0, free); 1565 if (__nc > static_cast<int>(__nbuf-1)) 1566 { 1567 if (__specify_precision) 1568 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); 1569 else 1570 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v); 1571 if (__nb == 0) 1572 __throw_bad_alloc(); 1573 __nbh.reset(__nb); 1574 } 1575 char* __ne = __nb + __nc; 1576 char* __np = this->__identify_padding(__nb, __ne, __iob); 1577 // Stage 2 - Widen __nar while adding thousands separators 1578 char_type __o[2*(__nbuf-1) - 1]; 1579 char_type* __ob = __o; 1580 unique_ptr<char_type, void(*)(void*)> __obh(0, free); 1581 if (__nb != __nar) 1582 { 1583 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type)); 1584 if (__ob == 0) 1585 __throw_bad_alloc(); 1586 __obh.reset(__ob); 1587 } 1588 char_type* __op; // pad here 1589 char_type* __oe; // end of output 1590 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); 1591 // [__o, __oe) contains thousands_sep'd wide number 1592 // Stage 3 & 4 1593 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl); 1594 return __s; 1595} 1596 1597template <class _CharT, class _OutputIterator> 1598_OutputIterator 1599num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, 1600 char_type __fl, const void* __v) const 1601{ 1602 // Stage 1 - Get pointer in narrow char 1603 char __fmt[6] = "%p"; 1604 const unsigned __nbuf = 20; 1605 char __nar[__nbuf]; 1606 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v); 1607 char* __ne = __nar + __nc; 1608 char* __np = this->__identify_padding(__nar, __ne, __iob); 1609 // Stage 2 - Widen __nar 1610 char_type __o[2*(__nbuf-1) - 1]; 1611 char_type* __op; // pad here 1612 char_type* __oe; // end of output 1613 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); 1614 __ct.widen(__nar, __ne, __o); 1615 __oe = __o + (__ne - __nar); 1616 if (__np == __ne) 1617 __op = __oe; 1618 else 1619 __op = __o + (__np - __nar); 1620 // [__o, __oe) contains wide number 1621 // Stage 3 & 4 1622 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); 1623} 1624 1625_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>) 1626_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>) 1627 1628template <class _CharT, class _InputIterator> 1629_LIBCPP_HIDDEN 1630int 1631__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e, 1632 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n) 1633{ 1634 // Precondition: __n >= 1 1635 if (__b == __e) 1636 { 1637 __err |= ios_base::eofbit | ios_base::failbit; 1638 return 0; 1639 } 1640 // get first digit 1641 _CharT __c = *__b; 1642 if (!__ct.is(ctype_base::digit, __c)) 1643 { 1644 __err |= ios_base::failbit; 1645 return 0; 1646 } 1647 int __r = __ct.narrow(__c, 0) - '0'; 1648 for (++__b, (void) --__n; __b != __e && __n > 0; ++__b, (void) --__n) 1649 { 1650 // get next digit 1651 __c = *__b; 1652 if (!__ct.is(ctype_base::digit, __c)) 1653 return __r; 1654 __r = __r * 10 + __ct.narrow(__c, 0) - '0'; 1655 } 1656 if (__b == __e) 1657 __err |= ios_base::eofbit; 1658 return __r; 1659} 1660 1661class _LIBCPP_TYPE_VIS time_base 1662{ 1663public: 1664 enum dateorder {no_order, dmy, mdy, ymd, ydm}; 1665}; 1666 1667template <class _CharT> 1668class _LIBCPP_TEMPLATE_VIS __time_get_c_storage 1669{ 1670protected: 1671 typedef basic_string<_CharT> string_type; 1672 1673 virtual const string_type* __weeks() const; 1674 virtual const string_type* __months() const; 1675 virtual const string_type* __am_pm() const; 1676 virtual const string_type& __c() const; 1677 virtual const string_type& __r() const; 1678 virtual const string_type& __x() const; 1679 virtual const string_type& __X() const; 1680 1681 _LIBCPP_ALWAYS_INLINE 1682 ~__time_get_c_storage() {} 1683}; 1684 1685template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> > 1686class _LIBCPP_TEMPLATE_VIS time_get 1687 : public locale::facet, 1688 public time_base, 1689 private __time_get_c_storage<_CharT> 1690{ 1691public: 1692 typedef _CharT char_type; 1693 typedef _InputIterator iter_type; 1694 typedef time_base::dateorder dateorder; 1695 typedef basic_string<char_type> string_type; 1696 1697 _LIBCPP_ALWAYS_INLINE 1698 explicit time_get(size_t __refs = 0) 1699 : locale::facet(__refs) {} 1700 1701 _LIBCPP_ALWAYS_INLINE 1702 dateorder date_order() const 1703 { 1704 return this->do_date_order(); 1705 } 1706 1707 _LIBCPP_ALWAYS_INLINE 1708 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob, 1709 ios_base::iostate& __err, tm* __tm) const 1710 { 1711 return do_get_time(__b, __e, __iob, __err, __tm); 1712 } 1713 1714 _LIBCPP_ALWAYS_INLINE 1715 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob, 1716 ios_base::iostate& __err, tm* __tm) const 1717 { 1718 return do_get_date(__b, __e, __iob, __err, __tm); 1719 } 1720 1721 _LIBCPP_ALWAYS_INLINE 1722 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob, 1723 ios_base::iostate& __err, tm* __tm) const 1724 { 1725 return do_get_weekday(__b, __e, __iob, __err, __tm); 1726 } 1727 1728 _LIBCPP_ALWAYS_INLINE 1729 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob, 1730 ios_base::iostate& __err, tm* __tm) const 1731 { 1732 return do_get_monthname(__b, __e, __iob, __err, __tm); 1733 } 1734 1735 _LIBCPP_ALWAYS_INLINE 1736 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob, 1737 ios_base::iostate& __err, tm* __tm) const 1738 { 1739 return do_get_year(__b, __e, __iob, __err, __tm); 1740 } 1741 1742 _LIBCPP_ALWAYS_INLINE 1743 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 1744 ios_base::iostate& __err, tm *__tm, 1745 char __fmt, char __mod = 0) const 1746 { 1747 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod); 1748 } 1749 1750 iter_type get(iter_type __b, iter_type __e, ios_base& __iob, 1751 ios_base::iostate& __err, tm* __tm, 1752 const char_type* __fmtb, const char_type* __fmte) const; 1753 1754 static locale::id id; 1755 1756protected: 1757 _LIBCPP_ALWAYS_INLINE 1758 ~time_get() {} 1759 1760 virtual dateorder do_date_order() const; 1761 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob, 1762 ios_base::iostate& __err, tm* __tm) const; 1763 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob, 1764 ios_base::iostate& __err, tm* __tm) const; 1765 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, 1766 ios_base::iostate& __err, tm* __tm) const; 1767 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, 1768 ios_base::iostate& __err, tm* __tm) const; 1769 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob, 1770 ios_base::iostate& __err, tm* __tm) const; 1771 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, 1772 ios_base::iostate& __err, tm* __tm, 1773 char __fmt, char __mod) const; 1774private: 1775 void __get_white_space(iter_type& __b, iter_type __e, 1776 ios_base::iostate& __err, const ctype<char_type>& __ct) const; 1777 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err, 1778 const ctype<char_type>& __ct) const; 1779 1780 void __get_weekdayname(int& __m, 1781 iter_type& __b, iter_type __e, 1782 ios_base::iostate& __err, 1783 const ctype<char_type>& __ct) const; 1784 void __get_monthname(int& __m, 1785 iter_type& __b, iter_type __e, 1786 ios_base::iostate& __err, 1787 const ctype<char_type>& __ct) const; 1788 void __get_day(int& __d, 1789 iter_type& __b, iter_type __e, 1790 ios_base::iostate& __err, 1791 const ctype<char_type>& __ct) const; 1792 void __get_month(int& __m, 1793 iter_type& __b, iter_type __e, 1794 ios_base::iostate& __err, 1795 const ctype<char_type>& __ct) const; 1796 void __get_year(int& __y, 1797 iter_type& __b, iter_type __e, 1798 ios_base::iostate& __err, 1799 const ctype<char_type>& __ct) const; 1800 void __get_year4(int& __y, 1801 iter_type& __b, iter_type __e, 1802 ios_base::iostate& __err, 1803 const ctype<char_type>& __ct) const; 1804 void __get_hour(int& __d, 1805 iter_type& __b, iter_type __e, 1806 ios_base::iostate& __err, 1807 const ctype<char_type>& __ct) const; 1808 void __get_12_hour(int& __h, 1809 iter_type& __b, iter_type __e, 1810 ios_base::iostate& __err, 1811 const ctype<char_type>& __ct) const; 1812 void __get_am_pm(int& __h, 1813 iter_type& __b, iter_type __e, 1814 ios_base::iostate& __err, 1815 const ctype<char_type>& __ct) const; 1816 void __get_minute(int& __m, 1817 iter_type& __b, iter_type __e, 1818 ios_base::iostate& __err, 1819 const ctype<char_type>& __ct) const; 1820 void __get_second(int& __s, 1821 iter_type& __b, iter_type __e, 1822 ios_base::iostate& __err, 1823 const ctype<char_type>& __ct) const; 1824 void __get_weekday(int& __w, 1825 iter_type& __b, iter_type __e, 1826 ios_base::iostate& __err, 1827 const ctype<char_type>& __ct) const; 1828 void __get_day_year_num(int& __w, 1829 iter_type& __b, iter_type __e, 1830 ios_base::iostate& __err, 1831 const ctype<char_type>& __ct) const; 1832}; 1833 1834template <class _CharT, class _InputIterator> 1835locale::id 1836time_get<_CharT, _InputIterator>::id; 1837 1838// time_get primitives 1839 1840template <class _CharT, class _InputIterator> 1841void 1842time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w, 1843 iter_type& __b, iter_type __e, 1844 ios_base::iostate& __err, 1845 const ctype<char_type>& __ct) const 1846{ 1847 // Note: ignoring case comes from the POSIX strptime spec 1848 const string_type* __wk = this->__weeks(); 1849 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk; 1850 if (__i < 14) 1851 __w = __i % 7; 1852} 1853 1854template <class _CharT, class _InputIterator> 1855void 1856time_get<_CharT, _InputIterator>::__get_monthname(int& __m, 1857 iter_type& __b, iter_type __e, 1858 ios_base::iostate& __err, 1859 const ctype<char_type>& __ct) const 1860{ 1861 // Note: ignoring case comes from the POSIX strptime spec 1862 const string_type* __month = this->__months(); 1863 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month; 1864 if (__i < 24) 1865 __m = __i % 12; 1866} 1867 1868template <class _CharT, class _InputIterator> 1869void 1870time_get<_CharT, _InputIterator>::__get_day(int& __d, 1871 iter_type& __b, iter_type __e, 1872 ios_base::iostate& __err, 1873 const ctype<char_type>& __ct) const 1874{ 1875 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); 1876 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31) 1877 __d = __t; 1878 else 1879 __err |= ios_base::failbit; 1880} 1881 1882template <class _CharT, class _InputIterator> 1883void 1884time_get<_CharT, _InputIterator>::__get_month(int& __m, 1885 iter_type& __b, iter_type __e, 1886 ios_base::iostate& __err, 1887 const ctype<char_type>& __ct) const 1888{ 1889 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1; 1890 if (!(__err & ios_base::failbit) && __t <= 11) 1891 __m = __t; 1892 else 1893 __err |= ios_base::failbit; 1894} 1895 1896template <class _CharT, class _InputIterator> 1897void 1898time_get<_CharT, _InputIterator>::__get_year(int& __y, 1899 iter_type& __b, iter_type __e, 1900 ios_base::iostate& __err, 1901 const ctype<char_type>& __ct) const 1902{ 1903 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4); 1904 if (!(__err & ios_base::failbit)) 1905 { 1906 if (__t < 69) 1907 __t += 2000; 1908 else if (69 <= __t && __t <= 99) 1909 __t += 1900; 1910 __y = __t - 1900; 1911 } 1912} 1913 1914template <class _CharT, class _InputIterator> 1915void 1916time_get<_CharT, _InputIterator>::__get_year4(int& __y, 1917 iter_type& __b, iter_type __e, 1918 ios_base::iostate& __err, 1919 const ctype<char_type>& __ct) const 1920{ 1921 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4); 1922 if (!(__err & ios_base::failbit)) 1923 __y = __t - 1900; 1924} 1925 1926template <class _CharT, class _InputIterator> 1927void 1928time_get<_CharT, _InputIterator>::__get_hour(int& __h, 1929 iter_type& __b, iter_type __e, 1930 ios_base::iostate& __err, 1931 const ctype<char_type>& __ct) const 1932{ 1933 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); 1934 if (!(__err & ios_base::failbit) && __t <= 23) 1935 __h = __t; 1936 else 1937 __err |= ios_base::failbit; 1938} 1939 1940template <class _CharT, class _InputIterator> 1941void 1942time_get<_CharT, _InputIterator>::__get_12_hour(int& __h, 1943 iter_type& __b, iter_type __e, 1944 ios_base::iostate& __err, 1945 const ctype<char_type>& __ct) const 1946{ 1947 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); 1948 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12) 1949 __h = __t; 1950 else 1951 __err |= ios_base::failbit; 1952} 1953 1954template <class _CharT, class _InputIterator> 1955void 1956time_get<_CharT, _InputIterator>::__get_minute(int& __m, 1957 iter_type& __b, iter_type __e, 1958 ios_base::iostate& __err, 1959 const ctype<char_type>& __ct) const 1960{ 1961 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); 1962 if (!(__err & ios_base::failbit) && __t <= 59) 1963 __m = __t; 1964 else 1965 __err |= ios_base::failbit; 1966} 1967 1968template <class _CharT, class _InputIterator> 1969void 1970time_get<_CharT, _InputIterator>::__get_second(int& __s, 1971 iter_type& __b, iter_type __e, 1972 ios_base::iostate& __err, 1973 const ctype<char_type>& __ct) const 1974{ 1975 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2); 1976 if (!(__err & ios_base::failbit) && __t <= 60) 1977 __s = __t; 1978 else 1979 __err |= ios_base::failbit; 1980} 1981 1982template <class _CharT, class _InputIterator> 1983void 1984time_get<_CharT, _InputIterator>::__get_weekday(int& __w, 1985 iter_type& __b, iter_type __e, 1986 ios_base::iostate& __err, 1987 const ctype<char_type>& __ct) const 1988{ 1989 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1); 1990 if (!(__err & ios_base::failbit) && __t <= 6) 1991 __w = __t; 1992 else 1993 __err |= ios_base::failbit; 1994} 1995 1996template <class _CharT, class _InputIterator> 1997void 1998time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d, 1999 iter_type& __b, iter_type __e, 2000 ios_base::iostate& __err, 2001 const ctype<char_type>& __ct) const 2002{ 2003 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3); 2004 if (!(__err & ios_base::failbit) && __t <= 365) 2005 __d = __t; 2006 else 2007 __err |= ios_base::failbit; 2008} 2009 2010template <class _CharT, class _InputIterator> 2011void 2012time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e, 2013 ios_base::iostate& __err, 2014 const ctype<char_type>& __ct) const 2015{ 2016 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) 2017 ; 2018 if (__b == __e) 2019 __err |= ios_base::eofbit; 2020} 2021 2022template <class _CharT, class _InputIterator> 2023void 2024time_get<_CharT, _InputIterator>::__get_am_pm(int& __h, 2025 iter_type& __b, iter_type __e, 2026 ios_base::iostate& __err, 2027 const ctype<char_type>& __ct) const 2028{ 2029 const string_type* __ap = this->__am_pm(); 2030 if (__ap[0].size() + __ap[1].size() == 0) 2031 { 2032 __err |= ios_base::failbit; 2033 return; 2034 } 2035 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap; 2036 if (__i == 0 && __h == 12) 2037 __h = 0; 2038 else if (__i == 1 && __h < 12) 2039 __h += 12; 2040} 2041 2042template <class _CharT, class _InputIterator> 2043void 2044time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e, 2045 ios_base::iostate& __err, 2046 const ctype<char_type>& __ct) const 2047{ 2048 if (__b == __e) 2049 { 2050 __err |= ios_base::eofbit | ios_base::failbit; 2051 return; 2052 } 2053 if (__ct.narrow(*__b, 0) != '%') 2054 __err |= ios_base::failbit; 2055 else if(++__b == __e) 2056 __err |= ios_base::eofbit; 2057} 2058 2059// time_get end primitives 2060 2061template <class _CharT, class _InputIterator> 2062_InputIterator 2063time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e, 2064 ios_base& __iob, 2065 ios_base::iostate& __err, tm* __tm, 2066 const char_type* __fmtb, const char_type* __fmte) const 2067{ 2068 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); 2069 __err = ios_base::goodbit; 2070 while (__fmtb != __fmte && __err == ios_base::goodbit) 2071 { 2072 if (__b == __e) 2073 { 2074 __err = ios_base::failbit; 2075 break; 2076 } 2077 if (__ct.narrow(*__fmtb, 0) == '%') 2078 { 2079 if (++__fmtb == __fmte) 2080 { 2081 __err = ios_base::failbit; 2082 break; 2083 } 2084 char __cmd = __ct.narrow(*__fmtb, 0); 2085 char __opt = '\0'; 2086 if (__cmd == 'E' || __cmd == '0') 2087 { 2088 if (++__fmtb == __fmte) 2089 { 2090 __err = ios_base::failbit; 2091 break; 2092 } 2093 __opt = __cmd; 2094 __cmd = __ct.narrow(*__fmtb, 0); 2095 } 2096 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt); 2097 ++__fmtb; 2098 } 2099 else if (__ct.is(ctype_base::space, *__fmtb)) 2100 { 2101 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb) 2102 ; 2103 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) 2104 ; 2105 } 2106 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb)) 2107 { 2108 ++__b; 2109 ++__fmtb; 2110 } 2111 else 2112 __err = ios_base::failbit; 2113 } 2114 if (__b == __e) 2115 __err |= ios_base::eofbit; 2116 return __b; 2117} 2118 2119template <class _CharT, class _InputIterator> 2120typename time_get<_CharT, _InputIterator>::dateorder 2121time_get<_CharT, _InputIterator>::do_date_order() const 2122{ 2123 return mdy; 2124} 2125 2126template <class _CharT, class _InputIterator> 2127_InputIterator 2128time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e, 2129 ios_base& __iob, 2130 ios_base::iostate& __err, 2131 tm* __tm) const 2132{ 2133 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; 2134 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0])); 2135} 2136 2137template <class _CharT, class _InputIterator> 2138_InputIterator 2139time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e, 2140 ios_base& __iob, 2141 ios_base::iostate& __err, 2142 tm* __tm) const 2143{ 2144 const string_type& __fmt = this->__x(); 2145 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size()); 2146} 2147 2148template <class _CharT, class _InputIterator> 2149_InputIterator 2150time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e, 2151 ios_base& __iob, 2152 ios_base::iostate& __err, 2153 tm* __tm) const 2154{ 2155 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); 2156 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); 2157 return __b; 2158} 2159 2160template <class _CharT, class _InputIterator> 2161_InputIterator 2162time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e, 2163 ios_base& __iob, 2164 ios_base::iostate& __err, 2165 tm* __tm) const 2166{ 2167 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); 2168 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); 2169 return __b; 2170} 2171 2172template <class _CharT, class _InputIterator> 2173_InputIterator 2174time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e, 2175 ios_base& __iob, 2176 ios_base::iostate& __err, 2177 tm* __tm) const 2178{ 2179 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); 2180 __get_year(__tm->tm_year, __b, __e, __err, __ct); 2181 return __b; 2182} 2183 2184template <class _CharT, class _InputIterator> 2185_InputIterator 2186time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, 2187 ios_base& __iob, 2188 ios_base::iostate& __err, tm* __tm, 2189 char __fmt, char) const 2190{ 2191 __err = ios_base::goodbit; 2192 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); 2193 switch (__fmt) 2194 { 2195 case 'a': 2196 case 'A': 2197 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); 2198 break; 2199 case 'b': 2200 case 'B': 2201 case 'h': 2202 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); 2203 break; 2204 case 'c': 2205 { 2206 const string_type& __fm = this->__c(); 2207 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); 2208 } 2209 break; 2210 case 'd': 2211 case 'e': 2212 __get_day(__tm->tm_mday, __b, __e, __err, __ct); 2213 break; 2214 case 'D': 2215 { 2216 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'}; 2217 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0])); 2218 } 2219 break; 2220 case 'F': 2221 { 2222 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'}; 2223 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0])); 2224 } 2225 break; 2226 case 'H': 2227 __get_hour(__tm->tm_hour, __b, __e, __err, __ct); 2228 break; 2229 case 'I': 2230 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct); 2231 break; 2232 case 'j': 2233 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct); 2234 break; 2235 case 'm': 2236 __get_month(__tm->tm_mon, __b, __e, __err, __ct); 2237 break; 2238 case 'M': 2239 __get_minute(__tm->tm_min, __b, __e, __err, __ct); 2240 break; 2241 case 'n': 2242 case 't': 2243 __get_white_space(__b, __e, __err, __ct); 2244 break; 2245 case 'p': 2246 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct); 2247 break; 2248 case 'r': 2249 { 2250 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'}; 2251 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0])); 2252 } 2253 break; 2254 case 'R': 2255 { 2256 const char_type __fm[] = {'%', 'H', ':', '%', 'M'}; 2257 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0])); 2258 } 2259 break; 2260 case 'S': 2261 __get_second(__tm->tm_sec, __b, __e, __err, __ct); 2262 break; 2263 case 'T': 2264 { 2265 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; 2266 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0])); 2267 } 2268 break; 2269 case 'w': 2270 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct); 2271 break; 2272 case 'x': 2273 return do_get_date(__b, __e, __iob, __err, __tm); 2274 case 'X': 2275 { 2276 const string_type& __fm = this->__X(); 2277 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); 2278 } 2279 break; 2280 case 'y': 2281 __get_year(__tm->tm_year, __b, __e, __err, __ct); 2282 break; 2283 case 'Y': 2284 __get_year4(__tm->tm_year, __b, __e, __err, __ct); 2285 break; 2286 case '%': 2287 __get_percent(__b, __e, __err, __ct); 2288 break; 2289 default: 2290 __err |= ios_base::failbit; 2291 } 2292 return __b; 2293} 2294 2295_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>) 2296_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>) 2297 2298class _LIBCPP_TYPE_VIS __time_get 2299{ 2300protected: 2301 locale_t __loc_; 2302 2303 __time_get(const char* __nm); 2304 __time_get(const string& __nm); 2305 ~__time_get(); 2306}; 2307 2308template <class _CharT> 2309class _LIBCPP_TEMPLATE_VIS __time_get_storage 2310 : public __time_get 2311{ 2312protected: 2313 typedef basic_string<_CharT> string_type; 2314 2315 string_type __weeks_[14]; 2316 string_type __months_[24]; 2317 string_type __am_pm_[2]; 2318 string_type __c_; 2319 string_type __r_; 2320 string_type __x_; 2321 string_type __X_; 2322 2323 explicit __time_get_storage(const char* __nm); 2324 explicit __time_get_storage(const string& __nm); 2325 2326 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {} 2327 2328 time_base::dateorder __do_date_order() const; 2329 2330private: 2331 void init(const ctype<_CharT>&); 2332 string_type __analyze(char __fmt, const ctype<_CharT>&); 2333}; 2334 2335template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> > 2336class _LIBCPP_TEMPLATE_VIS time_get_byname 2337 : public time_get<_CharT, _InputIterator>, 2338 private __time_get_storage<_CharT> 2339{ 2340public: 2341 typedef time_base::dateorder dateorder; 2342 typedef _InputIterator iter_type; 2343 typedef _CharT char_type; 2344 typedef basic_string<char_type> string_type; 2345 2346 _LIBCPP_INLINE_VISIBILITY 2347 explicit time_get_byname(const char* __nm, size_t __refs = 0) 2348 : time_get<_CharT, _InputIterator>(__refs), 2349 __time_get_storage<_CharT>(__nm) {} 2350 _LIBCPP_INLINE_VISIBILITY 2351 explicit time_get_byname(const string& __nm, size_t __refs = 0) 2352 : time_get<_CharT, _InputIterator>(__refs), 2353 __time_get_storage<_CharT>(__nm) {} 2354 2355protected: 2356 _LIBCPP_INLINE_VISIBILITY 2357 ~time_get_byname() {} 2358 2359 _LIBCPP_INLINE_VISIBILITY 2360 virtual dateorder do_date_order() const {return this->__do_date_order();} 2361private: 2362 _LIBCPP_INLINE_VISIBILITY 2363 virtual const string_type* __weeks() const {return this->__weeks_;} 2364 _LIBCPP_INLINE_VISIBILITY 2365 virtual const string_type* __months() const {return this->__months_;} 2366 _LIBCPP_INLINE_VISIBILITY 2367 virtual const string_type* __am_pm() const {return this->__am_pm_;} 2368 _LIBCPP_INLINE_VISIBILITY 2369 virtual const string_type& __c() const {return this->__c_;} 2370 _LIBCPP_INLINE_VISIBILITY 2371 virtual const string_type& __r() const {return this->__r_;} 2372 _LIBCPP_INLINE_VISIBILITY 2373 virtual const string_type& __x() const {return this->__x_;} 2374 _LIBCPP_INLINE_VISIBILITY 2375 virtual const string_type& __X() const {return this->__X_;} 2376}; 2377 2378_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>) 2379_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>) 2380 2381class _LIBCPP_TYPE_VIS __time_put 2382{ 2383 locale_t __loc_; 2384protected: 2385 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} 2386 __time_put(const char* __nm); 2387 __time_put(const string& __nm); 2388 ~__time_put(); 2389 void __do_put(char* __nb, char*& __ne, const tm* __tm, 2390 char __fmt, char __mod) const; 2391 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, 2392 char __fmt, char __mod) const; 2393}; 2394 2395template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> > 2396class _LIBCPP_TEMPLATE_VIS time_put 2397 : public locale::facet, 2398 private __time_put 2399{ 2400public: 2401 typedef _CharT char_type; 2402 typedef _OutputIterator iter_type; 2403 2404 _LIBCPP_ALWAYS_INLINE 2405 explicit time_put(size_t __refs = 0) 2406 : locale::facet(__refs) {} 2407 2408 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, 2409 const char_type* __pb, const char_type* __pe) const; 2410 2411 _LIBCPP_ALWAYS_INLINE 2412 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, 2413 const tm* __tm, char __fmt, char __mod = 0) const 2414 { 2415 return do_put(__s, __iob, __fl, __tm, __fmt, __mod); 2416 } 2417 2418 static locale::id id; 2419 2420protected: 2421 _LIBCPP_ALWAYS_INLINE 2422 ~time_put() {} 2423 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, 2424 char __fmt, char __mod) const; 2425 2426 _LIBCPP_ALWAYS_INLINE 2427 explicit time_put(const char* __nm, size_t __refs) 2428 : locale::facet(__refs), 2429 __time_put(__nm) {} 2430 _LIBCPP_ALWAYS_INLINE 2431 explicit time_put(const string& __nm, size_t __refs) 2432 : locale::facet(__refs), 2433 __time_put(__nm) {} 2434}; 2435 2436template <class _CharT, class _OutputIterator> 2437locale::id 2438time_put<_CharT, _OutputIterator>::id; 2439 2440template <class _CharT, class _OutputIterator> 2441_OutputIterator 2442time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob, 2443 char_type __fl, const tm* __tm, 2444 const char_type* __pb, 2445 const char_type* __pe) const 2446{ 2447 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc()); 2448 for (; __pb != __pe; ++__pb) 2449 { 2450 if (__ct.narrow(*__pb, 0) == '%') 2451 { 2452 if (++__pb == __pe) 2453 { 2454 *__s++ = __pb[-1]; 2455 break; 2456 } 2457 char __mod = 0; 2458 char __fmt = __ct.narrow(*__pb, 0); 2459 if (__fmt == 'E' || __fmt == 'O') 2460 { 2461 if (++__pb == __pe) 2462 { 2463 *__s++ = __pb[-2]; 2464 *__s++ = __pb[-1]; 2465 break; 2466 } 2467 __mod = __fmt; 2468 __fmt = __ct.narrow(*__pb, 0); 2469 } 2470 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod); 2471 } 2472 else 2473 *__s++ = *__pb; 2474 } 2475 return __s; 2476} 2477 2478template <class _CharT, class _OutputIterator> 2479_OutputIterator 2480time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&, 2481 char_type, const tm* __tm, 2482 char __fmt, char __mod) const 2483{ 2484 char_type __nar[100]; 2485 char_type* __nb = __nar; 2486 char_type* __ne = __nb + 100; 2487 __do_put(__nb, __ne, __tm, __fmt, __mod); 2488 return _VSTD::copy(__nb, __ne, __s); 2489} 2490 2491_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>) 2492_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>) 2493 2494template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> > 2495class _LIBCPP_TEMPLATE_VIS time_put_byname 2496 : public time_put<_CharT, _OutputIterator> 2497{ 2498public: 2499 _LIBCPP_ALWAYS_INLINE 2500 explicit time_put_byname(const char* __nm, size_t __refs = 0) 2501 : time_put<_CharT, _OutputIterator>(__nm, __refs) {} 2502 2503 _LIBCPP_ALWAYS_INLINE 2504 explicit time_put_byname(const string& __nm, size_t __refs = 0) 2505 : time_put<_CharT, _OutputIterator>(__nm, __refs) {} 2506 2507protected: 2508 _LIBCPP_ALWAYS_INLINE 2509 ~time_put_byname() {} 2510}; 2511 2512_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>) 2513_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>) 2514 2515// money_base 2516 2517class _LIBCPP_TYPE_VIS money_base 2518{ 2519public: 2520 enum part {none, space, symbol, sign, value}; 2521 struct pattern {char field[4];}; 2522 2523 _LIBCPP_ALWAYS_INLINE money_base() {} 2524}; 2525 2526// moneypunct 2527 2528template <class _CharT, bool _International = false> 2529class _LIBCPP_TEMPLATE_VIS moneypunct 2530 : public locale::facet, 2531 public money_base 2532{ 2533public: 2534 typedef _CharT char_type; 2535 typedef basic_string<char_type> string_type; 2536 2537 _LIBCPP_ALWAYS_INLINE 2538 explicit moneypunct(size_t __refs = 0) 2539 : locale::facet(__refs) {} 2540 2541 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} 2542 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} 2543 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} 2544 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();} 2545 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();} 2546 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();} 2547 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();} 2548 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();} 2549 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();} 2550 2551 static locale::id id; 2552 static const bool intl = _International; 2553 2554protected: 2555 _LIBCPP_ALWAYS_INLINE 2556 ~moneypunct() {} 2557 2558 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();} 2559 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();} 2560 virtual string do_grouping() const {return string();} 2561 virtual string_type do_curr_symbol() const {return string_type();} 2562 virtual string_type do_positive_sign() const {return string_type();} 2563 virtual string_type do_negative_sign() const {return string_type(1, '-');} 2564 virtual int do_frac_digits() const {return 0;} 2565 virtual pattern do_pos_format() const 2566 {pattern __p = {{symbol, sign, none, value}}; return __p;} 2567 virtual pattern do_neg_format() const 2568 {pattern __p = {{symbol, sign, none, value}}; return __p;} 2569}; 2570 2571template <class _CharT, bool _International> 2572locale::id 2573moneypunct<_CharT, _International>::id; 2574 2575template <class _CharT, bool _International> 2576const bool 2577moneypunct<_CharT, _International>::intl; 2578 2579_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>) 2580_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>) 2581_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>) 2582_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>) 2583 2584// moneypunct_byname 2585 2586template <class _CharT, bool _International = false> 2587class _LIBCPP_TEMPLATE_VIS moneypunct_byname 2588 : public moneypunct<_CharT, _International> 2589{ 2590public: 2591 typedef money_base::pattern pattern; 2592 typedef _CharT char_type; 2593 typedef basic_string<char_type> string_type; 2594 2595 _LIBCPP_ALWAYS_INLINE 2596 explicit moneypunct_byname(const char* __nm, size_t __refs = 0) 2597 : moneypunct<_CharT, _International>(__refs) {init(__nm);} 2598 2599 _LIBCPP_ALWAYS_INLINE 2600 explicit moneypunct_byname(const string& __nm, size_t __refs = 0) 2601 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());} 2602 2603protected: 2604 _LIBCPP_ALWAYS_INLINE 2605 ~moneypunct_byname() {} 2606 2607 virtual char_type do_decimal_point() const {return __decimal_point_;} 2608 virtual char_type do_thousands_sep() const {return __thousands_sep_;} 2609 virtual string do_grouping() const {return __grouping_;} 2610 virtual string_type do_curr_symbol() const {return __curr_symbol_;} 2611 virtual string_type do_positive_sign() const {return __positive_sign_;} 2612 virtual string_type do_negative_sign() const {return __negative_sign_;} 2613 virtual int do_frac_digits() const {return __frac_digits_;} 2614 virtual pattern do_pos_format() const {return __pos_format_;} 2615 virtual pattern do_neg_format() const {return __neg_format_;} 2616 2617private: 2618 char_type __decimal_point_; 2619 char_type __thousands_sep_; 2620 string __grouping_; 2621 string_type __curr_symbol_; 2622 string_type __positive_sign_; 2623 string_type __negative_sign_; 2624 int __frac_digits_; 2625 pattern __pos_format_; 2626 pattern __neg_format_; 2627 2628 void init(const char*); 2629}; 2630 2631template<> void moneypunct_byname<char, false>::init(const char*); 2632template<> void moneypunct_byname<char, true>::init(const char*); 2633template<> void moneypunct_byname<wchar_t, false>::init(const char*); 2634template<> void moneypunct_byname<wchar_t, true>::init(const char*); 2635 2636_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>) 2637_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>) 2638_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>) 2639_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>) 2640 2641// money_get 2642 2643template <class _CharT> 2644class __money_get 2645{ 2646protected: 2647 typedef _CharT char_type; 2648 typedef basic_string<char_type> string_type; 2649 2650 _LIBCPP_ALWAYS_INLINE __money_get() {} 2651 2652 static void __gather_info(bool __intl, const locale& __loc, 2653 money_base::pattern& __pat, char_type& __dp, 2654 char_type& __ts, string& __grp, 2655 string_type& __sym, string_type& __psn, 2656 string_type& __nsn, int& __fd); 2657}; 2658 2659template <class _CharT> 2660void 2661__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc, 2662 money_base::pattern& __pat, char_type& __dp, 2663 char_type& __ts, string& __grp, 2664 string_type& __sym, string_type& __psn, 2665 string_type& __nsn, int& __fd) 2666{ 2667 if (__intl) 2668 { 2669 const moneypunct<char_type, true>& __mp = 2670 use_facet<moneypunct<char_type, true> >(__loc); 2671 __pat = __mp.neg_format(); 2672 __nsn = __mp.negative_sign(); 2673 __psn = __mp.positive_sign(); 2674 __dp = __mp.decimal_point(); 2675 __ts = __mp.thousands_sep(); 2676 __grp = __mp.grouping(); 2677 __sym = __mp.curr_symbol(); 2678 __fd = __mp.frac_digits(); 2679 } 2680 else 2681 { 2682 const moneypunct<char_type, false>& __mp = 2683 use_facet<moneypunct<char_type, false> >(__loc); 2684 __pat = __mp.neg_format(); 2685 __nsn = __mp.negative_sign(); 2686 __psn = __mp.positive_sign(); 2687 __dp = __mp.decimal_point(); 2688 __ts = __mp.thousands_sep(); 2689 __grp = __mp.grouping(); 2690 __sym = __mp.curr_symbol(); 2691 __fd = __mp.frac_digits(); 2692 } 2693} 2694 2695_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>) 2696_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>) 2697 2698template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> > 2699class _LIBCPP_TEMPLATE_VIS money_get 2700 : public locale::facet, 2701 private __money_get<_CharT> 2702{ 2703public: 2704 typedef _CharT char_type; 2705 typedef _InputIterator iter_type; 2706 typedef basic_string<char_type> string_type; 2707 2708 _LIBCPP_ALWAYS_INLINE 2709 explicit money_get(size_t __refs = 0) 2710 : locale::facet(__refs) {} 2711 2712 _LIBCPP_ALWAYS_INLINE 2713 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, 2714 ios_base::iostate& __err, long double& __v) const 2715 { 2716 return do_get(__b, __e, __intl, __iob, __err, __v); 2717 } 2718 2719 _LIBCPP_ALWAYS_INLINE 2720 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, 2721 ios_base::iostate& __err, string_type& __v) const 2722 { 2723 return do_get(__b, __e, __intl, __iob, __err, __v); 2724 } 2725 2726 static locale::id id; 2727 2728protected: 2729 2730 _LIBCPP_ALWAYS_INLINE 2731 ~money_get() {} 2732 2733 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl, 2734 ios_base& __iob, ios_base::iostate& __err, 2735 long double& __v) const; 2736 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl, 2737 ios_base& __iob, ios_base::iostate& __err, 2738 string_type& __v) const; 2739 2740private: 2741 static bool __do_get(iter_type& __b, iter_type __e, 2742 bool __intl, const locale& __loc, 2743 ios_base::fmtflags __flags, ios_base::iostate& __err, 2744 bool& __neg, const ctype<char_type>& __ct, 2745 unique_ptr<char_type, void(*)(void*)>& __wb, 2746 char_type*& __wn, char_type* __we); 2747}; 2748 2749template <class _CharT, class _InputIterator> 2750locale::id 2751money_get<_CharT, _InputIterator>::id; 2752 2753_LIBCPP_FUNC_VIS void __do_nothing(void*); 2754 2755template <class _Tp> 2756_LIBCPP_HIDDEN 2757void 2758__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e) 2759{ 2760 bool __owns = __b.get_deleter() != __do_nothing; 2761 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp); 2762 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ? 2763 2 * __cur_cap : numeric_limits<size_t>::max(); 2764 if (__new_cap == 0) 2765 __new_cap = sizeof(_Tp); 2766 size_t __n_off = static_cast<size_t>(__n - __b.get()); 2767 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap); 2768 if (__t == 0) 2769 __throw_bad_alloc(); 2770 if (__owns) 2771 __b.release(); 2772 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free); 2773 __new_cap /= sizeof(_Tp); 2774 __n = __b.get() + __n_off; 2775 __e = __b.get() + __new_cap; 2776} 2777 2778// true == success 2779template <class _CharT, class _InputIterator> 2780bool 2781money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e, 2782 bool __intl, const locale& __loc, 2783 ios_base::fmtflags __flags, 2784 ios_base::iostate& __err, 2785 bool& __neg, 2786 const ctype<char_type>& __ct, 2787 unique_ptr<char_type, void(*)(void*)>& __wb, 2788 char_type*& __wn, char_type* __we) 2789{ 2790 const unsigned __bz = 100; 2791 unsigned __gbuf[__bz]; 2792 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing); 2793 unsigned* __gn = __gb.get(); 2794 unsigned* __ge = __gn + __bz; 2795 money_base::pattern __pat; 2796 char_type __dp; 2797 char_type __ts; 2798 string __grp; 2799 string_type __sym; 2800 string_type __psn; 2801 string_type __nsn; 2802 // Capture the spaces read into money_base::{space,none} so they 2803 // can be compared to initial spaces in __sym. 2804 string_type __spaces; 2805 int __fd; 2806 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, 2807 __sym, __psn, __nsn, __fd); 2808 const string_type* __trailing_sign = 0; 2809 __wn = __wb.get(); 2810 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) 2811 { 2812 switch (__pat.field[__p]) 2813 { 2814 case money_base::space: 2815 if (__p != 3) 2816 { 2817 if (__ct.is(ctype_base::space, *__b)) 2818 __spaces.push_back(*__b++); 2819 else 2820 { 2821 __err |= ios_base::failbit; 2822 return false; 2823 } 2824 } 2825 // drop through 2826 case money_base::none: 2827 if (__p != 3) 2828 { 2829 while (__b != __e && __ct.is(ctype_base::space, *__b)) 2830 __spaces.push_back(*__b++); 2831 } 2832 break; 2833 case money_base::sign: 2834 if (__psn.size() + __nsn.size() > 0) 2835 { 2836 if (__psn.size() == 0 || __nsn.size() == 0) 2837 { // sign is optional 2838 if (__psn.size() > 0) 2839 { // __nsn.size() == 0 2840 if (*__b == __psn[0]) 2841 { 2842 ++__b; 2843 if (__psn.size() > 1) 2844 __trailing_sign = &__psn; 2845 } 2846 else 2847 __neg = true; 2848 } 2849 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0 2850 { 2851 ++__b; 2852 __neg = true; 2853 if (__nsn.size() > 1) 2854 __trailing_sign = &__nsn; 2855 } 2856 } 2857 else // sign is required 2858 { 2859 if (*__b == __psn[0]) 2860 { 2861 ++__b; 2862 if (__psn.size() > 1) 2863 __trailing_sign = &__psn; 2864 } 2865 else if (*__b == __nsn[0]) 2866 { 2867 ++__b; 2868 __neg = true; 2869 if (__nsn.size() > 1) 2870 __trailing_sign = &__nsn; 2871 } 2872 else 2873 { 2874 __err |= ios_base::failbit; 2875 return false; 2876 } 2877 } 2878 } 2879 break; 2880 case money_base::symbol: 2881 { 2882 bool __more_needed = __trailing_sign || 2883 (__p < 2) || 2884 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none)); 2885 bool __sb = (__flags & ios_base::showbase) != 0; 2886 if (__sb || __more_needed) 2887 { 2888 typename string_type::const_iterator __sym_space_end = __sym.begin(); 2889 if (__p > 0 && (__pat.field[__p - 1] == money_base::none || 2890 __pat.field[__p - 1] == money_base::space)) { 2891 // Match spaces we've already read against spaces at 2892 // the beginning of __sym. 2893 while (__sym_space_end != __sym.end() && 2894 __ct.is(ctype_base::space, *__sym_space_end)) 2895 ++__sym_space_end; 2896 const size_t __num_spaces = __sym_space_end - __sym.begin(); 2897 if (__num_spaces > __spaces.size() || 2898 !equal(__spaces.end() - __num_spaces, __spaces.end(), 2899 __sym.begin())) { 2900 // No match. Put __sym_space_end back at the 2901 // beginning of __sym, which will prevent a 2902 // match in the next loop. 2903 __sym_space_end = __sym.begin(); 2904 } 2905 } 2906 typename string_type::const_iterator __sym_curr_char = __sym_space_end; 2907 while (__sym_curr_char != __sym.end() && __b != __e && 2908 *__b == *__sym_curr_char) { 2909 ++__b; 2910 ++__sym_curr_char; 2911 } 2912 if (__sb && __sym_curr_char != __sym.end()) 2913 { 2914 __err |= ios_base::failbit; 2915 return false; 2916 } 2917 } 2918 } 2919 break; 2920 case money_base::value: 2921 { 2922 unsigned __ng = 0; 2923 for (; __b != __e; ++__b) 2924 { 2925 char_type __c = *__b; 2926 if (__ct.is(ctype_base::digit, __c)) 2927 { 2928 if (__wn == __we) 2929 __double_or_nothing(__wb, __wn, __we); 2930 *__wn++ = __c; 2931 ++__ng; 2932 } 2933 else if (__grp.size() > 0 && __ng > 0 && __c == __ts) 2934 { 2935 if (__gn == __ge) 2936 __double_or_nothing(__gb, __gn, __ge); 2937 *__gn++ = __ng; 2938 __ng = 0; 2939 } 2940 else 2941 break; 2942 } 2943 if (__gb.get() != __gn && __ng > 0) 2944 { 2945 if (__gn == __ge) 2946 __double_or_nothing(__gb, __gn, __ge); 2947 *__gn++ = __ng; 2948 } 2949 if (__fd > 0) 2950 { 2951 if (__b == __e || *__b != __dp) 2952 { 2953 __err |= ios_base::failbit; 2954 return false; 2955 } 2956 for (++__b; __fd > 0; --__fd, ++__b) 2957 { 2958 if (__b == __e || !__ct.is(ctype_base::digit, *__b)) 2959 { 2960 __err |= ios_base::failbit; 2961 return false; 2962 } 2963 if (__wn == __we) 2964 __double_or_nothing(__wb, __wn, __we); 2965 *__wn++ = *__b; 2966 } 2967 } 2968 if (__wn == __wb.get()) 2969 { 2970 __err |= ios_base::failbit; 2971 return false; 2972 } 2973 } 2974 break; 2975 } 2976 } 2977 if (__trailing_sign) 2978 { 2979 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) 2980 { 2981 if (__b == __e || *__b != (*__trailing_sign)[__i]) 2982 { 2983 __err |= ios_base::failbit; 2984 return false; 2985 } 2986 } 2987 } 2988 if (__gb.get() != __gn) 2989 { 2990 ios_base::iostate __et = ios_base::goodbit; 2991 __check_grouping(__grp, __gb.get(), __gn, __et); 2992 if (__et) 2993 { 2994 __err |= ios_base::failbit; 2995 return false; 2996 } 2997 } 2998 return true; 2999} 3000 3001template <class _CharT, class _InputIterator> 3002_InputIterator 3003money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, 3004 bool __intl, ios_base& __iob, 3005 ios_base::iostate& __err, 3006 long double& __v) const 3007{ 3008 const int __bz = 100; 3009 char_type __wbuf[__bz]; 3010 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing); 3011 char_type* __wn; 3012 char_type* __we = __wbuf + __bz; 3013 locale __loc = __iob.getloc(); 3014 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); 3015 bool __neg = false; 3016 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, 3017 __wb, __wn, __we)) 3018 { 3019 const char __src[] = "0123456789"; 3020 char_type __atoms[sizeof(__src)-1]; 3021 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms); 3022 char __nbuf[__bz]; 3023 char* __nc = __nbuf; 3024 unique_ptr<char, void(*)(void*)> __h(0, free); 3025 if (__wn - __wb.get() > __bz-2) 3026 { 3027 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2))); 3028 if (__h.get() == 0) 3029 __throw_bad_alloc(); 3030 __nc = __h.get(); 3031 } 3032 if (__neg) 3033 *__nc++ = '-'; 3034 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc) 3035 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms]; 3036 *__nc = char(); 3037 if (sscanf(__nbuf, "%Lf", &__v) != 1) 3038 __throw_runtime_error("money_get error"); 3039 } 3040 if (__b == __e) 3041 __err |= ios_base::eofbit; 3042 return __b; 3043} 3044 3045template <class _CharT, class _InputIterator> 3046_InputIterator 3047money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, 3048 bool __intl, ios_base& __iob, 3049 ios_base::iostate& __err, 3050 string_type& __v) const 3051{ 3052 const int __bz = 100; 3053 char_type __wbuf[__bz]; 3054 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing); 3055 char_type* __wn; 3056 char_type* __we = __wbuf + __bz; 3057 locale __loc = __iob.getloc(); 3058 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); 3059 bool __neg = false; 3060 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, 3061 __wb, __wn, __we)) 3062 { 3063 __v.clear(); 3064 if (__neg) 3065 __v.push_back(__ct.widen('-')); 3066 char_type __z = __ct.widen('0'); 3067 char_type* __w; 3068 for (__w = __wb.get(); __w < __wn-1; ++__w) 3069 if (*__w != __z) 3070 break; 3071 __v.append(__w, __wn); 3072 } 3073 if (__b == __e) 3074 __err |= ios_base::eofbit; 3075 return __b; 3076} 3077 3078_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>) 3079_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>) 3080 3081// money_put 3082 3083template <class _CharT> 3084class __money_put 3085{ 3086protected: 3087 typedef _CharT char_type; 3088 typedef basic_string<char_type> string_type; 3089 3090 _LIBCPP_ALWAYS_INLINE __money_put() {} 3091 3092 static void __gather_info(bool __intl, bool __neg, const locale& __loc, 3093 money_base::pattern& __pat, char_type& __dp, 3094 char_type& __ts, string& __grp, 3095 string_type& __sym, string_type& __sn, 3096 int& __fd); 3097 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me, 3098 ios_base::fmtflags __flags, 3099 const char_type* __db, const char_type* __de, 3100 const ctype<char_type>& __ct, bool __neg, 3101 const money_base::pattern& __pat, char_type __dp, 3102 char_type __ts, const string& __grp, 3103 const string_type& __sym, const string_type& __sn, 3104 int __fd); 3105}; 3106 3107template <class _CharT> 3108void 3109__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc, 3110 money_base::pattern& __pat, char_type& __dp, 3111 char_type& __ts, string& __grp, 3112 string_type& __sym, string_type& __sn, 3113 int& __fd) 3114{ 3115 if (__intl) 3116 { 3117 const moneypunct<char_type, true>& __mp = 3118 use_facet<moneypunct<char_type, true> >(__loc); 3119 if (__neg) 3120 { 3121 __pat = __mp.neg_format(); 3122 __sn = __mp.negative_sign(); 3123 } 3124 else 3125 { 3126 __pat = __mp.pos_format(); 3127 __sn = __mp.positive_sign(); 3128 } 3129 __dp = __mp.decimal_point(); 3130 __ts = __mp.thousands_sep(); 3131 __grp = __mp.grouping(); 3132 __sym = __mp.curr_symbol(); 3133 __fd = __mp.frac_digits(); 3134 } 3135 else 3136 { 3137 const moneypunct<char_type, false>& __mp = 3138 use_facet<moneypunct<char_type, false> >(__loc); 3139 if (__neg) 3140 { 3141 __pat = __mp.neg_format(); 3142 __sn = __mp.negative_sign(); 3143 } 3144 else 3145 { 3146 __pat = __mp.pos_format(); 3147 __sn = __mp.positive_sign(); 3148 } 3149 __dp = __mp.decimal_point(); 3150 __ts = __mp.thousands_sep(); 3151 __grp = __mp.grouping(); 3152 __sym = __mp.curr_symbol(); 3153 __fd = __mp.frac_digits(); 3154 } 3155} 3156 3157template <class _CharT> 3158void 3159__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me, 3160 ios_base::fmtflags __flags, 3161 const char_type* __db, const char_type* __de, 3162 const ctype<char_type>& __ct, bool __neg, 3163 const money_base::pattern& __pat, char_type __dp, 3164 char_type __ts, const string& __grp, 3165 const string_type& __sym, const string_type& __sn, 3166 int __fd) 3167{ 3168 __me = __mb; 3169 for (unsigned __p = 0; __p < 4; ++__p) 3170 { 3171 switch (__pat.field[__p]) 3172 { 3173 case money_base::none: 3174 __mi = __me; 3175 break; 3176 case money_base::space: 3177 __mi = __me; 3178 *__me++ = __ct.widen(' '); 3179 break; 3180 case money_base::sign: 3181 if (!__sn.empty()) 3182 *__me++ = __sn[0]; 3183 break; 3184 case money_base::symbol: 3185 if (!__sym.empty() && (__flags & ios_base::showbase)) 3186 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me); 3187 break; 3188 case money_base::value: 3189 { 3190 // remember start of value so we can reverse it 3191 char_type* __t = __me; 3192 // find beginning of digits 3193 if (__neg) 3194 ++__db; 3195 // find end of digits 3196 const char_type* __d; 3197 for (__d = __db; __d < __de; ++__d) 3198 if (!__ct.is(ctype_base::digit, *__d)) 3199 break; 3200 // print fractional part 3201 if (__fd > 0) 3202 { 3203 int __f; 3204 for (__f = __fd; __d > __db && __f > 0; --__f) 3205 *__me++ = *--__d; 3206 char_type __z = __f > 0 ? __ct.widen('0') : char_type(); 3207 for (; __f > 0; --__f) 3208 *__me++ = __z; 3209 *__me++ = __dp; 3210 } 3211 // print units part 3212 if (__d == __db) 3213 { 3214 *__me++ = __ct.widen('0'); 3215 } 3216 else 3217 { 3218 unsigned __ng = 0; 3219 unsigned __ig = 0; 3220 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max() 3221 : static_cast<unsigned>(__grp[__ig]); 3222 while (__d != __db) 3223 { 3224 if (__ng == __gl) 3225 { 3226 *__me++ = __ts; 3227 __ng = 0; 3228 if (++__ig < __grp.size()) 3229 __gl = __grp[__ig] == numeric_limits<char>::max() ? 3230 numeric_limits<unsigned>::max() : 3231 static_cast<unsigned>(__grp[__ig]); 3232 } 3233 *__me++ = *--__d; 3234 ++__ng; 3235 } 3236 } 3237 // reverse it 3238 reverse(__t, __me); 3239 } 3240 break; 3241 } 3242 } 3243 // print rest of sign, if any 3244 if (__sn.size() > 1) 3245 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me); 3246 // set alignment 3247 if ((__flags & ios_base::adjustfield) == ios_base::left) 3248 __mi = __me; 3249 else if ((__flags & ios_base::adjustfield) != ios_base::internal) 3250 __mi = __mb; 3251} 3252 3253_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>) 3254_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>) 3255 3256template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> > 3257class _LIBCPP_TEMPLATE_VIS money_put 3258 : public locale::facet, 3259 private __money_put<_CharT> 3260{ 3261public: 3262 typedef _CharT char_type; 3263 typedef _OutputIterator iter_type; 3264 typedef basic_string<char_type> string_type; 3265 3266 _LIBCPP_ALWAYS_INLINE 3267 explicit money_put(size_t __refs = 0) 3268 : locale::facet(__refs) {} 3269 3270 _LIBCPP_ALWAYS_INLINE 3271 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, 3272 long double __units) const 3273 { 3274 return do_put(__s, __intl, __iob, __fl, __units); 3275 } 3276 3277 _LIBCPP_ALWAYS_INLINE 3278 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, 3279 const string_type& __digits) const 3280 { 3281 return do_put(__s, __intl, __iob, __fl, __digits); 3282 } 3283 3284 static locale::id id; 3285 3286protected: 3287 _LIBCPP_ALWAYS_INLINE 3288 ~money_put() {} 3289 3290 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, 3291 char_type __fl, long double __units) const; 3292 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, 3293 char_type __fl, const string_type& __digits) const; 3294}; 3295 3296template <class _CharT, class _OutputIterator> 3297locale::id 3298money_put<_CharT, _OutputIterator>::id; 3299 3300template <class _CharT, class _OutputIterator> 3301_OutputIterator 3302money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl, 3303 ios_base& __iob, char_type __fl, 3304 long double __units) const 3305{ 3306 // convert to char 3307 const size_t __bs = 100; 3308 char __buf[__bs]; 3309 char* __bb = __buf; 3310 char_type __digits[__bs]; 3311 char_type* __db = __digits; 3312 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units)); 3313 unique_ptr<char, void(*)(void*)> __hn(0, free); 3314 unique_ptr<char_type, void(*)(void*)> __hd(0, free); 3315 // secure memory for digit storage 3316 if (__n > __bs-1) 3317 { 3318 __n = static_cast<size_t>(__libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units)); 3319 if (__bb == 0) 3320 __throw_bad_alloc(); 3321 __hn.reset(__bb); 3322 __hd.reset((char_type*)malloc(__n * sizeof(char_type))); 3323 if (__hd == nullptr) 3324 __throw_bad_alloc(); 3325 __db = __hd.get(); 3326 } 3327 // gather info 3328 locale __loc = __iob.getloc(); 3329 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); 3330 __ct.widen(__bb, __bb + __n, __db); 3331 bool __neg = __n > 0 && __bb[0] == '-'; 3332 money_base::pattern __pat; 3333 char_type __dp; 3334 char_type __ts; 3335 string __grp; 3336 string_type __sym; 3337 string_type __sn; 3338 int __fd; 3339 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); 3340 // secure memory for formatting 3341 char_type __mbuf[__bs]; 3342 char_type* __mb = __mbuf; 3343 unique_ptr<char_type, void(*)(void*)> __hw(0, free); 3344 size_t __exn = static_cast<int>(__n) > __fd ? 3345 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() + 3346 __sym.size() + static_cast<size_t>(__fd) + 1 3347 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2; 3348 if (__exn > __bs) 3349 { 3350 __hw.reset((char_type*)malloc(__exn * sizeof(char_type))); 3351 __mb = __hw.get(); 3352 if (__mb == 0) 3353 __throw_bad_alloc(); 3354 } 3355 // format 3356 char_type* __mi; 3357 char_type* __me; 3358 this->__format(__mb, __mi, __me, __iob.flags(), 3359 __db, __db + __n, __ct, 3360 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); 3361 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl); 3362} 3363 3364template <class _CharT, class _OutputIterator> 3365_OutputIterator 3366money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl, 3367 ios_base& __iob, char_type __fl, 3368 const string_type& __digits) const 3369{ 3370 // gather info 3371 locale __loc = __iob.getloc(); 3372 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc); 3373 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-'); 3374 money_base::pattern __pat; 3375 char_type __dp; 3376 char_type __ts; 3377 string __grp; 3378 string_type __sym; 3379 string_type __sn; 3380 int __fd; 3381 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); 3382 // secure memory for formatting 3383 char_type __mbuf[100]; 3384 char_type* __mb = __mbuf; 3385 unique_ptr<char_type, void(*)(void*)> __h(0, free); 3386 size_t __exn = static_cast<int>(__digits.size()) > __fd ? 3387 (__digits.size() - static_cast<size_t>(__fd)) * 2 + 3388 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1 3389 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2; 3390 if (__exn > 100) 3391 { 3392 __h.reset((char_type*)malloc(__exn * sizeof(char_type))); 3393 __mb = __h.get(); 3394 if (__mb == 0) 3395 __throw_bad_alloc(); 3396 } 3397 // format 3398 char_type* __mi; 3399 char_type* __me; 3400 this->__format(__mb, __mi, __me, __iob.flags(), 3401 __digits.data(), __digits.data() + __digits.size(), __ct, 3402 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); 3403 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl); 3404} 3405 3406_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>) 3407_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>) 3408 3409// messages 3410 3411class _LIBCPP_TYPE_VIS messages_base 3412{ 3413public: 3414 typedef ptrdiff_t catalog; 3415 3416 _LIBCPP_ALWAYS_INLINE messages_base() {} 3417}; 3418 3419template <class _CharT> 3420class _LIBCPP_TEMPLATE_VIS messages 3421 : public locale::facet, 3422 public messages_base 3423{ 3424public: 3425 typedef _CharT char_type; 3426 typedef basic_string<_CharT> string_type; 3427 3428 _LIBCPP_ALWAYS_INLINE 3429 explicit messages(size_t __refs = 0) 3430 : locale::facet(__refs) {} 3431 3432 _LIBCPP_ALWAYS_INLINE 3433 catalog open(const basic_string<char>& __nm, const locale& __loc) const 3434 { 3435 return do_open(__nm, __loc); 3436 } 3437 3438 _LIBCPP_ALWAYS_INLINE 3439 string_type get(catalog __c, int __set, int __msgid, 3440 const string_type& __dflt) const 3441 { 3442 return do_get(__c, __set, __msgid, __dflt); 3443 } 3444 3445 _LIBCPP_ALWAYS_INLINE 3446 void close(catalog __c) const 3447 { 3448 do_close(__c); 3449 } 3450 3451 static locale::id id; 3452 3453protected: 3454 _LIBCPP_ALWAYS_INLINE 3455 ~messages() {} 3456 3457 virtual catalog do_open(const basic_string<char>&, const locale&) const; 3458 virtual string_type do_get(catalog, int __set, int __msgid, 3459 const string_type& __dflt) const; 3460 virtual void do_close(catalog) const; 3461}; 3462 3463template <class _CharT> 3464locale::id 3465messages<_CharT>::id; 3466 3467template <class _CharT> 3468typename messages<_CharT>::catalog 3469messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const 3470{ 3471#ifdef _LIBCPP_HAS_CATOPEN 3472 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE); 3473 if (__cat != -1) 3474 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1)); 3475 return __cat; 3476#else // !_LIBCPP_HAS_CATOPEN 3477 return -1; 3478#endif // _LIBCPP_HAS_CATOPEN 3479} 3480 3481template <class _CharT> 3482typename messages<_CharT>::string_type 3483messages<_CharT>::do_get(catalog __c, int __set, int __msgid, 3484 const string_type& __dflt) const 3485{ 3486#ifdef _LIBCPP_HAS_CATOPEN 3487 string __ndflt; 3488 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt), 3489 __dflt.c_str(), 3490 __dflt.c_str() + __dflt.size()); 3491 if (__c != -1) 3492 __c <<= 1; 3493 nl_catd __cat = (nl_catd)__c; 3494 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str()); 3495 string_type __w; 3496 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w), 3497 __n, __n + strlen(__n)); 3498 return __w; 3499#else // !_LIBCPP_HAS_CATOPEN 3500 return __dflt; 3501#endif // _LIBCPP_HAS_CATOPEN 3502} 3503 3504template <class _CharT> 3505void 3506messages<_CharT>::do_close(catalog __c) const 3507{ 3508#ifdef _LIBCPP_HAS_CATOPEN 3509 if (__c != -1) 3510 __c <<= 1; 3511 nl_catd __cat = (nl_catd)__c; 3512 catclose(__cat); 3513#endif // _LIBCPP_HAS_CATOPEN 3514} 3515 3516_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>) 3517_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>) 3518 3519template <class _CharT> 3520class _LIBCPP_TEMPLATE_VIS messages_byname 3521 : public messages<_CharT> 3522{ 3523public: 3524 typedef messages_base::catalog catalog; 3525 typedef basic_string<_CharT> string_type; 3526 3527 _LIBCPP_ALWAYS_INLINE 3528 explicit messages_byname(const char*, size_t __refs = 0) 3529 : messages<_CharT>(__refs) {} 3530 3531 _LIBCPP_ALWAYS_INLINE 3532 explicit messages_byname(const string&, size_t __refs = 0) 3533 : messages<_CharT>(__refs) {} 3534 3535protected: 3536 _LIBCPP_ALWAYS_INLINE 3537 ~messages_byname() {} 3538}; 3539 3540_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>) 3541_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>) 3542 3543template<class _Codecvt, class _Elem = wchar_t, 3544 class _Wide_alloc = allocator<_Elem>, 3545 class _Byte_alloc = allocator<char> > 3546class _LIBCPP_TEMPLATE_VIS wstring_convert 3547{ 3548public: 3549 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string; 3550 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string; 3551 typedef typename _Codecvt::state_type state_type; 3552 typedef typename wide_string::traits_type::int_type int_type; 3553 3554private: 3555 byte_string __byte_err_string_; 3556 wide_string __wide_err_string_; 3557 _Codecvt* __cvtptr_; 3558 state_type __cvtstate_; 3559 size_t __cvtcount_; 3560 3561 wstring_convert(const wstring_convert& __wc); 3562 wstring_convert& operator=(const wstring_convert& __wc); 3563public: 3564 _LIBCPP_ALWAYS_INLINE 3565 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt); 3566 _LIBCPP_ALWAYS_INLINE 3567 wstring_convert(_Codecvt* __pcvt, state_type __state); 3568 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err, 3569 const wide_string& __wide_err = wide_string()); 3570#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 3571 _LIBCPP_ALWAYS_INLINE 3572 wstring_convert(wstring_convert&& __wc); 3573#endif 3574 ~wstring_convert(); 3575 3576 _LIBCPP_ALWAYS_INLINE 3577 wide_string from_bytes(char __byte) 3578 {return from_bytes(&__byte, &__byte+1);} 3579 _LIBCPP_ALWAYS_INLINE 3580 wide_string from_bytes(const char* __ptr) 3581 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));} 3582 _LIBCPP_ALWAYS_INLINE 3583 wide_string from_bytes(const byte_string& __str) 3584 {return from_bytes(__str.data(), __str.data() + __str.size());} 3585 wide_string from_bytes(const char* __first, const char* __last); 3586 3587 _LIBCPP_ALWAYS_INLINE 3588 byte_string to_bytes(_Elem __wchar) 3589 {return to_bytes(&__wchar, &__wchar+1);} 3590 _LIBCPP_ALWAYS_INLINE 3591 byte_string to_bytes(const _Elem* __wptr) 3592 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));} 3593 _LIBCPP_ALWAYS_INLINE 3594 byte_string to_bytes(const wide_string& __wstr) 3595 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());} 3596 byte_string to_bytes(const _Elem* __first, const _Elem* __last); 3597 3598 _LIBCPP_ALWAYS_INLINE 3599 size_t converted() const _NOEXCEPT {return __cvtcount_;} 3600 _LIBCPP_ALWAYS_INLINE 3601 state_type state() const {return __cvtstate_;} 3602}; 3603 3604template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> 3605inline 3606wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: 3607 wstring_convert(_Codecvt* __pcvt) 3608 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) 3609{ 3610} 3611 3612template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> 3613inline 3614wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: 3615 wstring_convert(_Codecvt* __pcvt, state_type __state) 3616 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) 3617{ 3618} 3619 3620template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> 3621wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: 3622 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err) 3623 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), 3624 __cvtstate_(), __cvtcount_(0) 3625{ 3626 __cvtptr_ = new _Codecvt; 3627} 3628 3629#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 3630 3631template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> 3632inline 3633wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: 3634 wstring_convert(wstring_convert&& __wc) 3635 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)), 3636 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)), 3637 __cvtptr_(__wc.__cvtptr_), 3638 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtcount_) 3639{ 3640 __wc.__cvtptr_ = nullptr; 3641} 3642 3643#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 3644 3645template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> 3646wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert() 3647{ 3648 delete __cvtptr_; 3649} 3650 3651template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> 3652typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string 3653wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: 3654 from_bytes(const char* __frm, const char* __frm_end) 3655{ 3656 __cvtcount_ = 0; 3657 if (__cvtptr_ != nullptr) 3658 { 3659 wide_string __ws(2*(__frm_end - __frm), _Elem()); 3660 if (__frm != __frm_end) 3661 __ws.resize(__ws.capacity()); 3662 codecvt_base::result __r = codecvt_base::ok; 3663 state_type __st = __cvtstate_; 3664 if (__frm != __frm_end) 3665 { 3666 _Elem* __to = &__ws[0]; 3667 _Elem* __to_end = __to + __ws.size(); 3668 const char* __frm_nxt; 3669 do 3670 { 3671 _Elem* __to_nxt; 3672 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, 3673 __to, __to_end, __to_nxt); 3674 __cvtcount_ += __frm_nxt - __frm; 3675 if (__frm_nxt == __frm) 3676 { 3677 __r = codecvt_base::error; 3678 } 3679 else if (__r == codecvt_base::noconv) 3680 { 3681 __ws.resize(__to - &__ws[0]); 3682 // This only gets executed if _Elem is char 3683 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end); 3684 __frm = __frm_nxt; 3685 __r = codecvt_base::ok; 3686 } 3687 else if (__r == codecvt_base::ok) 3688 { 3689 __ws.resize(__to_nxt - &__ws[0]); 3690 __frm = __frm_nxt; 3691 } 3692 else if (__r == codecvt_base::partial) 3693 { 3694 ptrdiff_t __s = __to_nxt - &__ws[0]; 3695 __ws.resize(2 * __s); 3696 __to = &__ws[0] + __s; 3697 __to_end = &__ws[0] + __ws.size(); 3698 __frm = __frm_nxt; 3699 } 3700 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); 3701 } 3702 if (__r == codecvt_base::ok) 3703 return __ws; 3704 } 3705 3706 if (__wide_err_string_.empty()) 3707 __throw_range_error("wstring_convert: from_bytes error"); 3708 3709 return __wide_err_string_; 3710} 3711 3712template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> 3713typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string 3714wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: 3715 to_bytes(const _Elem* __frm, const _Elem* __frm_end) 3716{ 3717 __cvtcount_ = 0; 3718 if (__cvtptr_ != nullptr) 3719 { 3720 byte_string __bs(2*(__frm_end - __frm), char()); 3721 if (__frm != __frm_end) 3722 __bs.resize(__bs.capacity()); 3723 codecvt_base::result __r = codecvt_base::ok; 3724 state_type __st = __cvtstate_; 3725 if (__frm != __frm_end) 3726 { 3727 char* __to = &__bs[0]; 3728 char* __to_end = __to + __bs.size(); 3729 const _Elem* __frm_nxt; 3730 do 3731 { 3732 char* __to_nxt; 3733 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, 3734 __to, __to_end, __to_nxt); 3735 __cvtcount_ += __frm_nxt - __frm; 3736 if (__frm_nxt == __frm) 3737 { 3738 __r = codecvt_base::error; 3739 } 3740 else if (__r == codecvt_base::noconv) 3741 { 3742 __bs.resize(__to - &__bs[0]); 3743 // This only gets executed if _Elem is char 3744 __bs.append((const char*)__frm, (const char*)__frm_end); 3745 __frm = __frm_nxt; 3746 __r = codecvt_base::ok; 3747 } 3748 else if (__r == codecvt_base::ok) 3749 { 3750 __bs.resize(__to_nxt - &__bs[0]); 3751 __frm = __frm_nxt; 3752 } 3753 else if (__r == codecvt_base::partial) 3754 { 3755 ptrdiff_t __s = __to_nxt - &__bs[0]; 3756 __bs.resize(2 * __s); 3757 __to = &__bs[0] + __s; 3758 __to_end = &__bs[0] + __bs.size(); 3759 __frm = __frm_nxt; 3760 } 3761 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); 3762 } 3763 if (__r == codecvt_base::ok) 3764 { 3765 size_t __s = __bs.size(); 3766 __bs.resize(__bs.capacity()); 3767 char* __to = &__bs[0] + __s; 3768 char* __to_end = __to + __bs.size(); 3769 do 3770 { 3771 char* __to_nxt; 3772 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt); 3773 if (__r == codecvt_base::noconv) 3774 { 3775 __bs.resize(__to - &__bs[0]); 3776 __r = codecvt_base::ok; 3777 } 3778 else if (__r == codecvt_base::ok) 3779 { 3780 __bs.resize(__to_nxt - &__bs[0]); 3781 } 3782 else if (__r == codecvt_base::partial) 3783 { 3784 ptrdiff_t __sp = __to_nxt - &__bs[0]; 3785 __bs.resize(2 * __sp); 3786 __to = &__bs[0] + __sp; 3787 __to_end = &__bs[0] + __bs.size(); 3788 } 3789 } while (__r == codecvt_base::partial); 3790 if (__r == codecvt_base::ok) 3791 return __bs; 3792 } 3793 } 3794 3795 if (__byte_err_string_.empty()) 3796 __throw_range_error("wstring_convert: to_bytes error"); 3797 3798 return __byte_err_string_; 3799} 3800 3801template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> > 3802class _LIBCPP_TEMPLATE_VIS wbuffer_convert 3803 : public basic_streambuf<_Elem, _Tr> 3804{ 3805public: 3806 // types: 3807 typedef _Elem char_type; 3808 typedef _Tr traits_type; 3809 typedef typename traits_type::int_type int_type; 3810 typedef typename traits_type::pos_type pos_type; 3811 typedef typename traits_type::off_type off_type; 3812 typedef typename _Codecvt::state_type state_type; 3813 3814private: 3815 char* __extbuf_; 3816 const char* __extbufnext_; 3817 const char* __extbufend_; 3818 char __extbuf_min_[8]; 3819 size_t __ebs_; 3820 char_type* __intbuf_; 3821 size_t __ibs_; 3822 streambuf* __bufptr_; 3823 _Codecvt* __cv_; 3824 state_type __st_; 3825 ios_base::openmode __cm_; 3826 bool __owns_eb_; 3827 bool __owns_ib_; 3828 bool __always_noconv_; 3829 3830 wbuffer_convert(const wbuffer_convert&); 3831 wbuffer_convert& operator=(const wbuffer_convert&); 3832public: 3833 _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = 0, 3834 _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); 3835 ~wbuffer_convert(); 3836 3837 _LIBCPP_INLINE_VISIBILITY 3838 streambuf* rdbuf() const {return __bufptr_;} 3839 _LIBCPP_INLINE_VISIBILITY 3840 streambuf* rdbuf(streambuf* __bytebuf) 3841 { 3842 streambuf* __r = __bufptr_; 3843 __bufptr_ = __bytebuf; 3844 return __r; 3845 } 3846 3847 _LIBCPP_INLINE_VISIBILITY 3848 state_type state() const {return __st_;} 3849 3850protected: 3851 virtual int_type underflow(); 3852 virtual int_type pbackfail(int_type __c = traits_type::eof()); 3853 virtual int_type overflow (int_type __c = traits_type::eof()); 3854 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s, 3855 streamsize __n); 3856 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way, 3857 ios_base::openmode __wch = ios_base::in | ios_base::out); 3858 virtual pos_type seekpos(pos_type __sp, 3859 ios_base::openmode __wch = ios_base::in | ios_base::out); 3860 virtual int sync(); 3861 3862private: 3863 bool __read_mode(); 3864 void __write_mode(); 3865 wbuffer_convert* __close(); 3866}; 3867 3868template <class _Codecvt, class _Elem, class _Tr> 3869wbuffer_convert<_Codecvt, _Elem, _Tr>:: 3870 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state) 3871 : __extbuf_(0), 3872 __extbufnext_(0), 3873 __extbufend_(0), 3874 __ebs_(0), 3875 __intbuf_(0), 3876 __ibs_(0), 3877 __bufptr_(__bytebuf), 3878 __cv_(__pcvt), 3879 __st_(__state), 3880 __cm_(0), 3881 __owns_eb_(false), 3882 __owns_ib_(false), 3883 __always_noconv_(__cv_ ? __cv_->always_noconv() : false) 3884{ 3885 setbuf(0, 4096); 3886} 3887 3888template <class _Codecvt, class _Elem, class _Tr> 3889wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert() 3890{ 3891 __close(); 3892 delete __cv_; 3893 if (__owns_eb_) 3894 delete [] __extbuf_; 3895 if (__owns_ib_) 3896 delete [] __intbuf_; 3897} 3898 3899template <class _Codecvt, class _Elem, class _Tr> 3900typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type 3901wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow() 3902{ 3903 if (__cv_ == 0 || __bufptr_ == 0) 3904 return traits_type::eof(); 3905 bool __initial = __read_mode(); 3906 char_type __1buf; 3907 if (this->gptr() == 0) 3908 this->setg(&__1buf, &__1buf+1, &__1buf+1); 3909 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4); 3910 int_type __c = traits_type::eof(); 3911 if (this->gptr() == this->egptr()) 3912 { 3913 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type)); 3914 if (__always_noconv_) 3915 { 3916 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz); 3917 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb); 3918 if (__nmemb != 0) 3919 { 3920 this->setg(this->eback(), 3921 this->eback() + __unget_sz, 3922 this->eback() + __unget_sz + __nmemb); 3923 __c = *this->gptr(); 3924 } 3925 } 3926 else 3927 { 3928 _LIBCPP_ASSERT(!(__extbufnext_ == NULL && (__extbufend_ != __extbufnext_)), "underflow moving from NULL" ); 3929 if (__extbufend_ != __extbufnext_) 3930 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); 3931 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); 3932 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_); 3933 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz), 3934 static_cast<streamsize>(__extbufend_ - __extbufnext_)); 3935 codecvt_base::result __r; 3936 // FIXME: Do we ever need to restore the state here? 3937 //state_type __svs = __st_; 3938 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb); 3939 if (__nr != 0) 3940 { 3941 __extbufend_ = __extbufnext_ + __nr; 3942 char_type* __inext; 3943 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_, 3944 this->eback() + __unget_sz, 3945 this->egptr(), __inext); 3946 if (__r == codecvt_base::noconv) 3947 { 3948 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_); 3949 __c = *this->gptr(); 3950 } 3951 else if (__inext != this->eback() + __unget_sz) 3952 { 3953 this->setg(this->eback(), this->eback() + __unget_sz, __inext); 3954 __c = *this->gptr(); 3955 } 3956 } 3957 } 3958 } 3959 else 3960 __c = *this->gptr(); 3961 if (this->eback() == &__1buf) 3962 this->setg(0, 0, 0); 3963 return __c; 3964} 3965 3966template <class _Codecvt, class _Elem, class _Tr> 3967typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type 3968wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c) 3969{ 3970 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr()) 3971 { 3972 if (traits_type::eq_int_type(__c, traits_type::eof())) 3973 { 3974 this->gbump(-1); 3975 return traits_type::not_eof(__c); 3976 } 3977 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) 3978 { 3979 this->gbump(-1); 3980 *this->gptr() = traits_type::to_char_type(__c); 3981 return __c; 3982 } 3983 } 3984 return traits_type::eof(); 3985} 3986 3987template <class _Codecvt, class _Elem, class _Tr> 3988typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type 3989wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c) 3990{ 3991 if (__cv_ == 0 || __bufptr_ == 0) 3992 return traits_type::eof(); 3993 __write_mode(); 3994 char_type __1buf; 3995 char_type* __pb_save = this->pbase(); 3996 char_type* __epb_save = this->epptr(); 3997 if (!traits_type::eq_int_type(__c, traits_type::eof())) 3998 { 3999 if (this->pptr() == 0) 4000 this->setp(&__1buf, &__1buf+1); 4001 *this->pptr() = traits_type::to_char_type(__c); 4002 this->pbump(1); 4003 } 4004 if (this->pptr() != this->pbase()) 4005 { 4006 if (__always_noconv_) 4007 { 4008 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase()); 4009 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) 4010 return traits_type::eof(); 4011 } 4012 else 4013 { 4014 char* __extbe = __extbuf_; 4015 codecvt_base::result __r; 4016 do 4017 { 4018 const char_type* __e; 4019 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, 4020 __extbuf_, __extbuf_ + __ebs_, __extbe); 4021 if (__e == this->pbase()) 4022 return traits_type::eof(); 4023 if (__r == codecvt_base::noconv) 4024 { 4025 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase()); 4026 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) 4027 return traits_type::eof(); 4028 } 4029 else if (__r == codecvt_base::ok || __r == codecvt_base::partial) 4030 { 4031 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_); 4032 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) 4033 return traits_type::eof(); 4034 if (__r == codecvt_base::partial) 4035 { 4036 this->setp((char_type*)__e, this->pptr()); 4037 this->pbump(this->epptr() - this->pbase()); 4038 } 4039 } 4040 else 4041 return traits_type::eof(); 4042 } while (__r == codecvt_base::partial); 4043 } 4044 this->setp(__pb_save, __epb_save); 4045 } 4046 return traits_type::not_eof(__c); 4047} 4048 4049template <class _Codecvt, class _Elem, class _Tr> 4050basic_streambuf<_Elem, _Tr>* 4051wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n) 4052{ 4053 this->setg(0, 0, 0); 4054 this->setp(0, 0); 4055 if (__owns_eb_) 4056 delete [] __extbuf_; 4057 if (__owns_ib_) 4058 delete [] __intbuf_; 4059 __ebs_ = __n; 4060 if (__ebs_ > sizeof(__extbuf_min_)) 4061 { 4062 if (__always_noconv_ && __s) 4063 { 4064 __extbuf_ = (char*)__s; 4065 __owns_eb_ = false; 4066 } 4067 else 4068 { 4069 __extbuf_ = new char[__ebs_]; 4070 __owns_eb_ = true; 4071 } 4072 } 4073 else 4074 { 4075 __extbuf_ = __extbuf_min_; 4076 __ebs_ = sizeof(__extbuf_min_); 4077 __owns_eb_ = false; 4078 } 4079 if (!__always_noconv_) 4080 { 4081 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_)); 4082 if (__s && __ibs_ >= sizeof(__extbuf_min_)) 4083 { 4084 __intbuf_ = __s; 4085 __owns_ib_ = false; 4086 } 4087 else 4088 { 4089 __intbuf_ = new char_type[__ibs_]; 4090 __owns_ib_ = true; 4091 } 4092 } 4093 else 4094 { 4095 __ibs_ = 0; 4096 __intbuf_ = 0; 4097 __owns_ib_ = false; 4098 } 4099 return this; 4100} 4101 4102template <class _Codecvt, class _Elem, class _Tr> 4103typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type 4104wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way, 4105 ios_base::openmode __om) 4106{ 4107 int __width = __cv_->encoding(); 4108 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync()) 4109 return pos_type(off_type(-1)); 4110 // __width > 0 || __off == 0, now check __way 4111 if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end) 4112 return pos_type(off_type(-1)); 4113 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om); 4114 __r.state(__st_); 4115 return __r; 4116} 4117 4118template <class _Codecvt, class _Elem, class _Tr> 4119typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type 4120wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch) 4121{ 4122 if (__cv_ == 0 || __bufptr_ == 0 || sync()) 4123 return pos_type(off_type(-1)); 4124 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1))) 4125 return pos_type(off_type(-1)); 4126 return __sp; 4127} 4128 4129template <class _Codecvt, class _Elem, class _Tr> 4130int 4131wbuffer_convert<_Codecvt, _Elem, _Tr>::sync() 4132{ 4133 if (__cv_ == 0 || __bufptr_ == 0) 4134 return 0; 4135 if (__cm_ & ios_base::out) 4136 { 4137 if (this->pptr() != this->pbase()) 4138 if (overflow() == traits_type::eof()) 4139 return -1; 4140 codecvt_base::result __r; 4141 do 4142 { 4143 char* __extbe; 4144 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe); 4145 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_); 4146 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) 4147 return -1; 4148 } while (__r == codecvt_base::partial); 4149 if (__r == codecvt_base::error) 4150 return -1; 4151 if (__bufptr_->pubsync()) 4152 return -1; 4153 } 4154 else if (__cm_ & ios_base::in) 4155 { 4156 off_type __c; 4157 if (__always_noconv_) 4158 __c = this->egptr() - this->gptr(); 4159 else 4160 { 4161 int __width = __cv_->encoding(); 4162 __c = __extbufend_ - __extbufnext_; 4163 if (__width > 0) 4164 __c += __width * (this->egptr() - this->gptr()); 4165 else 4166 { 4167 if (this->gptr() != this->egptr()) 4168 { 4169 reverse(this->gptr(), this->egptr()); 4170 codecvt_base::result __r; 4171 const char_type* __e = this->gptr(); 4172 char* __extbe; 4173 do 4174 { 4175 __r = __cv_->out(__st_, __e, this->egptr(), __e, 4176 __extbuf_, __extbuf_ + __ebs_, __extbe); 4177 switch (__r) 4178 { 4179 case codecvt_base::noconv: 4180 __c += this->egptr() - this->gptr(); 4181 break; 4182 case codecvt_base::ok: 4183 case codecvt_base::partial: 4184 __c += __extbe - __extbuf_; 4185 break; 4186 default: 4187 return -1; 4188 } 4189 } while (__r == codecvt_base::partial); 4190 } 4191 } 4192 } 4193 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1))) 4194 return -1; 4195 this->setg(0, 0, 0); 4196 __cm_ = 0; 4197 } 4198 return 0; 4199} 4200 4201template <class _Codecvt, class _Elem, class _Tr> 4202bool 4203wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode() 4204{ 4205 if (!(__cm_ & ios_base::in)) 4206 { 4207 this->setp(0, 0); 4208 if (__always_noconv_) 4209 this->setg((char_type*)__extbuf_, 4210 (char_type*)__extbuf_ + __ebs_, 4211 (char_type*)__extbuf_ + __ebs_); 4212 else 4213 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_); 4214 __cm_ = ios_base::in; 4215 return true; 4216 } 4217 return false; 4218} 4219 4220template <class _Codecvt, class _Elem, class _Tr> 4221void 4222wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode() 4223{ 4224 if (!(__cm_ & ios_base::out)) 4225 { 4226 this->setg(0, 0, 0); 4227 if (__ebs_ > sizeof(__extbuf_min_)) 4228 { 4229 if (__always_noconv_) 4230 this->setp((char_type*)__extbuf_, 4231 (char_type*)__extbuf_ + (__ebs_ - 1)); 4232 else 4233 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1)); 4234 } 4235 else 4236 this->setp(0, 0); 4237 __cm_ = ios_base::out; 4238 } 4239} 4240 4241template <class _Codecvt, class _Elem, class _Tr> 4242wbuffer_convert<_Codecvt, _Elem, _Tr>* 4243wbuffer_convert<_Codecvt, _Elem, _Tr>::__close() 4244{ 4245 wbuffer_convert* __rt = 0; 4246 if (__cv_ != 0 && __bufptr_ != 0) 4247 { 4248 __rt = this; 4249 if ((__cm_ & ios_base::out) && sync()) 4250 __rt = 0; 4251 } 4252 return __rt; 4253} 4254 4255_LIBCPP_END_NAMESPACE_STD 4256 4257#endif // _LIBCPP_LOCALE 4258