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