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