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