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