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