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