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