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