locale.cpp (194554B)
1 //===------------------------- locale.cpp ---------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // On Solaris, we need to define something to make the C99 parts of localeconv 11 // visible. 12 #ifdef __sun__ 13 #define _LCONV_C99 14 #endif 15 16 #include "string" 17 #include "locale" 18 #include "codecvt" 19 #include "vector" 20 #include "algorithm" 21 #include "typeinfo" 22 #ifndef _LIBCPP_NO_EXCEPTIONS 23 # include "type_traits" 24 #endif 25 #include "clocale" 26 #include "cstring" 27 #if defined(_LIBCPP_MSVCRT) 28 #define _CTYPE_DISABLE_MACROS 29 #endif 30 #include "cwctype" 31 #include "__sso_allocator" 32 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 33 #include "support/win32/locale_win32.h" 34 #elif !defined(__BIONIC__) 35 #include <langinfo.h> 36 #endif 37 #include <stdlib.h> 38 #include <stdio.h> 39 #include "include/atomic_support.h" 40 #include "__undef_macros" 41 42 // On Linux, wint_t and wchar_t have different signed-ness, and this causes 43 // lots of noise in the build log, but no bugs that I know of. 44 #if defined(__clang__) 45 #pragma clang diagnostic ignored "-Wsign-conversion" 46 #endif 47 48 _LIBCPP_BEGIN_NAMESPACE_STD 49 50 struct __libcpp_unique_locale { 51 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {} 52 53 ~__libcpp_unique_locale() { 54 if (__loc_) 55 freelocale(__loc_); 56 } 57 58 explicit operator bool() const { return __loc_; } 59 60 locale_t& get() { return __loc_; } 61 62 locale_t __loc_; 63 private: 64 __libcpp_unique_locale(__libcpp_unique_locale const&); 65 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&); 66 }; 67 68 #ifdef __cloc_defined 69 locale_t __cloc() { 70 // In theory this could create a race condition. In practice 71 // the race condition is non-fatal since it will just create 72 // a little resource leak. Better approach would be appreciated. 73 static locale_t result = newlocale(LC_ALL_MASK, "C", 0); 74 return result; 75 } 76 #endif // __cloc_defined 77 78 namespace { 79 80 struct release 81 { 82 void operator()(locale::facet* p) {p->__release_shared();} 83 }; 84 85 template <class T, class A0> 86 inline 87 T& 88 make(A0 a0) 89 { 90 static typename aligned_storage<sizeof(T)>::type buf; 91 auto *obj = ::new (&buf) T(a0); 92 return *obj; 93 } 94 95 template <class T, class A0, class A1> 96 inline 97 T& 98 make(A0 a0, A1 a1) 99 { 100 static typename aligned_storage<sizeof(T)>::type buf; 101 ::new (&buf) T(a0, a1); 102 return *reinterpret_cast<T*>(&buf); 103 } 104 105 template <class T, class A0, class A1, class A2> 106 inline 107 T& 108 make(A0 a0, A1 a1, A2 a2) 109 { 110 static typename aligned_storage<sizeof(T)>::type buf; 111 auto *obj = ::new (&buf) T(a0, a1, a2); 112 return *obj; 113 } 114 115 template <typename T, size_t N> 116 inline 117 _LIBCPP_CONSTEXPR 118 size_t 119 countof(const T (&)[N]) 120 { 121 return N; 122 } 123 124 template <typename T> 125 inline 126 _LIBCPP_CONSTEXPR 127 size_t 128 countof(const T * const begin, const T * const end) 129 { 130 return static_cast<size_t>(end - begin); 131 } 132 133 _LIBCPP_NORETURN static void __throw_runtime_error(const string &msg) 134 { 135 #ifndef _LIBCPP_NO_EXCEPTIONS 136 throw runtime_error(msg); 137 #else 138 (void)msg; 139 _VSTD::abort(); 140 #endif 141 } 142 143 } 144 145 #if defined(_AIX) 146 // Set priority to INT_MIN + 256 + 150 147 # pragma priority ( -2147483242 ) 148 #endif 149 150 const locale::category locale::none; 151 const locale::category locale::collate; 152 const locale::category locale::ctype; 153 const locale::category locale::monetary; 154 const locale::category locale::numeric; 155 const locale::category locale::time; 156 const locale::category locale::messages; 157 const locale::category locale::all; 158 159 class _LIBCPP_HIDDEN locale::__imp 160 : public facet 161 { 162 enum {N = 28}; 163 #if defined(_LIBCPP_COMPILER_MSVC) 164 // FIXME: MSVC doesn't support aligned parameters by value. 165 // I can't get the __sso_allocator to work here 166 // for MSVC I think for this reason. 167 vector<facet*> facets_; 168 #else 169 vector<facet*, __sso_allocator<facet*, N> > facets_; 170 #endif 171 string name_; 172 public: 173 explicit __imp(size_t refs = 0); 174 explicit __imp(const string& name, size_t refs = 0); 175 __imp(const __imp&); 176 __imp(const __imp&, const string&, locale::category c); 177 __imp(const __imp& other, const __imp& one, locale::category c); 178 __imp(const __imp&, facet* f, long id); 179 ~__imp(); 180 181 const string& name() const {return name_;} 182 bool has_facet(long id) const 183 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];} 184 const locale::facet* use_facet(long id) const; 185 186 static const locale& make_classic(); 187 static locale& make_global(); 188 private: 189 void install(facet* f, long id); 190 template <class F> void install(F* f) {install(f, f->id.__get());} 191 template <class F> void install_from(const __imp& other); 192 }; 193 194 locale::__imp::__imp(size_t refs) 195 : facet(refs), 196 facets_(N), 197 name_("C") 198 { 199 facets_.clear(); 200 install(&make<_VSTD::collate<char> >(1u)); 201 #ifdef _LIBCPP_SUPPORT_WCHAR 202 install(&make<_VSTD::collate<wchar_t> >(1u)); 203 #endif 204 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u)); 205 #ifdef _LIBCPP_SUPPORT_WCHAR 206 install(&make<_VSTD::ctype<wchar_t> >(1u)); 207 #endif 208 install(&make<codecvt<char, char, mbstate_t> >(1u)); 209 #ifdef _LIBCPP_SUPPORT_WCHAR 210 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u)); 211 #endif 212 install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); 213 install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); 214 install(&make<numpunct<char> >(1u)); 215 #ifdef _LIBCPP_SUPPORT_WCHAR 216 install(&make<numpunct<wchar_t> >(1u)); 217 #endif 218 install(&make<num_get<char> >(1u)); 219 #ifdef _LIBCPP_SUPPORT_WCHAR 220 install(&make<num_get<wchar_t> >(1u)); 221 #endif 222 install(&make<num_put<char> >(1u)); 223 #ifdef _LIBCPP_SUPPORT_WCHAR 224 install(&make<num_put<wchar_t> >(1u)); 225 #endif 226 install(&make<moneypunct<char, false> >(1u)); 227 install(&make<moneypunct<char, true> >(1u)); 228 #ifdef _LIBCPP_SUPPORT_WCHAR 229 install(&make<moneypunct<wchar_t, false> >(1u)); 230 install(&make<moneypunct<wchar_t, true> >(1u)); 231 #endif 232 install(&make<money_get<char> >(1u)); 233 #ifdef _LIBCPP_SUPPORT_WCHAR 234 install(&make<money_get<wchar_t> >(1u)); 235 #endif 236 install(&make<money_put<char> >(1u)); 237 #ifdef _LIBCPP_SUPPORT_WCHAR 238 install(&make<money_put<wchar_t> >(1u)); 239 #endif 240 install(&make<time_get<char> >(1u)); 241 #ifdef _LIBCPP_SUPPORT_WCHAR 242 install(&make<time_get<wchar_t> >(1u)); 243 #endif 244 install(&make<time_put<char> >(1u)); 245 #ifdef _LIBCPP_SUPPORT_WCHAR 246 install(&make<time_put<wchar_t> >(1u)); 247 #endif 248 install(&make<_VSTD::messages<char> >(1u)); 249 #ifdef _LIBCPP_SUPPORT_WCHAR 250 install(&make<_VSTD::messages<wchar_t> >(1u)); 251 #endif 252 } 253 254 locale::__imp::__imp(const string& name, size_t refs) 255 : facet(refs), 256 facets_(N), 257 name_(name) 258 { 259 #ifndef _LIBCPP_NO_EXCEPTIONS 260 try 261 { 262 #endif // _LIBCPP_NO_EXCEPTIONS 263 facets_ = locale::classic().__locale_->facets_; 264 for (unsigned i = 0; i < facets_.size(); ++i) 265 if (facets_[i]) 266 facets_[i]->__add_shared(); 267 install(new collate_byname<char>(name_)); 268 install(new collate_byname<wchar_t>(name_)); 269 install(new ctype_byname<char>(name_)); 270 install(new ctype_byname<wchar_t>(name_)); 271 install(new codecvt_byname<char, char, mbstate_t>(name_)); 272 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_)); 273 install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); 274 install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); 275 install(new numpunct_byname<char>(name_)); 276 install(new numpunct_byname<wchar_t>(name_)); 277 install(new moneypunct_byname<char, false>(name_)); 278 install(new moneypunct_byname<char, true>(name_)); 279 install(new moneypunct_byname<wchar_t, false>(name_)); 280 install(new moneypunct_byname<wchar_t, true>(name_)); 281 install(new time_get_byname<char>(name_)); 282 install(new time_get_byname<wchar_t>(name_)); 283 install(new time_put_byname<char>(name_)); 284 install(new time_put_byname<wchar_t>(name_)); 285 install(new messages_byname<char>(name_)); 286 install(new messages_byname<wchar_t>(name_)); 287 #ifndef _LIBCPP_NO_EXCEPTIONS 288 } 289 catch (...) 290 { 291 for (unsigned i = 0; i < facets_.size(); ++i) 292 if (facets_[i]) 293 facets_[i]->__release_shared(); 294 throw; 295 } 296 #endif // _LIBCPP_NO_EXCEPTIONS 297 } 298 299 // NOTE avoid the `base class should be explicitly initialized in the 300 // copy constructor` warning emitted by GCC 301 #if defined(__clang__) || _GNUC_VER >= 406 302 #pragma GCC diagnostic push 303 #pragma GCC diagnostic ignored "-Wextra" 304 #endif 305 306 locale::__imp::__imp(const __imp& other) 307 : facets_(max<size_t>(N, other.facets_.size())), 308 name_(other.name_) 309 { 310 facets_ = other.facets_; 311 for (unsigned i = 0; i < facets_.size(); ++i) 312 if (facets_[i]) 313 facets_[i]->__add_shared(); 314 } 315 316 #if defined(__clang__) || _GNUC_VER >= 406 317 #pragma GCC diagnostic pop 318 #endif 319 320 locale::__imp::__imp(const __imp& other, const string& name, locale::category c) 321 : facets_(N), 322 name_("*") 323 { 324 facets_ = other.facets_; 325 for (unsigned i = 0; i < facets_.size(); ++i) 326 if (facets_[i]) 327 facets_[i]->__add_shared(); 328 #ifndef _LIBCPP_NO_EXCEPTIONS 329 try 330 { 331 #endif // _LIBCPP_NO_EXCEPTIONS 332 if (c & locale::collate) 333 { 334 install(new collate_byname<char>(name)); 335 install(new collate_byname<wchar_t>(name)); 336 } 337 if (c & locale::ctype) 338 { 339 install(new ctype_byname<char>(name)); 340 install(new ctype_byname<wchar_t>(name)); 341 install(new codecvt_byname<char, char, mbstate_t>(name)); 342 install(new codecvt_byname<wchar_t, char, mbstate_t>(name)); 343 install(new codecvt_byname<char16_t, char, mbstate_t>(name)); 344 install(new codecvt_byname<char32_t, char, mbstate_t>(name)); 345 } 346 if (c & locale::monetary) 347 { 348 install(new moneypunct_byname<char, false>(name)); 349 install(new moneypunct_byname<char, true>(name)); 350 install(new moneypunct_byname<wchar_t, false>(name)); 351 install(new moneypunct_byname<wchar_t, true>(name)); 352 } 353 if (c & locale::numeric) 354 { 355 install(new numpunct_byname<char>(name)); 356 install(new numpunct_byname<wchar_t>(name)); 357 } 358 if (c & locale::time) 359 { 360 install(new time_get_byname<char>(name)); 361 install(new time_get_byname<wchar_t>(name)); 362 install(new time_put_byname<char>(name)); 363 install(new time_put_byname<wchar_t>(name)); 364 } 365 if (c & locale::messages) 366 { 367 install(new messages_byname<char>(name)); 368 install(new messages_byname<wchar_t>(name)); 369 } 370 #ifndef _LIBCPP_NO_EXCEPTIONS 371 } 372 catch (...) 373 { 374 for (unsigned i = 0; i < facets_.size(); ++i) 375 if (facets_[i]) 376 facets_[i]->__release_shared(); 377 throw; 378 } 379 #endif // _LIBCPP_NO_EXCEPTIONS 380 } 381 382 template<class F> 383 inline 384 void 385 locale::__imp::install_from(const locale::__imp& one) 386 { 387 long id = F::id.__get(); 388 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id); 389 } 390 391 locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) 392 : facets_(N), 393 name_("*") 394 { 395 facets_ = other.facets_; 396 for (unsigned i = 0; i < facets_.size(); ++i) 397 if (facets_[i]) 398 facets_[i]->__add_shared(); 399 #ifndef _LIBCPP_NO_EXCEPTIONS 400 try 401 { 402 #endif // _LIBCPP_NO_EXCEPTIONS 403 if (c & locale::collate) 404 { 405 install_from<_VSTD::collate<char> >(one); 406 install_from<_VSTD::collate<wchar_t> >(one); 407 } 408 if (c & locale::ctype) 409 { 410 install_from<_VSTD::ctype<char> >(one); 411 install_from<_VSTD::ctype<wchar_t> >(one); 412 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one); 413 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one); 414 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one); 415 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one); 416 } 417 if (c & locale::monetary) 418 { 419 install_from<moneypunct<char, false> >(one); 420 install_from<moneypunct<char, true> >(one); 421 install_from<moneypunct<wchar_t, false> >(one); 422 install_from<moneypunct<wchar_t, true> >(one); 423 install_from<money_get<char> >(one); 424 install_from<money_get<wchar_t> >(one); 425 install_from<money_put<char> >(one); 426 install_from<money_put<wchar_t> >(one); 427 } 428 if (c & locale::numeric) 429 { 430 install_from<numpunct<char> >(one); 431 install_from<numpunct<wchar_t> >(one); 432 install_from<num_get<char> >(one); 433 install_from<num_get<wchar_t> >(one); 434 install_from<num_put<char> >(one); 435 install_from<num_put<wchar_t> >(one); 436 } 437 if (c & locale::time) 438 { 439 install_from<time_get<char> >(one); 440 install_from<time_get<wchar_t> >(one); 441 install_from<time_put<char> >(one); 442 install_from<time_put<wchar_t> >(one); 443 } 444 if (c & locale::messages) 445 { 446 install_from<_VSTD::messages<char> >(one); 447 install_from<_VSTD::messages<wchar_t> >(one); 448 } 449 #ifndef _LIBCPP_NO_EXCEPTIONS 450 } 451 catch (...) 452 { 453 for (unsigned i = 0; i < facets_.size(); ++i) 454 if (facets_[i]) 455 facets_[i]->__release_shared(); 456 throw; 457 } 458 #endif // _LIBCPP_NO_EXCEPTIONS 459 } 460 461 locale::__imp::__imp(const __imp& other, facet* f, long id) 462 : facets_(max<size_t>(N, other.facets_.size()+1)), 463 name_("*") 464 { 465 f->__add_shared(); 466 unique_ptr<facet, release> hold(f); 467 facets_ = other.facets_; 468 for (unsigned i = 0; i < other.facets_.size(); ++i) 469 if (facets_[i]) 470 facets_[i]->__add_shared(); 471 install(hold.get(), id); 472 } 473 474 locale::__imp::~__imp() 475 { 476 for (unsigned i = 0; i < facets_.size(); ++i) 477 if (facets_[i]) 478 facets_[i]->__release_shared(); 479 } 480 481 void 482 locale::__imp::install(facet* f, long id) 483 { 484 f->__add_shared(); 485 unique_ptr<facet, release> hold(f); 486 if (static_cast<size_t>(id) >= facets_.size()) 487 facets_.resize(static_cast<size_t>(id+1)); 488 if (facets_[static_cast<size_t>(id)]) 489 facets_[static_cast<size_t>(id)]->__release_shared(); 490 facets_[static_cast<size_t>(id)] = hold.release(); 491 } 492 493 const locale::facet* 494 locale::__imp::use_facet(long id) const 495 { 496 #ifndef _LIBCPP_NO_EXCEPTIONS 497 if (!has_facet(id)) 498 throw bad_cast(); 499 #endif // _LIBCPP_NO_EXCEPTIONS 500 return facets_[static_cast<size_t>(id)]; 501 } 502 503 // locale 504 505 const locale& 506 locale::__imp::make_classic() 507 { 508 // only one thread can get in here and it only gets in once 509 static aligned_storage<sizeof(locale)>::type buf; 510 locale* c = reinterpret_cast<locale*>(&buf); 511 c->__locale_ = &make<__imp>(1u); 512 return *c; 513 } 514 515 const locale& 516 locale::classic() 517 { 518 static const locale& c = __imp::make_classic(); 519 return c; 520 } 521 522 locale& 523 locale::__imp::make_global() 524 { 525 // only one thread can get in here and it only gets in once 526 static aligned_storage<sizeof(locale)>::type buf; 527 auto *obj = ::new (&buf) locale(locale::classic()); 528 return *obj; 529 } 530 531 locale& 532 locale::__global() 533 { 534 static locale& g = __imp::make_global(); 535 return g; 536 } 537 538 locale::locale() _NOEXCEPT 539 : __locale_(__global().__locale_) 540 { 541 __locale_->__add_shared(); 542 } 543 544 locale::locale(const locale& l) _NOEXCEPT 545 : __locale_(l.__locale_) 546 { 547 __locale_->__add_shared(); 548 } 549 550 locale::~locale() 551 { 552 __locale_->__release_shared(); 553 } 554 555 const locale& 556 locale::operator=(const locale& other) _NOEXCEPT 557 { 558 other.__locale_->__add_shared(); 559 __locale_->__release_shared(); 560 __locale_ = other.__locale_; 561 return *this; 562 } 563 564 locale::locale(const char* name) 565 #ifndef _LIBCPP_NO_EXCEPTIONS 566 : __locale_(name ? new __imp(name) 567 : throw runtime_error("locale constructed with null")) 568 #else // _LIBCPP_NO_EXCEPTIONS 569 : __locale_(new __imp(name)) 570 #endif 571 { 572 __locale_->__add_shared(); 573 } 574 575 locale::locale(const string& name) 576 : __locale_(new __imp(name)) 577 { 578 __locale_->__add_shared(); 579 } 580 581 locale::locale(const locale& other, const char* name, category c) 582 #ifndef _LIBCPP_NO_EXCEPTIONS 583 : __locale_(name ? new __imp(*other.__locale_, name, c) 584 : throw runtime_error("locale constructed with null")) 585 #else // _LIBCPP_NO_EXCEPTIONS 586 : __locale_(new __imp(*other.__locale_, name, c)) 587 #endif 588 { 589 __locale_->__add_shared(); 590 } 591 592 locale::locale(const locale& other, const string& name, category c) 593 : __locale_(new __imp(*other.__locale_, name, c)) 594 { 595 __locale_->__add_shared(); 596 } 597 598 locale::locale(const locale& other, const locale& one, category c) 599 : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) 600 { 601 __locale_->__add_shared(); 602 } 603 604 string 605 locale::name() const 606 { 607 return __locale_->name(); 608 } 609 610 void 611 locale::__install_ctor(const locale& other, facet* f, long id) 612 { 613 if (f) 614 __locale_ = new __imp(*other.__locale_, f, id); 615 else 616 __locale_ = other.__locale_; 617 __locale_->__add_shared(); 618 } 619 620 locale 621 locale::global(const locale& loc) 622 { 623 locale& g = __global(); 624 locale r = g; 625 g = loc; 626 if (g.name() != "*") 627 setlocale(LC_ALL, g.name().c_str()); 628 return r; 629 } 630 631 bool 632 locale::has_facet(id& x) const 633 { 634 return __locale_->has_facet(x.__get()); 635 } 636 637 const locale::facet* 638 locale::use_facet(id& x) const 639 { 640 return __locale_->use_facet(x.__get()); 641 } 642 643 bool 644 locale::operator==(const locale& y) const 645 { 646 return (__locale_ == y.__locale_) 647 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name()); 648 } 649 650 // locale::facet 651 652 locale::facet::~facet() 653 { 654 } 655 656 void 657 locale::facet::__on_zero_shared() _NOEXCEPT 658 { 659 delete this; 660 } 661 662 // locale::id 663 664 int32_t locale::id::__next_id = 0; 665 666 namespace 667 { 668 669 class __fake_bind 670 { 671 locale::id* id_; 672 void (locale::id::* pmf_)(); 673 public: 674 __fake_bind(void (locale::id::* pmf)(), locale::id* id) 675 : id_(id), pmf_(pmf) {} 676 677 void operator()() const 678 { 679 (id_->*pmf_)(); 680 } 681 }; 682 683 } 684 685 long 686 locale::id::__get() 687 { 688 call_once(__flag_, __fake_bind(&locale::id::__init, this)); 689 return __id_ - 1; 690 } 691 692 void 693 locale::id::__init() 694 { 695 __id_ = __libcpp_atomic_add(&__next_id, 1); 696 } 697 698 // template <> class collate_byname<char> 699 700 collate_byname<char>::collate_byname(const char* n, size_t refs) 701 : collate<char>(refs), 702 __l(newlocale(LC_ALL_MASK, n, 0)) 703 { 704 if (__l == 0) 705 __throw_runtime_error("collate_byname<char>::collate_byname" 706 " failed to construct for " + string(n)); 707 } 708 709 collate_byname<char>::collate_byname(const string& name, size_t refs) 710 : collate<char>(refs), 711 __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) 712 { 713 if (__l == 0) 714 __throw_runtime_error("collate_byname<char>::collate_byname" 715 " failed to construct for " + name); 716 } 717 718 collate_byname<char>::~collate_byname() 719 { 720 freelocale(__l); 721 } 722 723 int 724 collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1, 725 const char_type* __lo2, const char_type* __hi2) const 726 { 727 string_type lhs(__lo1, __hi1); 728 string_type rhs(__lo2, __hi2); 729 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l); 730 if (r < 0) 731 return -1; 732 if (r > 0) 733 return 1; 734 return r; 735 } 736 737 collate_byname<char>::string_type 738 collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const 739 { 740 const string_type in(lo, hi); 741 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char()); 742 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l); 743 return out; 744 } 745 746 // template <> class collate_byname<wchar_t> 747 748 collate_byname<wchar_t>::collate_byname(const char* n, size_t refs) 749 : collate<wchar_t>(refs), 750 __l(newlocale(LC_ALL_MASK, n, 0)) 751 { 752 if (__l == 0) 753 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" 754 " failed to construct for " + string(n)); 755 } 756 757 collate_byname<wchar_t>::collate_byname(const string& name, size_t refs) 758 : collate<wchar_t>(refs), 759 __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) 760 { 761 if (__l == 0) 762 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" 763 " failed to construct for " + name); 764 } 765 766 collate_byname<wchar_t>::~collate_byname() 767 { 768 freelocale(__l); 769 } 770 771 int 772 collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1, 773 const char_type* __lo2, const char_type* __hi2) const 774 { 775 string_type lhs(__lo1, __hi1); 776 string_type rhs(__lo2, __hi2); 777 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l); 778 if (r < 0) 779 return -1; 780 if (r > 0) 781 return 1; 782 return r; 783 } 784 785 collate_byname<wchar_t>::string_type 786 collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const 787 { 788 const string_type in(lo, hi); 789 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t()); 790 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l); 791 return out; 792 } 793 794 // template <> class ctype<wchar_t>; 795 796 const ctype_base::mask ctype_base::space; 797 const ctype_base::mask ctype_base::print; 798 const ctype_base::mask ctype_base::cntrl; 799 const ctype_base::mask ctype_base::upper; 800 const ctype_base::mask ctype_base::lower; 801 const ctype_base::mask ctype_base::alpha; 802 const ctype_base::mask ctype_base::digit; 803 const ctype_base::mask ctype_base::punct; 804 const ctype_base::mask ctype_base::xdigit; 805 const ctype_base::mask ctype_base::blank; 806 const ctype_base::mask ctype_base::alnum; 807 const ctype_base::mask ctype_base::graph; 808 809 locale::id ctype<wchar_t>::id; 810 811 ctype<wchar_t>::~ctype() 812 { 813 } 814 815 bool 816 ctype<wchar_t>::do_is(mask m, char_type c) const 817 { 818 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false; 819 } 820 821 const wchar_t* 822 ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const 823 { 824 for (; low != high; ++low, ++vec) 825 *vec = static_cast<mask>(isascii(*low) ? 826 ctype<char>::classic_table()[*low] : 0); 827 return low; 828 } 829 830 const wchar_t* 831 ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const 832 { 833 for (; low != high; ++low) 834 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m)) 835 break; 836 return low; 837 } 838 839 const wchar_t* 840 ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const 841 { 842 for (; low != high; ++low) 843 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m))) 844 break; 845 return low; 846 } 847 848 wchar_t 849 ctype<wchar_t>::do_toupper(char_type c) const 850 { 851 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 852 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; 853 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ 854 defined(__NetBSD__) 855 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; 856 #else 857 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c; 858 #endif 859 } 860 861 const wchar_t* 862 ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const 863 { 864 for (; low != high; ++low) 865 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 866 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; 867 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ 868 defined(__NetBSD__) 869 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] 870 : *low; 871 #else 872 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low; 873 #endif 874 return low; 875 } 876 877 wchar_t 878 ctype<wchar_t>::do_tolower(char_type c) const 879 { 880 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 881 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; 882 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ 883 defined(__NetBSD__) 884 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; 885 #else 886 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c; 887 #endif 888 } 889 890 const wchar_t* 891 ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const 892 { 893 for (; low != high; ++low) 894 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 895 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; 896 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ 897 defined(__NetBSD__) 898 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] 899 : *low; 900 #else 901 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low; 902 #endif 903 return low; 904 } 905 906 wchar_t 907 ctype<wchar_t>::do_widen(char c) const 908 { 909 return c; 910 } 911 912 const char* 913 ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const 914 { 915 for (; low != high; ++low, ++dest) 916 *dest = *low; 917 return low; 918 } 919 920 char 921 ctype<wchar_t>::do_narrow(char_type c, char dfault) const 922 { 923 if (isascii(c)) 924 return static_cast<char>(c); 925 return dfault; 926 } 927 928 const wchar_t* 929 ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const 930 { 931 for (; low != high; ++low, ++dest) 932 if (isascii(*low)) 933 *dest = static_cast<char>(*low); 934 else 935 *dest = dfault; 936 return low; 937 } 938 939 // template <> class ctype<char>; 940 941 locale::id ctype<char>::id; 942 943 ctype<char>::ctype(const mask* tab, bool del, size_t refs) 944 : locale::facet(refs), 945 __tab_(tab), 946 __del_(del) 947 { 948 if (__tab_ == 0) 949 __tab_ = classic_table(); 950 } 951 952 ctype<char>::~ctype() 953 { 954 if (__tab_ && __del_) 955 delete [] __tab_; 956 } 957 958 char 959 ctype<char>::do_toupper(char_type c) const 960 { 961 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 962 return isascii(c) ? 963 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c; 964 #elif defined(__NetBSD__) 965 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]); 966 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) 967 return isascii(c) ? 968 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c; 969 #else 970 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c; 971 #endif 972 } 973 974 const char* 975 ctype<char>::do_toupper(char_type* low, const char_type* high) const 976 { 977 for (; low != high; ++low) 978 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 979 *low = isascii(*low) ? 980 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low; 981 #elif defined(__NetBSD__) 982 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]); 983 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) 984 *low = isascii(*low) ? 985 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low; 986 #else 987 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low; 988 #endif 989 return low; 990 } 991 992 char 993 ctype<char>::do_tolower(char_type c) const 994 { 995 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 996 return isascii(c) ? 997 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c; 998 #elif defined(__NetBSD__) 999 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]); 1000 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) 1001 return isascii(c) ? 1002 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c; 1003 #else 1004 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c; 1005 #endif 1006 } 1007 1008 const char* 1009 ctype<char>::do_tolower(char_type* low, const char_type* high) const 1010 { 1011 for (; low != high; ++low) 1012 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 1013 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low; 1014 #elif defined(__NetBSD__) 1015 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]); 1016 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) 1017 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low; 1018 #else 1019 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low; 1020 #endif 1021 return low; 1022 } 1023 1024 char 1025 ctype<char>::do_widen(char c) const 1026 { 1027 return c; 1028 } 1029 1030 const char* 1031 ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const 1032 { 1033 for (; low != high; ++low, ++dest) 1034 *dest = *low; 1035 return low; 1036 } 1037 1038 char 1039 ctype<char>::do_narrow(char_type c, char dfault) const 1040 { 1041 if (isascii(c)) 1042 return static_cast<char>(c); 1043 return dfault; 1044 } 1045 1046 const char* 1047 ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const 1048 { 1049 for (; low != high; ++low, ++dest) 1050 if (isascii(*low)) 1051 *dest = *low; 1052 else 1053 *dest = dfault; 1054 return low; 1055 } 1056 1057 #if defined(__EMSCRIPTEN__) 1058 extern "C" const unsigned short ** __ctype_b_loc(); 1059 extern "C" const int ** __ctype_tolower_loc(); 1060 extern "C" const int ** __ctype_toupper_loc(); 1061 #endif 1062 1063 #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 1064 const ctype<char>::mask* 1065 ctype<char>::classic_table() _NOEXCEPT 1066 { 1067 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = { 1068 cntrl, cntrl, 1069 cntrl, cntrl, 1070 cntrl, cntrl, 1071 cntrl, cntrl, 1072 cntrl, cntrl | space | blank, 1073 cntrl | space, cntrl | space, 1074 cntrl | space, cntrl | space, 1075 cntrl, cntrl, 1076 cntrl, cntrl, 1077 cntrl, cntrl, 1078 cntrl, cntrl, 1079 cntrl, cntrl, 1080 cntrl, cntrl, 1081 cntrl, cntrl, 1082 cntrl, cntrl, 1083 cntrl, cntrl, 1084 space | blank | print, punct | print, 1085 punct | print, punct | print, 1086 punct | print, punct | print, 1087 punct | print, punct | print, 1088 punct | print, punct | print, 1089 punct | print, punct | print, 1090 punct | print, punct | print, 1091 punct | print, punct | print, 1092 digit | print | xdigit, digit | print | xdigit, 1093 digit | print | xdigit, digit | print | xdigit, 1094 digit | print | xdigit, digit | print | xdigit, 1095 digit | print | xdigit, digit | print | xdigit, 1096 digit | print | xdigit, digit | print | xdigit, 1097 punct | print, punct | print, 1098 punct | print, punct | print, 1099 punct | print, punct | print, 1100 punct | print, upper | xdigit | print | alpha, 1101 upper | xdigit | print | alpha, upper | xdigit | print | alpha, 1102 upper | xdigit | print | alpha, upper | xdigit | print | alpha, 1103 upper | xdigit | print | alpha, upper | print | alpha, 1104 upper | print | alpha, upper | print | alpha, 1105 upper | print | alpha, upper | print | alpha, 1106 upper | print | alpha, upper | print | alpha, 1107 upper | print | alpha, upper | print | alpha, 1108 upper | print | alpha, upper | print | alpha, 1109 upper | print | alpha, upper | print | alpha, 1110 upper | print | alpha, upper | print | alpha, 1111 upper | print | alpha, upper | print | alpha, 1112 upper | print | alpha, upper | print | alpha, 1113 upper | print | alpha, punct | print, 1114 punct | print, punct | print, 1115 punct | print, punct | print, 1116 punct | print, lower | xdigit | print | alpha, 1117 lower | xdigit | print | alpha, lower | xdigit | print | alpha, 1118 lower | xdigit | print | alpha, lower | xdigit | print | alpha, 1119 lower | xdigit | print | alpha, lower | print | alpha, 1120 lower | print | alpha, lower | print | alpha, 1121 lower | print | alpha, lower | print | alpha, 1122 lower | print | alpha, lower | print | alpha, 1123 lower | print | alpha, lower | print | alpha, 1124 lower | print | alpha, lower | print | alpha, 1125 lower | print | alpha, lower | print | alpha, 1126 lower | print | alpha, lower | print | alpha, 1127 lower | print | alpha, lower | print | alpha, 1128 lower | print | alpha, lower | print | alpha, 1129 lower | print | alpha, punct | print, 1130 punct | print, punct | print, 1131 punct | print, cntrl, 1132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 1140 }; 1141 return builtin_table; 1142 } 1143 #else 1144 const ctype<char>::mask* 1145 ctype<char>::classic_table() _NOEXCEPT 1146 { 1147 #if defined(__APPLE__) || defined(__FreeBSD__) 1148 return _DefaultRuneLocale.__runetype; 1149 #elif defined(__NetBSD__) 1150 return _C_ctype_tab_ + 1; 1151 #elif defined(__GLIBC__) 1152 return _LIBCPP_GET_C_LOCALE->__ctype_b; 1153 #elif __sun__ 1154 return __ctype_mask; 1155 #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 1156 return __pctype_func(); 1157 #elif defined(__EMSCRIPTEN__) 1158 return *__ctype_b_loc(); 1159 #elif defined(_NEWLIB_VERSION) 1160 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1]. 1161 return _ctype_ + 1; 1162 #elif defined(_AIX) 1163 return (const unsigned int *)__lc_ctype_ptr->obj->mask; 1164 #else 1165 // Platform not supported: abort so the person doing the port knows what to 1166 // fix 1167 # warning ctype<char>::classic_table() is not implemented 1168 printf("ctype<char>::classic_table() is not implemented\n"); 1169 abort(); 1170 return NULL; 1171 #endif 1172 } 1173 #endif 1174 1175 #if defined(__GLIBC__) 1176 const int* 1177 ctype<char>::__classic_lower_table() _NOEXCEPT 1178 { 1179 return _LIBCPP_GET_C_LOCALE->__ctype_tolower; 1180 } 1181 1182 const int* 1183 ctype<char>::__classic_upper_table() _NOEXCEPT 1184 { 1185 return _LIBCPP_GET_C_LOCALE->__ctype_toupper; 1186 } 1187 #elif __NetBSD__ 1188 const short* 1189 ctype<char>::__classic_lower_table() _NOEXCEPT 1190 { 1191 return _C_tolower_tab_ + 1; 1192 } 1193 1194 const short* 1195 ctype<char>::__classic_upper_table() _NOEXCEPT 1196 { 1197 return _C_toupper_tab_ + 1; 1198 } 1199 1200 #elif defined(__EMSCRIPTEN__) 1201 const int* 1202 ctype<char>::__classic_lower_table() _NOEXCEPT 1203 { 1204 return *__ctype_tolower_loc(); 1205 } 1206 1207 const int* 1208 ctype<char>::__classic_upper_table() _NOEXCEPT 1209 { 1210 return *__ctype_toupper_loc(); 1211 } 1212 #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ 1213 1214 // template <> class ctype_byname<char> 1215 1216 ctype_byname<char>::ctype_byname(const char* name, size_t refs) 1217 : ctype<char>(0, false, refs), 1218 __l(newlocale(LC_ALL_MASK, name, 0)) 1219 { 1220 if (__l == 0) 1221 __throw_runtime_error("ctype_byname<char>::ctype_byname" 1222 " failed to construct for " + string(name)); 1223 } 1224 1225 ctype_byname<char>::ctype_byname(const string& name, size_t refs) 1226 : ctype<char>(0, false, refs), 1227 __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) 1228 { 1229 if (__l == 0) 1230 __throw_runtime_error("ctype_byname<char>::ctype_byname" 1231 " failed to construct for " + name); 1232 } 1233 1234 ctype_byname<char>::~ctype_byname() 1235 { 1236 freelocale(__l); 1237 } 1238 1239 char 1240 ctype_byname<char>::do_toupper(char_type c) const 1241 { 1242 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l)); 1243 } 1244 1245 const char* 1246 ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const 1247 { 1248 for (; low != high; ++low) 1249 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l)); 1250 return low; 1251 } 1252 1253 char 1254 ctype_byname<char>::do_tolower(char_type c) const 1255 { 1256 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l)); 1257 } 1258 1259 const char* 1260 ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const 1261 { 1262 for (; low != high; ++low) 1263 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l)); 1264 return low; 1265 } 1266 1267 // template <> class ctype_byname<wchar_t> 1268 1269 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs) 1270 : ctype<wchar_t>(refs), 1271 __l(newlocale(LC_ALL_MASK, name, 0)) 1272 { 1273 if (__l == 0) 1274 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" 1275 " failed to construct for " + string(name)); 1276 } 1277 1278 ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs) 1279 : ctype<wchar_t>(refs), 1280 __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) 1281 { 1282 if (__l == 0) 1283 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" 1284 " failed to construct for " + name); 1285 } 1286 1287 ctype_byname<wchar_t>::~ctype_byname() 1288 { 1289 freelocale(__l); 1290 } 1291 1292 bool 1293 ctype_byname<wchar_t>::do_is(mask m, char_type c) const 1294 { 1295 #ifdef _LIBCPP_WCTYPE_IS_MASK 1296 return static_cast<bool>(iswctype_l(c, m, __l)); 1297 #else 1298 bool result = false; 1299 wint_t ch = static_cast<wint_t>(c); 1300 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0); 1301 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0); 1302 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0); 1303 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0); 1304 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0); 1305 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0); 1306 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0); 1307 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0); 1308 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0); 1309 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0); 1310 return result; 1311 #endif 1312 } 1313 1314 const wchar_t* 1315 ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const 1316 { 1317 for (; low != high; ++low, ++vec) 1318 { 1319 if (isascii(*low)) 1320 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]); 1321 else 1322 { 1323 *vec = 0; 1324 wint_t ch = static_cast<wint_t>(*low); 1325 if (iswspace_l(ch, __l)) 1326 *vec |= space; 1327 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT 1328 if (iswprint_l(ch, __l)) 1329 *vec |= print; 1330 #endif 1331 if (iswcntrl_l(ch, __l)) 1332 *vec |= cntrl; 1333 if (iswupper_l(ch, __l)) 1334 *vec |= upper; 1335 if (iswlower_l(ch, __l)) 1336 *vec |= lower; 1337 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA 1338 if (iswalpha_l(ch, __l)) 1339 *vec |= alpha; 1340 #endif 1341 if (iswdigit_l(ch, __l)) 1342 *vec |= digit; 1343 if (iswpunct_l(ch, __l)) 1344 *vec |= punct; 1345 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT 1346 if (iswxdigit_l(ch, __l)) 1347 *vec |= xdigit; 1348 #endif 1349 #if !defined(__sun__) 1350 if (iswblank_l(ch, __l)) 1351 *vec |= blank; 1352 #endif 1353 } 1354 } 1355 return low; 1356 } 1357 1358 const wchar_t* 1359 ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const 1360 { 1361 for (; low != high; ++low) 1362 { 1363 #ifdef _LIBCPP_WCTYPE_IS_MASK 1364 if (iswctype_l(*low, m, __l)) 1365 break; 1366 #else 1367 wint_t ch = static_cast<wint_t>(*low); 1368 if ((m & space) == space && iswspace_l(ch, __l)) break; 1369 if ((m & print) == print && iswprint_l(ch, __l)) break; 1370 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break; 1371 if ((m & upper) == upper && iswupper_l(ch, __l)) break; 1372 if ((m & lower) == lower && iswlower_l(ch, __l)) break; 1373 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break; 1374 if ((m & digit) == digit && iswdigit_l(ch, __l)) break; 1375 if ((m & punct) == punct && iswpunct_l(ch, __l)) break; 1376 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break; 1377 if ((m & blank) == blank && iswblank_l(ch, __l)) break; 1378 #endif 1379 } 1380 return low; 1381 } 1382 1383 const wchar_t* 1384 ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const 1385 { 1386 for (; low != high; ++low) 1387 { 1388 #ifdef _LIBCPP_WCTYPE_IS_MASK 1389 if (!iswctype_l(*low, m, __l)) 1390 break; 1391 #else 1392 wint_t ch = static_cast<wint_t>(*low); 1393 if ((m & space) == space && iswspace_l(ch, __l)) continue; 1394 if ((m & print) == print && iswprint_l(ch, __l)) continue; 1395 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue; 1396 if ((m & upper) == upper && iswupper_l(ch, __l)) continue; 1397 if ((m & lower) == lower && iswlower_l(ch, __l)) continue; 1398 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue; 1399 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue; 1400 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue; 1401 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue; 1402 if ((m & blank) == blank && iswblank_l(ch, __l)) continue; 1403 break; 1404 #endif 1405 } 1406 return low; 1407 } 1408 1409 wchar_t 1410 ctype_byname<wchar_t>::do_toupper(char_type c) const 1411 { 1412 return towupper_l(c, __l); 1413 } 1414 1415 const wchar_t* 1416 ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const 1417 { 1418 for (; low != high; ++low) 1419 *low = towupper_l(*low, __l); 1420 return low; 1421 } 1422 1423 wchar_t 1424 ctype_byname<wchar_t>::do_tolower(char_type c) const 1425 { 1426 return towlower_l(c, __l); 1427 } 1428 1429 const wchar_t* 1430 ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const 1431 { 1432 for (; low != high; ++low) 1433 *low = towlower_l(*low, __l); 1434 return low; 1435 } 1436 1437 wchar_t 1438 ctype_byname<wchar_t>::do_widen(char c) const 1439 { 1440 return __libcpp_btowc_l(c, __l); 1441 } 1442 1443 const char* 1444 ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const 1445 { 1446 for (; low != high; ++low, ++dest) 1447 *dest = __libcpp_btowc_l(*low, __l); 1448 return low; 1449 } 1450 1451 char 1452 ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const 1453 { 1454 int r = __libcpp_wctob_l(c, __l); 1455 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; 1456 } 1457 1458 const wchar_t* 1459 ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const 1460 { 1461 for (; low != high; ++low, ++dest) 1462 { 1463 int r = __libcpp_wctob_l(*low, __l); 1464 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; 1465 } 1466 return low; 1467 } 1468 1469 // template <> class codecvt<char, char, mbstate_t> 1470 1471 locale::id codecvt<char, char, mbstate_t>::id; 1472 1473 codecvt<char, char, mbstate_t>::~codecvt() 1474 { 1475 } 1476 1477 codecvt<char, char, mbstate_t>::result 1478 codecvt<char, char, mbstate_t>::do_out(state_type&, 1479 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt, 1480 extern_type* to, extern_type*, extern_type*& to_nxt) const 1481 { 1482 frm_nxt = frm; 1483 to_nxt = to; 1484 return noconv; 1485 } 1486 1487 codecvt<char, char, mbstate_t>::result 1488 codecvt<char, char, mbstate_t>::do_in(state_type&, 1489 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt, 1490 intern_type* to, intern_type*, intern_type*& to_nxt) const 1491 { 1492 frm_nxt = frm; 1493 to_nxt = to; 1494 return noconv; 1495 } 1496 1497 codecvt<char, char, mbstate_t>::result 1498 codecvt<char, char, mbstate_t>::do_unshift(state_type&, 1499 extern_type* to, extern_type*, extern_type*& to_nxt) const 1500 { 1501 to_nxt = to; 1502 return noconv; 1503 } 1504 1505 int 1506 codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT 1507 { 1508 return 1; 1509 } 1510 1511 bool 1512 codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT 1513 { 1514 return true; 1515 } 1516 1517 int 1518 codecvt<char, char, mbstate_t>::do_length(state_type&, 1519 const extern_type* frm, const extern_type* end, size_t mx) const 1520 { 1521 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm))); 1522 } 1523 1524 int 1525 codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT 1526 { 1527 return 1; 1528 } 1529 1530 // template <> class codecvt<wchar_t, char, mbstate_t> 1531 1532 locale::id codecvt<wchar_t, char, mbstate_t>::id; 1533 1534 codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) 1535 : locale::facet(refs), 1536 __l(_LIBCPP_GET_C_LOCALE) 1537 { 1538 } 1539 1540 codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs) 1541 : locale::facet(refs), 1542 __l(newlocale(LC_ALL_MASK, nm, 0)) 1543 { 1544 if (__l == 0) 1545 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname" 1546 " failed to construct for " + string(nm)); 1547 } 1548 1549 codecvt<wchar_t, char, mbstate_t>::~codecvt() 1550 { 1551 if (__l != _LIBCPP_GET_C_LOCALE) 1552 freelocale(__l); 1553 } 1554 1555 codecvt<wchar_t, char, mbstate_t>::result 1556 codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st, 1557 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 1558 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 1559 { 1560 // look for first internal null in frm 1561 const intern_type* fend = frm; 1562 for (; fend != frm_end; ++fend) 1563 if (*fend == 0) 1564 break; 1565 // loop over all null-terminated sequences in frm 1566 to_nxt = to; 1567 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) 1568 { 1569 // save state in case it is needed to recover to_nxt on error 1570 mbstate_t save_state = st; 1571 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), 1572 static_cast<size_t>(to_end-to), &st, __l); 1573 if (n == size_t(-1)) 1574 { 1575 // need to recover to_nxt 1576 for (to_nxt = to; frm != frm_nxt; ++frm) 1577 { 1578 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l); 1579 if (n == size_t(-1)) 1580 break; 1581 to_nxt += n; 1582 } 1583 frm_nxt = frm; 1584 return error; 1585 } 1586 if (n == 0) 1587 return partial; 1588 to_nxt += n; 1589 if (to_nxt == to_end) 1590 break; 1591 if (fend != frm_end) // set up next null terminated sequence 1592 { 1593 // Try to write the terminating null 1594 extern_type tmp[MB_LEN_MAX]; 1595 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); 1596 if (n == size_t(-1)) // on error 1597 return error; 1598 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? 1599 return partial; 1600 for (extern_type* p = tmp; n; --n) // write it 1601 *to_nxt++ = *p++; 1602 ++frm_nxt; 1603 // look for next null in frm 1604 for (fend = frm_nxt; fend != frm_end; ++fend) 1605 if (*fend == 0) 1606 break; 1607 } 1608 } 1609 return frm_nxt == frm_end ? ok : partial; 1610 } 1611 1612 codecvt<wchar_t, char, mbstate_t>::result 1613 codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, 1614 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 1615 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 1616 { 1617 // look for first internal null in frm 1618 const extern_type* fend = frm; 1619 for (; fend != frm_end; ++fend) 1620 if (*fend == 0) 1621 break; 1622 // loop over all null-terminated sequences in frm 1623 to_nxt = to; 1624 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) 1625 { 1626 // save state in case it is needed to recover to_nxt on error 1627 mbstate_t save_state = st; 1628 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), 1629 static_cast<size_t>(to_end-to), &st, __l); 1630 if (n == size_t(-1)) 1631 { 1632 // need to recover to_nxt 1633 for (to_nxt = to; frm != frm_nxt; ++to_nxt) 1634 { 1635 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm), 1636 &save_state, __l); 1637 switch (n) 1638 { 1639 case 0: 1640 ++frm; 1641 break; 1642 case size_t(-1): 1643 frm_nxt = frm; 1644 return error; 1645 case size_t(-2): 1646 frm_nxt = frm; 1647 return partial; 1648 default: 1649 frm += n; 1650 break; 1651 } 1652 } 1653 frm_nxt = frm; 1654 return frm_nxt == frm_end ? ok : partial; 1655 } 1656 if (n == size_t(-1)) 1657 return error; 1658 to_nxt += n; 1659 if (to_nxt == to_end) 1660 break; 1661 if (fend != frm_end) // set up next null terminated sequence 1662 { 1663 // Try to write the terminating null 1664 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); 1665 if (n != 0) // on error 1666 return error; 1667 ++to_nxt; 1668 ++frm_nxt; 1669 // look for next null in frm 1670 for (fend = frm_nxt; fend != frm_end; ++fend) 1671 if (*fend == 0) 1672 break; 1673 } 1674 } 1675 return frm_nxt == frm_end ? ok : partial; 1676 } 1677 1678 codecvt<wchar_t, char, mbstate_t>::result 1679 codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, 1680 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 1681 { 1682 to_nxt = to; 1683 extern_type tmp[MB_LEN_MAX]; 1684 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); 1685 if (n == size_t(-1) || n == 0) // on error 1686 return error; 1687 --n; 1688 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? 1689 return partial; 1690 for (extern_type* p = tmp; n; --n) // write it 1691 *to_nxt++ = *p++; 1692 return ok; 1693 } 1694 1695 int 1696 codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT 1697 { 1698 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) 1699 return -1; 1700 1701 // stateless encoding 1702 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings 1703 return 1; // which take more than 1 char to form a wchar_t 1704 return 0; 1705 } 1706 1707 bool 1708 codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT 1709 { 1710 return false; 1711 } 1712 1713 int 1714 codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, 1715 const extern_type* frm, const extern_type* frm_end, size_t mx) const 1716 { 1717 int nbytes = 0; 1718 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) 1719 { 1720 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l); 1721 switch (n) 1722 { 1723 case 0: 1724 ++nbytes; 1725 ++frm; 1726 break; 1727 case size_t(-1): 1728 case size_t(-2): 1729 return nbytes; 1730 default: 1731 nbytes += n; 1732 frm += n; 1733 break; 1734 } 1735 } 1736 return nbytes; 1737 } 1738 1739 int 1740 codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT 1741 { 1742 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l)); 1743 } 1744 1745 // Valid UTF ranges 1746 // UTF-32 UTF-16 UTF-8 # of code points 1747 // first second first second third fourth 1748 // 000000 - 00007F 0000 - 007F 00 - 7F 127 1749 // 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920 1750 // 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048 1751 // 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152 1752 // 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048 1753 // 00D800 - 00DFFF invalid 1754 // 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192 1755 // 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608 1756 // 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432 1757 // 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536 1758 1759 static 1760 codecvt_base::result 1761 utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, 1762 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 1763 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 1764 { 1765 frm_nxt = frm; 1766 to_nxt = to; 1767 if (mode & generate_header) 1768 { 1769 if (to_end-to_nxt < 3) 1770 return codecvt_base::partial; 1771 *to_nxt++ = static_cast<uint8_t>(0xEF); 1772 *to_nxt++ = static_cast<uint8_t>(0xBB); 1773 *to_nxt++ = static_cast<uint8_t>(0xBF); 1774 } 1775 for (; frm_nxt < frm_end; ++frm_nxt) 1776 { 1777 uint16_t wc1 = *frm_nxt; 1778 if (wc1 > Maxcode) 1779 return codecvt_base::error; 1780 if (wc1 < 0x0080) 1781 { 1782 if (to_end-to_nxt < 1) 1783 return codecvt_base::partial; 1784 *to_nxt++ = static_cast<uint8_t>(wc1); 1785 } 1786 else if (wc1 < 0x0800) 1787 { 1788 if (to_end-to_nxt < 2) 1789 return codecvt_base::partial; 1790 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); 1791 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); 1792 } 1793 else if (wc1 < 0xD800) 1794 { 1795 if (to_end-to_nxt < 3) 1796 return codecvt_base::partial; 1797 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 1798 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 1799 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 1800 } 1801 else if (wc1 < 0xDC00) 1802 { 1803 if (frm_end-frm_nxt < 2) 1804 return codecvt_base::partial; 1805 uint16_t wc2 = frm_nxt[1]; 1806 if ((wc2 & 0xFC00) != 0xDC00) 1807 return codecvt_base::error; 1808 if (to_end-to_nxt < 4) 1809 return codecvt_base::partial; 1810 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + 1811 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) 1812 return codecvt_base::error; 1813 ++frm_nxt; 1814 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; 1815 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); 1816 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); 1817 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); 1818 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); 1819 } 1820 else if (wc1 < 0xE000) 1821 { 1822 return codecvt_base::error; 1823 } 1824 else 1825 { 1826 if (to_end-to_nxt < 3) 1827 return codecvt_base::partial; 1828 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 1829 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 1830 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 1831 } 1832 } 1833 return codecvt_base::ok; 1834 } 1835 1836 static 1837 codecvt_base::result 1838 utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, 1839 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 1840 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 1841 { 1842 frm_nxt = frm; 1843 to_nxt = to; 1844 if (mode & generate_header) 1845 { 1846 if (to_end-to_nxt < 3) 1847 return codecvt_base::partial; 1848 *to_nxt++ = static_cast<uint8_t>(0xEF); 1849 *to_nxt++ = static_cast<uint8_t>(0xBB); 1850 *to_nxt++ = static_cast<uint8_t>(0xBF); 1851 } 1852 for (; frm_nxt < frm_end; ++frm_nxt) 1853 { 1854 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt); 1855 if (wc1 > Maxcode) 1856 return codecvt_base::error; 1857 if (wc1 < 0x0080) 1858 { 1859 if (to_end-to_nxt < 1) 1860 return codecvt_base::partial; 1861 *to_nxt++ = static_cast<uint8_t>(wc1); 1862 } 1863 else if (wc1 < 0x0800) 1864 { 1865 if (to_end-to_nxt < 2) 1866 return codecvt_base::partial; 1867 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); 1868 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); 1869 } 1870 else if (wc1 < 0xD800) 1871 { 1872 if (to_end-to_nxt < 3) 1873 return codecvt_base::partial; 1874 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 1875 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 1876 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 1877 } 1878 else if (wc1 < 0xDC00) 1879 { 1880 if (frm_end-frm_nxt < 2) 1881 return codecvt_base::partial; 1882 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]); 1883 if ((wc2 & 0xFC00) != 0xDC00) 1884 return codecvt_base::error; 1885 if (to_end-to_nxt < 4) 1886 return codecvt_base::partial; 1887 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + 1888 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) 1889 return codecvt_base::error; 1890 ++frm_nxt; 1891 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; 1892 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); 1893 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); 1894 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); 1895 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); 1896 } 1897 else if (wc1 < 0xE000) 1898 { 1899 return codecvt_base::error; 1900 } 1901 else 1902 { 1903 if (to_end-to_nxt < 3) 1904 return codecvt_base::partial; 1905 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 1906 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 1907 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 1908 } 1909 } 1910 return codecvt_base::ok; 1911 } 1912 1913 static 1914 codecvt_base::result 1915 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 1916 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, 1917 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 1918 { 1919 frm_nxt = frm; 1920 to_nxt = to; 1921 if (mode & consume_header) 1922 { 1923 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && 1924 frm_nxt[2] == 0xBF) 1925 frm_nxt += 3; 1926 } 1927 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) 1928 { 1929 uint8_t c1 = *frm_nxt; 1930 if (c1 > Maxcode) 1931 return codecvt_base::error; 1932 if (c1 < 0x80) 1933 { 1934 *to_nxt = static_cast<uint16_t>(c1); 1935 ++frm_nxt; 1936 } 1937 else if (c1 < 0xC2) 1938 { 1939 return codecvt_base::error; 1940 } 1941 else if (c1 < 0xE0) 1942 { 1943 if (frm_end-frm_nxt < 2) 1944 return codecvt_base::partial; 1945 uint8_t c2 = frm_nxt[1]; 1946 if ((c2 & 0xC0) != 0x80) 1947 return codecvt_base::error; 1948 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); 1949 if (t > Maxcode) 1950 return codecvt_base::error; 1951 *to_nxt = t; 1952 frm_nxt += 2; 1953 } 1954 else if (c1 < 0xF0) 1955 { 1956 if (frm_end-frm_nxt < 3) 1957 return codecvt_base::partial; 1958 uint8_t c2 = frm_nxt[1]; 1959 uint8_t c3 = frm_nxt[2]; 1960 switch (c1) 1961 { 1962 case 0xE0: 1963 if ((c2 & 0xE0) != 0xA0) 1964 return codecvt_base::error; 1965 break; 1966 case 0xED: 1967 if ((c2 & 0xE0) != 0x80) 1968 return codecvt_base::error; 1969 break; 1970 default: 1971 if ((c2 & 0xC0) != 0x80) 1972 return codecvt_base::error; 1973 break; 1974 } 1975 if ((c3 & 0xC0) != 0x80) 1976 return codecvt_base::error; 1977 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) 1978 | ((c2 & 0x3F) << 6) 1979 | (c3 & 0x3F)); 1980 if (t > Maxcode) 1981 return codecvt_base::error; 1982 *to_nxt = t; 1983 frm_nxt += 3; 1984 } 1985 else if (c1 < 0xF5) 1986 { 1987 if (frm_end-frm_nxt < 4) 1988 return codecvt_base::partial; 1989 uint8_t c2 = frm_nxt[1]; 1990 uint8_t c3 = frm_nxt[2]; 1991 uint8_t c4 = frm_nxt[3]; 1992 switch (c1) 1993 { 1994 case 0xF0: 1995 if (!(0x90 <= c2 && c2 <= 0xBF)) 1996 return codecvt_base::error; 1997 break; 1998 case 0xF4: 1999 if ((c2 & 0xF0) != 0x80) 2000 return codecvt_base::error; 2001 break; 2002 default: 2003 if ((c2 & 0xC0) != 0x80) 2004 return codecvt_base::error; 2005 break; 2006 } 2007 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) 2008 return codecvt_base::error; 2009 if (to_end-to_nxt < 2) 2010 return codecvt_base::partial; 2011 if ((((c1 & 7UL) << 18) + 2012 ((c2 & 0x3FUL) << 12) + 2013 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) 2014 return codecvt_base::error; 2015 *to_nxt = static_cast<uint16_t>( 2016 0xD800 2017 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) 2018 | ((c2 & 0x0F) << 2) 2019 | ((c3 & 0x30) >> 4)); 2020 *++to_nxt = static_cast<uint16_t>( 2021 0xDC00 2022 | ((c3 & 0x0F) << 6) 2023 | (c4 & 0x3F)); 2024 frm_nxt += 4; 2025 } 2026 else 2027 { 2028 return codecvt_base::error; 2029 } 2030 } 2031 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 2032 } 2033 2034 static 2035 codecvt_base::result 2036 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 2037 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, 2038 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2039 { 2040 frm_nxt = frm; 2041 to_nxt = to; 2042 if (mode & consume_header) 2043 { 2044 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && 2045 frm_nxt[2] == 0xBF) 2046 frm_nxt += 3; 2047 } 2048 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) 2049 { 2050 uint8_t c1 = *frm_nxt; 2051 if (c1 > Maxcode) 2052 return codecvt_base::error; 2053 if (c1 < 0x80) 2054 { 2055 *to_nxt = static_cast<uint32_t>(c1); 2056 ++frm_nxt; 2057 } 2058 else if (c1 < 0xC2) 2059 { 2060 return codecvt_base::error; 2061 } 2062 else if (c1 < 0xE0) 2063 { 2064 if (frm_end-frm_nxt < 2) 2065 return codecvt_base::partial; 2066 uint8_t c2 = frm_nxt[1]; 2067 if ((c2 & 0xC0) != 0x80) 2068 return codecvt_base::error; 2069 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); 2070 if (t > Maxcode) 2071 return codecvt_base::error; 2072 *to_nxt = static_cast<uint32_t>(t); 2073 frm_nxt += 2; 2074 } 2075 else if (c1 < 0xF0) 2076 { 2077 if (frm_end-frm_nxt < 3) 2078 return codecvt_base::partial; 2079 uint8_t c2 = frm_nxt[1]; 2080 uint8_t c3 = frm_nxt[2]; 2081 switch (c1) 2082 { 2083 case 0xE0: 2084 if ((c2 & 0xE0) != 0xA0) 2085 return codecvt_base::error; 2086 break; 2087 case 0xED: 2088 if ((c2 & 0xE0) != 0x80) 2089 return codecvt_base::error; 2090 break; 2091 default: 2092 if ((c2 & 0xC0) != 0x80) 2093 return codecvt_base::error; 2094 break; 2095 } 2096 if ((c3 & 0xC0) != 0x80) 2097 return codecvt_base::error; 2098 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) 2099 | ((c2 & 0x3F) << 6) 2100 | (c3 & 0x3F)); 2101 if (t > Maxcode) 2102 return codecvt_base::error; 2103 *to_nxt = static_cast<uint32_t>(t); 2104 frm_nxt += 3; 2105 } 2106 else if (c1 < 0xF5) 2107 { 2108 if (frm_end-frm_nxt < 4) 2109 return codecvt_base::partial; 2110 uint8_t c2 = frm_nxt[1]; 2111 uint8_t c3 = frm_nxt[2]; 2112 uint8_t c4 = frm_nxt[3]; 2113 switch (c1) 2114 { 2115 case 0xF0: 2116 if (!(0x90 <= c2 && c2 <= 0xBF)) 2117 return codecvt_base::error; 2118 break; 2119 case 0xF4: 2120 if ((c2 & 0xF0) != 0x80) 2121 return codecvt_base::error; 2122 break; 2123 default: 2124 if ((c2 & 0xC0) != 0x80) 2125 return codecvt_base::error; 2126 break; 2127 } 2128 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) 2129 return codecvt_base::error; 2130 if (to_end-to_nxt < 2) 2131 return codecvt_base::partial; 2132 if ((((c1 & 7UL) << 18) + 2133 ((c2 & 0x3FUL) << 12) + 2134 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) 2135 return codecvt_base::error; 2136 *to_nxt = static_cast<uint32_t>( 2137 0xD800 2138 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) 2139 | ((c2 & 0x0F) << 2) 2140 | ((c3 & 0x30) >> 4)); 2141 *++to_nxt = static_cast<uint32_t>( 2142 0xDC00 2143 | ((c3 & 0x0F) << 6) 2144 | (c4 & 0x3F)); 2145 frm_nxt += 4; 2146 } 2147 else 2148 { 2149 return codecvt_base::error; 2150 } 2151 } 2152 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 2153 } 2154 2155 static 2156 int 2157 utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end, 2158 size_t mx, unsigned long Maxcode = 0x10FFFF, 2159 codecvt_mode mode = codecvt_mode(0)) 2160 { 2161 const uint8_t* frm_nxt = frm; 2162 if (mode & consume_header) 2163 { 2164 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && 2165 frm_nxt[2] == 0xBF) 2166 frm_nxt += 3; 2167 } 2168 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) 2169 { 2170 uint8_t c1 = *frm_nxt; 2171 if (c1 > Maxcode) 2172 break; 2173 if (c1 < 0x80) 2174 { 2175 ++frm_nxt; 2176 } 2177 else if (c1 < 0xC2) 2178 { 2179 break; 2180 } 2181 else if (c1 < 0xE0) 2182 { 2183 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80) 2184 break; 2185 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)); 2186 if (t > Maxcode) 2187 break; 2188 frm_nxt += 2; 2189 } 2190 else if (c1 < 0xF0) 2191 { 2192 if (frm_end-frm_nxt < 3) 2193 break; 2194 uint8_t c2 = frm_nxt[1]; 2195 uint8_t c3 = frm_nxt[2]; 2196 switch (c1) 2197 { 2198 case 0xE0: 2199 if ((c2 & 0xE0) != 0xA0) 2200 return static_cast<int>(frm_nxt - frm); 2201 break; 2202 case 0xED: 2203 if ((c2 & 0xE0) != 0x80) 2204 return static_cast<int>(frm_nxt - frm); 2205 break; 2206 default: 2207 if ((c2 & 0xC0) != 0x80) 2208 return static_cast<int>(frm_nxt - frm); 2209 break; 2210 } 2211 if ((c3 & 0xC0) != 0x80) 2212 break; 2213 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) 2214 break; 2215 frm_nxt += 3; 2216 } 2217 else if (c1 < 0xF5) 2218 { 2219 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2) 2220 break; 2221 uint8_t c2 = frm_nxt[1]; 2222 uint8_t c3 = frm_nxt[2]; 2223 uint8_t c4 = frm_nxt[3]; 2224 switch (c1) 2225 { 2226 case 0xF0: 2227 if (!(0x90 <= c2 && c2 <= 0xBF)) 2228 return static_cast<int>(frm_nxt - frm); 2229 break; 2230 case 0xF4: 2231 if ((c2 & 0xF0) != 0x80) 2232 return static_cast<int>(frm_nxt - frm); 2233 break; 2234 default: 2235 if ((c2 & 0xC0) != 0x80) 2236 return static_cast<int>(frm_nxt - frm); 2237 break; 2238 } 2239 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) 2240 break; 2241 if ((((c1 & 7UL) << 18) + 2242 ((c2 & 0x3FUL) << 12) + 2243 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) 2244 break; 2245 ++nchar16_t; 2246 frm_nxt += 4; 2247 } 2248 else 2249 { 2250 break; 2251 } 2252 } 2253 return static_cast<int>(frm_nxt - frm); 2254 } 2255 2256 static 2257 codecvt_base::result 2258 ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, 2259 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 2260 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2261 { 2262 frm_nxt = frm; 2263 to_nxt = to; 2264 if (mode & generate_header) 2265 { 2266 if (to_end-to_nxt < 3) 2267 return codecvt_base::partial; 2268 *to_nxt++ = static_cast<uint8_t>(0xEF); 2269 *to_nxt++ = static_cast<uint8_t>(0xBB); 2270 *to_nxt++ = static_cast<uint8_t>(0xBF); 2271 } 2272 for (; frm_nxt < frm_end; ++frm_nxt) 2273 { 2274 uint32_t wc = *frm_nxt; 2275 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) 2276 return codecvt_base::error; 2277 if (wc < 0x000080) 2278 { 2279 if (to_end-to_nxt < 1) 2280 return codecvt_base::partial; 2281 *to_nxt++ = static_cast<uint8_t>(wc); 2282 } 2283 else if (wc < 0x000800) 2284 { 2285 if (to_end-to_nxt < 2) 2286 return codecvt_base::partial; 2287 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); 2288 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); 2289 } 2290 else if (wc < 0x010000) 2291 { 2292 if (to_end-to_nxt < 3) 2293 return codecvt_base::partial; 2294 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); 2295 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); 2296 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); 2297 } 2298 else // if (wc < 0x110000) 2299 { 2300 if (to_end-to_nxt < 4) 2301 return codecvt_base::partial; 2302 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18)); 2303 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12)); 2304 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6)); 2305 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F)); 2306 } 2307 } 2308 return codecvt_base::ok; 2309 } 2310 2311 static 2312 codecvt_base::result 2313 utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 2314 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, 2315 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2316 { 2317 frm_nxt = frm; 2318 to_nxt = to; 2319 if (mode & consume_header) 2320 { 2321 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && 2322 frm_nxt[2] == 0xBF) 2323 frm_nxt += 3; 2324 } 2325 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) 2326 { 2327 uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2328 if (c1 < 0x80) 2329 { 2330 if (c1 > Maxcode) 2331 return codecvt_base::error; 2332 *to_nxt = static_cast<uint32_t>(c1); 2333 ++frm_nxt; 2334 } 2335 else if (c1 < 0xC2) 2336 { 2337 return codecvt_base::error; 2338 } 2339 else if (c1 < 0xE0) 2340 { 2341 if (frm_end-frm_nxt < 2) 2342 return codecvt_base::partial; 2343 uint8_t c2 = frm_nxt[1]; 2344 if ((c2 & 0xC0) != 0x80) 2345 return codecvt_base::error; 2346 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) 2347 | (c2 & 0x3F)); 2348 if (t > Maxcode) 2349 return codecvt_base::error; 2350 *to_nxt = t; 2351 frm_nxt += 2; 2352 } 2353 else if (c1 < 0xF0) 2354 { 2355 if (frm_end-frm_nxt < 3) 2356 return codecvt_base::partial; 2357 uint8_t c2 = frm_nxt[1]; 2358 uint8_t c3 = frm_nxt[2]; 2359 switch (c1) 2360 { 2361 case 0xE0: 2362 if ((c2 & 0xE0) != 0xA0) 2363 return codecvt_base::error; 2364 break; 2365 case 0xED: 2366 if ((c2 & 0xE0) != 0x80) 2367 return codecvt_base::error; 2368 break; 2369 default: 2370 if ((c2 & 0xC0) != 0x80) 2371 return codecvt_base::error; 2372 break; 2373 } 2374 if ((c3 & 0xC0) != 0x80) 2375 return codecvt_base::error; 2376 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) 2377 | ((c2 & 0x3F) << 6) 2378 | (c3 & 0x3F)); 2379 if (t > Maxcode) 2380 return codecvt_base::error; 2381 *to_nxt = t; 2382 frm_nxt += 3; 2383 } 2384 else if (c1 < 0xF5) 2385 { 2386 if (frm_end-frm_nxt < 4) 2387 return codecvt_base::partial; 2388 uint8_t c2 = frm_nxt[1]; 2389 uint8_t c3 = frm_nxt[2]; 2390 uint8_t c4 = frm_nxt[3]; 2391 switch (c1) 2392 { 2393 case 0xF0: 2394 if (!(0x90 <= c2 && c2 <= 0xBF)) 2395 return codecvt_base::error; 2396 break; 2397 case 0xF4: 2398 if ((c2 & 0xF0) != 0x80) 2399 return codecvt_base::error; 2400 break; 2401 default: 2402 if ((c2 & 0xC0) != 0x80) 2403 return codecvt_base::error; 2404 break; 2405 } 2406 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) 2407 return codecvt_base::error; 2408 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) 2409 | ((c2 & 0x3F) << 12) 2410 | ((c3 & 0x3F) << 6) 2411 | (c4 & 0x3F)); 2412 if (t > Maxcode) 2413 return codecvt_base::error; 2414 *to_nxt = t; 2415 frm_nxt += 4; 2416 } 2417 else 2418 { 2419 return codecvt_base::error; 2420 } 2421 } 2422 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 2423 } 2424 2425 static 2426 int 2427 utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, 2428 size_t mx, unsigned long Maxcode = 0x10FFFF, 2429 codecvt_mode mode = codecvt_mode(0)) 2430 { 2431 const uint8_t* frm_nxt = frm; 2432 if (mode & consume_header) 2433 { 2434 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && 2435 frm_nxt[2] == 0xBF) 2436 frm_nxt += 3; 2437 } 2438 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) 2439 { 2440 uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2441 if (c1 < 0x80) 2442 { 2443 if (c1 > Maxcode) 2444 break; 2445 ++frm_nxt; 2446 } 2447 else if (c1 < 0xC2) 2448 { 2449 break; 2450 } 2451 else if (c1 < 0xE0) 2452 { 2453 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) 2454 break; 2455 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) 2456 break; 2457 frm_nxt += 2; 2458 } 2459 else if (c1 < 0xF0) 2460 { 2461 if (frm_end-frm_nxt < 3) 2462 break; 2463 uint8_t c2 = frm_nxt[1]; 2464 uint8_t c3 = frm_nxt[2]; 2465 switch (c1) 2466 { 2467 case 0xE0: 2468 if ((c2 & 0xE0) != 0xA0) 2469 return static_cast<int>(frm_nxt - frm); 2470 break; 2471 case 0xED: 2472 if ((c2 & 0xE0) != 0x80) 2473 return static_cast<int>(frm_nxt - frm); 2474 break; 2475 default: 2476 if ((c2 & 0xC0) != 0x80) 2477 return static_cast<int>(frm_nxt - frm); 2478 break; 2479 } 2480 if ((c3 & 0xC0) != 0x80) 2481 break; 2482 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) 2483 break; 2484 frm_nxt += 3; 2485 } 2486 else if (c1 < 0xF5) 2487 { 2488 if (frm_end-frm_nxt < 4) 2489 break; 2490 uint8_t c2 = frm_nxt[1]; 2491 uint8_t c3 = frm_nxt[2]; 2492 uint8_t c4 = frm_nxt[3]; 2493 switch (c1) 2494 { 2495 case 0xF0: 2496 if (!(0x90 <= c2 && c2 <= 0xBF)) 2497 return static_cast<int>(frm_nxt - frm); 2498 break; 2499 case 0xF4: 2500 if ((c2 & 0xF0) != 0x80) 2501 return static_cast<int>(frm_nxt - frm); 2502 break; 2503 default: 2504 if ((c2 & 0xC0) != 0x80) 2505 return static_cast<int>(frm_nxt - frm); 2506 break; 2507 } 2508 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) 2509 break; 2510 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | 2511 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode) 2512 break; 2513 frm_nxt += 4; 2514 } 2515 else 2516 { 2517 break; 2518 } 2519 } 2520 return static_cast<int>(frm_nxt - frm); 2521 } 2522 2523 static 2524 codecvt_base::result 2525 ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, 2526 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 2527 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2528 { 2529 frm_nxt = frm; 2530 to_nxt = to; 2531 if (mode & generate_header) 2532 { 2533 if (to_end-to_nxt < 3) 2534 return codecvt_base::partial; 2535 *to_nxt++ = static_cast<uint8_t>(0xEF); 2536 *to_nxt++ = static_cast<uint8_t>(0xBB); 2537 *to_nxt++ = static_cast<uint8_t>(0xBF); 2538 } 2539 for (; frm_nxt < frm_end; ++frm_nxt) 2540 { 2541 uint16_t wc = *frm_nxt; 2542 if ((wc & 0xF800) == 0xD800 || wc > Maxcode) 2543 return codecvt_base::error; 2544 if (wc < 0x0080) 2545 { 2546 if (to_end-to_nxt < 1) 2547 return codecvt_base::partial; 2548 *to_nxt++ = static_cast<uint8_t>(wc); 2549 } 2550 else if (wc < 0x0800) 2551 { 2552 if (to_end-to_nxt < 2) 2553 return codecvt_base::partial; 2554 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); 2555 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); 2556 } 2557 else // if (wc <= 0xFFFF) 2558 { 2559 if (to_end-to_nxt < 3) 2560 return codecvt_base::partial; 2561 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); 2562 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); 2563 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); 2564 } 2565 } 2566 return codecvt_base::ok; 2567 } 2568 2569 static 2570 codecvt_base::result 2571 utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 2572 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, 2573 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2574 { 2575 frm_nxt = frm; 2576 to_nxt = to; 2577 if (mode & consume_header) 2578 { 2579 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && 2580 frm_nxt[2] == 0xBF) 2581 frm_nxt += 3; 2582 } 2583 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) 2584 { 2585 uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2586 if (c1 < 0x80) 2587 { 2588 if (c1 > Maxcode) 2589 return codecvt_base::error; 2590 *to_nxt = static_cast<uint16_t>(c1); 2591 ++frm_nxt; 2592 } 2593 else if (c1 < 0xC2) 2594 { 2595 return codecvt_base::error; 2596 } 2597 else if (c1 < 0xE0) 2598 { 2599 if (frm_end-frm_nxt < 2) 2600 return codecvt_base::partial; 2601 uint8_t c2 = frm_nxt[1]; 2602 if ((c2 & 0xC0) != 0x80) 2603 return codecvt_base::error; 2604 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) 2605 | (c2 & 0x3F)); 2606 if (t > Maxcode) 2607 return codecvt_base::error; 2608 *to_nxt = t; 2609 frm_nxt += 2; 2610 } 2611 else if (c1 < 0xF0) 2612 { 2613 if (frm_end-frm_nxt < 3) 2614 return codecvt_base::partial; 2615 uint8_t c2 = frm_nxt[1]; 2616 uint8_t c3 = frm_nxt[2]; 2617 switch (c1) 2618 { 2619 case 0xE0: 2620 if ((c2 & 0xE0) != 0xA0) 2621 return codecvt_base::error; 2622 break; 2623 case 0xED: 2624 if ((c2 & 0xE0) != 0x80) 2625 return codecvt_base::error; 2626 break; 2627 default: 2628 if ((c2 & 0xC0) != 0x80) 2629 return codecvt_base::error; 2630 break; 2631 } 2632 if ((c3 & 0xC0) != 0x80) 2633 return codecvt_base::error; 2634 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) 2635 | ((c2 & 0x3F) << 6) 2636 | (c3 & 0x3F)); 2637 if (t > Maxcode) 2638 return codecvt_base::error; 2639 *to_nxt = t; 2640 frm_nxt += 3; 2641 } 2642 else 2643 { 2644 return codecvt_base::error; 2645 } 2646 } 2647 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 2648 } 2649 2650 static 2651 int 2652 utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, 2653 size_t mx, unsigned long Maxcode = 0x10FFFF, 2654 codecvt_mode mode = codecvt_mode(0)) 2655 { 2656 const uint8_t* frm_nxt = frm; 2657 if (mode & consume_header) 2658 { 2659 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && 2660 frm_nxt[2] == 0xBF) 2661 frm_nxt += 3; 2662 } 2663 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) 2664 { 2665 uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2666 if (c1 < 0x80) 2667 { 2668 if (c1 > Maxcode) 2669 break; 2670 ++frm_nxt; 2671 } 2672 else if (c1 < 0xC2) 2673 { 2674 break; 2675 } 2676 else if (c1 < 0xE0) 2677 { 2678 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) 2679 break; 2680 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) 2681 break; 2682 frm_nxt += 2; 2683 } 2684 else if (c1 < 0xF0) 2685 { 2686 if (frm_end-frm_nxt < 3) 2687 break; 2688 uint8_t c2 = frm_nxt[1]; 2689 uint8_t c3 = frm_nxt[2]; 2690 switch (c1) 2691 { 2692 case 0xE0: 2693 if ((c2 & 0xE0) != 0xA0) 2694 return static_cast<int>(frm_nxt - frm); 2695 break; 2696 case 0xED: 2697 if ((c2 & 0xE0) != 0x80) 2698 return static_cast<int>(frm_nxt - frm); 2699 break; 2700 default: 2701 if ((c2 & 0xC0) != 0x80) 2702 return static_cast<int>(frm_nxt - frm); 2703 break; 2704 } 2705 if ((c3 & 0xC0) != 0x80) 2706 break; 2707 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) 2708 break; 2709 frm_nxt += 3; 2710 } 2711 else 2712 { 2713 break; 2714 } 2715 } 2716 return static_cast<int>(frm_nxt - frm); 2717 } 2718 2719 static 2720 codecvt_base::result 2721 ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, 2722 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 2723 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2724 { 2725 frm_nxt = frm; 2726 to_nxt = to; 2727 if (mode & generate_header) 2728 { 2729 if (to_end-to_nxt < 2) 2730 return codecvt_base::partial; 2731 *to_nxt++ = static_cast<uint8_t>(0xFE); 2732 *to_nxt++ = static_cast<uint8_t>(0xFF); 2733 } 2734 for (; frm_nxt < frm_end; ++frm_nxt) 2735 { 2736 uint32_t wc = *frm_nxt; 2737 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) 2738 return codecvt_base::error; 2739 if (wc < 0x010000) 2740 { 2741 if (to_end-to_nxt < 2) 2742 return codecvt_base::partial; 2743 *to_nxt++ = static_cast<uint8_t>(wc >> 8); 2744 *to_nxt++ = static_cast<uint8_t>(wc); 2745 } 2746 else 2747 { 2748 if (to_end-to_nxt < 4) 2749 return codecvt_base::partial; 2750 uint16_t t = static_cast<uint16_t>( 2751 0xD800 2752 | ((((wc & 0x1F0000) >> 16) - 1) << 6) 2753 | ((wc & 0x00FC00) >> 10)); 2754 *to_nxt++ = static_cast<uint8_t>(t >> 8); 2755 *to_nxt++ = static_cast<uint8_t>(t); 2756 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); 2757 *to_nxt++ = static_cast<uint8_t>(t >> 8); 2758 *to_nxt++ = static_cast<uint8_t>(t); 2759 } 2760 } 2761 return codecvt_base::ok; 2762 } 2763 2764 static 2765 codecvt_base::result 2766 utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 2767 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, 2768 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2769 { 2770 frm_nxt = frm; 2771 to_nxt = to; 2772 if (mode & consume_header) 2773 { 2774 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 2775 frm_nxt += 2; 2776 } 2777 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) 2778 { 2779 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 2780 if ((c1 & 0xFC00) == 0xDC00) 2781 return codecvt_base::error; 2782 if ((c1 & 0xFC00) != 0xD800) 2783 { 2784 if (c1 > Maxcode) 2785 return codecvt_base::error; 2786 *to_nxt = static_cast<uint32_t>(c1); 2787 frm_nxt += 2; 2788 } 2789 else 2790 { 2791 if (frm_end-frm_nxt < 4) 2792 return codecvt_base::partial; 2793 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); 2794 if ((c2 & 0xFC00) != 0xDC00) 2795 return codecvt_base::error; 2796 uint32_t t = static_cast<uint32_t>( 2797 ((((c1 & 0x03C0) >> 6) + 1) << 16) 2798 | ((c1 & 0x003F) << 10) 2799 | (c2 & 0x03FF)); 2800 if (t > Maxcode) 2801 return codecvt_base::error; 2802 *to_nxt = t; 2803 frm_nxt += 4; 2804 } 2805 } 2806 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 2807 } 2808 2809 static 2810 int 2811 utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, 2812 size_t mx, unsigned long Maxcode = 0x10FFFF, 2813 codecvt_mode mode = codecvt_mode(0)) 2814 { 2815 const uint8_t* frm_nxt = frm; 2816 if (mode & consume_header) 2817 { 2818 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 2819 frm_nxt += 2; 2820 } 2821 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) 2822 { 2823 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 2824 if ((c1 & 0xFC00) == 0xDC00) 2825 break; 2826 if ((c1 & 0xFC00) != 0xD800) 2827 { 2828 if (c1 > Maxcode) 2829 break; 2830 frm_nxt += 2; 2831 } 2832 else 2833 { 2834 if (frm_end-frm_nxt < 4) 2835 break; 2836 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); 2837 if ((c2 & 0xFC00) != 0xDC00) 2838 break; 2839 uint32_t t = static_cast<uint32_t>( 2840 ((((c1 & 0x03C0) >> 6) + 1) << 16) 2841 | ((c1 & 0x003F) << 10) 2842 | (c2 & 0x03FF)); 2843 if (t > Maxcode) 2844 break; 2845 frm_nxt += 4; 2846 } 2847 } 2848 return static_cast<int>(frm_nxt - frm); 2849 } 2850 2851 static 2852 codecvt_base::result 2853 ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, 2854 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 2855 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2856 { 2857 frm_nxt = frm; 2858 to_nxt = to; 2859 if (mode & generate_header) 2860 { 2861 if (to_end - to_nxt < 2) 2862 return codecvt_base::partial; 2863 *to_nxt++ = static_cast<uint8_t>(0xFF); 2864 *to_nxt++ = static_cast<uint8_t>(0xFE); 2865 } 2866 for (; frm_nxt < frm_end; ++frm_nxt) 2867 { 2868 uint32_t wc = *frm_nxt; 2869 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) 2870 return codecvt_base::error; 2871 if (wc < 0x010000) 2872 { 2873 if (to_end-to_nxt < 2) 2874 return codecvt_base::partial; 2875 *to_nxt++ = static_cast<uint8_t>(wc); 2876 *to_nxt++ = static_cast<uint8_t>(wc >> 8); 2877 } 2878 else 2879 { 2880 if (to_end-to_nxt < 4) 2881 return codecvt_base::partial; 2882 uint16_t t = static_cast<uint16_t>( 2883 0xD800 2884 | ((((wc & 0x1F0000) >> 16) - 1) << 6) 2885 | ((wc & 0x00FC00) >> 10)); 2886 *to_nxt++ = static_cast<uint8_t>(t); 2887 *to_nxt++ = static_cast<uint8_t>(t >> 8); 2888 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); 2889 *to_nxt++ = static_cast<uint8_t>(t); 2890 *to_nxt++ = static_cast<uint8_t>(t >> 8); 2891 } 2892 } 2893 return codecvt_base::ok; 2894 } 2895 2896 static 2897 codecvt_base::result 2898 utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 2899 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, 2900 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2901 { 2902 frm_nxt = frm; 2903 to_nxt = to; 2904 if (mode & consume_header) 2905 { 2906 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 2907 frm_nxt += 2; 2908 } 2909 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) 2910 { 2911 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 2912 if ((c1 & 0xFC00) == 0xDC00) 2913 return codecvt_base::error; 2914 if ((c1 & 0xFC00) != 0xD800) 2915 { 2916 if (c1 > Maxcode) 2917 return codecvt_base::error; 2918 *to_nxt = static_cast<uint32_t>(c1); 2919 frm_nxt += 2; 2920 } 2921 else 2922 { 2923 if (frm_end-frm_nxt < 4) 2924 return codecvt_base::partial; 2925 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); 2926 if ((c2 & 0xFC00) != 0xDC00) 2927 return codecvt_base::error; 2928 uint32_t t = static_cast<uint32_t>( 2929 ((((c1 & 0x03C0) >> 6) + 1) << 16) 2930 | ((c1 & 0x003F) << 10) 2931 | (c2 & 0x03FF)); 2932 if (t > Maxcode) 2933 return codecvt_base::error; 2934 *to_nxt = t; 2935 frm_nxt += 4; 2936 } 2937 } 2938 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 2939 } 2940 2941 static 2942 int 2943 utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, 2944 size_t mx, unsigned long Maxcode = 0x10FFFF, 2945 codecvt_mode mode = codecvt_mode(0)) 2946 { 2947 const uint8_t* frm_nxt = frm; 2948 if (mode & consume_header) 2949 { 2950 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 2951 frm_nxt += 2; 2952 } 2953 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) 2954 { 2955 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 2956 if ((c1 & 0xFC00) == 0xDC00) 2957 break; 2958 if ((c1 & 0xFC00) != 0xD800) 2959 { 2960 if (c1 > Maxcode) 2961 break; 2962 frm_nxt += 2; 2963 } 2964 else 2965 { 2966 if (frm_end-frm_nxt < 4) 2967 break; 2968 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); 2969 if ((c2 & 0xFC00) != 0xDC00) 2970 break; 2971 uint32_t t = static_cast<uint32_t>( 2972 ((((c1 & 0x03C0) >> 6) + 1) << 16) 2973 | ((c1 & 0x003F) << 10) 2974 | (c2 & 0x03FF)); 2975 if (t > Maxcode) 2976 break; 2977 frm_nxt += 4; 2978 } 2979 } 2980 return static_cast<int>(frm_nxt - frm); 2981 } 2982 2983 static 2984 codecvt_base::result 2985 ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, 2986 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 2987 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 2988 { 2989 frm_nxt = frm; 2990 to_nxt = to; 2991 if (mode & generate_header) 2992 { 2993 if (to_end-to_nxt < 2) 2994 return codecvt_base::partial; 2995 *to_nxt++ = static_cast<uint8_t>(0xFE); 2996 *to_nxt++ = static_cast<uint8_t>(0xFF); 2997 } 2998 for (; frm_nxt < frm_end; ++frm_nxt) 2999 { 3000 uint16_t wc = *frm_nxt; 3001 if ((wc & 0xF800) == 0xD800 || wc > Maxcode) 3002 return codecvt_base::error; 3003 if (to_end-to_nxt < 2) 3004 return codecvt_base::partial; 3005 *to_nxt++ = static_cast<uint8_t>(wc >> 8); 3006 *to_nxt++ = static_cast<uint8_t>(wc); 3007 } 3008 return codecvt_base::ok; 3009 } 3010 3011 static 3012 codecvt_base::result 3013 utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 3014 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, 3015 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 3016 { 3017 frm_nxt = frm; 3018 to_nxt = to; 3019 if (mode & consume_header) 3020 { 3021 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 3022 frm_nxt += 2; 3023 } 3024 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) 3025 { 3026 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 3027 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 3028 return codecvt_base::error; 3029 *to_nxt = c1; 3030 frm_nxt += 2; 3031 } 3032 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 3033 } 3034 3035 static 3036 int 3037 utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, 3038 size_t mx, unsigned long Maxcode = 0x10FFFF, 3039 codecvt_mode mode = codecvt_mode(0)) 3040 { 3041 const uint8_t* frm_nxt = frm; 3042 if (mode & consume_header) 3043 { 3044 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 3045 frm_nxt += 2; 3046 } 3047 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) 3048 { 3049 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 3050 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 3051 break; 3052 frm_nxt += 2; 3053 } 3054 return static_cast<int>(frm_nxt - frm); 3055 } 3056 3057 static 3058 codecvt_base::result 3059 ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, 3060 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, 3061 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 3062 { 3063 frm_nxt = frm; 3064 to_nxt = to; 3065 if (mode & generate_header) 3066 { 3067 if (to_end-to_nxt < 2) 3068 return codecvt_base::partial; 3069 *to_nxt++ = static_cast<uint8_t>(0xFF); 3070 *to_nxt++ = static_cast<uint8_t>(0xFE); 3071 } 3072 for (; frm_nxt < frm_end; ++frm_nxt) 3073 { 3074 uint16_t wc = *frm_nxt; 3075 if ((wc & 0xF800) == 0xD800 || wc > Maxcode) 3076 return codecvt_base::error; 3077 if (to_end-to_nxt < 2) 3078 return codecvt_base::partial; 3079 *to_nxt++ = static_cast<uint8_t>(wc); 3080 *to_nxt++ = static_cast<uint8_t>(wc >> 8); 3081 } 3082 return codecvt_base::ok; 3083 } 3084 3085 static 3086 codecvt_base::result 3087 utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, 3088 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, 3089 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) 3090 { 3091 frm_nxt = frm; 3092 to_nxt = to; 3093 if (mode & consume_header) 3094 { 3095 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 3096 frm_nxt += 2; 3097 } 3098 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) 3099 { 3100 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 3101 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 3102 return codecvt_base::error; 3103 *to_nxt = c1; 3104 frm_nxt += 2; 3105 } 3106 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 3107 } 3108 3109 static 3110 int 3111 utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, 3112 size_t mx, unsigned long Maxcode = 0x10FFFF, 3113 codecvt_mode mode = codecvt_mode(0)) 3114 { 3115 const uint8_t* frm_nxt = frm; 3116 frm_nxt = frm; 3117 if (mode & consume_header) 3118 { 3119 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 3120 frm_nxt += 2; 3121 } 3122 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) 3123 { 3124 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 3125 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 3126 break; 3127 frm_nxt += 2; 3128 } 3129 return static_cast<int>(frm_nxt - frm); 3130 } 3131 3132 // template <> class codecvt<char16_t, char, mbstate_t> 3133 3134 locale::id codecvt<char16_t, char, mbstate_t>::id; 3135 3136 codecvt<char16_t, char, mbstate_t>::~codecvt() 3137 { 3138 } 3139 3140 codecvt<char16_t, char, mbstate_t>::result 3141 codecvt<char16_t, char, mbstate_t>::do_out(state_type&, 3142 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3143 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3144 { 3145 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3146 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3147 const uint16_t* _frm_nxt = _frm; 3148 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3149 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3150 uint8_t* _to_nxt = _to; 3151 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 3152 frm_nxt = frm + (_frm_nxt - _frm); 3153 to_nxt = to + (_to_nxt - _to); 3154 return r; 3155 } 3156 3157 codecvt<char16_t, char, mbstate_t>::result 3158 codecvt<char16_t, char, mbstate_t>::do_in(state_type&, 3159 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3160 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3161 { 3162 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3163 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3164 const uint8_t* _frm_nxt = _frm; 3165 uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3166 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3167 uint16_t* _to_nxt = _to; 3168 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 3169 frm_nxt = frm + (_frm_nxt - _frm); 3170 to_nxt = to + (_to_nxt - _to); 3171 return r; 3172 } 3173 3174 codecvt<char16_t, char, mbstate_t>::result 3175 codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, 3176 extern_type* to, extern_type*, extern_type*& to_nxt) const 3177 { 3178 to_nxt = to; 3179 return noconv; 3180 } 3181 3182 int 3183 codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT 3184 { 3185 return 0; 3186 } 3187 3188 bool 3189 codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT 3190 { 3191 return false; 3192 } 3193 3194 int 3195 codecvt<char16_t, char, mbstate_t>::do_length(state_type&, 3196 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3197 { 3198 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3199 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3200 return utf8_to_utf16_length(_frm, _frm_end, mx); 3201 } 3202 3203 int 3204 codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT 3205 { 3206 return 4; 3207 } 3208 3209 // template <> class codecvt<char32_t, char, mbstate_t> 3210 3211 locale::id codecvt<char32_t, char, mbstate_t>::id; 3212 3213 codecvt<char32_t, char, mbstate_t>::~codecvt() 3214 { 3215 } 3216 3217 codecvt<char32_t, char, mbstate_t>::result 3218 codecvt<char32_t, char, mbstate_t>::do_out(state_type&, 3219 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3220 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3221 { 3222 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3223 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3224 const uint32_t* _frm_nxt = _frm; 3225 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3226 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3227 uint8_t* _to_nxt = _to; 3228 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 3229 frm_nxt = frm + (_frm_nxt - _frm); 3230 to_nxt = to + (_to_nxt - _to); 3231 return r; 3232 } 3233 3234 codecvt<char32_t, char, mbstate_t>::result 3235 codecvt<char32_t, char, mbstate_t>::do_in(state_type&, 3236 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3237 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3238 { 3239 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3240 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3241 const uint8_t* _frm_nxt = _frm; 3242 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 3243 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 3244 uint32_t* _to_nxt = _to; 3245 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 3246 frm_nxt = frm + (_frm_nxt - _frm); 3247 to_nxt = to + (_to_nxt - _to); 3248 return r; 3249 } 3250 3251 codecvt<char32_t, char, mbstate_t>::result 3252 codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, 3253 extern_type* to, extern_type*, extern_type*& to_nxt) const 3254 { 3255 to_nxt = to; 3256 return noconv; 3257 } 3258 3259 int 3260 codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT 3261 { 3262 return 0; 3263 } 3264 3265 bool 3266 codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT 3267 { 3268 return false; 3269 } 3270 3271 int 3272 codecvt<char32_t, char, mbstate_t>::do_length(state_type&, 3273 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3274 { 3275 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3276 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3277 return utf8_to_ucs4_length(_frm, _frm_end, mx); 3278 } 3279 3280 int 3281 codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT 3282 { 3283 return 4; 3284 } 3285 3286 // __codecvt_utf8<wchar_t> 3287 3288 __codecvt_utf8<wchar_t>::result 3289 __codecvt_utf8<wchar_t>::do_out(state_type&, 3290 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3291 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3292 { 3293 #if defined(_LIBCPP_SHORT_WCHAR) 3294 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3295 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3296 const uint16_t* _frm_nxt = _frm; 3297 #else 3298 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3299 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3300 const uint32_t* _frm_nxt = _frm; 3301 #endif 3302 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3303 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3304 uint8_t* _to_nxt = _to; 3305 #if defined(_LIBCPP_SHORT_WCHAR) 3306 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3307 _Maxcode_, _Mode_); 3308 #else 3309 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3310 _Maxcode_, _Mode_); 3311 #endif 3312 frm_nxt = frm + (_frm_nxt - _frm); 3313 to_nxt = to + (_to_nxt - _to); 3314 return r; 3315 } 3316 3317 __codecvt_utf8<wchar_t>::result 3318 __codecvt_utf8<wchar_t>::do_in(state_type&, 3319 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3320 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3321 { 3322 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3323 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3324 const uint8_t* _frm_nxt = _frm; 3325 #if defined(_LIBCPP_SHORT_WCHAR) 3326 uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3327 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3328 uint16_t* _to_nxt = _to; 3329 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3330 _Maxcode_, _Mode_); 3331 #else 3332 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 3333 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 3334 uint32_t* _to_nxt = _to; 3335 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3336 _Maxcode_, _Mode_); 3337 #endif 3338 frm_nxt = frm + (_frm_nxt - _frm); 3339 to_nxt = to + (_to_nxt - _to); 3340 return r; 3341 } 3342 3343 __codecvt_utf8<wchar_t>::result 3344 __codecvt_utf8<wchar_t>::do_unshift(state_type&, 3345 extern_type* to, extern_type*, extern_type*& to_nxt) const 3346 { 3347 to_nxt = to; 3348 return noconv; 3349 } 3350 3351 int 3352 __codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT 3353 { 3354 return 0; 3355 } 3356 3357 bool 3358 __codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT 3359 { 3360 return false; 3361 } 3362 3363 int 3364 __codecvt_utf8<wchar_t>::do_length(state_type&, 3365 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3366 { 3367 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3368 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3369 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3370 } 3371 3372 int 3373 __codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT 3374 { 3375 if (_Mode_ & consume_header) 3376 return 7; 3377 return 4; 3378 } 3379 3380 // __codecvt_utf8<char16_t> 3381 3382 __codecvt_utf8<char16_t>::result 3383 __codecvt_utf8<char16_t>::do_out(state_type&, 3384 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3385 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3386 { 3387 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3388 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3389 const uint16_t* _frm_nxt = _frm; 3390 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3391 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3392 uint8_t* _to_nxt = _to; 3393 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3394 _Maxcode_, _Mode_); 3395 frm_nxt = frm + (_frm_nxt - _frm); 3396 to_nxt = to + (_to_nxt - _to); 3397 return r; 3398 } 3399 3400 __codecvt_utf8<char16_t>::result 3401 __codecvt_utf8<char16_t>::do_in(state_type&, 3402 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3403 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3404 { 3405 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3406 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3407 const uint8_t* _frm_nxt = _frm; 3408 uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3409 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3410 uint16_t* _to_nxt = _to; 3411 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3412 _Maxcode_, _Mode_); 3413 frm_nxt = frm + (_frm_nxt - _frm); 3414 to_nxt = to + (_to_nxt - _to); 3415 return r; 3416 } 3417 3418 __codecvt_utf8<char16_t>::result 3419 __codecvt_utf8<char16_t>::do_unshift(state_type&, 3420 extern_type* to, extern_type*, extern_type*& to_nxt) const 3421 { 3422 to_nxt = to; 3423 return noconv; 3424 } 3425 3426 int 3427 __codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT 3428 { 3429 return 0; 3430 } 3431 3432 bool 3433 __codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT 3434 { 3435 return false; 3436 } 3437 3438 int 3439 __codecvt_utf8<char16_t>::do_length(state_type&, 3440 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3441 { 3442 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3443 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3444 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3445 } 3446 3447 int 3448 __codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT 3449 { 3450 if (_Mode_ & consume_header) 3451 return 6; 3452 return 3; 3453 } 3454 3455 // __codecvt_utf8<char32_t> 3456 3457 __codecvt_utf8<char32_t>::result 3458 __codecvt_utf8<char32_t>::do_out(state_type&, 3459 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3460 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3461 { 3462 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3463 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3464 const uint32_t* _frm_nxt = _frm; 3465 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3466 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3467 uint8_t* _to_nxt = _to; 3468 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3469 _Maxcode_, _Mode_); 3470 frm_nxt = frm + (_frm_nxt - _frm); 3471 to_nxt = to + (_to_nxt - _to); 3472 return r; 3473 } 3474 3475 __codecvt_utf8<char32_t>::result 3476 __codecvt_utf8<char32_t>::do_in(state_type&, 3477 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3478 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3479 { 3480 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3481 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3482 const uint8_t* _frm_nxt = _frm; 3483 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 3484 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 3485 uint32_t* _to_nxt = _to; 3486 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3487 _Maxcode_, _Mode_); 3488 frm_nxt = frm + (_frm_nxt - _frm); 3489 to_nxt = to + (_to_nxt - _to); 3490 return r; 3491 } 3492 3493 __codecvt_utf8<char32_t>::result 3494 __codecvt_utf8<char32_t>::do_unshift(state_type&, 3495 extern_type* to, extern_type*, extern_type*& to_nxt) const 3496 { 3497 to_nxt = to; 3498 return noconv; 3499 } 3500 3501 int 3502 __codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT 3503 { 3504 return 0; 3505 } 3506 3507 bool 3508 __codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT 3509 { 3510 return false; 3511 } 3512 3513 int 3514 __codecvt_utf8<char32_t>::do_length(state_type&, 3515 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3516 { 3517 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3518 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3519 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3520 } 3521 3522 int 3523 __codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT 3524 { 3525 if (_Mode_ & consume_header) 3526 return 7; 3527 return 4; 3528 } 3529 3530 // __codecvt_utf16<wchar_t, false> 3531 3532 __codecvt_utf16<wchar_t, false>::result 3533 __codecvt_utf16<wchar_t, false>::do_out(state_type&, 3534 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3535 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3536 { 3537 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3538 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3539 const uint32_t* _frm_nxt = _frm; 3540 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3541 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3542 uint8_t* _to_nxt = _to; 3543 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3544 _Maxcode_, _Mode_); 3545 frm_nxt = frm + (_frm_nxt - _frm); 3546 to_nxt = to + (_to_nxt - _to); 3547 return r; 3548 } 3549 3550 __codecvt_utf16<wchar_t, false>::result 3551 __codecvt_utf16<wchar_t, false>::do_in(state_type&, 3552 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3553 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3554 { 3555 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3556 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3557 const uint8_t* _frm_nxt = _frm; 3558 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 3559 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 3560 uint32_t* _to_nxt = _to; 3561 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3562 _Maxcode_, _Mode_); 3563 frm_nxt = frm + (_frm_nxt - _frm); 3564 to_nxt = to + (_to_nxt - _to); 3565 return r; 3566 } 3567 3568 __codecvt_utf16<wchar_t, false>::result 3569 __codecvt_utf16<wchar_t, false>::do_unshift(state_type&, 3570 extern_type* to, extern_type*, extern_type*& to_nxt) const 3571 { 3572 to_nxt = to; 3573 return noconv; 3574 } 3575 3576 int 3577 __codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT 3578 { 3579 return 0; 3580 } 3581 3582 bool 3583 __codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT 3584 { 3585 return false; 3586 } 3587 3588 int 3589 __codecvt_utf16<wchar_t, false>::do_length(state_type&, 3590 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3591 { 3592 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3593 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3594 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3595 } 3596 3597 int 3598 __codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT 3599 { 3600 if (_Mode_ & consume_header) 3601 return 6; 3602 return 4; 3603 } 3604 3605 // __codecvt_utf16<wchar_t, true> 3606 3607 __codecvt_utf16<wchar_t, true>::result 3608 __codecvt_utf16<wchar_t, true>::do_out(state_type&, 3609 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3610 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3611 { 3612 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3613 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3614 const uint32_t* _frm_nxt = _frm; 3615 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3616 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3617 uint8_t* _to_nxt = _to; 3618 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3619 _Maxcode_, _Mode_); 3620 frm_nxt = frm + (_frm_nxt - _frm); 3621 to_nxt = to + (_to_nxt - _to); 3622 return r; 3623 } 3624 3625 __codecvt_utf16<wchar_t, true>::result 3626 __codecvt_utf16<wchar_t, true>::do_in(state_type&, 3627 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3628 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3629 { 3630 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3631 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3632 const uint8_t* _frm_nxt = _frm; 3633 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 3634 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 3635 uint32_t* _to_nxt = _to; 3636 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3637 _Maxcode_, _Mode_); 3638 frm_nxt = frm + (_frm_nxt - _frm); 3639 to_nxt = to + (_to_nxt - _to); 3640 return r; 3641 } 3642 3643 __codecvt_utf16<wchar_t, true>::result 3644 __codecvt_utf16<wchar_t, true>::do_unshift(state_type&, 3645 extern_type* to, extern_type*, extern_type*& to_nxt) const 3646 { 3647 to_nxt = to; 3648 return noconv; 3649 } 3650 3651 int 3652 __codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT 3653 { 3654 return 0; 3655 } 3656 3657 bool 3658 __codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT 3659 { 3660 return false; 3661 } 3662 3663 int 3664 __codecvt_utf16<wchar_t, true>::do_length(state_type&, 3665 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3666 { 3667 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3668 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3669 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3670 } 3671 3672 int 3673 __codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT 3674 { 3675 if (_Mode_ & consume_header) 3676 return 6; 3677 return 4; 3678 } 3679 3680 // __codecvt_utf16<char16_t, false> 3681 3682 __codecvt_utf16<char16_t, false>::result 3683 __codecvt_utf16<char16_t, false>::do_out(state_type&, 3684 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3685 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3686 { 3687 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3688 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3689 const uint16_t* _frm_nxt = _frm; 3690 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3691 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3692 uint8_t* _to_nxt = _to; 3693 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3694 _Maxcode_, _Mode_); 3695 frm_nxt = frm + (_frm_nxt - _frm); 3696 to_nxt = to + (_to_nxt - _to); 3697 return r; 3698 } 3699 3700 __codecvt_utf16<char16_t, false>::result 3701 __codecvt_utf16<char16_t, false>::do_in(state_type&, 3702 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3703 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3704 { 3705 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3706 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3707 const uint8_t* _frm_nxt = _frm; 3708 uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3709 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3710 uint16_t* _to_nxt = _to; 3711 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3712 _Maxcode_, _Mode_); 3713 frm_nxt = frm + (_frm_nxt - _frm); 3714 to_nxt = to + (_to_nxt - _to); 3715 return r; 3716 } 3717 3718 __codecvt_utf16<char16_t, false>::result 3719 __codecvt_utf16<char16_t, false>::do_unshift(state_type&, 3720 extern_type* to, extern_type*, extern_type*& to_nxt) const 3721 { 3722 to_nxt = to; 3723 return noconv; 3724 } 3725 3726 int 3727 __codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT 3728 { 3729 return 0; 3730 } 3731 3732 bool 3733 __codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT 3734 { 3735 return false; 3736 } 3737 3738 int 3739 __codecvt_utf16<char16_t, false>::do_length(state_type&, 3740 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3741 { 3742 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3743 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3744 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3745 } 3746 3747 int 3748 __codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT 3749 { 3750 if (_Mode_ & consume_header) 3751 return 4; 3752 return 2; 3753 } 3754 3755 // __codecvt_utf16<char16_t, true> 3756 3757 __codecvt_utf16<char16_t, true>::result 3758 __codecvt_utf16<char16_t, true>::do_out(state_type&, 3759 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3760 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3761 { 3762 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3763 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3764 const uint16_t* _frm_nxt = _frm; 3765 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3766 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3767 uint8_t* _to_nxt = _to; 3768 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3769 _Maxcode_, _Mode_); 3770 frm_nxt = frm + (_frm_nxt - _frm); 3771 to_nxt = to + (_to_nxt - _to); 3772 return r; 3773 } 3774 3775 __codecvt_utf16<char16_t, true>::result 3776 __codecvt_utf16<char16_t, true>::do_in(state_type&, 3777 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3778 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3779 { 3780 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3781 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3782 const uint8_t* _frm_nxt = _frm; 3783 uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3784 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3785 uint16_t* _to_nxt = _to; 3786 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3787 _Maxcode_, _Mode_); 3788 frm_nxt = frm + (_frm_nxt - _frm); 3789 to_nxt = to + (_to_nxt - _to); 3790 return r; 3791 } 3792 3793 __codecvt_utf16<char16_t, true>::result 3794 __codecvt_utf16<char16_t, true>::do_unshift(state_type&, 3795 extern_type* to, extern_type*, extern_type*& to_nxt) const 3796 { 3797 to_nxt = to; 3798 return noconv; 3799 } 3800 3801 int 3802 __codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT 3803 { 3804 return 0; 3805 } 3806 3807 bool 3808 __codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT 3809 { 3810 return false; 3811 } 3812 3813 int 3814 __codecvt_utf16<char16_t, true>::do_length(state_type&, 3815 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3816 { 3817 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3818 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3819 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3820 } 3821 3822 int 3823 __codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT 3824 { 3825 if (_Mode_ & consume_header) 3826 return 4; 3827 return 2; 3828 } 3829 3830 // __codecvt_utf16<char32_t, false> 3831 3832 __codecvt_utf16<char32_t, false>::result 3833 __codecvt_utf16<char32_t, false>::do_out(state_type&, 3834 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3835 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3836 { 3837 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3838 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3839 const uint32_t* _frm_nxt = _frm; 3840 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3841 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3842 uint8_t* _to_nxt = _to; 3843 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3844 _Maxcode_, _Mode_); 3845 frm_nxt = frm + (_frm_nxt - _frm); 3846 to_nxt = to + (_to_nxt - _to); 3847 return r; 3848 } 3849 3850 __codecvt_utf16<char32_t, false>::result 3851 __codecvt_utf16<char32_t, false>::do_in(state_type&, 3852 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3853 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3854 { 3855 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3856 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3857 const uint8_t* _frm_nxt = _frm; 3858 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 3859 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 3860 uint32_t* _to_nxt = _to; 3861 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3862 _Maxcode_, _Mode_); 3863 frm_nxt = frm + (_frm_nxt - _frm); 3864 to_nxt = to + (_to_nxt - _to); 3865 return r; 3866 } 3867 3868 __codecvt_utf16<char32_t, false>::result 3869 __codecvt_utf16<char32_t, false>::do_unshift(state_type&, 3870 extern_type* to, extern_type*, extern_type*& to_nxt) const 3871 { 3872 to_nxt = to; 3873 return noconv; 3874 } 3875 3876 int 3877 __codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT 3878 { 3879 return 0; 3880 } 3881 3882 bool 3883 __codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT 3884 { 3885 return false; 3886 } 3887 3888 int 3889 __codecvt_utf16<char32_t, false>::do_length(state_type&, 3890 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3891 { 3892 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3893 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3894 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3895 } 3896 3897 int 3898 __codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT 3899 { 3900 if (_Mode_ & consume_header) 3901 return 6; 3902 return 4; 3903 } 3904 3905 // __codecvt_utf16<char32_t, true> 3906 3907 __codecvt_utf16<char32_t, true>::result 3908 __codecvt_utf16<char32_t, true>::do_out(state_type&, 3909 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3910 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3911 { 3912 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3913 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3914 const uint32_t* _frm_nxt = _frm; 3915 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3916 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3917 uint8_t* _to_nxt = _to; 3918 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3919 _Maxcode_, _Mode_); 3920 frm_nxt = frm + (_frm_nxt - _frm); 3921 to_nxt = to + (_to_nxt - _to); 3922 return r; 3923 } 3924 3925 __codecvt_utf16<char32_t, true>::result 3926 __codecvt_utf16<char32_t, true>::do_in(state_type&, 3927 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 3928 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 3929 { 3930 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3931 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3932 const uint8_t* _frm_nxt = _frm; 3933 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 3934 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 3935 uint32_t* _to_nxt = _to; 3936 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3937 _Maxcode_, _Mode_); 3938 frm_nxt = frm + (_frm_nxt - _frm); 3939 to_nxt = to + (_to_nxt - _to); 3940 return r; 3941 } 3942 3943 __codecvt_utf16<char32_t, true>::result 3944 __codecvt_utf16<char32_t, true>::do_unshift(state_type&, 3945 extern_type* to, extern_type*, extern_type*& to_nxt) const 3946 { 3947 to_nxt = to; 3948 return noconv; 3949 } 3950 3951 int 3952 __codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT 3953 { 3954 return 0; 3955 } 3956 3957 bool 3958 __codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT 3959 { 3960 return false; 3961 } 3962 3963 int 3964 __codecvt_utf16<char32_t, true>::do_length(state_type&, 3965 const extern_type* frm, const extern_type* frm_end, size_t mx) const 3966 { 3967 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3968 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3969 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 3970 } 3971 3972 int 3973 __codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT 3974 { 3975 if (_Mode_ & consume_header) 3976 return 6; 3977 return 4; 3978 } 3979 3980 // __codecvt_utf8_utf16<wchar_t> 3981 3982 __codecvt_utf8_utf16<wchar_t>::result 3983 __codecvt_utf8_utf16<wchar_t>::do_out(state_type&, 3984 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 3985 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 3986 { 3987 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 3988 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 3989 const uint32_t* _frm_nxt = _frm; 3990 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 3991 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 3992 uint8_t* _to_nxt = _to; 3993 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 3994 _Maxcode_, _Mode_); 3995 frm_nxt = frm + (_frm_nxt - _frm); 3996 to_nxt = to + (_to_nxt - _to); 3997 return r; 3998 } 3999 4000 __codecvt_utf8_utf16<wchar_t>::result 4001 __codecvt_utf8_utf16<wchar_t>::do_in(state_type&, 4002 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 4003 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 4004 { 4005 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 4006 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 4007 const uint8_t* _frm_nxt = _frm; 4008 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 4009 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 4010 uint32_t* _to_nxt = _to; 4011 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 4012 _Maxcode_, _Mode_); 4013 frm_nxt = frm + (_frm_nxt - _frm); 4014 to_nxt = to + (_to_nxt - _to); 4015 return r; 4016 } 4017 4018 __codecvt_utf8_utf16<wchar_t>::result 4019 __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, 4020 extern_type* to, extern_type*, extern_type*& to_nxt) const 4021 { 4022 to_nxt = to; 4023 return noconv; 4024 } 4025 4026 int 4027 __codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT 4028 { 4029 return 0; 4030 } 4031 4032 bool 4033 __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT 4034 { 4035 return false; 4036 } 4037 4038 int 4039 __codecvt_utf8_utf16<wchar_t>::do_length(state_type&, 4040 const extern_type* frm, const extern_type* frm_end, size_t mx) const 4041 { 4042 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 4043 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 4044 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 4045 } 4046 4047 int 4048 __codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT 4049 { 4050 if (_Mode_ & consume_header) 4051 return 7; 4052 return 4; 4053 } 4054 4055 // __codecvt_utf8_utf16<char16_t> 4056 4057 __codecvt_utf8_utf16<char16_t>::result 4058 __codecvt_utf8_utf16<char16_t>::do_out(state_type&, 4059 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 4060 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 4061 { 4062 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 4063 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 4064 const uint16_t* _frm_nxt = _frm; 4065 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 4066 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 4067 uint8_t* _to_nxt = _to; 4068 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 4069 _Maxcode_, _Mode_); 4070 frm_nxt = frm + (_frm_nxt - _frm); 4071 to_nxt = to + (_to_nxt - _to); 4072 return r; 4073 } 4074 4075 __codecvt_utf8_utf16<char16_t>::result 4076 __codecvt_utf8_utf16<char16_t>::do_in(state_type&, 4077 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 4078 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 4079 { 4080 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 4081 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 4082 const uint8_t* _frm_nxt = _frm; 4083 uint16_t* _to = reinterpret_cast<uint16_t*>(to); 4084 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 4085 uint16_t* _to_nxt = _to; 4086 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 4087 _Maxcode_, _Mode_); 4088 frm_nxt = frm + (_frm_nxt - _frm); 4089 to_nxt = to + (_to_nxt - _to); 4090 return r; 4091 } 4092 4093 __codecvt_utf8_utf16<char16_t>::result 4094 __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, 4095 extern_type* to, extern_type*, extern_type*& to_nxt) const 4096 { 4097 to_nxt = to; 4098 return noconv; 4099 } 4100 4101 int 4102 __codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT 4103 { 4104 return 0; 4105 } 4106 4107 bool 4108 __codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT 4109 { 4110 return false; 4111 } 4112 4113 int 4114 __codecvt_utf8_utf16<char16_t>::do_length(state_type&, 4115 const extern_type* frm, const extern_type* frm_end, size_t mx) const 4116 { 4117 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 4118 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 4119 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 4120 } 4121 4122 int 4123 __codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT 4124 { 4125 if (_Mode_ & consume_header) 4126 return 7; 4127 return 4; 4128 } 4129 4130 // __codecvt_utf8_utf16<char32_t> 4131 4132 __codecvt_utf8_utf16<char32_t>::result 4133 __codecvt_utf8_utf16<char32_t>::do_out(state_type&, 4134 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, 4135 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const 4136 { 4137 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 4138 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 4139 const uint32_t* _frm_nxt = _frm; 4140 uint8_t* _to = reinterpret_cast<uint8_t*>(to); 4141 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 4142 uint8_t* _to_nxt = _to; 4143 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 4144 _Maxcode_, _Mode_); 4145 frm_nxt = frm + (_frm_nxt - _frm); 4146 to_nxt = to + (_to_nxt - _to); 4147 return r; 4148 } 4149 4150 __codecvt_utf8_utf16<char32_t>::result 4151 __codecvt_utf8_utf16<char32_t>::do_in(state_type&, 4152 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, 4153 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const 4154 { 4155 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 4156 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 4157 const uint8_t* _frm_nxt = _frm; 4158 uint32_t* _to = reinterpret_cast<uint32_t*>(to); 4159 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 4160 uint32_t* _to_nxt = _to; 4161 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, 4162 _Maxcode_, _Mode_); 4163 frm_nxt = frm + (_frm_nxt - _frm); 4164 to_nxt = to + (_to_nxt - _to); 4165 return r; 4166 } 4167 4168 __codecvt_utf8_utf16<char32_t>::result 4169 __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, 4170 extern_type* to, extern_type*, extern_type*& to_nxt) const 4171 { 4172 to_nxt = to; 4173 return noconv; 4174 } 4175 4176 int 4177 __codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT 4178 { 4179 return 0; 4180 } 4181 4182 bool 4183 __codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT 4184 { 4185 return false; 4186 } 4187 4188 int 4189 __codecvt_utf8_utf16<char32_t>::do_length(state_type&, 4190 const extern_type* frm, const extern_type* frm_end, size_t mx) const 4191 { 4192 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 4193 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 4194 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); 4195 } 4196 4197 int 4198 __codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT 4199 { 4200 if (_Mode_ & consume_header) 4201 return 7; 4202 return 4; 4203 } 4204 4205 // __narrow_to_utf8<16> 4206 4207 __narrow_to_utf8<16>::~__narrow_to_utf8() 4208 { 4209 } 4210 4211 // __narrow_to_utf8<32> 4212 4213 __narrow_to_utf8<32>::~__narrow_to_utf8() 4214 { 4215 } 4216 4217 // __widen_from_utf8<16> 4218 4219 __widen_from_utf8<16>::~__widen_from_utf8() 4220 { 4221 } 4222 4223 // __widen_from_utf8<32> 4224 4225 __widen_from_utf8<32>::~__widen_from_utf8() 4226 { 4227 } 4228 4229 4230 static bool checked_string_to_wchar_convert(wchar_t& dest, 4231 const char* ptr, 4232 locale_t loc) { 4233 if (*ptr == '\0') 4234 return false; 4235 mbstate_t mb = {}; 4236 wchar_t out; 4237 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc); 4238 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) { 4239 return false; 4240 } 4241 dest = out; 4242 return true; 4243 } 4244 4245 static bool checked_string_to_char_convert(char& dest, 4246 const char* ptr, 4247 locale_t __loc) { 4248 if (*ptr == '\0') 4249 return false; 4250 if (!ptr[1]) { 4251 dest = *ptr; 4252 return true; 4253 } 4254 // First convert the MBS into a wide char then attempt to narrow it using 4255 // wctob_l. 4256 wchar_t wout; 4257 if (!checked_string_to_wchar_convert(wout, ptr, __loc)) 4258 return false; 4259 int res; 4260 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) { 4261 dest = res; 4262 return true; 4263 } 4264 // FIXME: Work around specific multibyte sequences that we can reasonable 4265 // translate into a different single byte. 4266 switch (wout) { 4267 case L'\u202F': // narrow non-breaking space 4268 case L'\u00A0': // non-breaking space 4269 dest = ' '; 4270 return true; 4271 default: 4272 return false; 4273 } 4274 _LIBCPP_UNREACHABLE(); 4275 } 4276 4277 4278 // numpunct<char> && numpunct<wchar_t> 4279 4280 locale::id numpunct< char >::id; 4281 locale::id numpunct<wchar_t>::id; 4282 4283 numpunct<char>::numpunct(size_t refs) 4284 : locale::facet(refs), 4285 __decimal_point_('.'), 4286 __thousands_sep_(',') 4287 { 4288 } 4289 4290 numpunct<wchar_t>::numpunct(size_t refs) 4291 : locale::facet(refs), 4292 __decimal_point_(L'.'), 4293 __thousands_sep_(L',') 4294 { 4295 } 4296 4297 numpunct<char>::~numpunct() 4298 { 4299 } 4300 4301 numpunct<wchar_t>::~numpunct() 4302 { 4303 } 4304 4305 char numpunct< char >::do_decimal_point() const {return __decimal_point_;} 4306 wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;} 4307 4308 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;} 4309 wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;} 4310 4311 string numpunct< char >::do_grouping() const {return __grouping_;} 4312 string numpunct<wchar_t>::do_grouping() const {return __grouping_;} 4313 4314 string numpunct< char >::do_truename() const {return "true";} 4315 wstring numpunct<wchar_t>::do_truename() const {return L"true";} 4316 4317 string numpunct< char >::do_falsename() const {return "false";} 4318 wstring numpunct<wchar_t>::do_falsename() const {return L"false";} 4319 4320 // numpunct_byname<char> 4321 4322 numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs) 4323 : numpunct<char>(refs) 4324 { 4325 __init(nm); 4326 } 4327 4328 numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs) 4329 : numpunct<char>(refs) 4330 { 4331 __init(nm.c_str()); 4332 } 4333 4334 numpunct_byname<char>::~numpunct_byname() 4335 { 4336 } 4337 4338 void 4339 numpunct_byname<char>::__init(const char* nm) 4340 { 4341 if (strcmp(nm, "C") != 0) 4342 { 4343 __libcpp_unique_locale loc(nm); 4344 if (!loc) 4345 __throw_runtime_error("numpunct_byname<char>::numpunct_byname" 4346 " failed to construct for " + string(nm)); 4347 4348 lconv* lc = __libcpp_localeconv_l(loc.get()); 4349 checked_string_to_char_convert(__decimal_point_, lc->decimal_point, 4350 loc.get()); 4351 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, 4352 loc.get()); 4353 __grouping_ = lc->grouping; 4354 // localization for truename and falsename is not available 4355 } 4356 } 4357 4358 // numpunct_byname<wchar_t> 4359 4360 numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs) 4361 : numpunct<wchar_t>(refs) 4362 { 4363 __init(nm); 4364 } 4365 4366 numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs) 4367 : numpunct<wchar_t>(refs) 4368 { 4369 __init(nm.c_str()); 4370 } 4371 4372 numpunct_byname<wchar_t>::~numpunct_byname() 4373 { 4374 } 4375 4376 void 4377 numpunct_byname<wchar_t>::__init(const char* nm) 4378 { 4379 if (strcmp(nm, "C") != 0) 4380 { 4381 __libcpp_unique_locale loc(nm); 4382 if (!loc) 4383 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname" 4384 " failed to construct for " + string(nm)); 4385 4386 lconv* lc = __libcpp_localeconv_l(loc.get()); 4387 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, 4388 loc.get()); 4389 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, 4390 loc.get()); 4391 __grouping_ = lc->grouping; 4392 // localization for truename and falsename is not available 4393 } 4394 } 4395 4396 // num_get helpers 4397 4398 int 4399 __num_get_base::__get_base(ios_base& iob) 4400 { 4401 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield; 4402 if (__basefield == ios_base::oct) 4403 return 8; 4404 else if (__basefield == ios_base::hex) 4405 return 16; 4406 else if (__basefield == 0) 4407 return 0; 4408 return 10; 4409 } 4410 4411 const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN"; 4412 4413 void 4414 __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, 4415 ios_base::iostate& __err) 4416 { 4417 if (__grouping.size() != 0) 4418 { 4419 reverse(__g, __g_end); 4420 const char* __ig = __grouping.data(); 4421 const char* __eg = __ig + __grouping.size(); 4422 for (unsigned* __r = __g; __r < __g_end-1; ++__r) 4423 { 4424 if (0 < *__ig && *__ig < numeric_limits<char>::max()) 4425 { 4426 if (static_cast<unsigned>(*__ig) != *__r) 4427 { 4428 __err = ios_base::failbit; 4429 return; 4430 } 4431 } 4432 if (__eg - __ig > 1) 4433 ++__ig; 4434 } 4435 if (0 < *__ig && *__ig < numeric_limits<char>::max()) 4436 { 4437 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0) 4438 __err = ios_base::failbit; 4439 } 4440 } 4441 } 4442 4443 void 4444 __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, 4445 ios_base::fmtflags __flags) 4446 { 4447 if (__flags & ios_base::showpos) 4448 *__fmtp++ = '+'; 4449 if (__flags & ios_base::showbase) 4450 *__fmtp++ = '#'; 4451 while(*__len) 4452 *__fmtp++ = *__len++; 4453 if ((__flags & ios_base::basefield) == ios_base::oct) 4454 *__fmtp = 'o'; 4455 else if ((__flags & ios_base::basefield) == ios_base::hex) 4456 { 4457 if (__flags & ios_base::uppercase) 4458 *__fmtp = 'X'; 4459 else 4460 *__fmtp = 'x'; 4461 } 4462 else if (__signd) 4463 *__fmtp = 'd'; 4464 else 4465 *__fmtp = 'u'; 4466 } 4467 4468 bool 4469 __num_put_base::__format_float(char* __fmtp, const char* __len, 4470 ios_base::fmtflags __flags) 4471 { 4472 bool specify_precision = true; 4473 if (__flags & ios_base::showpos) 4474 *__fmtp++ = '+'; 4475 if (__flags & ios_base::showpoint) 4476 *__fmtp++ = '#'; 4477 ios_base::fmtflags floatfield = __flags & ios_base::floatfield; 4478 bool uppercase = (__flags & ios_base::uppercase) != 0; 4479 if (floatfield == (ios_base::fixed | ios_base::scientific)) 4480 specify_precision = false; 4481 else 4482 { 4483 *__fmtp++ = '.'; 4484 *__fmtp++ = '*'; 4485 } 4486 while(*__len) 4487 *__fmtp++ = *__len++; 4488 if (floatfield == ios_base::fixed) 4489 { 4490 if (uppercase) 4491 *__fmtp = 'F'; 4492 else 4493 *__fmtp = 'f'; 4494 } 4495 else if (floatfield == ios_base::scientific) 4496 { 4497 if (uppercase) 4498 *__fmtp = 'E'; 4499 else 4500 *__fmtp = 'e'; 4501 } 4502 else if (floatfield == (ios_base::fixed | ios_base::scientific)) 4503 { 4504 if (uppercase) 4505 *__fmtp = 'A'; 4506 else 4507 *__fmtp = 'a'; 4508 } 4509 else 4510 { 4511 if (uppercase) 4512 *__fmtp = 'G'; 4513 else 4514 *__fmtp = 'g'; 4515 } 4516 return specify_precision; 4517 } 4518 4519 char* 4520 __num_put_base::__identify_padding(char* __nb, char* __ne, 4521 const ios_base& __iob) 4522 { 4523 switch (__iob.flags() & ios_base::adjustfield) 4524 { 4525 case ios_base::internal: 4526 if (__nb[0] == '-' || __nb[0] == '+') 4527 return __nb+1; 4528 if (__ne - __nb >= 2 && __nb[0] == '0' 4529 && (__nb[1] == 'x' || __nb[1] == 'X')) 4530 return __nb+2; 4531 break; 4532 case ios_base::left: 4533 return __ne; 4534 case ios_base::right: 4535 default: 4536 break; 4537 } 4538 return __nb; 4539 } 4540 4541 // time_get 4542 4543 static 4544 string* 4545 init_weeks() 4546 { 4547 static string weeks[14]; 4548 weeks[0] = "Sunday"; 4549 weeks[1] = "Monday"; 4550 weeks[2] = "Tuesday"; 4551 weeks[3] = "Wednesday"; 4552 weeks[4] = "Thursday"; 4553 weeks[5] = "Friday"; 4554 weeks[6] = "Saturday"; 4555 weeks[7] = "Sun"; 4556 weeks[8] = "Mon"; 4557 weeks[9] = "Tue"; 4558 weeks[10] = "Wed"; 4559 weeks[11] = "Thu"; 4560 weeks[12] = "Fri"; 4561 weeks[13] = "Sat"; 4562 return weeks; 4563 } 4564 4565 static 4566 wstring* 4567 init_wweeks() 4568 { 4569 static wstring weeks[14]; 4570 weeks[0] = L"Sunday"; 4571 weeks[1] = L"Monday"; 4572 weeks[2] = L"Tuesday"; 4573 weeks[3] = L"Wednesday"; 4574 weeks[4] = L"Thursday"; 4575 weeks[5] = L"Friday"; 4576 weeks[6] = L"Saturday"; 4577 weeks[7] = L"Sun"; 4578 weeks[8] = L"Mon"; 4579 weeks[9] = L"Tue"; 4580 weeks[10] = L"Wed"; 4581 weeks[11] = L"Thu"; 4582 weeks[12] = L"Fri"; 4583 weeks[13] = L"Sat"; 4584 return weeks; 4585 } 4586 4587 template <> 4588 const string* 4589 __time_get_c_storage<char>::__weeks() const 4590 { 4591 static const string* weeks = init_weeks(); 4592 return weeks; 4593 } 4594 4595 template <> 4596 const wstring* 4597 __time_get_c_storage<wchar_t>::__weeks() const 4598 { 4599 static const wstring* weeks = init_wweeks(); 4600 return weeks; 4601 } 4602 4603 static 4604 string* 4605 init_months() 4606 { 4607 static string months[24]; 4608 months[0] = "January"; 4609 months[1] = "February"; 4610 months[2] = "March"; 4611 months[3] = "April"; 4612 months[4] = "May"; 4613 months[5] = "June"; 4614 months[6] = "July"; 4615 months[7] = "August"; 4616 months[8] = "September"; 4617 months[9] = "October"; 4618 months[10] = "November"; 4619 months[11] = "December"; 4620 months[12] = "Jan"; 4621 months[13] = "Feb"; 4622 months[14] = "Mar"; 4623 months[15] = "Apr"; 4624 months[16] = "May"; 4625 months[17] = "Jun"; 4626 months[18] = "Jul"; 4627 months[19] = "Aug"; 4628 months[20] = "Sep"; 4629 months[21] = "Oct"; 4630 months[22] = "Nov"; 4631 months[23] = "Dec"; 4632 return months; 4633 } 4634 4635 static 4636 wstring* 4637 init_wmonths() 4638 { 4639 static wstring months[24]; 4640 months[0] = L"January"; 4641 months[1] = L"February"; 4642 months[2] = L"March"; 4643 months[3] = L"April"; 4644 months[4] = L"May"; 4645 months[5] = L"June"; 4646 months[6] = L"July"; 4647 months[7] = L"August"; 4648 months[8] = L"September"; 4649 months[9] = L"October"; 4650 months[10] = L"November"; 4651 months[11] = L"December"; 4652 months[12] = L"Jan"; 4653 months[13] = L"Feb"; 4654 months[14] = L"Mar"; 4655 months[15] = L"Apr"; 4656 months[16] = L"May"; 4657 months[17] = L"Jun"; 4658 months[18] = L"Jul"; 4659 months[19] = L"Aug"; 4660 months[20] = L"Sep"; 4661 months[21] = L"Oct"; 4662 months[22] = L"Nov"; 4663 months[23] = L"Dec"; 4664 return months; 4665 } 4666 4667 template <> 4668 const string* 4669 __time_get_c_storage<char>::__months() const 4670 { 4671 static const string* months = init_months(); 4672 return months; 4673 } 4674 4675 template <> 4676 const wstring* 4677 __time_get_c_storage<wchar_t>::__months() const 4678 { 4679 static const wstring* months = init_wmonths(); 4680 return months; 4681 } 4682 4683 static 4684 string* 4685 init_am_pm() 4686 { 4687 static string am_pm[2]; 4688 am_pm[0] = "AM"; 4689 am_pm[1] = "PM"; 4690 return am_pm; 4691 } 4692 4693 static 4694 wstring* 4695 init_wam_pm() 4696 { 4697 static wstring am_pm[2]; 4698 am_pm[0] = L"AM"; 4699 am_pm[1] = L"PM"; 4700 return am_pm; 4701 } 4702 4703 template <> 4704 const string* 4705 __time_get_c_storage<char>::__am_pm() const 4706 { 4707 static const string* am_pm = init_am_pm(); 4708 return am_pm; 4709 } 4710 4711 template <> 4712 const wstring* 4713 __time_get_c_storage<wchar_t>::__am_pm() const 4714 { 4715 static const wstring* am_pm = init_wam_pm(); 4716 return am_pm; 4717 } 4718 4719 template <> 4720 const string& 4721 __time_get_c_storage<char>::__x() const 4722 { 4723 static string s("%m/%d/%y"); 4724 return s; 4725 } 4726 4727 template <> 4728 const wstring& 4729 __time_get_c_storage<wchar_t>::__x() const 4730 { 4731 static wstring s(L"%m/%d/%y"); 4732 return s; 4733 } 4734 4735 template <> 4736 const string& 4737 __time_get_c_storage<char>::__X() const 4738 { 4739 static string s("%H:%M:%S"); 4740 return s; 4741 } 4742 4743 template <> 4744 const wstring& 4745 __time_get_c_storage<wchar_t>::__X() const 4746 { 4747 static wstring s(L"%H:%M:%S"); 4748 return s; 4749 } 4750 4751 template <> 4752 const string& 4753 __time_get_c_storage<char>::__c() const 4754 { 4755 static string s("%a %b %d %H:%M:%S %Y"); 4756 return s; 4757 } 4758 4759 template <> 4760 const wstring& 4761 __time_get_c_storage<wchar_t>::__c() const 4762 { 4763 static wstring s(L"%a %b %d %H:%M:%S %Y"); 4764 return s; 4765 } 4766 4767 template <> 4768 const string& 4769 __time_get_c_storage<char>::__r() const 4770 { 4771 static string s("%I:%M:%S %p"); 4772 return s; 4773 } 4774 4775 template <> 4776 const wstring& 4777 __time_get_c_storage<wchar_t>::__r() const 4778 { 4779 static wstring s(L"%I:%M:%S %p"); 4780 return s; 4781 } 4782 4783 // time_get_byname 4784 4785 __time_get::__time_get(const char* nm) 4786 : __loc_(newlocale(LC_ALL_MASK, nm, 0)) 4787 { 4788 if (__loc_ == 0) 4789 __throw_runtime_error("time_get_byname" 4790 " failed to construct for " + string(nm)); 4791 } 4792 4793 __time_get::__time_get(const string& nm) 4794 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) 4795 { 4796 if (__loc_ == 0) 4797 __throw_runtime_error("time_get_byname" 4798 " failed to construct for " + nm); 4799 } 4800 4801 __time_get::~__time_get() 4802 { 4803 freelocale(__loc_); 4804 } 4805 #if defined(__clang__) 4806 #pragma clang diagnostic ignored "-Wmissing-field-initializers" 4807 #endif 4808 #if defined(__GNUG__) 4809 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 4810 #endif 4811 4812 template <> 4813 string 4814 __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) 4815 { 4816 tm t = {0}; 4817 t.tm_sec = 59; 4818 t.tm_min = 55; 4819 t.tm_hour = 23; 4820 t.tm_mday = 31; 4821 t.tm_mon = 11; 4822 t.tm_year = 161; 4823 t.tm_wday = 6; 4824 t.tm_yday = 364; 4825 t.tm_isdst = -1; 4826 char buf[100]; 4827 char f[3] = {0}; 4828 f[0] = '%'; 4829 f[1] = fmt; 4830 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_); 4831 char* bb = buf; 4832 char* be = buf + n; 4833 string result; 4834 while (bb != be) 4835 { 4836 if (ct.is(ctype_base::space, *bb)) 4837 { 4838 result.push_back(' '); 4839 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb) 4840 ; 4841 continue; 4842 } 4843 char* w = bb; 4844 ios_base::iostate err = ios_base::goodbit; 4845 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14, 4846 ct, err, false) 4847 - this->__weeks_; 4848 if (i < 14) 4849 { 4850 result.push_back('%'); 4851 if (i < 7) 4852 result.push_back('A'); 4853 else 4854 result.push_back('a'); 4855 bb = w; 4856 continue; 4857 } 4858 w = bb; 4859 i = __scan_keyword(w, be, this->__months_, this->__months_+24, 4860 ct, err, false) 4861 - this->__months_; 4862 if (i < 24) 4863 { 4864 result.push_back('%'); 4865 if (i < 12) 4866 result.push_back('B'); 4867 else 4868 result.push_back('b'); 4869 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) 4870 result.back() = 'm'; 4871 bb = w; 4872 continue; 4873 } 4874 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) 4875 { 4876 w = bb; 4877 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2, 4878 ct, err, false) - this->__am_pm_; 4879 if (i < 2) 4880 { 4881 result.push_back('%'); 4882 result.push_back('p'); 4883 bb = w; 4884 continue; 4885 } 4886 } 4887 w = bb; 4888 if (ct.is(ctype_base::digit, *bb)) 4889 { 4890 switch(__get_up_to_n_digits(bb, be, err, ct, 4)) 4891 { 4892 case 6: 4893 result.push_back('%'); 4894 result.push_back('w'); 4895 break; 4896 case 7: 4897 result.push_back('%'); 4898 result.push_back('u'); 4899 break; 4900 case 11: 4901 result.push_back('%'); 4902 result.push_back('I'); 4903 break; 4904 case 12: 4905 result.push_back('%'); 4906 result.push_back('m'); 4907 break; 4908 case 23: 4909 result.push_back('%'); 4910 result.push_back('H'); 4911 break; 4912 case 31: 4913 result.push_back('%'); 4914 result.push_back('d'); 4915 break; 4916 case 55: 4917 result.push_back('%'); 4918 result.push_back('M'); 4919 break; 4920 case 59: 4921 result.push_back('%'); 4922 result.push_back('S'); 4923 break; 4924 case 61: 4925 result.push_back('%'); 4926 result.push_back('y'); 4927 break; 4928 case 364: 4929 result.push_back('%'); 4930 result.push_back('j'); 4931 break; 4932 case 2061: 4933 result.push_back('%'); 4934 result.push_back('Y'); 4935 break; 4936 default: 4937 for (; w != bb; ++w) 4938 result.push_back(*w); 4939 break; 4940 } 4941 continue; 4942 } 4943 if (*bb == '%') 4944 { 4945 result.push_back('%'); 4946 result.push_back('%'); 4947 ++bb; 4948 continue; 4949 } 4950 result.push_back(*bb); 4951 ++bb; 4952 } 4953 return result; 4954 } 4955 4956 #if defined(__clang__) 4957 #pragma clang diagnostic ignored "-Wmissing-braces" 4958 #endif 4959 4960 template <> 4961 wstring 4962 __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) 4963 { 4964 tm t = {0}; 4965 t.tm_sec = 59; 4966 t.tm_min = 55; 4967 t.tm_hour = 23; 4968 t.tm_mday = 31; 4969 t.tm_mon = 11; 4970 t.tm_year = 161; 4971 t.tm_wday = 6; 4972 t.tm_yday = 364; 4973 t.tm_isdst = -1; 4974 char buf[100]; 4975 char f[3] = {0}; 4976 f[0] = '%'; 4977 f[1] = fmt; 4978 strftime_l(buf, countof(buf), f, &t, __loc_); 4979 wchar_t wbuf[100]; 4980 wchar_t* wbb = wbuf; 4981 mbstate_t mb = {0}; 4982 const char* bb = buf; 4983 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); 4984 if (j == size_t(-1)) 4985 __throw_runtime_error("locale not supported"); 4986 wchar_t* wbe = wbb + j; 4987 wstring result; 4988 while (wbb != wbe) 4989 { 4990 if (ct.is(ctype_base::space, *wbb)) 4991 { 4992 result.push_back(L' '); 4993 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb) 4994 ; 4995 continue; 4996 } 4997 wchar_t* w = wbb; 4998 ios_base::iostate err = ios_base::goodbit; 4999 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14, 5000 ct, err, false) 5001 - this->__weeks_; 5002 if (i < 14) 5003 { 5004 result.push_back(L'%'); 5005 if (i < 7) 5006 result.push_back(L'A'); 5007 else 5008 result.push_back(L'a'); 5009 wbb = w; 5010 continue; 5011 } 5012 w = wbb; 5013 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24, 5014 ct, err, false) 5015 - this->__months_; 5016 if (i < 24) 5017 { 5018 result.push_back(L'%'); 5019 if (i < 12) 5020 result.push_back(L'B'); 5021 else 5022 result.push_back(L'b'); 5023 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) 5024 result.back() = L'm'; 5025 wbb = w; 5026 continue; 5027 } 5028 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) 5029 { 5030 w = wbb; 5031 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2, 5032 ct, err, false) - this->__am_pm_; 5033 if (i < 2) 5034 { 5035 result.push_back(L'%'); 5036 result.push_back(L'p'); 5037 wbb = w; 5038 continue; 5039 } 5040 } 5041 w = wbb; 5042 if (ct.is(ctype_base::digit, *wbb)) 5043 { 5044 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4)) 5045 { 5046 case 6: 5047 result.push_back(L'%'); 5048 result.push_back(L'w'); 5049 break; 5050 case 7: 5051 result.push_back(L'%'); 5052 result.push_back(L'u'); 5053 break; 5054 case 11: 5055 result.push_back(L'%'); 5056 result.push_back(L'I'); 5057 break; 5058 case 12: 5059 result.push_back(L'%'); 5060 result.push_back(L'm'); 5061 break; 5062 case 23: 5063 result.push_back(L'%'); 5064 result.push_back(L'H'); 5065 break; 5066 case 31: 5067 result.push_back(L'%'); 5068 result.push_back(L'd'); 5069 break; 5070 case 55: 5071 result.push_back(L'%'); 5072 result.push_back(L'M'); 5073 break; 5074 case 59: 5075 result.push_back(L'%'); 5076 result.push_back(L'S'); 5077 break; 5078 case 61: 5079 result.push_back(L'%'); 5080 result.push_back(L'y'); 5081 break; 5082 case 364: 5083 result.push_back(L'%'); 5084 result.push_back(L'j'); 5085 break; 5086 case 2061: 5087 result.push_back(L'%'); 5088 result.push_back(L'Y'); 5089 break; 5090 default: 5091 for (; w != wbb; ++w) 5092 result.push_back(*w); 5093 break; 5094 } 5095 continue; 5096 } 5097 if (ct.narrow(*wbb, 0) == '%') 5098 { 5099 result.push_back(L'%'); 5100 result.push_back(L'%'); 5101 ++wbb; 5102 continue; 5103 } 5104 result.push_back(*wbb); 5105 ++wbb; 5106 } 5107 return result; 5108 } 5109 5110 template <> 5111 void 5112 __time_get_storage<char>::init(const ctype<char>& ct) 5113 { 5114 tm t = {0}; 5115 char buf[100]; 5116 // __weeks_ 5117 for (int i = 0; i < 7; ++i) 5118 { 5119 t.tm_wday = i; 5120 strftime_l(buf, countof(buf), "%A", &t, __loc_); 5121 __weeks_[i] = buf; 5122 strftime_l(buf, countof(buf), "%a", &t, __loc_); 5123 __weeks_[i+7] = buf; 5124 } 5125 // __months_ 5126 for (int i = 0; i < 12; ++i) 5127 { 5128 t.tm_mon = i; 5129 strftime_l(buf, countof(buf), "%B", &t, __loc_); 5130 __months_[i] = buf; 5131 strftime_l(buf, countof(buf), "%b", &t, __loc_); 5132 __months_[i+12] = buf; 5133 } 5134 // __am_pm_ 5135 t.tm_hour = 1; 5136 strftime_l(buf, countof(buf), "%p", &t, __loc_); 5137 __am_pm_[0] = buf; 5138 t.tm_hour = 13; 5139 strftime_l(buf, countof(buf), "%p", &t, __loc_); 5140 __am_pm_[1] = buf; 5141 __c_ = __analyze('c', ct); 5142 __r_ = __analyze('r', ct); 5143 __x_ = __analyze('x', ct); 5144 __X_ = __analyze('X', ct); 5145 } 5146 5147 template <> 5148 void 5149 __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) 5150 { 5151 tm t = {0}; 5152 char buf[100]; 5153 wchar_t wbuf[100]; 5154 wchar_t* wbe; 5155 mbstate_t mb = {0}; 5156 // __weeks_ 5157 for (int i = 0; i < 7; ++i) 5158 { 5159 t.tm_wday = i; 5160 strftime_l(buf, countof(buf), "%A", &t, __loc_); 5161 mb = mbstate_t(); 5162 const char* bb = buf; 5163 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 5164 if (j == size_t(-1)) 5165 __throw_runtime_error("locale not supported"); 5166 wbe = wbuf + j; 5167 __weeks_[i].assign(wbuf, wbe); 5168 strftime_l(buf, countof(buf), "%a", &t, __loc_); 5169 mb = mbstate_t(); 5170 bb = buf; 5171 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 5172 if (j == size_t(-1)) 5173 __throw_runtime_error("locale not supported"); 5174 wbe = wbuf + j; 5175 __weeks_[i+7].assign(wbuf, wbe); 5176 } 5177 // __months_ 5178 for (int i = 0; i < 12; ++i) 5179 { 5180 t.tm_mon = i; 5181 strftime_l(buf, countof(buf), "%B", &t, __loc_); 5182 mb = mbstate_t(); 5183 const char* bb = buf; 5184 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 5185 if (j == size_t(-1)) 5186 __throw_runtime_error("locale not supported"); 5187 wbe = wbuf + j; 5188 __months_[i].assign(wbuf, wbe); 5189 strftime_l(buf, countof(buf), "%b", &t, __loc_); 5190 mb = mbstate_t(); 5191 bb = buf; 5192 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 5193 if (j == size_t(-1)) 5194 __throw_runtime_error("locale not supported"); 5195 wbe = wbuf + j; 5196 __months_[i+12].assign(wbuf, wbe); 5197 } 5198 // __am_pm_ 5199 t.tm_hour = 1; 5200 strftime_l(buf, countof(buf), "%p", &t, __loc_); 5201 mb = mbstate_t(); 5202 const char* bb = buf; 5203 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 5204 if (j == size_t(-1)) 5205 __throw_runtime_error("locale not supported"); 5206 wbe = wbuf + j; 5207 __am_pm_[0].assign(wbuf, wbe); 5208 t.tm_hour = 13; 5209 strftime_l(buf, countof(buf), "%p", &t, __loc_); 5210 mb = mbstate_t(); 5211 bb = buf; 5212 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 5213 if (j == size_t(-1)) 5214 __throw_runtime_error("locale not supported"); 5215 wbe = wbuf + j; 5216 __am_pm_[1].assign(wbuf, wbe); 5217 __c_ = __analyze('c', ct); 5218 __r_ = __analyze('r', ct); 5219 __x_ = __analyze('x', ct); 5220 __X_ = __analyze('X', ct); 5221 } 5222 5223 template <class CharT> 5224 struct _LIBCPP_HIDDEN __time_get_temp 5225 : public ctype_byname<CharT> 5226 { 5227 explicit __time_get_temp(const char* nm) 5228 : ctype_byname<CharT>(nm, 1) {} 5229 explicit __time_get_temp(const string& nm) 5230 : ctype_byname<CharT>(nm, 1) {} 5231 }; 5232 5233 template <> 5234 __time_get_storage<char>::__time_get_storage(const char* __nm) 5235 : __time_get(__nm) 5236 { 5237 const __time_get_temp<char> ct(__nm); 5238 init(ct); 5239 } 5240 5241 template <> 5242 __time_get_storage<char>::__time_get_storage(const string& __nm) 5243 : __time_get(__nm) 5244 { 5245 const __time_get_temp<char> ct(__nm); 5246 init(ct); 5247 } 5248 5249 template <> 5250 __time_get_storage<wchar_t>::__time_get_storage(const char* __nm) 5251 : __time_get(__nm) 5252 { 5253 const __time_get_temp<wchar_t> ct(__nm); 5254 init(ct); 5255 } 5256 5257 template <> 5258 __time_get_storage<wchar_t>::__time_get_storage(const string& __nm) 5259 : __time_get(__nm) 5260 { 5261 const __time_get_temp<wchar_t> ct(__nm); 5262 init(ct); 5263 } 5264 5265 template <> 5266 time_base::dateorder 5267 __time_get_storage<char>::__do_date_order() const 5268 { 5269 unsigned i; 5270 for (i = 0; i < __x_.size(); ++i) 5271 if (__x_[i] == '%') 5272 break; 5273 ++i; 5274 switch (__x_[i]) 5275 { 5276 case 'y': 5277 case 'Y': 5278 for (++i; i < __x_.size(); ++i) 5279 if (__x_[i] == '%') 5280 break; 5281 if (i == __x_.size()) 5282 break; 5283 ++i; 5284 switch (__x_[i]) 5285 { 5286 case 'm': 5287 for (++i; i < __x_.size(); ++i) 5288 if (__x_[i] == '%') 5289 break; 5290 if (i == __x_.size()) 5291 break; 5292 ++i; 5293 if (__x_[i] == 'd') 5294 return time_base::ymd; 5295 break; 5296 case 'd': 5297 for (++i; i < __x_.size(); ++i) 5298 if (__x_[i] == '%') 5299 break; 5300 if (i == __x_.size()) 5301 break; 5302 ++i; 5303 if (__x_[i] == 'm') 5304 return time_base::ydm; 5305 break; 5306 } 5307 break; 5308 case 'm': 5309 for (++i; i < __x_.size(); ++i) 5310 if (__x_[i] == '%') 5311 break; 5312 if (i == __x_.size()) 5313 break; 5314 ++i; 5315 if (__x_[i] == 'd') 5316 { 5317 for (++i; i < __x_.size(); ++i) 5318 if (__x_[i] == '%') 5319 break; 5320 if (i == __x_.size()) 5321 break; 5322 ++i; 5323 if (__x_[i] == 'y' || __x_[i] == 'Y') 5324 return time_base::mdy; 5325 break; 5326 } 5327 break; 5328 case 'd': 5329 for (++i; i < __x_.size(); ++i) 5330 if (__x_[i] == '%') 5331 break; 5332 if (i == __x_.size()) 5333 break; 5334 ++i; 5335 if (__x_[i] == 'm') 5336 { 5337 for (++i; i < __x_.size(); ++i) 5338 if (__x_[i] == '%') 5339 break; 5340 if (i == __x_.size()) 5341 break; 5342 ++i; 5343 if (__x_[i] == 'y' || __x_[i] == 'Y') 5344 return time_base::dmy; 5345 break; 5346 } 5347 break; 5348 } 5349 return time_base::no_order; 5350 } 5351 5352 template <> 5353 time_base::dateorder 5354 __time_get_storage<wchar_t>::__do_date_order() const 5355 { 5356 unsigned i; 5357 for (i = 0; i < __x_.size(); ++i) 5358 if (__x_[i] == L'%') 5359 break; 5360 ++i; 5361 switch (__x_[i]) 5362 { 5363 case L'y': 5364 case L'Y': 5365 for (++i; i < __x_.size(); ++i) 5366 if (__x_[i] == L'%') 5367 break; 5368 if (i == __x_.size()) 5369 break; 5370 ++i; 5371 switch (__x_[i]) 5372 { 5373 case L'm': 5374 for (++i; i < __x_.size(); ++i) 5375 if (__x_[i] == L'%') 5376 break; 5377 if (i == __x_.size()) 5378 break; 5379 ++i; 5380 if (__x_[i] == L'd') 5381 return time_base::ymd; 5382 break; 5383 case L'd': 5384 for (++i; i < __x_.size(); ++i) 5385 if (__x_[i] == L'%') 5386 break; 5387 if (i == __x_.size()) 5388 break; 5389 ++i; 5390 if (__x_[i] == L'm') 5391 return time_base::ydm; 5392 break; 5393 } 5394 break; 5395 case L'm': 5396 for (++i; i < __x_.size(); ++i) 5397 if (__x_[i] == L'%') 5398 break; 5399 if (i == __x_.size()) 5400 break; 5401 ++i; 5402 if (__x_[i] == L'd') 5403 { 5404 for (++i; i < __x_.size(); ++i) 5405 if (__x_[i] == L'%') 5406 break; 5407 if (i == __x_.size()) 5408 break; 5409 ++i; 5410 if (__x_[i] == L'y' || __x_[i] == L'Y') 5411 return time_base::mdy; 5412 break; 5413 } 5414 break; 5415 case L'd': 5416 for (++i; i < __x_.size(); ++i) 5417 if (__x_[i] == L'%') 5418 break; 5419 if (i == __x_.size()) 5420 break; 5421 ++i; 5422 if (__x_[i] == L'm') 5423 { 5424 for (++i; i < __x_.size(); ++i) 5425 if (__x_[i] == L'%') 5426 break; 5427 if (i == __x_.size()) 5428 break; 5429 ++i; 5430 if (__x_[i] == L'y' || __x_[i] == L'Y') 5431 return time_base::dmy; 5432 break; 5433 } 5434 break; 5435 } 5436 return time_base::no_order; 5437 } 5438 5439 // time_put 5440 5441 __time_put::__time_put(const char* nm) 5442 : __loc_(newlocale(LC_ALL_MASK, nm, 0)) 5443 { 5444 if (__loc_ == 0) 5445 __throw_runtime_error("time_put_byname" 5446 " failed to construct for " + string(nm)); 5447 } 5448 5449 __time_put::__time_put(const string& nm) 5450 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) 5451 { 5452 if (__loc_ == 0) 5453 __throw_runtime_error("time_put_byname" 5454 " failed to construct for " + nm); 5455 } 5456 5457 __time_put::~__time_put() 5458 { 5459 if (__loc_ != _LIBCPP_GET_C_LOCALE) 5460 freelocale(__loc_); 5461 } 5462 5463 void 5464 __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, 5465 char __fmt, char __mod) const 5466 { 5467 char fmt[] = {'%', __fmt, __mod, 0}; 5468 if (__mod != 0) 5469 swap(fmt[1], fmt[2]); 5470 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_); 5471 __ne = __nb + n; 5472 } 5473 5474 void 5475 __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, 5476 char __fmt, char __mod) const 5477 { 5478 char __nar[100]; 5479 char* __ne = __nar + 100; 5480 __do_put(__nar, __ne, __tm, __fmt, __mod); 5481 mbstate_t mb = {0}; 5482 const char* __nb = __nar; 5483 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); 5484 if (j == size_t(-1)) 5485 __throw_runtime_error("locale not supported"); 5486 __we = __wb + j; 5487 } 5488 5489 // moneypunct_byname 5490 5491 template <class charT> 5492 static 5493 void 5494 __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_, 5495 bool intl, char cs_precedes, char sep_by_space, char sign_posn, 5496 charT space_char) 5497 { 5498 const char sign = static_cast<char>(money_base::sign); 5499 const char space = static_cast<char>(money_base::space); 5500 const char none = static_cast<char>(money_base::none); 5501 const char symbol = static_cast<char>(money_base::symbol); 5502 const char value = static_cast<char>(money_base::value); 5503 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4; 5504 5505 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv 5506 // function'. "Space between sign and symbol or value" means that 5507 // if the sign is adjacent to the symbol, there's a space between 5508 // them, and otherwise there's a space between the sign and value. 5509 // 5510 // C11's localeconv specifies that the fourth character of an 5511 // international curr_symbol is used to separate the sign and 5512 // value when sep_by_space says to do so. C++ can't represent 5513 // that, so we just use a space. When sep_by_space says to 5514 // separate the symbol and value-or-sign with a space, we rearrange the 5515 // curr_symbol to put its spacing character on the correct side of 5516 // the symbol. 5517 // 5518 // We also need to avoid adding an extra space between the sign 5519 // and value when the currency symbol is suppressed (by not 5520 // setting showbase). We match glibc's strfmon by interpreting 5521 // sep_by_space==1 as "omit the space when the currency symbol is 5522 // absent". 5523 // 5524 // Users who want to get this right should use ICU instead. 5525 5526 switch (cs_precedes) 5527 { 5528 case 0: // value before curr_symbol 5529 if (symbol_contains_sep) { 5530 // Move the separator to before the symbol, to place it 5531 // between the value and symbol. 5532 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3, 5533 __curr_symbol_.end()); 5534 } 5535 switch (sign_posn) 5536 { 5537 case 0: // Parentheses surround the quantity and currency symbol. 5538 pat.field[0] = sign; 5539 pat.field[1] = value; 5540 pat.field[2] = none; // Any space appears in the symbol. 5541 pat.field[3] = symbol; 5542 switch (sep_by_space) 5543 { 5544 case 0: // No space separates the currency symbol and value. 5545 // This case may have changed between C99 and C11; 5546 // assume the currency symbol matches the intention. 5547 case 2: // Space between sign and currency or value. 5548 // The "sign" is two parentheses, so no space here either. 5549 return; 5550 case 1: // Space between currency-and-sign or currency and value. 5551 if (!symbol_contains_sep) { 5552 // We insert the space into the symbol instead of 5553 // setting pat.field[2]=space so that when 5554 // showbase is not set, the space goes away too. 5555 __curr_symbol_.insert(0, 1, space_char); 5556 } 5557 return; 5558 default: 5559 break; 5560 } 5561 break; 5562 case 1: // The sign string precedes the quantity and currency symbol. 5563 pat.field[0] = sign; 5564 pat.field[3] = symbol; 5565 switch (sep_by_space) 5566 { 5567 case 0: // No space separates the currency symbol and value. 5568 pat.field[1] = value; 5569 pat.field[2] = none; 5570 return; 5571 case 1: // Space between currency-and-sign or currency and value. 5572 pat.field[1] = value; 5573 pat.field[2] = none; 5574 if (!symbol_contains_sep) { 5575 // We insert the space into the symbol instead of 5576 // setting pat.field[2]=space so that when 5577 // showbase is not set, the space goes away too. 5578 __curr_symbol_.insert(0, 1, space_char); 5579 } 5580 return; 5581 case 2: // Space between sign and currency or value. 5582 pat.field[1] = space; 5583 pat.field[2] = value; 5584 if (symbol_contains_sep) { 5585 // Remove the separator from the symbol, since it 5586 // has already appeared after the sign. 5587 __curr_symbol_.erase(__curr_symbol_.begin()); 5588 } 5589 return; 5590 default: 5591 break; 5592 } 5593 break; 5594 case 2: // The sign string succeeds the quantity and currency symbol. 5595 pat.field[0] = value; 5596 pat.field[3] = sign; 5597 switch (sep_by_space) 5598 { 5599 case 0: // No space separates the currency symbol and value. 5600 pat.field[1] = none; 5601 pat.field[2] = symbol; 5602 return; 5603 case 1: // Space between currency-and-sign or currency and value. 5604 if (!symbol_contains_sep) { 5605 // We insert the space into the symbol instead of 5606 // setting pat.field[1]=space so that when 5607 // showbase is not set, the space goes away too. 5608 __curr_symbol_.insert(0, 1, space_char); 5609 } 5610 pat.field[1] = none; 5611 pat.field[2] = symbol; 5612 return; 5613 case 2: // Space between sign and currency or value. 5614 pat.field[1] = symbol; 5615 pat.field[2] = space; 5616 if (symbol_contains_sep) { 5617 // Remove the separator from the symbol, since it 5618 // should not be removed if showbase is absent. 5619 __curr_symbol_.erase(__curr_symbol_.begin()); 5620 } 5621 return; 5622 default: 5623 break; 5624 } 5625 break; 5626 case 3: // The sign string immediately precedes the currency symbol. 5627 pat.field[0] = value; 5628 pat.field[3] = symbol; 5629 switch (sep_by_space) 5630 { 5631 case 0: // No space separates the currency symbol and value. 5632 pat.field[1] = none; 5633 pat.field[2] = sign; 5634 return; 5635 case 1: // Space between currency-and-sign or currency and value. 5636 pat.field[1] = space; 5637 pat.field[2] = sign; 5638 if (symbol_contains_sep) { 5639 // Remove the separator from the symbol, since it 5640 // has already appeared before the sign. 5641 __curr_symbol_.erase(__curr_symbol_.begin()); 5642 } 5643 return; 5644 case 2: // Space between sign and currency or value. 5645 pat.field[1] = sign; 5646 pat.field[2] = none; 5647 if (!symbol_contains_sep) { 5648 // We insert the space into the symbol instead of 5649 // setting pat.field[2]=space so that when 5650 // showbase is not set, the space goes away too. 5651 __curr_symbol_.insert(0, 1, space_char); 5652 } 5653 return; 5654 default: 5655 break; 5656 } 5657 break; 5658 case 4: // The sign string immediately succeeds the currency symbol. 5659 pat.field[0] = value; 5660 pat.field[3] = sign; 5661 switch (sep_by_space) 5662 { 5663 case 0: // No space separates the currency symbol and value. 5664 pat.field[1] = none; 5665 pat.field[2] = symbol; 5666 return; 5667 case 1: // Space between currency-and-sign or currency and value. 5668 pat.field[1] = none; 5669 pat.field[2] = symbol; 5670 if (!symbol_contains_sep) { 5671 // We insert the space into the symbol instead of 5672 // setting pat.field[1]=space so that when 5673 // showbase is not set, the space goes away too. 5674 __curr_symbol_.insert(0, 1, space_char); 5675 } 5676 return; 5677 case 2: // Space between sign and currency or value. 5678 pat.field[1] = symbol; 5679 pat.field[2] = space; 5680 if (symbol_contains_sep) { 5681 // Remove the separator from the symbol, since it 5682 // should not disappear when showbase is absent. 5683 __curr_symbol_.erase(__curr_symbol_.begin()); 5684 } 5685 return; 5686 default: 5687 break; 5688 } 5689 break; 5690 default: 5691 break; 5692 } 5693 break; 5694 case 1: // curr_symbol before value 5695 switch (sign_posn) 5696 { 5697 case 0: // Parentheses surround the quantity and currency symbol. 5698 pat.field[0] = sign; 5699 pat.field[1] = symbol; 5700 pat.field[2] = none; // Any space appears in the symbol. 5701 pat.field[3] = value; 5702 switch (sep_by_space) 5703 { 5704 case 0: // No space separates the currency symbol and value. 5705 // This case may have changed between C99 and C11; 5706 // assume the currency symbol matches the intention. 5707 case 2: // Space between sign and currency or value. 5708 // The "sign" is two parentheses, so no space here either. 5709 return; 5710 case 1: // Space between currency-and-sign or currency and value. 5711 if (!symbol_contains_sep) { 5712 // We insert the space into the symbol instead of 5713 // setting pat.field[2]=space so that when 5714 // showbase is not set, the space goes away too. 5715 __curr_symbol_.insert(0, 1, space_char); 5716 } 5717 return; 5718 default: 5719 break; 5720 } 5721 break; 5722 case 1: // The sign string precedes the quantity and currency symbol. 5723 pat.field[0] = sign; 5724 pat.field[3] = value; 5725 switch (sep_by_space) 5726 { 5727 case 0: // No space separates the currency symbol and value. 5728 pat.field[1] = symbol; 5729 pat.field[2] = none; 5730 return; 5731 case 1: // Space between currency-and-sign or currency and value. 5732 pat.field[1] = symbol; 5733 pat.field[2] = none; 5734 if (!symbol_contains_sep) { 5735 // We insert the space into the symbol instead of 5736 // setting pat.field[2]=space so that when 5737 // showbase is not set, the space goes away too. 5738 __curr_symbol_.push_back(space_char); 5739 } 5740 return; 5741 case 2: // Space between sign and currency or value. 5742 pat.field[1] = space; 5743 pat.field[2] = symbol; 5744 if (symbol_contains_sep) { 5745 // Remove the separator from the symbol, since it 5746 // has already appeared after the sign. 5747 __curr_symbol_.pop_back(); 5748 } 5749 return; 5750 default: 5751 break; 5752 } 5753 break; 5754 case 2: // The sign string succeeds the quantity and currency symbol. 5755 pat.field[0] = symbol; 5756 pat.field[3] = sign; 5757 switch (sep_by_space) 5758 { 5759 case 0: // No space separates the currency symbol and value. 5760 pat.field[1] = none; 5761 pat.field[2] = value; 5762 return; 5763 case 1: // Space between currency-and-sign or currency and value. 5764 pat.field[1] = none; 5765 pat.field[2] = value; 5766 if (!symbol_contains_sep) { 5767 // We insert the space into the symbol instead of 5768 // setting pat.field[1]=space so that when 5769 // showbase is not set, the space goes away too. 5770 __curr_symbol_.push_back(space_char); 5771 } 5772 return; 5773 case 2: // Space between sign and currency or value. 5774 pat.field[1] = value; 5775 pat.field[2] = space; 5776 if (symbol_contains_sep) { 5777 // Remove the separator from the symbol, since it 5778 // will appear before the sign. 5779 __curr_symbol_.pop_back(); 5780 } 5781 return; 5782 default: 5783 break; 5784 } 5785 break; 5786 case 3: // The sign string immediately precedes the currency symbol. 5787 pat.field[0] = sign; 5788 pat.field[3] = value; 5789 switch (sep_by_space) 5790 { 5791 case 0: // No space separates the currency symbol and value. 5792 pat.field[1] = symbol; 5793 pat.field[2] = none; 5794 return; 5795 case 1: // Space between currency-and-sign or currency and value. 5796 pat.field[1] = symbol; 5797 pat.field[2] = none; 5798 if (!symbol_contains_sep) { 5799 // We insert the space into the symbol instead of 5800 // setting pat.field[2]=space so that when 5801 // showbase is not set, the space goes away too. 5802 __curr_symbol_.push_back(space_char); 5803 } 5804 return; 5805 case 2: // Space between sign and currency or value. 5806 pat.field[1] = space; 5807 pat.field[2] = symbol; 5808 if (symbol_contains_sep) { 5809 // Remove the separator from the symbol, since it 5810 // has already appeared after the sign. 5811 __curr_symbol_.pop_back(); 5812 } 5813 return; 5814 default: 5815 break; 5816 } 5817 break; 5818 case 4: // The sign string immediately succeeds the currency symbol. 5819 pat.field[0] = symbol; 5820 pat.field[3] = value; 5821 switch (sep_by_space) 5822 { 5823 case 0: // No space separates the currency symbol and value. 5824 pat.field[1] = sign; 5825 pat.field[2] = none; 5826 return; 5827 case 1: // Space between currency-and-sign or currency and value. 5828 pat.field[1] = sign; 5829 pat.field[2] = space; 5830 if (symbol_contains_sep) { 5831 // Remove the separator from the symbol, since it 5832 // should not disappear when showbase is absent. 5833 __curr_symbol_.pop_back(); 5834 } 5835 return; 5836 case 2: // Space between sign and currency or value. 5837 pat.field[1] = none; 5838 pat.field[2] = sign; 5839 if (!symbol_contains_sep) { 5840 // We insert the space into the symbol instead of 5841 // setting pat.field[1]=space so that when 5842 // showbase is not set, the space goes away too. 5843 __curr_symbol_.push_back(space_char); 5844 } 5845 return; 5846 default: 5847 break; 5848 } 5849 break; 5850 default: 5851 break; 5852 } 5853 break; 5854 default: 5855 break; 5856 } 5857 pat.field[0] = symbol; 5858 pat.field[1] = sign; 5859 pat.field[2] = none; 5860 pat.field[3] = value; 5861 } 5862 5863 template<> 5864 void 5865 moneypunct_byname<char, false>::init(const char* nm) 5866 { 5867 typedef moneypunct<char, false> base; 5868 __libcpp_unique_locale loc(nm); 5869 if (!loc) 5870 __throw_runtime_error("moneypunct_byname" 5871 " failed to construct for " + string(nm)); 5872 5873 lconv* lc = __libcpp_localeconv_l(loc.get()); 5874 if (!checked_string_to_char_convert(__decimal_point_, 5875 lc->mon_decimal_point, 5876 loc.get())) 5877 __decimal_point_ = base::do_decimal_point(); 5878 if (!checked_string_to_char_convert(__thousands_sep_, 5879 lc->mon_thousands_sep, 5880 loc.get())) 5881 __thousands_sep_ = base::do_thousands_sep(); 5882 5883 __grouping_ = lc->mon_grouping; 5884 __curr_symbol_ = lc->currency_symbol; 5885 if (lc->frac_digits != CHAR_MAX) 5886 __frac_digits_ = lc->frac_digits; 5887 else 5888 __frac_digits_ = base::do_frac_digits(); 5889 if (lc->p_sign_posn == 0) 5890 __positive_sign_ = "()"; 5891 else 5892 __positive_sign_ = lc->positive_sign; 5893 if (lc->n_sign_posn == 0) 5894 __negative_sign_ = "()"; 5895 else 5896 __negative_sign_ = lc->negative_sign; 5897 // Assume the positive and negative formats will want spaces in 5898 // the same places in curr_symbol since there's no way to 5899 // represent anything else. 5900 string_type __dummy_curr_symbol = __curr_symbol_; 5901 __init_pat(__pos_format_, __dummy_curr_symbol, false, 5902 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); 5903 __init_pat(__neg_format_, __curr_symbol_, false, 5904 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); 5905 } 5906 5907 template<> 5908 void 5909 moneypunct_byname<char, true>::init(const char* nm) 5910 { 5911 typedef moneypunct<char, true> base; 5912 __libcpp_unique_locale loc(nm); 5913 if (!loc) 5914 __throw_runtime_error("moneypunct_byname" 5915 " failed to construct for " + string(nm)); 5916 5917 lconv* lc = __libcpp_localeconv_l(loc.get()); 5918 if (!checked_string_to_char_convert(__decimal_point_, 5919 lc->mon_decimal_point, 5920 loc.get())) 5921 __decimal_point_ = base::do_decimal_point(); 5922 if (!checked_string_to_char_convert(__thousands_sep_, 5923 lc->mon_thousands_sep, 5924 loc.get())) 5925 __thousands_sep_ = base::do_thousands_sep(); 5926 __grouping_ = lc->mon_grouping; 5927 __curr_symbol_ = lc->int_curr_symbol; 5928 if (lc->int_frac_digits != CHAR_MAX) 5929 __frac_digits_ = lc->int_frac_digits; 5930 else 5931 __frac_digits_ = base::do_frac_digits(); 5932 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 5933 if (lc->p_sign_posn == 0) 5934 #else // _LIBCPP_MSVCRT 5935 if (lc->int_p_sign_posn == 0) 5936 #endif // !_LIBCPP_MSVCRT 5937 __positive_sign_ = "()"; 5938 else 5939 __positive_sign_ = lc->positive_sign; 5940 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 5941 if(lc->n_sign_posn == 0) 5942 #else // _LIBCPP_MSVCRT 5943 if (lc->int_n_sign_posn == 0) 5944 #endif // !_LIBCPP_MSVCRT 5945 __negative_sign_ = "()"; 5946 else 5947 __negative_sign_ = lc->negative_sign; 5948 // Assume the positive and negative formats will want spaces in 5949 // the same places in curr_symbol since there's no way to 5950 // represent anything else. 5951 string_type __dummy_curr_symbol = __curr_symbol_; 5952 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 5953 __init_pat(__pos_format_, __dummy_curr_symbol, true, 5954 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); 5955 __init_pat(__neg_format_, __curr_symbol_, true, 5956 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); 5957 #else // _LIBCPP_MSVCRT 5958 __init_pat(__pos_format_, __dummy_curr_symbol, true, 5959 lc->int_p_cs_precedes, lc->int_p_sep_by_space, 5960 lc->int_p_sign_posn, ' '); 5961 __init_pat(__neg_format_, __curr_symbol_, true, 5962 lc->int_n_cs_precedes, lc->int_n_sep_by_space, 5963 lc->int_n_sign_posn, ' '); 5964 #endif // !_LIBCPP_MSVCRT 5965 } 5966 5967 template<> 5968 void 5969 moneypunct_byname<wchar_t, false>::init(const char* nm) 5970 { 5971 typedef moneypunct<wchar_t, false> base; 5972 __libcpp_unique_locale loc(nm); 5973 if (!loc) 5974 __throw_runtime_error("moneypunct_byname" 5975 " failed to construct for " + string(nm)); 5976 lconv* lc = __libcpp_localeconv_l(loc.get()); 5977 if (!checked_string_to_wchar_convert(__decimal_point_, 5978 lc->mon_decimal_point, 5979 loc.get())) 5980 __decimal_point_ = base::do_decimal_point(); 5981 if (!checked_string_to_wchar_convert(__thousands_sep_, 5982 lc->mon_thousands_sep, 5983 loc.get())) 5984 __thousands_sep_ = base::do_thousands_sep(); 5985 __grouping_ = lc->mon_grouping; 5986 wchar_t wbuf[100]; 5987 mbstate_t mb = {0}; 5988 const char* bb = lc->currency_symbol; 5989 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 5990 if (j == size_t(-1)) 5991 __throw_runtime_error("locale not supported"); 5992 wchar_t* wbe = wbuf + j; 5993 __curr_symbol_.assign(wbuf, wbe); 5994 if (lc->frac_digits != CHAR_MAX) 5995 __frac_digits_ = lc->frac_digits; 5996 else 5997 __frac_digits_ = base::do_frac_digits(); 5998 if (lc->p_sign_posn == 0) 5999 __positive_sign_ = L"()"; 6000 else 6001 { 6002 mb = mbstate_t(); 6003 bb = lc->positive_sign; 6004 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 6005 if (j == size_t(-1)) 6006 __throw_runtime_error("locale not supported"); 6007 wbe = wbuf + j; 6008 __positive_sign_.assign(wbuf, wbe); 6009 } 6010 if (lc->n_sign_posn == 0) 6011 __negative_sign_ = L"()"; 6012 else 6013 { 6014 mb = mbstate_t(); 6015 bb = lc->negative_sign; 6016 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 6017 if (j == size_t(-1)) 6018 __throw_runtime_error("locale not supported"); 6019 wbe = wbuf + j; 6020 __negative_sign_.assign(wbuf, wbe); 6021 } 6022 // Assume the positive and negative formats will want spaces in 6023 // the same places in curr_symbol since there's no way to 6024 // represent anything else. 6025 string_type __dummy_curr_symbol = __curr_symbol_; 6026 __init_pat(__pos_format_, __dummy_curr_symbol, false, 6027 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); 6028 __init_pat(__neg_format_, __curr_symbol_, false, 6029 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); 6030 } 6031 6032 template<> 6033 void 6034 moneypunct_byname<wchar_t, true>::init(const char* nm) 6035 { 6036 typedef moneypunct<wchar_t, true> base; 6037 __libcpp_unique_locale loc(nm); 6038 if (!loc) 6039 __throw_runtime_error("moneypunct_byname" 6040 " failed to construct for " + string(nm)); 6041 6042 lconv* lc = __libcpp_localeconv_l(loc.get()); 6043 if (!checked_string_to_wchar_convert(__decimal_point_, 6044 lc->mon_decimal_point, 6045 loc.get())) 6046 __decimal_point_ = base::do_decimal_point(); 6047 if (!checked_string_to_wchar_convert(__thousands_sep_, 6048 lc->mon_thousands_sep, 6049 loc.get())) 6050 __thousands_sep_ = base::do_thousands_sep(); 6051 __grouping_ = lc->mon_grouping; 6052 wchar_t wbuf[100]; 6053 mbstate_t mb = {0}; 6054 const char* bb = lc->int_curr_symbol; 6055 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 6056 if (j == size_t(-1)) 6057 __throw_runtime_error("locale not supported"); 6058 wchar_t* wbe = wbuf + j; 6059 __curr_symbol_.assign(wbuf, wbe); 6060 if (lc->int_frac_digits != CHAR_MAX) 6061 __frac_digits_ = lc->int_frac_digits; 6062 else 6063 __frac_digits_ = base::do_frac_digits(); 6064 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 6065 if (lc->p_sign_posn == 0) 6066 #else // _LIBCPP_MSVCRT 6067 if (lc->int_p_sign_posn == 0) 6068 #endif // !_LIBCPP_MSVCRT 6069 __positive_sign_ = L"()"; 6070 else 6071 { 6072 mb = mbstate_t(); 6073 bb = lc->positive_sign; 6074 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 6075 if (j == size_t(-1)) 6076 __throw_runtime_error("locale not supported"); 6077 wbe = wbuf + j; 6078 __positive_sign_.assign(wbuf, wbe); 6079 } 6080 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 6081 if (lc->n_sign_posn == 0) 6082 #else // _LIBCPP_MSVCRT 6083 if (lc->int_n_sign_posn == 0) 6084 #endif // !_LIBCPP_MSVCRT 6085 __negative_sign_ = L"()"; 6086 else 6087 { 6088 mb = mbstate_t(); 6089 bb = lc->negative_sign; 6090 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 6091 if (j == size_t(-1)) 6092 __throw_runtime_error("locale not supported"); 6093 wbe = wbuf + j; 6094 __negative_sign_.assign(wbuf, wbe); 6095 } 6096 // Assume the positive and negative formats will want spaces in 6097 // the same places in curr_symbol since there's no way to 6098 // represent anything else. 6099 string_type __dummy_curr_symbol = __curr_symbol_; 6100 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 6101 __init_pat(__pos_format_, __dummy_curr_symbol, true, 6102 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); 6103 __init_pat(__neg_format_, __curr_symbol_, true, 6104 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); 6105 #else // _LIBCPP_MSVCRT 6106 __init_pat(__pos_format_, __dummy_curr_symbol, true, 6107 lc->int_p_cs_precedes, lc->int_p_sep_by_space, 6108 lc->int_p_sign_posn, L' '); 6109 __init_pat(__neg_format_, __curr_symbol_, true, 6110 lc->int_n_cs_precedes, lc->int_n_sep_by_space, 6111 lc->int_n_sign_posn, L' '); 6112 #endif // !_LIBCPP_MSVCRT 6113 } 6114 6115 void __do_nothing(void*) {} 6116 6117 void __throw_runtime_error(const char* msg) 6118 { 6119 #ifndef _LIBCPP_NO_EXCEPTIONS 6120 throw runtime_error(msg); 6121 #else 6122 (void)msg; 6123 _VSTD::abort(); 6124 #endif 6125 } 6126 6127 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>; 6128 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>; 6129 6130 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>; 6131 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>; 6132 6133 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>; 6134 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>; 6135 6136 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>; 6137 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>; 6138 6139 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>; 6140 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>; 6141 6142 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>; 6143 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>; 6144 6145 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>; 6146 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>; 6147 6148 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>; 6149 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>; 6150 6151 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>; 6152 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>; 6153 6154 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>; 6155 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>; 6156 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>; 6157 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>; 6158 6159 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>; 6160 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>; 6161 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>; 6162 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>; 6163 6164 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>; 6165 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>; 6166 6167 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>; 6168 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>; 6169 6170 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>; 6171 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>; 6172 6173 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>; 6174 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>; 6175 6176 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>; 6177 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>; 6178 6179 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>; 6180 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>; 6181 6182 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>; 6183 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>; 6184 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>; 6185 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>; 6186 6187 _LIBCPP_END_NAMESPACE_STD