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