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