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