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