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