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