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