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