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