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