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