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