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