xref: /llvm-project-15.0.7/libcxx/src/locale.cpp (revision 4d75e8d6)
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 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1404     return btowc_l(c, __l);
1405 #else
1406     return __btowc_l(c, __l);
1407 #endif
1408 }
1409 
1410 const char*
1411 ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1412 {
1413     for (; low != high; ++low, ++dest)
1414 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1415         *dest = btowc_l(*low, __l);
1416 #else
1417         *dest = __btowc_l(*low, __l);
1418 #endif
1419     return low;
1420 }
1421 
1422 char
1423 ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1424 {
1425 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1426     int r = wctob_l(c, __l);
1427 #else
1428     int r = __wctob_l(c, __l);
1429 #endif
1430     return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
1431 }
1432 
1433 const wchar_t*
1434 ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1435 {
1436     for (; low != high; ++low, ++dest)
1437     {
1438 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1439         int r = wctob_l(*low, __l);
1440 #else
1441         int r = __wctob_l(*low, __l);
1442 #endif
1443         *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
1444     }
1445     return low;
1446 }
1447 
1448 // template <> class codecvt<char, char, mbstate_t>
1449 
1450 locale::id codecvt<char, char, mbstate_t>::id;
1451 
1452 codecvt<char, char, mbstate_t>::~codecvt()
1453 {
1454 }
1455 
1456 codecvt<char, char, mbstate_t>::result
1457 codecvt<char, char, mbstate_t>::do_out(state_type&,
1458     const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
1459     extern_type* to, extern_type*, extern_type*& to_nxt) const
1460 {
1461     frm_nxt = frm;
1462     to_nxt = to;
1463     return noconv;
1464 }
1465 
1466 codecvt<char, char, mbstate_t>::result
1467 codecvt<char, char, mbstate_t>::do_in(state_type&,
1468     const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
1469     intern_type* to, intern_type*, intern_type*& to_nxt) const
1470 {
1471     frm_nxt = frm;
1472     to_nxt = to;
1473     return noconv;
1474 }
1475 
1476 codecvt<char, char, mbstate_t>::result
1477 codecvt<char, char, mbstate_t>::do_unshift(state_type&,
1478     extern_type* to, extern_type*, extern_type*& to_nxt) const
1479 {
1480     to_nxt = to;
1481     return noconv;
1482 }
1483 
1484 int
1485 codecvt<char, char, mbstate_t>::do_encoding() const  _NOEXCEPT
1486 {
1487     return 1;
1488 }
1489 
1490 bool
1491 codecvt<char, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
1492 {
1493     return true;
1494 }
1495 
1496 int
1497 codecvt<char, char, mbstate_t>::do_length(state_type&,
1498     const extern_type* frm, const extern_type* end, size_t mx) const
1499 {
1500     return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
1501 }
1502 
1503 int
1504 codecvt<char, char, mbstate_t>::do_max_length() const  _NOEXCEPT
1505 {
1506     return 1;
1507 }
1508 
1509 // template <> class codecvt<wchar_t, char, mbstate_t>
1510 
1511 locale::id codecvt<wchar_t, char, mbstate_t>::id;
1512 
1513 codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1514     : locale::facet(refs),
1515       __l(_LIBCPP_GET_C_LOCALE)
1516 {
1517 }
1518 
1519 codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1520     : locale::facet(refs),
1521       __l(newlocale(LC_ALL_MASK, nm, 0))
1522 {
1523 #ifndef _LIBCPP_NO_EXCEPTIONS
1524     if (__l == 0)
1525         throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1526                             " failed to construct for " + string(nm));
1527 #endif  // _LIBCPP_NO_EXCEPTIONS
1528 }
1529 
1530 codecvt<wchar_t, char, mbstate_t>::~codecvt()
1531 {
1532     if (__l != _LIBCPP_GET_C_LOCALE)
1533         freelocale(__l);
1534 }
1535 
1536 codecvt<wchar_t, char, mbstate_t>::result
1537 codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
1538     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1539     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1540 {
1541     // look for first internal null in frm
1542     const intern_type* fend = frm;
1543     for (; fend != frm_end; ++fend)
1544         if (*fend == 0)
1545             break;
1546     // loop over all null-terminated sequences in frm
1547     to_nxt = to;
1548     for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1549     {
1550         // save state in case it is needed to recover to_nxt on error
1551         mbstate_t save_state = st;
1552 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1553         size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1554                                 static_cast<size_t>(to_end-to), &st, __l);
1555 #else
1556         size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1557 #endif
1558         if (n == size_t(-1))
1559         {
1560             // need to recover to_nxt
1561             for (to_nxt = to; frm != frm_nxt; ++frm)
1562             {
1563 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1564                 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1565 #else
1566                 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1567 #endif
1568                 if (n == size_t(-1))
1569                     break;
1570                 to_nxt += n;
1571             }
1572             frm_nxt = frm;
1573             return error;
1574         }
1575         if (n == 0)
1576             return partial;
1577         to_nxt += n;
1578         if (to_nxt == to_end)
1579             break;
1580         if (fend != frm_end)  // set up next null terminated sequence
1581         {
1582             // Try to write the terminating null
1583             extern_type tmp[MB_LEN_MAX];
1584 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1585             n = wcrtomb_l(tmp, intern_type(), &st, __l);
1586 #else
1587             n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1588 #endif
1589             if (n == size_t(-1))  // on error
1590                 return error;
1591             if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
1592                 return partial;
1593             for (extern_type* p = tmp; n; --n)  // write it
1594                 *to_nxt++ = *p++;
1595             ++frm_nxt;
1596             // look for next null in frm
1597             for (fend = frm_nxt; fend != frm_end; ++fend)
1598                 if (*fend == 0)
1599                     break;
1600         }
1601     }
1602     return frm_nxt == frm_end ? ok : partial;
1603 }
1604 
1605 codecvt<wchar_t, char, mbstate_t>::result
1606 codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
1607     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1608     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1609 {
1610     // look for first internal null in frm
1611     const extern_type* fend = frm;
1612     for (; fend != frm_end; ++fend)
1613         if (*fend == 0)
1614             break;
1615     // loop over all null-terminated sequences in frm
1616     to_nxt = to;
1617     for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1618     {
1619         // save state in case it is needed to recover to_nxt on error
1620         mbstate_t save_state = st;
1621 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1622         size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1623                                 static_cast<size_t>(to_end-to), &st, __l);
1624 #else
1625         size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1626 #endif
1627         if (n == size_t(-1))
1628         {
1629             // need to recover to_nxt
1630             for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1631             {
1632 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1633                 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1634                               &save_state, __l);
1635 #else
1636                 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1637 #endif
1638                 switch (n)
1639                 {
1640                 case 0:
1641                     ++frm;
1642                     break;
1643                 case size_t(-1):
1644                     frm_nxt = frm;
1645                     return error;
1646                 case size_t(-2):
1647                     frm_nxt = frm;
1648                     return partial;
1649                 default:
1650                     frm += n;
1651                     break;
1652                 }
1653             }
1654             frm_nxt = frm;
1655             return frm_nxt == frm_end ? ok : partial;
1656         }
1657         if (n == size_t(-1))
1658             return error;
1659         to_nxt += n;
1660         if (to_nxt == to_end)
1661             break;
1662         if (fend != frm_end)  // set up next null terminated sequence
1663         {
1664             // Try to write the terminating null
1665 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1666             n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1667 #else
1668             n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1669 #endif
1670             if (n != 0)  // on error
1671                 return error;
1672             ++to_nxt;
1673             ++frm_nxt;
1674             // look for next null in frm
1675             for (fend = frm_nxt; fend != frm_end; ++fend)
1676                 if (*fend == 0)
1677                     break;
1678         }
1679     }
1680     return frm_nxt == frm_end ? ok : partial;
1681 }
1682 
1683 codecvt<wchar_t, char, mbstate_t>::result
1684 codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1685     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1686 {
1687     to_nxt = to;
1688     extern_type tmp[MB_LEN_MAX];
1689 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1690     size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1691 #else
1692     size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1693 #endif
1694     if (n == size_t(-1) || n == 0)  // on error
1695         return error;
1696     --n;
1697     if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
1698         return partial;
1699     for (extern_type* p = tmp; n; --n)  // write it
1700         *to_nxt++ = *p++;
1701     return ok;
1702 }
1703 
1704 int
1705 codecvt<wchar_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
1706 {
1707 #ifndef __CloudABI__
1708 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1709     if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
1710 #else
1711     if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
1712 #endif
1713         return -1;
1714 #endif
1715 
1716     // stateless encoding
1717 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1718     if (__l == 0 || MB_CUR_MAX_L(__l) == 1)  // there are no known constant length encodings
1719 #else
1720     if (__l == 0 || __mb_cur_max_l(__l) == 1)  // there are no known constant length encodings
1721 #endif
1722         return 1;                // which take more than 1 char to form a wchar_t
1723     return 0;
1724 }
1725 
1726 bool
1727 codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
1728 {
1729     return false;
1730 }
1731 
1732 int
1733 codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1734     const extern_type* frm, const extern_type* frm_end, size_t mx) const
1735 {
1736     int nbytes = 0;
1737     for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1738     {
1739 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1740         size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
1741 #else
1742         size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1743 #endif
1744         switch (n)
1745         {
1746         case 0:
1747             ++nbytes;
1748             ++frm;
1749             break;
1750         case size_t(-1):
1751         case size_t(-2):
1752             return nbytes;
1753         default:
1754             nbytes += n;
1755             frm += n;
1756             break;
1757         }
1758     }
1759     return nbytes;
1760 }
1761 
1762 int
1763 codecvt<wchar_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
1764 {
1765 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
1766     return __l == 0 ? 1 : static_cast<int>(  MB_CUR_MAX_L(__l));
1767 #else
1768     return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
1769 #endif
1770 }
1771 
1772 //                                     Valid UTF ranges
1773 //     UTF-32               UTF-16                          UTF-8               # of code points
1774 //                     first      second       first   second    third   fourth
1775 // 000000 - 00007F  0000 - 007F               00 - 7F                                 127
1776 // 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920
1777 // 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048
1778 // 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152
1779 // 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048
1780 // 00D800 - 00DFFF                invalid
1781 // 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192
1782 // 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608
1783 // 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432
1784 // 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536
1785 
1786 static
1787 codecvt_base::result
1788 utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1789               uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1790               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1791 {
1792     frm_nxt = frm;
1793     to_nxt = to;
1794     if (mode & generate_header)
1795     {
1796         if (to_end-to_nxt < 3)
1797             return codecvt_base::partial;
1798         *to_nxt++ = static_cast<uint8_t>(0xEF);
1799         *to_nxt++ = static_cast<uint8_t>(0xBB);
1800         *to_nxt++ = static_cast<uint8_t>(0xBF);
1801     }
1802     for (; frm_nxt < frm_end; ++frm_nxt)
1803     {
1804         uint16_t wc1 = *frm_nxt;
1805         if (wc1 > Maxcode)
1806             return codecvt_base::error;
1807         if (wc1 < 0x0080)
1808         {
1809             if (to_end-to_nxt < 1)
1810                 return codecvt_base::partial;
1811             *to_nxt++ = static_cast<uint8_t>(wc1);
1812         }
1813         else if (wc1 < 0x0800)
1814         {
1815             if (to_end-to_nxt < 2)
1816                 return codecvt_base::partial;
1817             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1818             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1819         }
1820         else if (wc1 < 0xD800)
1821         {
1822             if (to_end-to_nxt < 3)
1823                 return codecvt_base::partial;
1824             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1825             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1826             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1827         }
1828         else if (wc1 < 0xDC00)
1829         {
1830             if (frm_end-frm_nxt < 2)
1831                 return codecvt_base::partial;
1832             uint16_t wc2 = frm_nxt[1];
1833             if ((wc2 & 0xFC00) != 0xDC00)
1834                 return codecvt_base::error;
1835             if (to_end-to_nxt < 4)
1836                 return codecvt_base::partial;
1837             if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1838                 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1839                 return codecvt_base::error;
1840             ++frm_nxt;
1841             uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1842             *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1843             *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
1844             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1845             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
1846         }
1847         else if (wc1 < 0xE000)
1848         {
1849             return codecvt_base::error;
1850         }
1851         else
1852         {
1853             if (to_end-to_nxt < 3)
1854                 return codecvt_base::partial;
1855             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1856             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1857             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1858         }
1859     }
1860     return codecvt_base::ok;
1861 }
1862 
1863 static
1864 codecvt_base::result
1865 utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1866               uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1867               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1868 {
1869     frm_nxt = frm;
1870     to_nxt = to;
1871     if (mode & generate_header)
1872     {
1873         if (to_end-to_nxt < 3)
1874             return codecvt_base::partial;
1875         *to_nxt++ = static_cast<uint8_t>(0xEF);
1876         *to_nxt++ = static_cast<uint8_t>(0xBB);
1877         *to_nxt++ = static_cast<uint8_t>(0xBF);
1878     }
1879     for (; frm_nxt < frm_end; ++frm_nxt)
1880     {
1881         uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1882         if (wc1 > Maxcode)
1883             return codecvt_base::error;
1884         if (wc1 < 0x0080)
1885         {
1886             if (to_end-to_nxt < 1)
1887                 return codecvt_base::partial;
1888             *to_nxt++ = static_cast<uint8_t>(wc1);
1889         }
1890         else if (wc1 < 0x0800)
1891         {
1892             if (to_end-to_nxt < 2)
1893                 return codecvt_base::partial;
1894             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1895             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1896         }
1897         else if (wc1 < 0xD800)
1898         {
1899             if (to_end-to_nxt < 3)
1900                 return codecvt_base::partial;
1901             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1902             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1903             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1904         }
1905         else if (wc1 < 0xDC00)
1906         {
1907             if (frm_end-frm_nxt < 2)
1908                 return codecvt_base::partial;
1909             uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1910             if ((wc2 & 0xFC00) != 0xDC00)
1911                 return codecvt_base::error;
1912             if (to_end-to_nxt < 4)
1913                 return codecvt_base::partial;
1914             if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1915                 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1916                 return codecvt_base::error;
1917             ++frm_nxt;
1918             uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1919             *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1920             *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
1921             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1922             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
1923         }
1924         else if (wc1 < 0xE000)
1925         {
1926             return codecvt_base::error;
1927         }
1928         else
1929         {
1930             if (to_end-to_nxt < 3)
1931                 return codecvt_base::partial;
1932             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
1933             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1934             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
1935         }
1936     }
1937     return codecvt_base::ok;
1938 }
1939 
1940 static
1941 codecvt_base::result
1942 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1943               uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1944               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1945 {
1946     frm_nxt = frm;
1947     to_nxt = to;
1948     if (mode & consume_header)
1949     {
1950         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1951                                                           frm_nxt[2] == 0xBF)
1952             frm_nxt += 3;
1953     }
1954     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1955     {
1956         uint8_t c1 = *frm_nxt;
1957         if (c1 > Maxcode)
1958             return codecvt_base::error;
1959         if (c1 < 0x80)
1960         {
1961             *to_nxt = static_cast<uint16_t>(c1);
1962             ++frm_nxt;
1963         }
1964         else if (c1 < 0xC2)
1965         {
1966             return codecvt_base::error;
1967         }
1968         else if (c1 < 0xE0)
1969         {
1970             if (frm_end-frm_nxt < 2)
1971                 return codecvt_base::partial;
1972             uint8_t c2 = frm_nxt[1];
1973             if ((c2 & 0xC0) != 0x80)
1974                 return codecvt_base::error;
1975             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1976             if (t > Maxcode)
1977                 return codecvt_base::error;
1978             *to_nxt = t;
1979             frm_nxt += 2;
1980         }
1981         else if (c1 < 0xF0)
1982         {
1983             if (frm_end-frm_nxt < 3)
1984                 return codecvt_base::partial;
1985             uint8_t c2 = frm_nxt[1];
1986             uint8_t c3 = frm_nxt[2];
1987             switch (c1)
1988             {
1989             case 0xE0:
1990                 if ((c2 & 0xE0) != 0xA0)
1991                     return codecvt_base::error;
1992                  break;
1993             case 0xED:
1994                 if ((c2 & 0xE0) != 0x80)
1995                     return codecvt_base::error;
1996                  break;
1997             default:
1998                 if ((c2 & 0xC0) != 0x80)
1999                     return codecvt_base::error;
2000                  break;
2001             }
2002             if ((c3 & 0xC0) != 0x80)
2003                 return codecvt_base::error;
2004             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2005                                              | ((c2 & 0x3F) << 6)
2006                                              |  (c3 & 0x3F));
2007             if (t > Maxcode)
2008                 return codecvt_base::error;
2009             *to_nxt = t;
2010             frm_nxt += 3;
2011         }
2012         else if (c1 < 0xF5)
2013         {
2014             if (frm_end-frm_nxt < 4)
2015                 return codecvt_base::partial;
2016             uint8_t c2 = frm_nxt[1];
2017             uint8_t c3 = frm_nxt[2];
2018             uint8_t c4 = frm_nxt[3];
2019             switch (c1)
2020             {
2021             case 0xF0:
2022                 if (!(0x90 <= c2 && c2 <= 0xBF))
2023                     return codecvt_base::error;
2024                  break;
2025             case 0xF4:
2026                 if ((c2 & 0xF0) != 0x80)
2027                     return codecvt_base::error;
2028                  break;
2029             default:
2030                 if ((c2 & 0xC0) != 0x80)
2031                     return codecvt_base::error;
2032                  break;
2033             }
2034             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2035                 return codecvt_base::error;
2036             if (to_end-to_nxt < 2)
2037                 return codecvt_base::partial;
2038             if ((((c1 & 7UL) << 18) +
2039                 ((c2 & 0x3FUL) << 12) +
2040                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2041                 return codecvt_base::error;
2042             *to_nxt = static_cast<uint16_t>(
2043                     0xD800
2044                   | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2045                   | ((c2 & 0x0F) << 2)
2046                   | ((c3 & 0x30) >> 4));
2047             *++to_nxt = static_cast<uint16_t>(
2048                     0xDC00
2049                   | ((c3 & 0x0F) << 6)
2050                   |  (c4 & 0x3F));
2051             frm_nxt += 4;
2052         }
2053         else
2054         {
2055             return codecvt_base::error;
2056         }
2057     }
2058     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2059 }
2060 
2061 static
2062 codecvt_base::result
2063 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2064               uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2065               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2066 {
2067     frm_nxt = frm;
2068     to_nxt = to;
2069     if (mode & consume_header)
2070     {
2071         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2072                                                           frm_nxt[2] == 0xBF)
2073             frm_nxt += 3;
2074     }
2075     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2076     {
2077         uint8_t c1 = *frm_nxt;
2078         if (c1 > Maxcode)
2079             return codecvt_base::error;
2080         if (c1 < 0x80)
2081         {
2082             *to_nxt = static_cast<uint32_t>(c1);
2083             ++frm_nxt;
2084         }
2085         else if (c1 < 0xC2)
2086         {
2087             return codecvt_base::error;
2088         }
2089         else if (c1 < 0xE0)
2090         {
2091             if (frm_end-frm_nxt < 2)
2092                 return codecvt_base::partial;
2093             uint8_t c2 = frm_nxt[1];
2094             if ((c2 & 0xC0) != 0x80)
2095                 return codecvt_base::error;
2096             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2097             if (t > Maxcode)
2098                 return codecvt_base::error;
2099             *to_nxt = static_cast<uint32_t>(t);
2100             frm_nxt += 2;
2101         }
2102         else if (c1 < 0xF0)
2103         {
2104             if (frm_end-frm_nxt < 3)
2105                 return codecvt_base::partial;
2106             uint8_t c2 = frm_nxt[1];
2107             uint8_t c3 = frm_nxt[2];
2108             switch (c1)
2109             {
2110             case 0xE0:
2111                 if ((c2 & 0xE0) != 0xA0)
2112                     return codecvt_base::error;
2113                  break;
2114             case 0xED:
2115                 if ((c2 & 0xE0) != 0x80)
2116                     return codecvt_base::error;
2117                  break;
2118             default:
2119                 if ((c2 & 0xC0) != 0x80)
2120                     return codecvt_base::error;
2121                  break;
2122             }
2123             if ((c3 & 0xC0) != 0x80)
2124                 return codecvt_base::error;
2125             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2126                                              | ((c2 & 0x3F) << 6)
2127                                              |  (c3 & 0x3F));
2128             if (t > Maxcode)
2129                 return codecvt_base::error;
2130             *to_nxt = static_cast<uint32_t>(t);
2131             frm_nxt += 3;
2132         }
2133         else if (c1 < 0xF5)
2134         {
2135             if (frm_end-frm_nxt < 4)
2136                 return codecvt_base::partial;
2137             uint8_t c2 = frm_nxt[1];
2138             uint8_t c3 = frm_nxt[2];
2139             uint8_t c4 = frm_nxt[3];
2140             switch (c1)
2141             {
2142             case 0xF0:
2143                 if (!(0x90 <= c2 && c2 <= 0xBF))
2144                     return codecvt_base::error;
2145                  break;
2146             case 0xF4:
2147                 if ((c2 & 0xF0) != 0x80)
2148                     return codecvt_base::error;
2149                  break;
2150             default:
2151                 if ((c2 & 0xC0) != 0x80)
2152                     return codecvt_base::error;
2153                  break;
2154             }
2155             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2156                 return codecvt_base::error;
2157             if (to_end-to_nxt < 2)
2158                 return codecvt_base::partial;
2159             if ((((c1 & 7UL) << 18) +
2160                 ((c2 & 0x3FUL) << 12) +
2161                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2162                 return codecvt_base::error;
2163             *to_nxt = static_cast<uint32_t>(
2164                     0xD800
2165                   | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2166                   | ((c2 & 0x0F) << 2)
2167                   | ((c3 & 0x30) >> 4));
2168             *++to_nxt = static_cast<uint32_t>(
2169                     0xDC00
2170                   | ((c3 & 0x0F) << 6)
2171                   |  (c4 & 0x3F));
2172             frm_nxt += 4;
2173         }
2174         else
2175         {
2176             return codecvt_base::error;
2177         }
2178     }
2179     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2180 }
2181 
2182 static
2183 int
2184 utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2185                      size_t mx, unsigned long Maxcode = 0x10FFFF,
2186                      codecvt_mode mode = codecvt_mode(0))
2187 {
2188     const uint8_t* frm_nxt = frm;
2189     if (mode & consume_header)
2190     {
2191         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2192                                                           frm_nxt[2] == 0xBF)
2193             frm_nxt += 3;
2194     }
2195     for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2196     {
2197         uint8_t c1 = *frm_nxt;
2198         if (c1 > Maxcode)
2199             break;
2200         if (c1 < 0x80)
2201         {
2202             ++frm_nxt;
2203         }
2204         else if (c1 < 0xC2)
2205         {
2206             break;
2207         }
2208         else if (c1 < 0xE0)
2209         {
2210             if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2211                 break;
2212             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2213             if (t > Maxcode)
2214                 break;
2215             frm_nxt += 2;
2216         }
2217         else if (c1 < 0xF0)
2218         {
2219             if (frm_end-frm_nxt < 3)
2220                 break;
2221             uint8_t c2 = frm_nxt[1];
2222             uint8_t c3 = frm_nxt[2];
2223             switch (c1)
2224             {
2225             case 0xE0:
2226                 if ((c2 & 0xE0) != 0xA0)
2227                     return static_cast<int>(frm_nxt - frm);
2228                 break;
2229             case 0xED:
2230                 if ((c2 & 0xE0) != 0x80)
2231                     return static_cast<int>(frm_nxt - frm);
2232                  break;
2233             default:
2234                 if ((c2 & 0xC0) != 0x80)
2235                     return static_cast<int>(frm_nxt - frm);
2236                  break;
2237             }
2238             if ((c3 & 0xC0) != 0x80)
2239                 break;
2240             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2241                 break;
2242             frm_nxt += 3;
2243         }
2244         else if (c1 < 0xF5)
2245         {
2246             if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2247                 break;
2248             uint8_t c2 = frm_nxt[1];
2249             uint8_t c3 = frm_nxt[2];
2250             uint8_t c4 = frm_nxt[3];
2251             switch (c1)
2252             {
2253             case 0xF0:
2254                 if (!(0x90 <= c2 && c2 <= 0xBF))
2255                     return static_cast<int>(frm_nxt - frm);
2256                  break;
2257             case 0xF4:
2258                 if ((c2 & 0xF0) != 0x80)
2259                     return static_cast<int>(frm_nxt - frm);
2260                  break;
2261             default:
2262                 if ((c2 & 0xC0) != 0x80)
2263                     return static_cast<int>(frm_nxt - frm);
2264                  break;
2265             }
2266             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2267                 break;
2268             if ((((c1 & 7UL) << 18) +
2269                 ((c2 & 0x3FUL) << 12) +
2270                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2271                 break;
2272             ++nchar16_t;
2273             frm_nxt += 4;
2274         }
2275         else
2276         {
2277             break;
2278         }
2279     }
2280     return static_cast<int>(frm_nxt - frm);
2281 }
2282 
2283 static
2284 codecvt_base::result
2285 ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2286              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2287              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2288 {
2289     frm_nxt = frm;
2290     to_nxt = to;
2291     if (mode & generate_header)
2292     {
2293         if (to_end-to_nxt < 3)
2294             return codecvt_base::partial;
2295         *to_nxt++ = static_cast<uint8_t>(0xEF);
2296         *to_nxt++ = static_cast<uint8_t>(0xBB);
2297         *to_nxt++ = static_cast<uint8_t>(0xBF);
2298     }
2299     for (; frm_nxt < frm_end; ++frm_nxt)
2300     {
2301         uint32_t wc = *frm_nxt;
2302         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2303             return codecvt_base::error;
2304         if (wc < 0x000080)
2305         {
2306             if (to_end-to_nxt < 1)
2307                 return codecvt_base::partial;
2308             *to_nxt++ = static_cast<uint8_t>(wc);
2309         }
2310         else if (wc < 0x000800)
2311         {
2312             if (to_end-to_nxt < 2)
2313                 return codecvt_base::partial;
2314             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2315             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2316         }
2317         else if (wc < 0x010000)
2318         {
2319             if (to_end-to_nxt < 3)
2320                 return codecvt_base::partial;
2321             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
2322             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2323             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
2324         }
2325         else // if (wc < 0x110000)
2326         {
2327             if (to_end-to_nxt < 4)
2328                 return codecvt_base::partial;
2329             *to_nxt++ = static_cast<uint8_t>(0xF0 |  (wc >> 18));
2330             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2331             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2332             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x00003F));
2333         }
2334     }
2335     return codecvt_base::ok;
2336 }
2337 
2338 static
2339 codecvt_base::result
2340 utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2341              uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2342              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2343 {
2344     frm_nxt = frm;
2345     to_nxt = to;
2346     if (mode & consume_header)
2347     {
2348         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2349                                                           frm_nxt[2] == 0xBF)
2350             frm_nxt += 3;
2351     }
2352     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2353     {
2354         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2355         if (c1 < 0x80)
2356         {
2357             if (c1 > Maxcode)
2358                 return codecvt_base::error;
2359             *to_nxt = static_cast<uint32_t>(c1);
2360             ++frm_nxt;
2361         }
2362         else if (c1 < 0xC2)
2363         {
2364             return codecvt_base::error;
2365         }
2366         else if (c1 < 0xE0)
2367         {
2368             if (frm_end-frm_nxt < 2)
2369                 return codecvt_base::partial;
2370             uint8_t c2 = frm_nxt[1];
2371             if ((c2 & 0xC0) != 0x80)
2372                 return codecvt_base::error;
2373             uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2374                                               | (c2 & 0x3F));
2375             if (t > Maxcode)
2376                 return codecvt_base::error;
2377             *to_nxt = t;
2378             frm_nxt += 2;
2379         }
2380         else if (c1 < 0xF0)
2381         {
2382             if (frm_end-frm_nxt < 3)
2383                 return codecvt_base::partial;
2384             uint8_t c2 = frm_nxt[1];
2385             uint8_t c3 = frm_nxt[2];
2386             switch (c1)
2387             {
2388             case 0xE0:
2389                 if ((c2 & 0xE0) != 0xA0)
2390                     return codecvt_base::error;
2391                  break;
2392             case 0xED:
2393                 if ((c2 & 0xE0) != 0x80)
2394                     return codecvt_base::error;
2395                  break;
2396             default:
2397                 if ((c2 & 0xC0) != 0x80)
2398                     return codecvt_base::error;
2399                  break;
2400             }
2401             if ((c3 & 0xC0) != 0x80)
2402                 return codecvt_base::error;
2403             uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2404                                              | ((c2 & 0x3F) << 6)
2405                                              |  (c3 & 0x3F));
2406             if (t > Maxcode)
2407                 return codecvt_base::error;
2408             *to_nxt = t;
2409             frm_nxt += 3;
2410         }
2411         else if (c1 < 0xF5)
2412         {
2413             if (frm_end-frm_nxt < 4)
2414                 return codecvt_base::partial;
2415             uint8_t c2 = frm_nxt[1];
2416             uint8_t c3 = frm_nxt[2];
2417             uint8_t c4 = frm_nxt[3];
2418             switch (c1)
2419             {
2420             case 0xF0:
2421                 if (!(0x90 <= c2 && c2 <= 0xBF))
2422                     return codecvt_base::error;
2423                  break;
2424             case 0xF4:
2425                 if ((c2 & 0xF0) != 0x80)
2426                     return codecvt_base::error;
2427                  break;
2428             default:
2429                 if ((c2 & 0xC0) != 0x80)
2430                     return codecvt_base::error;
2431                  break;
2432             }
2433             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2434                 return codecvt_base::error;
2435             uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2436                                              | ((c2 & 0x3F) << 12)
2437                                              | ((c3 & 0x3F) << 6)
2438                                              |  (c4 & 0x3F));
2439             if (t > Maxcode)
2440                 return codecvt_base::error;
2441             *to_nxt = t;
2442             frm_nxt += 4;
2443         }
2444         else
2445         {
2446             return codecvt_base::error;
2447         }
2448     }
2449     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2450 }
2451 
2452 static
2453 int
2454 utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2455                     size_t mx, unsigned long Maxcode = 0x10FFFF,
2456                     codecvt_mode mode = codecvt_mode(0))
2457 {
2458     const uint8_t* frm_nxt = frm;
2459     if (mode & consume_header)
2460     {
2461         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2462                                                           frm_nxt[2] == 0xBF)
2463             frm_nxt += 3;
2464     }
2465     for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2466     {
2467         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2468         if (c1 < 0x80)
2469         {
2470             if (c1 > Maxcode)
2471                 break;
2472             ++frm_nxt;
2473         }
2474         else if (c1 < 0xC2)
2475         {
2476             break;
2477         }
2478         else if (c1 < 0xE0)
2479         {
2480             if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2481                 break;
2482             if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2483                 break;
2484             frm_nxt += 2;
2485         }
2486         else if (c1 < 0xF0)
2487         {
2488             if (frm_end-frm_nxt < 3)
2489                 break;
2490             uint8_t c2 = frm_nxt[1];
2491             uint8_t c3 = frm_nxt[2];
2492             switch (c1)
2493             {
2494             case 0xE0:
2495                 if ((c2 & 0xE0) != 0xA0)
2496                     return static_cast<int>(frm_nxt - frm);
2497                 break;
2498             case 0xED:
2499                 if ((c2 & 0xE0) != 0x80)
2500                     return static_cast<int>(frm_nxt - frm);
2501                  break;
2502             default:
2503                 if ((c2 & 0xC0) != 0x80)
2504                     return static_cast<int>(frm_nxt - frm);
2505                  break;
2506             }
2507             if ((c3 & 0xC0) != 0x80)
2508                 break;
2509             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2510                 break;
2511             frm_nxt += 3;
2512         }
2513         else if (c1 < 0xF5)
2514         {
2515             if (frm_end-frm_nxt < 4)
2516                 break;
2517             uint8_t c2 = frm_nxt[1];
2518             uint8_t c3 = frm_nxt[2];
2519             uint8_t c4 = frm_nxt[3];
2520             switch (c1)
2521             {
2522             case 0xF0:
2523                 if (!(0x90 <= c2 && c2 <= 0xBF))
2524                     return static_cast<int>(frm_nxt - frm);
2525                  break;
2526             case 0xF4:
2527                 if ((c2 & 0xF0) != 0x80)
2528                     return static_cast<int>(frm_nxt - frm);
2529                  break;
2530             default:
2531                 if ((c2 & 0xC0) != 0x80)
2532                     return static_cast<int>(frm_nxt - frm);
2533                  break;
2534             }
2535             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2536                 break;
2537             if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2538                  ((c3 & 0x3Fu) << 6)  |  (c4 & 0x3Fu)) > Maxcode)
2539                 break;
2540             frm_nxt += 4;
2541         }
2542         else
2543         {
2544             break;
2545         }
2546     }
2547     return static_cast<int>(frm_nxt - frm);
2548 }
2549 
2550 static
2551 codecvt_base::result
2552 ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2553              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2554              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2555 {
2556     frm_nxt = frm;
2557     to_nxt = to;
2558     if (mode & generate_header)
2559     {
2560         if (to_end-to_nxt < 3)
2561             return codecvt_base::partial;
2562         *to_nxt++ = static_cast<uint8_t>(0xEF);
2563         *to_nxt++ = static_cast<uint8_t>(0xBB);
2564         *to_nxt++ = static_cast<uint8_t>(0xBF);
2565     }
2566     for (; frm_nxt < frm_end; ++frm_nxt)
2567     {
2568         uint16_t wc = *frm_nxt;
2569         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2570             return codecvt_base::error;
2571         if (wc < 0x0080)
2572         {
2573             if (to_end-to_nxt < 1)
2574                 return codecvt_base::partial;
2575             *to_nxt++ = static_cast<uint8_t>(wc);
2576         }
2577         else if (wc < 0x0800)
2578         {
2579             if (to_end-to_nxt < 2)
2580                 return codecvt_base::partial;
2581             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2582             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2583         }
2584         else // if (wc <= 0xFFFF)
2585         {
2586             if (to_end-to_nxt < 3)
2587                 return codecvt_base::partial;
2588             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
2589             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2590             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
2591         }
2592     }
2593     return codecvt_base::ok;
2594 }
2595 
2596 static
2597 codecvt_base::result
2598 utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2599              uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2600              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2601 {
2602     frm_nxt = frm;
2603     to_nxt = to;
2604     if (mode & consume_header)
2605     {
2606         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2607                                                           frm_nxt[2] == 0xBF)
2608             frm_nxt += 3;
2609     }
2610     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2611     {
2612         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2613         if (c1 < 0x80)
2614         {
2615             if (c1 > Maxcode)
2616                 return codecvt_base::error;
2617             *to_nxt = static_cast<uint16_t>(c1);
2618             ++frm_nxt;
2619         }
2620         else if (c1 < 0xC2)
2621         {
2622             return codecvt_base::error;
2623         }
2624         else if (c1 < 0xE0)
2625         {
2626             if (frm_end-frm_nxt < 2)
2627                 return codecvt_base::partial;
2628             uint8_t c2 = frm_nxt[1];
2629             if ((c2 & 0xC0) != 0x80)
2630                 return codecvt_base::error;
2631             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2632                                               | (c2 & 0x3F));
2633             if (t > Maxcode)
2634                 return codecvt_base::error;
2635             *to_nxt = t;
2636             frm_nxt += 2;
2637         }
2638         else if (c1 < 0xF0)
2639         {
2640             if (frm_end-frm_nxt < 3)
2641                 return codecvt_base::partial;
2642             uint8_t c2 = frm_nxt[1];
2643             uint8_t c3 = frm_nxt[2];
2644             switch (c1)
2645             {
2646             case 0xE0:
2647                 if ((c2 & 0xE0) != 0xA0)
2648                     return codecvt_base::error;
2649                  break;
2650             case 0xED:
2651                 if ((c2 & 0xE0) != 0x80)
2652                     return codecvt_base::error;
2653                  break;
2654             default:
2655                 if ((c2 & 0xC0) != 0x80)
2656                     return codecvt_base::error;
2657                  break;
2658             }
2659             if ((c3 & 0xC0) != 0x80)
2660                 return codecvt_base::error;
2661             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2662                                              | ((c2 & 0x3F) << 6)
2663                                              |  (c3 & 0x3F));
2664             if (t > Maxcode)
2665                 return codecvt_base::error;
2666             *to_nxt = t;
2667             frm_nxt += 3;
2668         }
2669         else
2670         {
2671             return codecvt_base::error;
2672         }
2673     }
2674     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2675 }
2676 
2677 static
2678 int
2679 utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2680                     size_t mx, unsigned long Maxcode = 0x10FFFF,
2681                     codecvt_mode mode = codecvt_mode(0))
2682 {
2683     const uint8_t* frm_nxt = frm;
2684     if (mode & consume_header)
2685     {
2686         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2687                                                           frm_nxt[2] == 0xBF)
2688             frm_nxt += 3;
2689     }
2690     for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2691     {
2692         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2693         if (c1 < 0x80)
2694         {
2695             if (c1 > Maxcode)
2696                 break;
2697             ++frm_nxt;
2698         }
2699         else if (c1 < 0xC2)
2700         {
2701             break;
2702         }
2703         else if (c1 < 0xE0)
2704         {
2705             if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2706                 break;
2707             if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2708                 break;
2709             frm_nxt += 2;
2710         }
2711         else if (c1 < 0xF0)
2712         {
2713             if (frm_end-frm_nxt < 3)
2714                 break;
2715             uint8_t c2 = frm_nxt[1];
2716             uint8_t c3 = frm_nxt[2];
2717             switch (c1)
2718             {
2719             case 0xE0:
2720                 if ((c2 & 0xE0) != 0xA0)
2721                     return static_cast<int>(frm_nxt - frm);
2722                 break;
2723             case 0xED:
2724                 if ((c2 & 0xE0) != 0x80)
2725                     return static_cast<int>(frm_nxt - frm);
2726                  break;
2727             default:
2728                 if ((c2 & 0xC0) != 0x80)
2729                     return static_cast<int>(frm_nxt - frm);
2730                  break;
2731             }
2732             if ((c3 & 0xC0) != 0x80)
2733                 break;
2734             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2735                 break;
2736             frm_nxt += 3;
2737         }
2738         else
2739         {
2740             break;
2741         }
2742     }
2743     return static_cast<int>(frm_nxt - frm);
2744 }
2745 
2746 static
2747 codecvt_base::result
2748 ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2749                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2750                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2751 {
2752     frm_nxt = frm;
2753     to_nxt = to;
2754     if (mode & generate_header)
2755     {
2756         if (to_end-to_nxt < 2)
2757             return codecvt_base::partial;
2758         *to_nxt++ = static_cast<uint8_t>(0xFE);
2759         *to_nxt++ = static_cast<uint8_t>(0xFF);
2760     }
2761     for (; frm_nxt < frm_end; ++frm_nxt)
2762     {
2763         uint32_t wc = *frm_nxt;
2764         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2765             return codecvt_base::error;
2766         if (wc < 0x010000)
2767         {
2768             if (to_end-to_nxt < 2)
2769                 return codecvt_base::partial;
2770             *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2771             *to_nxt++ = static_cast<uint8_t>(wc);
2772         }
2773         else
2774         {
2775             if (to_end-to_nxt < 4)
2776                 return codecvt_base::partial;
2777             uint16_t t = static_cast<uint16_t>(
2778                     0xD800
2779                   | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2780                   |   ((wc & 0x00FC00) >> 10));
2781             *to_nxt++ = static_cast<uint8_t>(t >> 8);
2782             *to_nxt++ = static_cast<uint8_t>(t);
2783             t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2784             *to_nxt++ = static_cast<uint8_t>(t >> 8);
2785             *to_nxt++ = static_cast<uint8_t>(t);
2786         }
2787     }
2788     return codecvt_base::ok;
2789 }
2790 
2791 static
2792 codecvt_base::result
2793 utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2794                 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2795                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2796 {
2797     frm_nxt = frm;
2798     to_nxt = to;
2799     if (mode & consume_header)
2800     {
2801         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2802             frm_nxt += 2;
2803     }
2804     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2805     {
2806         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2807         if ((c1 & 0xFC00) == 0xDC00)
2808             return codecvt_base::error;
2809         if ((c1 & 0xFC00) != 0xD800)
2810         {
2811             if (c1 > Maxcode)
2812                 return codecvt_base::error;
2813             *to_nxt = static_cast<uint32_t>(c1);
2814             frm_nxt += 2;
2815         }
2816         else
2817         {
2818             if (frm_end-frm_nxt < 4)
2819                 return codecvt_base::partial;
2820             uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2821             if ((c2 & 0xFC00) != 0xDC00)
2822                 return codecvt_base::error;
2823             uint32_t t = static_cast<uint32_t>(
2824                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
2825                   |   ((c1 & 0x003F) << 10)
2826                   |    (c2 & 0x03FF));
2827             if (t > Maxcode)
2828                 return codecvt_base::error;
2829             *to_nxt = t;
2830             frm_nxt += 4;
2831         }
2832     }
2833     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2834 }
2835 
2836 static
2837 int
2838 utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2839                        size_t mx, unsigned long Maxcode = 0x10FFFF,
2840                        codecvt_mode mode = codecvt_mode(0))
2841 {
2842     const uint8_t* frm_nxt = frm;
2843     if (mode & consume_header)
2844     {
2845         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2846             frm_nxt += 2;
2847     }
2848     for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2849     {
2850         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2851         if ((c1 & 0xFC00) == 0xDC00)
2852             break;
2853         if ((c1 & 0xFC00) != 0xD800)
2854         {
2855             if (c1 > Maxcode)
2856                 break;
2857             frm_nxt += 2;
2858         }
2859         else
2860         {
2861             if (frm_end-frm_nxt < 4)
2862                 break;
2863             uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2864             if ((c2 & 0xFC00) != 0xDC00)
2865                 break;
2866             uint32_t t = static_cast<uint32_t>(
2867                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
2868                   |   ((c1 & 0x003F) << 10)
2869                   |    (c2 & 0x03FF));
2870             if (t > Maxcode)
2871                 break;
2872             frm_nxt += 4;
2873         }
2874     }
2875     return static_cast<int>(frm_nxt - frm);
2876 }
2877 
2878 static
2879 codecvt_base::result
2880 ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2881                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2882                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2883 {
2884     frm_nxt = frm;
2885     to_nxt = to;
2886     if (mode & generate_header)
2887     {
2888         if (to_end-to_nxt < 2)
2889             return codecvt_base::partial;
2890             *to_nxt++ = static_cast<uint8_t>(0xFF);
2891             *to_nxt++ = static_cast<uint8_t>(0xFE);
2892     }
2893     for (; frm_nxt < frm_end; ++frm_nxt)
2894     {
2895         uint32_t wc = *frm_nxt;
2896         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2897             return codecvt_base::error;
2898         if (wc < 0x010000)
2899         {
2900             if (to_end-to_nxt < 2)
2901                 return codecvt_base::partial;
2902             *to_nxt++ = static_cast<uint8_t>(wc);
2903             *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2904         }
2905         else
2906         {
2907             if (to_end-to_nxt < 4)
2908                 return codecvt_base::partial;
2909             uint16_t t = static_cast<uint16_t>(
2910                     0xD800
2911                   | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2912                   |   ((wc & 0x00FC00) >> 10));
2913             *to_nxt++ = static_cast<uint8_t>(t);
2914             *to_nxt++ = static_cast<uint8_t>(t >> 8);
2915             t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2916             *to_nxt++ = static_cast<uint8_t>(t);
2917             *to_nxt++ = static_cast<uint8_t>(t >> 8);
2918         }
2919     }
2920     return codecvt_base::ok;
2921 }
2922 
2923 static
2924 codecvt_base::result
2925 utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2926                 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2927                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2928 {
2929     frm_nxt = frm;
2930     to_nxt = to;
2931     if (mode & consume_header)
2932     {
2933         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2934             frm_nxt += 2;
2935     }
2936     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2937     {
2938         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2939         if ((c1 & 0xFC00) == 0xDC00)
2940             return codecvt_base::error;
2941         if ((c1 & 0xFC00) != 0xD800)
2942         {
2943             if (c1 > Maxcode)
2944                 return codecvt_base::error;
2945             *to_nxt = static_cast<uint32_t>(c1);
2946             frm_nxt += 2;
2947         }
2948         else
2949         {
2950             if (frm_end-frm_nxt < 4)
2951                 return codecvt_base::partial;
2952             uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2953             if ((c2 & 0xFC00) != 0xDC00)
2954                 return codecvt_base::error;
2955             uint32_t t = static_cast<uint32_t>(
2956                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
2957                   |   ((c1 & 0x003F) << 10)
2958                   |    (c2 & 0x03FF));
2959             if (t > Maxcode)
2960                 return codecvt_base::error;
2961             *to_nxt = t;
2962             frm_nxt += 4;
2963         }
2964     }
2965     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2966 }
2967 
2968 static
2969 int
2970 utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2971                        size_t mx, unsigned long Maxcode = 0x10FFFF,
2972                        codecvt_mode mode = codecvt_mode(0))
2973 {
2974     const uint8_t* frm_nxt = frm;
2975     if (mode & consume_header)
2976     {
2977         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2978             frm_nxt += 2;
2979     }
2980     for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2981     {
2982         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2983         if ((c1 & 0xFC00) == 0xDC00)
2984             break;
2985         if ((c1 & 0xFC00) != 0xD800)
2986         {
2987             if (c1 > Maxcode)
2988                 break;
2989             frm_nxt += 2;
2990         }
2991         else
2992         {
2993             if (frm_end-frm_nxt < 4)
2994                 break;
2995             uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2996             if ((c2 & 0xFC00) != 0xDC00)
2997                 break;
2998             uint32_t t = static_cast<uint32_t>(
2999                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
3000                   |   ((c1 & 0x003F) << 10)
3001                   |    (c2 & 0x03FF));
3002             if (t > Maxcode)
3003                 break;
3004             frm_nxt += 4;
3005         }
3006     }
3007     return static_cast<int>(frm_nxt - frm);
3008 }
3009 
3010 static
3011 codecvt_base::result
3012 ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3013                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3014                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3015 {
3016     frm_nxt = frm;
3017     to_nxt = to;
3018     if (mode & generate_header)
3019     {
3020         if (to_end-to_nxt < 2)
3021             return codecvt_base::partial;
3022         *to_nxt++ = static_cast<uint8_t>(0xFE);
3023         *to_nxt++ = static_cast<uint8_t>(0xFF);
3024     }
3025     for (; frm_nxt < frm_end; ++frm_nxt)
3026     {
3027         uint16_t wc = *frm_nxt;
3028         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3029             return codecvt_base::error;
3030         if (to_end-to_nxt < 2)
3031             return codecvt_base::partial;
3032         *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3033         *to_nxt++ = static_cast<uint8_t>(wc);
3034     }
3035     return codecvt_base::ok;
3036 }
3037 
3038 static
3039 codecvt_base::result
3040 utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3041                 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3042                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3043 {
3044     frm_nxt = frm;
3045     to_nxt = to;
3046     if (mode & consume_header)
3047     {
3048         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3049             frm_nxt += 2;
3050     }
3051     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3052     {
3053         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3054         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3055             return codecvt_base::error;
3056         *to_nxt = c1;
3057         frm_nxt += 2;
3058     }
3059     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3060 }
3061 
3062 static
3063 int
3064 utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3065                        size_t mx, unsigned long Maxcode = 0x10FFFF,
3066                        codecvt_mode mode = codecvt_mode(0))
3067 {
3068     const uint8_t* frm_nxt = frm;
3069     if (mode & consume_header)
3070     {
3071         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3072             frm_nxt += 2;
3073     }
3074     for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3075     {
3076         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3077         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3078             break;
3079         frm_nxt += 2;
3080     }
3081     return static_cast<int>(frm_nxt - frm);
3082 }
3083 
3084 static
3085 codecvt_base::result
3086 ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3087                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3088                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3089 {
3090     frm_nxt = frm;
3091     to_nxt = to;
3092     if (mode & generate_header)
3093     {
3094         if (to_end-to_nxt < 2)
3095             return codecvt_base::partial;
3096         *to_nxt++ = static_cast<uint8_t>(0xFF);
3097         *to_nxt++ = static_cast<uint8_t>(0xFE);
3098     }
3099     for (; frm_nxt < frm_end; ++frm_nxt)
3100     {
3101         uint16_t wc = *frm_nxt;
3102         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3103             return codecvt_base::error;
3104         if (to_end-to_nxt < 2)
3105             return codecvt_base::partial;
3106         *to_nxt++ = static_cast<uint8_t>(wc);
3107         *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3108     }
3109     return codecvt_base::ok;
3110 }
3111 
3112 static
3113 codecvt_base::result
3114 utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3115                 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3116                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3117 {
3118     frm_nxt = frm;
3119     to_nxt = to;
3120     if (mode & consume_header)
3121     {
3122         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3123             frm_nxt += 2;
3124     }
3125     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3126     {
3127         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3128         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3129             return codecvt_base::error;
3130         *to_nxt = c1;
3131         frm_nxt += 2;
3132     }
3133     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3134 }
3135 
3136 static
3137 int
3138 utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3139                        size_t mx, unsigned long Maxcode = 0x10FFFF,
3140                        codecvt_mode mode = codecvt_mode(0))
3141 {
3142     const uint8_t* frm_nxt = frm;
3143     frm_nxt = frm;
3144     if (mode & consume_header)
3145     {
3146         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3147             frm_nxt += 2;
3148     }
3149     for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3150     {
3151         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3152         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3153             break;
3154         frm_nxt += 2;
3155     }
3156     return static_cast<int>(frm_nxt - frm);
3157 }
3158 
3159 // template <> class codecvt<char16_t, char, mbstate_t>
3160 
3161 locale::id codecvt<char16_t, char, mbstate_t>::id;
3162 
3163 codecvt<char16_t, char, mbstate_t>::~codecvt()
3164 {
3165 }
3166 
3167 codecvt<char16_t, char, mbstate_t>::result
3168 codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
3169     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3170     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3171 {
3172     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3173     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3174     const uint16_t* _frm_nxt = _frm;
3175     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3176     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3177     uint8_t* _to_nxt = _to;
3178     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3179     frm_nxt = frm + (_frm_nxt - _frm);
3180     to_nxt = to + (_to_nxt - _to);
3181     return r;
3182 }
3183 
3184 codecvt<char16_t, char, mbstate_t>::result
3185 codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
3186     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3187     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3188 {
3189     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3190     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3191     const uint8_t* _frm_nxt = _frm;
3192     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3193     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3194     uint16_t* _to_nxt = _to;
3195     result r = utf8_to_utf16(_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<char16_t, char, mbstate_t>::result
3202 codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3203     extern_type* to, extern_type*, extern_type*& to_nxt) const
3204 {
3205     to_nxt = to;
3206     return noconv;
3207 }
3208 
3209 int
3210 codecvt<char16_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
3211 {
3212     return 0;
3213 }
3214 
3215 bool
3216 codecvt<char16_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3217 {
3218     return false;
3219 }
3220 
3221 int
3222 codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3223     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3224 {
3225     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3226     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3227     return utf8_to_utf16_length(_frm, _frm_end, mx);
3228 }
3229 
3230 int
3231 codecvt<char16_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
3232 {
3233     return 4;
3234 }
3235 
3236 // template <> class codecvt<char32_t, char, mbstate_t>
3237 
3238 locale::id codecvt<char32_t, char, mbstate_t>::id;
3239 
3240 codecvt<char32_t, char, mbstate_t>::~codecvt()
3241 {
3242 }
3243 
3244 codecvt<char32_t, char, mbstate_t>::result
3245 codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
3246     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3247     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3248 {
3249     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3250     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3251     const uint32_t* _frm_nxt = _frm;
3252     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3253     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3254     uint8_t* _to_nxt = _to;
3255     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3256     frm_nxt = frm + (_frm_nxt - _frm);
3257     to_nxt = to + (_to_nxt - _to);
3258     return r;
3259 }
3260 
3261 codecvt<char32_t, char, mbstate_t>::result
3262 codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
3263     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3264     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3265 {
3266     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3267     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3268     const uint8_t* _frm_nxt = _frm;
3269     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3270     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3271     uint32_t* _to_nxt = _to;
3272     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3273     frm_nxt = frm + (_frm_nxt - _frm);
3274     to_nxt = to + (_to_nxt - _to);
3275     return r;
3276 }
3277 
3278 codecvt<char32_t, char, mbstate_t>::result
3279 codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3280     extern_type* to, extern_type*, extern_type*& to_nxt) const
3281 {
3282     to_nxt = to;
3283     return noconv;
3284 }
3285 
3286 int
3287 codecvt<char32_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
3288 {
3289     return 0;
3290 }
3291 
3292 bool
3293 codecvt<char32_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3294 {
3295     return false;
3296 }
3297 
3298 int
3299 codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3300     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3301 {
3302     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3303     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3304     return utf8_to_ucs4_length(_frm, _frm_end, mx);
3305 }
3306 
3307 int
3308 codecvt<char32_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
3309 {
3310     return 4;
3311 }
3312 
3313 // __codecvt_utf8<wchar_t>
3314 
3315 __codecvt_utf8<wchar_t>::result
3316 __codecvt_utf8<wchar_t>::do_out(state_type&,
3317     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3318     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3319 {
3320 #if _WIN32
3321     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3322     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3323     const uint16_t* _frm_nxt = _frm;
3324 #else
3325     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3326     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3327     const uint32_t* _frm_nxt = _frm;
3328 #endif
3329     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3330     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3331     uint8_t* _to_nxt = _to;
3332 #if _WIN32
3333     result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3334                             _Maxcode_, _Mode_);
3335 #else
3336     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3337                             _Maxcode_, _Mode_);
3338 #endif
3339     frm_nxt = frm + (_frm_nxt - _frm);
3340     to_nxt = to + (_to_nxt - _to);
3341     return r;
3342 }
3343 
3344 __codecvt_utf8<wchar_t>::result
3345 __codecvt_utf8<wchar_t>::do_in(state_type&,
3346     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3347     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3348 {
3349     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3350     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3351     const uint8_t* _frm_nxt = _frm;
3352 #if _WIN32
3353     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3354     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3355     uint16_t* _to_nxt = _to;
3356     result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3357                             _Maxcode_, _Mode_);
3358 #else
3359     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3360     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3361     uint32_t* _to_nxt = _to;
3362     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3363                             _Maxcode_, _Mode_);
3364 #endif
3365     frm_nxt = frm + (_frm_nxt - _frm);
3366     to_nxt = to + (_to_nxt - _to);
3367     return r;
3368 }
3369 
3370 __codecvt_utf8<wchar_t>::result
3371 __codecvt_utf8<wchar_t>::do_unshift(state_type&,
3372     extern_type* to, extern_type*, extern_type*& to_nxt) const
3373 {
3374     to_nxt = to;
3375     return noconv;
3376 }
3377 
3378 int
3379 __codecvt_utf8<wchar_t>::do_encoding() const  _NOEXCEPT
3380 {
3381     return 0;
3382 }
3383 
3384 bool
3385 __codecvt_utf8<wchar_t>::do_always_noconv() const  _NOEXCEPT
3386 {
3387     return false;
3388 }
3389 
3390 int
3391 __codecvt_utf8<wchar_t>::do_length(state_type&,
3392     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3393 {
3394     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3395     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3396     return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3397 }
3398 
3399 int
3400 __codecvt_utf8<wchar_t>::do_max_length() const  _NOEXCEPT
3401 {
3402     if (_Mode_ & consume_header)
3403         return 7;
3404     return 4;
3405 }
3406 
3407 // __codecvt_utf8<char16_t>
3408 
3409 __codecvt_utf8<char16_t>::result
3410 __codecvt_utf8<char16_t>::do_out(state_type&,
3411     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3412     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3413 {
3414     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3415     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3416     const uint16_t* _frm_nxt = _frm;
3417     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3418     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3419     uint8_t* _to_nxt = _to;
3420     result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3421                             _Maxcode_, _Mode_);
3422     frm_nxt = frm + (_frm_nxt - _frm);
3423     to_nxt = to + (_to_nxt - _to);
3424     return r;
3425 }
3426 
3427 __codecvt_utf8<char16_t>::result
3428 __codecvt_utf8<char16_t>::do_in(state_type&,
3429     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3430     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3431 {
3432     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3433     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3434     const uint8_t* _frm_nxt = _frm;
3435     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3436     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3437     uint16_t* _to_nxt = _to;
3438     result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3439                             _Maxcode_, _Mode_);
3440     frm_nxt = frm + (_frm_nxt - _frm);
3441     to_nxt = to + (_to_nxt - _to);
3442     return r;
3443 }
3444 
3445 __codecvt_utf8<char16_t>::result
3446 __codecvt_utf8<char16_t>::do_unshift(state_type&,
3447     extern_type* to, extern_type*, extern_type*& to_nxt) const
3448 {
3449     to_nxt = to;
3450     return noconv;
3451 }
3452 
3453 int
3454 __codecvt_utf8<char16_t>::do_encoding() const  _NOEXCEPT
3455 {
3456     return 0;
3457 }
3458 
3459 bool
3460 __codecvt_utf8<char16_t>::do_always_noconv() const  _NOEXCEPT
3461 {
3462     return false;
3463 }
3464 
3465 int
3466 __codecvt_utf8<char16_t>::do_length(state_type&,
3467     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3468 {
3469     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3470     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3471     return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3472 }
3473 
3474 int
3475 __codecvt_utf8<char16_t>::do_max_length() const  _NOEXCEPT
3476 {
3477     if (_Mode_ & consume_header)
3478         return 6;
3479     return 3;
3480 }
3481 
3482 // __codecvt_utf8<char32_t>
3483 
3484 __codecvt_utf8<char32_t>::result
3485 __codecvt_utf8<char32_t>::do_out(state_type&,
3486     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3487     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3488 {
3489     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3490     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3491     const uint32_t* _frm_nxt = _frm;
3492     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3493     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3494     uint8_t* _to_nxt = _to;
3495     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3496                             _Maxcode_, _Mode_);
3497     frm_nxt = frm + (_frm_nxt - _frm);
3498     to_nxt = to + (_to_nxt - _to);
3499     return r;
3500 }
3501 
3502 __codecvt_utf8<char32_t>::result
3503 __codecvt_utf8<char32_t>::do_in(state_type&,
3504     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3505     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3506 {
3507     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3508     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3509     const uint8_t* _frm_nxt = _frm;
3510     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3511     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3512     uint32_t* _to_nxt = _to;
3513     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3514                             _Maxcode_, _Mode_);
3515     frm_nxt = frm + (_frm_nxt - _frm);
3516     to_nxt = to + (_to_nxt - _to);
3517     return r;
3518 }
3519 
3520 __codecvt_utf8<char32_t>::result
3521 __codecvt_utf8<char32_t>::do_unshift(state_type&,
3522     extern_type* to, extern_type*, extern_type*& to_nxt) const
3523 {
3524     to_nxt = to;
3525     return noconv;
3526 }
3527 
3528 int
3529 __codecvt_utf8<char32_t>::do_encoding() const  _NOEXCEPT
3530 {
3531     return 0;
3532 }
3533 
3534 bool
3535 __codecvt_utf8<char32_t>::do_always_noconv() const  _NOEXCEPT
3536 {
3537     return false;
3538 }
3539 
3540 int
3541 __codecvt_utf8<char32_t>::do_length(state_type&,
3542     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3543 {
3544     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3545     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3546     return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3547 }
3548 
3549 int
3550 __codecvt_utf8<char32_t>::do_max_length() const  _NOEXCEPT
3551 {
3552     if (_Mode_ & consume_header)
3553         return 7;
3554     return 4;
3555 }
3556 
3557 // __codecvt_utf16<wchar_t, false>
3558 
3559 __codecvt_utf16<wchar_t, false>::result
3560 __codecvt_utf16<wchar_t, false>::do_out(state_type&,
3561     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3562     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3563 {
3564     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3565     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3566     const uint32_t* _frm_nxt = _frm;
3567     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3568     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3569     uint8_t* _to_nxt = _to;
3570     result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3571                                _Maxcode_, _Mode_);
3572     frm_nxt = frm + (_frm_nxt - _frm);
3573     to_nxt = to + (_to_nxt - _to);
3574     return r;
3575 }
3576 
3577 __codecvt_utf16<wchar_t, false>::result
3578 __codecvt_utf16<wchar_t, false>::do_in(state_type&,
3579     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3580     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3581 {
3582     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3583     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3584     const uint8_t* _frm_nxt = _frm;
3585     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3586     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3587     uint32_t* _to_nxt = _to;
3588     result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3589                                _Maxcode_, _Mode_);
3590     frm_nxt = frm + (_frm_nxt - _frm);
3591     to_nxt = to + (_to_nxt - _to);
3592     return r;
3593 }
3594 
3595 __codecvt_utf16<wchar_t, false>::result
3596 __codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3597     extern_type* to, extern_type*, extern_type*& to_nxt) const
3598 {
3599     to_nxt = to;
3600     return noconv;
3601 }
3602 
3603 int
3604 __codecvt_utf16<wchar_t, false>::do_encoding() const  _NOEXCEPT
3605 {
3606     return 0;
3607 }
3608 
3609 bool
3610 __codecvt_utf16<wchar_t, false>::do_always_noconv() const  _NOEXCEPT
3611 {
3612     return false;
3613 }
3614 
3615 int
3616 __codecvt_utf16<wchar_t, false>::do_length(state_type&,
3617     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3618 {
3619     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3620     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3621     return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3622 }
3623 
3624 int
3625 __codecvt_utf16<wchar_t, false>::do_max_length() const  _NOEXCEPT
3626 {
3627     if (_Mode_ & consume_header)
3628         return 6;
3629     return 4;
3630 }
3631 
3632 // __codecvt_utf16<wchar_t, true>
3633 
3634 __codecvt_utf16<wchar_t, true>::result
3635 __codecvt_utf16<wchar_t, true>::do_out(state_type&,
3636     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3637     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3638 {
3639     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3640     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3641     const uint32_t* _frm_nxt = _frm;
3642     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3643     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3644     uint8_t* _to_nxt = _to;
3645     result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3646                                _Maxcode_, _Mode_);
3647     frm_nxt = frm + (_frm_nxt - _frm);
3648     to_nxt = to + (_to_nxt - _to);
3649     return r;
3650 }
3651 
3652 __codecvt_utf16<wchar_t, true>::result
3653 __codecvt_utf16<wchar_t, true>::do_in(state_type&,
3654     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3655     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3656 {
3657     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3658     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3659     const uint8_t* _frm_nxt = _frm;
3660     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3661     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3662     uint32_t* _to_nxt = _to;
3663     result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3664                                _Maxcode_, _Mode_);
3665     frm_nxt = frm + (_frm_nxt - _frm);
3666     to_nxt = to + (_to_nxt - _to);
3667     return r;
3668 }
3669 
3670 __codecvt_utf16<wchar_t, true>::result
3671 __codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3672     extern_type* to, extern_type*, extern_type*& to_nxt) const
3673 {
3674     to_nxt = to;
3675     return noconv;
3676 }
3677 
3678 int
3679 __codecvt_utf16<wchar_t, true>::do_encoding() const  _NOEXCEPT
3680 {
3681     return 0;
3682 }
3683 
3684 bool
3685 __codecvt_utf16<wchar_t, true>::do_always_noconv() const  _NOEXCEPT
3686 {
3687     return false;
3688 }
3689 
3690 int
3691 __codecvt_utf16<wchar_t, true>::do_length(state_type&,
3692     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3693 {
3694     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3695     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3696     return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3697 }
3698 
3699 int
3700 __codecvt_utf16<wchar_t, true>::do_max_length() const  _NOEXCEPT
3701 {
3702     if (_Mode_ & consume_header)
3703         return 6;
3704     return 4;
3705 }
3706 
3707 // __codecvt_utf16<char16_t, false>
3708 
3709 __codecvt_utf16<char16_t, false>::result
3710 __codecvt_utf16<char16_t, false>::do_out(state_type&,
3711     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3712     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3713 {
3714     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3715     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3716     const uint16_t* _frm_nxt = _frm;
3717     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3718     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3719     uint8_t* _to_nxt = _to;
3720     result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3721                                _Maxcode_, _Mode_);
3722     frm_nxt = frm + (_frm_nxt - _frm);
3723     to_nxt = to + (_to_nxt - _to);
3724     return r;
3725 }
3726 
3727 __codecvt_utf16<char16_t, false>::result
3728 __codecvt_utf16<char16_t, false>::do_in(state_type&,
3729     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3730     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3731 {
3732     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3733     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3734     const uint8_t* _frm_nxt = _frm;
3735     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3736     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3737     uint16_t* _to_nxt = _to;
3738     result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3739                                _Maxcode_, _Mode_);
3740     frm_nxt = frm + (_frm_nxt - _frm);
3741     to_nxt = to + (_to_nxt - _to);
3742     return r;
3743 }
3744 
3745 __codecvt_utf16<char16_t, false>::result
3746 __codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3747     extern_type* to, extern_type*, extern_type*& to_nxt) const
3748 {
3749     to_nxt = to;
3750     return noconv;
3751 }
3752 
3753 int
3754 __codecvt_utf16<char16_t, false>::do_encoding() const  _NOEXCEPT
3755 {
3756     return 0;
3757 }
3758 
3759 bool
3760 __codecvt_utf16<char16_t, false>::do_always_noconv() const  _NOEXCEPT
3761 {
3762     return false;
3763 }
3764 
3765 int
3766 __codecvt_utf16<char16_t, false>::do_length(state_type&,
3767     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3768 {
3769     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3770     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3771     return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3772 }
3773 
3774 int
3775 __codecvt_utf16<char16_t, false>::do_max_length() const  _NOEXCEPT
3776 {
3777     if (_Mode_ & consume_header)
3778         return 4;
3779     return 2;
3780 }
3781 
3782 // __codecvt_utf16<char16_t, true>
3783 
3784 __codecvt_utf16<char16_t, true>::result
3785 __codecvt_utf16<char16_t, true>::do_out(state_type&,
3786     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3787     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3788 {
3789     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3790     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3791     const uint16_t* _frm_nxt = _frm;
3792     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3793     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3794     uint8_t* _to_nxt = _to;
3795     result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3796                                _Maxcode_, _Mode_);
3797     frm_nxt = frm + (_frm_nxt - _frm);
3798     to_nxt = to + (_to_nxt - _to);
3799     return r;
3800 }
3801 
3802 __codecvt_utf16<char16_t, true>::result
3803 __codecvt_utf16<char16_t, true>::do_in(state_type&,
3804     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3805     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3806 {
3807     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3808     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3809     const uint8_t* _frm_nxt = _frm;
3810     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3811     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3812     uint16_t* _to_nxt = _to;
3813     result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3814                                _Maxcode_, _Mode_);
3815     frm_nxt = frm + (_frm_nxt - _frm);
3816     to_nxt = to + (_to_nxt - _to);
3817     return r;
3818 }
3819 
3820 __codecvt_utf16<char16_t, true>::result
3821 __codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3822     extern_type* to, extern_type*, extern_type*& to_nxt) const
3823 {
3824     to_nxt = to;
3825     return noconv;
3826 }
3827 
3828 int
3829 __codecvt_utf16<char16_t, true>::do_encoding() const  _NOEXCEPT
3830 {
3831     return 0;
3832 }
3833 
3834 bool
3835 __codecvt_utf16<char16_t, true>::do_always_noconv() const  _NOEXCEPT
3836 {
3837     return false;
3838 }
3839 
3840 int
3841 __codecvt_utf16<char16_t, true>::do_length(state_type&,
3842     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3843 {
3844     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3845     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3846     return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3847 }
3848 
3849 int
3850 __codecvt_utf16<char16_t, true>::do_max_length() const  _NOEXCEPT
3851 {
3852     if (_Mode_ & consume_header)
3853         return 4;
3854     return 2;
3855 }
3856 
3857 // __codecvt_utf16<char32_t, false>
3858 
3859 __codecvt_utf16<char32_t, false>::result
3860 __codecvt_utf16<char32_t, false>::do_out(state_type&,
3861     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3862     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3863 {
3864     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3865     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3866     const uint32_t* _frm_nxt = _frm;
3867     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3868     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3869     uint8_t* _to_nxt = _to;
3870     result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3871                                _Maxcode_, _Mode_);
3872     frm_nxt = frm + (_frm_nxt - _frm);
3873     to_nxt = to + (_to_nxt - _to);
3874     return r;
3875 }
3876 
3877 __codecvt_utf16<char32_t, false>::result
3878 __codecvt_utf16<char32_t, false>::do_in(state_type&,
3879     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3880     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3881 {
3882     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3883     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3884     const uint8_t* _frm_nxt = _frm;
3885     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3886     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3887     uint32_t* _to_nxt = _to;
3888     result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3889                                _Maxcode_, _Mode_);
3890     frm_nxt = frm + (_frm_nxt - _frm);
3891     to_nxt = to + (_to_nxt - _to);
3892     return r;
3893 }
3894 
3895 __codecvt_utf16<char32_t, false>::result
3896 __codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3897     extern_type* to, extern_type*, extern_type*& to_nxt) const
3898 {
3899     to_nxt = to;
3900     return noconv;
3901 }
3902 
3903 int
3904 __codecvt_utf16<char32_t, false>::do_encoding() const  _NOEXCEPT
3905 {
3906     return 0;
3907 }
3908 
3909 bool
3910 __codecvt_utf16<char32_t, false>::do_always_noconv() const  _NOEXCEPT
3911 {
3912     return false;
3913 }
3914 
3915 int
3916 __codecvt_utf16<char32_t, false>::do_length(state_type&,
3917     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3918 {
3919     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3920     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3921     return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3922 }
3923 
3924 int
3925 __codecvt_utf16<char32_t, false>::do_max_length() const  _NOEXCEPT
3926 {
3927     if (_Mode_ & consume_header)
3928         return 6;
3929     return 4;
3930 }
3931 
3932 // __codecvt_utf16<char32_t, true>
3933 
3934 __codecvt_utf16<char32_t, true>::result
3935 __codecvt_utf16<char32_t, true>::do_out(state_type&,
3936     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3937     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3938 {
3939     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3940     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3941     const uint32_t* _frm_nxt = _frm;
3942     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3943     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3944     uint8_t* _to_nxt = _to;
3945     result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3946                                _Maxcode_, _Mode_);
3947     frm_nxt = frm + (_frm_nxt - _frm);
3948     to_nxt = to + (_to_nxt - _to);
3949     return r;
3950 }
3951 
3952 __codecvt_utf16<char32_t, true>::result
3953 __codecvt_utf16<char32_t, true>::do_in(state_type&,
3954     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3955     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3956 {
3957     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3958     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3959     const uint8_t* _frm_nxt = _frm;
3960     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3961     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3962     uint32_t* _to_nxt = _to;
3963     result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3964                                _Maxcode_, _Mode_);
3965     frm_nxt = frm + (_frm_nxt - _frm);
3966     to_nxt = to + (_to_nxt - _to);
3967     return r;
3968 }
3969 
3970 __codecvt_utf16<char32_t, true>::result
3971 __codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3972     extern_type* to, extern_type*, extern_type*& to_nxt) const
3973 {
3974     to_nxt = to;
3975     return noconv;
3976 }
3977 
3978 int
3979 __codecvt_utf16<char32_t, true>::do_encoding() const  _NOEXCEPT
3980 {
3981     return 0;
3982 }
3983 
3984 bool
3985 __codecvt_utf16<char32_t, true>::do_always_noconv() const  _NOEXCEPT
3986 {
3987     return false;
3988 }
3989 
3990 int
3991 __codecvt_utf16<char32_t, true>::do_length(state_type&,
3992     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3993 {
3994     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3995     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3996     return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3997 }
3998 
3999 int
4000 __codecvt_utf16<char32_t, true>::do_max_length() const  _NOEXCEPT
4001 {
4002     if (_Mode_ & consume_header)
4003         return 6;
4004     return 4;
4005 }
4006 
4007 // __codecvt_utf8_utf16<wchar_t>
4008 
4009 __codecvt_utf8_utf16<wchar_t>::result
4010 __codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4011     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4012     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4013 {
4014     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4015     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4016     const uint32_t* _frm_nxt = _frm;
4017     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4018     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4019     uint8_t* _to_nxt = _to;
4020     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4021                              _Maxcode_, _Mode_);
4022     frm_nxt = frm + (_frm_nxt - _frm);
4023     to_nxt = to + (_to_nxt - _to);
4024     return r;
4025 }
4026 
4027 __codecvt_utf8_utf16<wchar_t>::result
4028 __codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4029     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4030     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4031 {
4032     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4033     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4034     const uint8_t* _frm_nxt = _frm;
4035     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4036     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4037     uint32_t* _to_nxt = _to;
4038     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4039                              _Maxcode_, _Mode_);
4040     frm_nxt = frm + (_frm_nxt - _frm);
4041     to_nxt = to + (_to_nxt - _to);
4042     return r;
4043 }
4044 
4045 __codecvt_utf8_utf16<wchar_t>::result
4046 __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4047     extern_type* to, extern_type*, extern_type*& to_nxt) const
4048 {
4049     to_nxt = to;
4050     return noconv;
4051 }
4052 
4053 int
4054 __codecvt_utf8_utf16<wchar_t>::do_encoding() const  _NOEXCEPT
4055 {
4056     return 0;
4057 }
4058 
4059 bool
4060 __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const  _NOEXCEPT
4061 {
4062     return false;
4063 }
4064 
4065 int
4066 __codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4067     const extern_type* frm, const extern_type* frm_end, size_t mx) const
4068 {
4069     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4070     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4071     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4072 }
4073 
4074 int
4075 __codecvt_utf8_utf16<wchar_t>::do_max_length() const  _NOEXCEPT
4076 {
4077     if (_Mode_ & consume_header)
4078         return 7;
4079     return 4;
4080 }
4081 
4082 // __codecvt_utf8_utf16<char16_t>
4083 
4084 __codecvt_utf8_utf16<char16_t>::result
4085 __codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4086     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4087     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4088 {
4089     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4090     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4091     const uint16_t* _frm_nxt = _frm;
4092     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4093     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4094     uint8_t* _to_nxt = _to;
4095     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4096                              _Maxcode_, _Mode_);
4097     frm_nxt = frm + (_frm_nxt - _frm);
4098     to_nxt = to + (_to_nxt - _to);
4099     return r;
4100 }
4101 
4102 __codecvt_utf8_utf16<char16_t>::result
4103 __codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4104     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4105     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4106 {
4107     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4108     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4109     const uint8_t* _frm_nxt = _frm;
4110     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4111     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4112     uint16_t* _to_nxt = _to;
4113     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4114                              _Maxcode_, _Mode_);
4115     frm_nxt = frm + (_frm_nxt - _frm);
4116     to_nxt = to + (_to_nxt - _to);
4117     return r;
4118 }
4119 
4120 __codecvt_utf8_utf16<char16_t>::result
4121 __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4122     extern_type* to, extern_type*, extern_type*& to_nxt) const
4123 {
4124     to_nxt = to;
4125     return noconv;
4126 }
4127 
4128 int
4129 __codecvt_utf8_utf16<char16_t>::do_encoding() const  _NOEXCEPT
4130 {
4131     return 0;
4132 }
4133 
4134 bool
4135 __codecvt_utf8_utf16<char16_t>::do_always_noconv() const  _NOEXCEPT
4136 {
4137     return false;
4138 }
4139 
4140 int
4141 __codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4142     const extern_type* frm, const extern_type* frm_end, size_t mx) const
4143 {
4144     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4145     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4146     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4147 }
4148 
4149 int
4150 __codecvt_utf8_utf16<char16_t>::do_max_length() const  _NOEXCEPT
4151 {
4152     if (_Mode_ & consume_header)
4153         return 7;
4154     return 4;
4155 }
4156 
4157 // __codecvt_utf8_utf16<char32_t>
4158 
4159 __codecvt_utf8_utf16<char32_t>::result
4160 __codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4161     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4162     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4163 {
4164     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4165     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4166     const uint32_t* _frm_nxt = _frm;
4167     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4168     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4169     uint8_t* _to_nxt = _to;
4170     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4171                              _Maxcode_, _Mode_);
4172     frm_nxt = frm + (_frm_nxt - _frm);
4173     to_nxt = to + (_to_nxt - _to);
4174     return r;
4175 }
4176 
4177 __codecvt_utf8_utf16<char32_t>::result
4178 __codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4179     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4180     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4181 {
4182     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4183     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4184     const uint8_t* _frm_nxt = _frm;
4185     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4186     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4187     uint32_t* _to_nxt = _to;
4188     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4189                              _Maxcode_, _Mode_);
4190     frm_nxt = frm + (_frm_nxt - _frm);
4191     to_nxt = to + (_to_nxt - _to);
4192     return r;
4193 }
4194 
4195 __codecvt_utf8_utf16<char32_t>::result
4196 __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4197     extern_type* to, extern_type*, extern_type*& to_nxt) const
4198 {
4199     to_nxt = to;
4200     return noconv;
4201 }
4202 
4203 int
4204 __codecvt_utf8_utf16<char32_t>::do_encoding() const  _NOEXCEPT
4205 {
4206     return 0;
4207 }
4208 
4209 bool
4210 __codecvt_utf8_utf16<char32_t>::do_always_noconv() const  _NOEXCEPT
4211 {
4212     return false;
4213 }
4214 
4215 int
4216 __codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4217     const extern_type* frm, const extern_type* frm_end, size_t mx) const
4218 {
4219     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4220     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4221     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4222 }
4223 
4224 int
4225 __codecvt_utf8_utf16<char32_t>::do_max_length() const  _NOEXCEPT
4226 {
4227     if (_Mode_ & consume_header)
4228         return 7;
4229     return 4;
4230 }
4231 
4232 // __narrow_to_utf8<16>
4233 
4234 __narrow_to_utf8<16>::~__narrow_to_utf8()
4235 {
4236 }
4237 
4238 // __narrow_to_utf8<32>
4239 
4240 __narrow_to_utf8<32>::~__narrow_to_utf8()
4241 {
4242 }
4243 
4244 // __widen_from_utf8<16>
4245 
4246 __widen_from_utf8<16>::~__widen_from_utf8()
4247 {
4248 }
4249 
4250 // __widen_from_utf8<32>
4251 
4252 __widen_from_utf8<32>::~__widen_from_utf8()
4253 {
4254 }
4255 
4256 // numpunct<char> && numpunct<wchar_t>
4257 
4258 locale::id numpunct< char  >::id;
4259 locale::id numpunct<wchar_t>::id;
4260 
4261 numpunct<char>::numpunct(size_t refs)
4262     : locale::facet(refs),
4263       __decimal_point_('.'),
4264       __thousands_sep_(',')
4265 {
4266 }
4267 
4268 numpunct<wchar_t>::numpunct(size_t refs)
4269     : locale::facet(refs),
4270       __decimal_point_(L'.'),
4271       __thousands_sep_(L',')
4272 {
4273 }
4274 
4275 numpunct<char>::~numpunct()
4276 {
4277 }
4278 
4279 numpunct<wchar_t>::~numpunct()
4280 {
4281 }
4282 
4283  char   numpunct< char  >::do_decimal_point() const {return __decimal_point_;}
4284 wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4285 
4286  char   numpunct< char  >::do_thousands_sep() const {return __thousands_sep_;}
4287 wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4288 
4289 string numpunct< char  >::do_grouping() const {return __grouping_;}
4290 string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4291 
4292  string numpunct< char  >::do_truename() const {return "true";}
4293 wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4294 
4295  string numpunct< char  >::do_falsename() const {return "false";}
4296 wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4297 
4298 // numpunct_byname<char>
4299 
4300 numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4301     : numpunct<char>(refs)
4302 {
4303     __init(nm);
4304 }
4305 
4306 numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4307     : numpunct<char>(refs)
4308 {
4309     __init(nm.c_str());
4310 }
4311 
4312 numpunct_byname<char>::~numpunct_byname()
4313 {
4314 }
4315 
4316 void
4317 numpunct_byname<char>::__init(const char* nm)
4318 {
4319     if (strcmp(nm, "C") != 0)
4320     {
4321         __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
4322 #ifndef _LIBCPP_NO_EXCEPTIONS
4323         if (loc == nullptr)
4324             throw runtime_error("numpunct_byname<char>::numpunct_byname"
4325                                 " failed to construct for " + string(nm));
4326 #endif  // _LIBCPP_NO_EXCEPTIONS
4327 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4328         lconv* lc = localeconv_l(loc.get());
4329 #else
4330         lconv* lc = __localeconv_l(loc.get());
4331 #endif
4332         if (*lc->decimal_point)
4333             __decimal_point_ = *lc->decimal_point;
4334         if (*lc->thousands_sep)
4335             __thousands_sep_ = *lc->thousands_sep;
4336         __grouping_ = lc->grouping;
4337         // localization for truename and falsename is not available
4338     }
4339 }
4340 
4341 // numpunct_byname<wchar_t>
4342 
4343 numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4344     : numpunct<wchar_t>(refs)
4345 {
4346     __init(nm);
4347 }
4348 
4349 numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4350     : numpunct<wchar_t>(refs)
4351 {
4352     __init(nm.c_str());
4353 }
4354 
4355 numpunct_byname<wchar_t>::~numpunct_byname()
4356 {
4357 }
4358 
4359 void
4360 numpunct_byname<wchar_t>::__init(const char* nm)
4361 {
4362     if (strcmp(nm, "C") != 0)
4363     {
4364         __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
4365 #ifndef _LIBCPP_NO_EXCEPTIONS
4366         if (loc == nullptr)
4367             throw runtime_error("numpunct_byname<char>::numpunct_byname"
4368                                 " failed to construct for " + string(nm));
4369 #endif  // _LIBCPP_NO_EXCEPTIONS
4370 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4371         lconv* lc = localeconv_l(loc.get());
4372 #else
4373         lconv* lc = __localeconv_l(loc.get());
4374 #endif
4375         if (*lc->decimal_point)
4376             __decimal_point_ = *lc->decimal_point;
4377         if (*lc->thousands_sep)
4378             __thousands_sep_ = *lc->thousands_sep;
4379         __grouping_ = lc->grouping;
4380         // locallization for truename and falsename is not available
4381     }
4382 }
4383 
4384 // num_get helpers
4385 
4386 int
4387 __num_get_base::__get_base(ios_base& iob)
4388 {
4389     ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4390     if (__basefield == ios_base::oct)
4391         return 8;
4392     else if (__basefield == ios_base::hex)
4393         return 16;
4394     else if (__basefield == 0)
4395         return 0;
4396     return 10;
4397 }
4398 
4399 const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4400 
4401 void
4402 __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4403                  ios_base::iostate& __err)
4404 {
4405     if (__grouping.size() != 0)
4406     {
4407         reverse(__g, __g_end);
4408         const char* __ig = __grouping.data();
4409         const char* __eg = __ig + __grouping.size();
4410         for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4411         {
4412             if (0 < *__ig && *__ig < numeric_limits<char>::max())
4413             {
4414                 if (static_cast<unsigned>(*__ig) != *__r)
4415                 {
4416                     __err = ios_base::failbit;
4417                     return;
4418                 }
4419             }
4420             if (__eg - __ig > 1)
4421                 ++__ig;
4422         }
4423         if (0 < *__ig && *__ig < numeric_limits<char>::max())
4424         {
4425             if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
4426                 __err = ios_base::failbit;
4427         }
4428     }
4429 }
4430 
4431 void
4432 __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4433                              ios_base::fmtflags __flags)
4434 {
4435     if (__flags & ios_base::showpos)
4436         *__fmtp++ = '+';
4437     if (__flags & ios_base::showbase)
4438         *__fmtp++ = '#';
4439     while(*__len)
4440         *__fmtp++ = *__len++;
4441     if ((__flags & ios_base::basefield) == ios_base::oct)
4442         *__fmtp = 'o';
4443     else if ((__flags & ios_base::basefield) == ios_base::hex)
4444     {
4445         if (__flags & ios_base::uppercase)
4446             *__fmtp = 'X';
4447         else
4448             *__fmtp = 'x';
4449     }
4450     else if (__signd)
4451         *__fmtp = 'd';
4452     else
4453         *__fmtp = 'u';
4454 }
4455 
4456 bool
4457 __num_put_base::__format_float(char* __fmtp, const char* __len,
4458                                ios_base::fmtflags __flags)
4459 {
4460     bool specify_precision = true;
4461     if (__flags & ios_base::showpos)
4462         *__fmtp++ = '+';
4463     if (__flags & ios_base::showpoint)
4464         *__fmtp++ = '#';
4465     ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4466     bool uppercase = (__flags & ios_base::uppercase) != 0;
4467     if (floatfield == (ios_base::fixed | ios_base::scientific))
4468         specify_precision = false;
4469     else
4470     {
4471         *__fmtp++ = '.';
4472         *__fmtp++ = '*';
4473     }
4474     while(*__len)
4475         *__fmtp++ = *__len++;
4476     if (floatfield == ios_base::fixed)
4477     {
4478         if (uppercase)
4479             *__fmtp = 'F';
4480         else
4481             *__fmtp = 'f';
4482     }
4483     else if (floatfield == ios_base::scientific)
4484     {
4485         if (uppercase)
4486             *__fmtp = 'E';
4487         else
4488             *__fmtp = 'e';
4489     }
4490     else if (floatfield == (ios_base::fixed | ios_base::scientific))
4491     {
4492         if (uppercase)
4493             *__fmtp = 'A';
4494         else
4495             *__fmtp = 'a';
4496     }
4497     else
4498     {
4499         if (uppercase)
4500             *__fmtp = 'G';
4501         else
4502             *__fmtp = 'g';
4503     }
4504     return specify_precision;
4505 }
4506 
4507 char*
4508 __num_put_base::__identify_padding(char* __nb, char* __ne,
4509                                    const ios_base& __iob)
4510 {
4511     switch (__iob.flags() & ios_base::adjustfield)
4512     {
4513     case ios_base::internal:
4514         if (__nb[0] == '-' || __nb[0] == '+')
4515             return __nb+1;
4516         if (__ne - __nb >= 2 && __nb[0] == '0'
4517                             && (__nb[1] == 'x' || __nb[1] == 'X'))
4518             return __nb+2;
4519         break;
4520     case ios_base::left:
4521         return __ne;
4522     case ios_base::right:
4523     default:
4524         break;
4525     }
4526     return __nb;
4527 }
4528 
4529 // time_get
4530 
4531 static
4532 string*
4533 init_weeks()
4534 {
4535     static string weeks[14];
4536     weeks[0]  = "Sunday";
4537     weeks[1]  = "Monday";
4538     weeks[2]  = "Tuesday";
4539     weeks[3]  = "Wednesday";
4540     weeks[4]  = "Thursday";
4541     weeks[5]  = "Friday";
4542     weeks[6]  = "Saturday";
4543     weeks[7]  = "Sun";
4544     weeks[8]  = "Mon";
4545     weeks[9]  = "Tue";
4546     weeks[10] = "Wed";
4547     weeks[11] = "Thu";
4548     weeks[12] = "Fri";
4549     weeks[13] = "Sat";
4550     return weeks;
4551 }
4552 
4553 static
4554 wstring*
4555 init_wweeks()
4556 {
4557     static wstring weeks[14];
4558     weeks[0]  = L"Sunday";
4559     weeks[1]  = L"Monday";
4560     weeks[2]  = L"Tuesday";
4561     weeks[3]  = L"Wednesday";
4562     weeks[4]  = L"Thursday";
4563     weeks[5]  = L"Friday";
4564     weeks[6]  = L"Saturday";
4565     weeks[7]  = L"Sun";
4566     weeks[8]  = L"Mon";
4567     weeks[9]  = L"Tue";
4568     weeks[10] = L"Wed";
4569     weeks[11] = L"Thu";
4570     weeks[12] = L"Fri";
4571     weeks[13] = L"Sat";
4572     return weeks;
4573 }
4574 
4575 template <>
4576 const string*
4577 __time_get_c_storage<char>::__weeks() const
4578 {
4579     static const string* weeks = init_weeks();
4580     return weeks;
4581 }
4582 
4583 template <>
4584 const wstring*
4585 __time_get_c_storage<wchar_t>::__weeks() const
4586 {
4587     static const wstring* weeks = init_wweeks();
4588     return weeks;
4589 }
4590 
4591 static
4592 string*
4593 init_months()
4594 {
4595     static string months[24];
4596     months[0]  = "January";
4597     months[1]  = "February";
4598     months[2]  = "March";
4599     months[3]  = "April";
4600     months[4]  = "May";
4601     months[5]  = "June";
4602     months[6]  = "July";
4603     months[7]  = "August";
4604     months[8]  = "September";
4605     months[9]  = "October";
4606     months[10] = "November";
4607     months[11] = "December";
4608     months[12] = "Jan";
4609     months[13] = "Feb";
4610     months[14] = "Mar";
4611     months[15] = "Apr";
4612     months[16] = "May";
4613     months[17] = "Jun";
4614     months[18] = "Jul";
4615     months[19] = "Aug";
4616     months[20] = "Sep";
4617     months[21] = "Oct";
4618     months[22] = "Nov";
4619     months[23] = "Dec";
4620     return months;
4621 }
4622 
4623 static
4624 wstring*
4625 init_wmonths()
4626 {
4627     static wstring months[24];
4628     months[0]  = L"January";
4629     months[1]  = L"February";
4630     months[2]  = L"March";
4631     months[3]  = L"April";
4632     months[4]  = L"May";
4633     months[5]  = L"June";
4634     months[6]  = L"July";
4635     months[7]  = L"August";
4636     months[8]  = L"September";
4637     months[9]  = L"October";
4638     months[10] = L"November";
4639     months[11] = L"December";
4640     months[12] = L"Jan";
4641     months[13] = L"Feb";
4642     months[14] = L"Mar";
4643     months[15] = L"Apr";
4644     months[16] = L"May";
4645     months[17] = L"Jun";
4646     months[18] = L"Jul";
4647     months[19] = L"Aug";
4648     months[20] = L"Sep";
4649     months[21] = L"Oct";
4650     months[22] = L"Nov";
4651     months[23] = L"Dec";
4652     return months;
4653 }
4654 
4655 template <>
4656 const string*
4657 __time_get_c_storage<char>::__months() const
4658 {
4659     static const string* months = init_months();
4660     return months;
4661 }
4662 
4663 template <>
4664 const wstring*
4665 __time_get_c_storage<wchar_t>::__months() const
4666 {
4667     static const wstring* months = init_wmonths();
4668     return months;
4669 }
4670 
4671 static
4672 string*
4673 init_am_pm()
4674 {
4675     static string am_pm[24];
4676     am_pm[0]  = "AM";
4677     am_pm[1]  = "PM";
4678     return am_pm;
4679 }
4680 
4681 static
4682 wstring*
4683 init_wam_pm()
4684 {
4685     static wstring am_pm[24];
4686     am_pm[0]  = L"AM";
4687     am_pm[1]  = L"PM";
4688     return am_pm;
4689 }
4690 
4691 template <>
4692 const string*
4693 __time_get_c_storage<char>::__am_pm() const
4694 {
4695     static const string* am_pm = init_am_pm();
4696     return am_pm;
4697 }
4698 
4699 template <>
4700 const wstring*
4701 __time_get_c_storage<wchar_t>::__am_pm() const
4702 {
4703     static const wstring* am_pm = init_wam_pm();
4704     return am_pm;
4705 }
4706 
4707 template <>
4708 const string&
4709 __time_get_c_storage<char>::__x() const
4710 {
4711     static string s("%m/%d/%y");
4712     return s;
4713 }
4714 
4715 template <>
4716 const wstring&
4717 __time_get_c_storage<wchar_t>::__x() const
4718 {
4719     static wstring s(L"%m/%d/%y");
4720     return s;
4721 }
4722 
4723 template <>
4724 const string&
4725 __time_get_c_storage<char>::__X() const
4726 {
4727     static string s("%H:%M:%S");
4728     return s;
4729 }
4730 
4731 template <>
4732 const wstring&
4733 __time_get_c_storage<wchar_t>::__X() const
4734 {
4735     static wstring s(L"%H:%M:%S");
4736     return s;
4737 }
4738 
4739 template <>
4740 const string&
4741 __time_get_c_storage<char>::__c() const
4742 {
4743     static string s("%a %b %d %H:%M:%S %Y");
4744     return s;
4745 }
4746 
4747 template <>
4748 const wstring&
4749 __time_get_c_storage<wchar_t>::__c() const
4750 {
4751     static wstring s(L"%a %b %d %H:%M:%S %Y");
4752     return s;
4753 }
4754 
4755 template <>
4756 const string&
4757 __time_get_c_storage<char>::__r() const
4758 {
4759     static string s("%I:%M:%S %p");
4760     return s;
4761 }
4762 
4763 template <>
4764 const wstring&
4765 __time_get_c_storage<wchar_t>::__r() const
4766 {
4767     static wstring s(L"%I:%M:%S %p");
4768     return s;
4769 }
4770 
4771 // time_get_byname
4772 
4773 __time_get::__time_get(const char* nm)
4774     : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4775 {
4776 #ifndef _LIBCPP_NO_EXCEPTIONS
4777     if (__loc_ == 0)
4778         throw runtime_error("time_get_byname"
4779                             " failed to construct for " + string(nm));
4780 #endif  // _LIBCPP_NO_EXCEPTIONS
4781 }
4782 
4783 __time_get::__time_get(const string& nm)
4784     : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4785 {
4786 #ifndef _LIBCPP_NO_EXCEPTIONS
4787     if (__loc_ == 0)
4788         throw runtime_error("time_get_byname"
4789                             " failed to construct for " + nm);
4790 #endif  // _LIBCPP_NO_EXCEPTIONS
4791 }
4792 
4793 __time_get::~__time_get()
4794 {
4795     freelocale(__loc_);
4796 }
4797 #if defined(__clang__)
4798 #pragma clang diagnostic ignored "-Wmissing-field-initializers"
4799 #endif
4800 #if defined(__GNUG__)
4801 #pragma GCC   diagnostic ignored "-Wmissing-field-initializers"
4802 #endif
4803 
4804 template <>
4805 string
4806 __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4807 {
4808     tm t = {0};
4809     t.tm_sec = 59;
4810     t.tm_min = 55;
4811     t.tm_hour = 23;
4812     t.tm_mday = 31;
4813     t.tm_mon = 11;
4814     t.tm_year = 161;
4815     t.tm_wday = 6;
4816     t.tm_yday = 364;
4817     t.tm_isdst = -1;
4818     char buf[100];
4819     char f[3] = {0};
4820     f[0] = '%';
4821     f[1] = fmt;
4822     size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
4823     char* bb = buf;
4824     char* be = buf + n;
4825     string result;
4826     while (bb != be)
4827     {
4828         if (ct.is(ctype_base::space, *bb))
4829         {
4830             result.push_back(' ');
4831             for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4832                 ;
4833             continue;
4834         }
4835         char* w = bb;
4836         ios_base::iostate err = ios_base::goodbit;
4837         ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4838                                ct, err, false)
4839                                - this->__weeks_;
4840         if (i < 14)
4841         {
4842             result.push_back('%');
4843             if (i < 7)
4844                 result.push_back('A');
4845             else
4846                 result.push_back('a');
4847             bb = w;
4848             continue;
4849         }
4850         w = bb;
4851         i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4852                            ct, err, false)
4853                            - this->__months_;
4854         if (i < 24)
4855         {
4856             result.push_back('%');
4857             if (i < 12)
4858                 result.push_back('B');
4859             else
4860                 result.push_back('b');
4861             if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4862                 result.back() = 'm';
4863             bb = w;
4864             continue;
4865         }
4866         if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4867         {
4868             w = bb;
4869             i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4870                                ct, err, false) - this->__am_pm_;
4871             if (i < 2)
4872             {
4873                 result.push_back('%');
4874                 result.push_back('p');
4875                 bb = w;
4876                 continue;
4877             }
4878         }
4879         w = bb;
4880         if (ct.is(ctype_base::digit, *bb))
4881         {
4882             switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4883             {
4884             case 6:
4885                 result.push_back('%');
4886                 result.push_back('w');
4887                 break;
4888             case 7:
4889                 result.push_back('%');
4890                 result.push_back('u');
4891                 break;
4892             case 11:
4893                 result.push_back('%');
4894                 result.push_back('I');
4895                 break;
4896             case 12:
4897                 result.push_back('%');
4898                 result.push_back('m');
4899                 break;
4900             case 23:
4901                 result.push_back('%');
4902                 result.push_back('H');
4903                 break;
4904             case 31:
4905                 result.push_back('%');
4906                 result.push_back('d');
4907                 break;
4908             case 55:
4909                 result.push_back('%');
4910                 result.push_back('M');
4911                 break;
4912             case 59:
4913                 result.push_back('%');
4914                 result.push_back('S');
4915                 break;
4916             case 61:
4917                 result.push_back('%');
4918                 result.push_back('y');
4919                 break;
4920             case 364:
4921                 result.push_back('%');
4922                 result.push_back('j');
4923                 break;
4924             case 2061:
4925                 result.push_back('%');
4926                 result.push_back('Y');
4927                 break;
4928             default:
4929                 for (; w != bb; ++w)
4930                     result.push_back(*w);
4931                 break;
4932             }
4933             continue;
4934         }
4935         if (*bb == '%')
4936         {
4937             result.push_back('%');
4938             result.push_back('%');
4939             ++bb;
4940             continue;
4941         }
4942         result.push_back(*bb);
4943         ++bb;
4944     }
4945     return result;
4946 }
4947 
4948 #if defined(__clang__)
4949 #pragma clang diagnostic ignored "-Wmissing-braces"
4950 #endif
4951 
4952 template <>
4953 wstring
4954 __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4955 {
4956     tm t = {0};
4957     t.tm_sec = 59;
4958     t.tm_min = 55;
4959     t.tm_hour = 23;
4960     t.tm_mday = 31;
4961     t.tm_mon = 11;
4962     t.tm_year = 161;
4963     t.tm_wday = 6;
4964     t.tm_yday = 364;
4965     t.tm_isdst = -1;
4966     char buf[100];
4967     char f[3] = {0};
4968     f[0] = '%';
4969     f[1] = fmt;
4970     strftime_l(buf, countof(buf), f, &t, __loc_);
4971     wchar_t wbuf[100];
4972     wchar_t* wbb = wbuf;
4973     mbstate_t mb = {0};
4974     const char* bb = buf;
4975 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
4976     size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
4977 #else
4978     size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
4979 #endif
4980     if (j == size_t(-1))
4981         __throw_runtime_error("locale not supported");
4982     wchar_t* wbe = wbb + j;
4983     wstring result;
4984     while (wbb != wbe)
4985     {
4986         if (ct.is(ctype_base::space, *wbb))
4987         {
4988             result.push_back(L' ');
4989             for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4990                 ;
4991             continue;
4992         }
4993         wchar_t* w = wbb;
4994         ios_base::iostate err = ios_base::goodbit;
4995         ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4996                                ct, err, false)
4997                                - this->__weeks_;
4998         if (i < 14)
4999         {
5000             result.push_back(L'%');
5001             if (i < 7)
5002                 result.push_back(L'A');
5003             else
5004                 result.push_back(L'a');
5005             wbb = w;
5006             continue;
5007         }
5008         w = wbb;
5009         i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5010                            ct, err, false)
5011                            - this->__months_;
5012         if (i < 24)
5013         {
5014             result.push_back(L'%');
5015             if (i < 12)
5016                 result.push_back(L'B');
5017             else
5018                 result.push_back(L'b');
5019             if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5020                 result.back() = L'm';
5021             wbb = w;
5022             continue;
5023         }
5024         if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5025         {
5026             w = wbb;
5027             i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5028                                ct, err, false) - this->__am_pm_;
5029             if (i < 2)
5030             {
5031                 result.push_back(L'%');
5032                 result.push_back(L'p');
5033                 wbb = w;
5034                 continue;
5035             }
5036         }
5037         w = wbb;
5038         if (ct.is(ctype_base::digit, *wbb))
5039         {
5040             switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5041             {
5042             case 6:
5043                 result.push_back(L'%');
5044                 result.push_back(L'w');
5045                 break;
5046             case 7:
5047                 result.push_back(L'%');
5048                 result.push_back(L'u');
5049                 break;
5050             case 11:
5051                 result.push_back(L'%');
5052                 result.push_back(L'I');
5053                 break;
5054             case 12:
5055                 result.push_back(L'%');
5056                 result.push_back(L'm');
5057                 break;
5058             case 23:
5059                 result.push_back(L'%');
5060                 result.push_back(L'H');
5061                 break;
5062             case 31:
5063                 result.push_back(L'%');
5064                 result.push_back(L'd');
5065                 break;
5066             case 55:
5067                 result.push_back(L'%');
5068                 result.push_back(L'M');
5069                 break;
5070             case 59:
5071                 result.push_back(L'%');
5072                 result.push_back(L'S');
5073                 break;
5074             case 61:
5075                 result.push_back(L'%');
5076                 result.push_back(L'y');
5077                 break;
5078             case 364:
5079                 result.push_back(L'%');
5080                 result.push_back(L'j');
5081                 break;
5082             case 2061:
5083                 result.push_back(L'%');
5084                 result.push_back(L'Y');
5085                 break;
5086             default:
5087                 for (; w != wbb; ++w)
5088                     result.push_back(*w);
5089                 break;
5090             }
5091             continue;
5092         }
5093         if (ct.narrow(*wbb, 0) == '%')
5094         {
5095             result.push_back(L'%');
5096             result.push_back(L'%');
5097             ++wbb;
5098             continue;
5099         }
5100         result.push_back(*wbb);
5101         ++wbb;
5102     }
5103     return result;
5104 }
5105 
5106 template <>
5107 void
5108 __time_get_storage<char>::init(const ctype<char>& ct)
5109 {
5110     tm t = {0};
5111     char buf[100];
5112     // __weeks_
5113     for (int i = 0; i < 7; ++i)
5114     {
5115         t.tm_wday = i;
5116         strftime_l(buf, countof(buf), "%A", &t, __loc_);
5117         __weeks_[i] = buf;
5118         strftime_l(buf, countof(buf), "%a", &t, __loc_);
5119         __weeks_[i+7] = buf;
5120     }
5121     // __months_
5122     for (int i = 0; i < 12; ++i)
5123     {
5124         t.tm_mon = i;
5125         strftime_l(buf, countof(buf), "%B", &t, __loc_);
5126         __months_[i] = buf;
5127         strftime_l(buf, countof(buf), "%b", &t, __loc_);
5128         __months_[i+12] = buf;
5129     }
5130     // __am_pm_
5131     t.tm_hour = 1;
5132     strftime_l(buf, countof(buf), "%p", &t, __loc_);
5133     __am_pm_[0] = buf;
5134     t.tm_hour = 13;
5135     strftime_l(buf, countof(buf), "%p", &t, __loc_);
5136     __am_pm_[1] = buf;
5137     __c_ = __analyze('c', ct);
5138     __r_ = __analyze('r', ct);
5139     __x_ = __analyze('x', ct);
5140     __X_ = __analyze('X', ct);
5141 }
5142 
5143 template <>
5144 void
5145 __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5146 {
5147     tm t = {0};
5148     char buf[100];
5149     wchar_t wbuf[100];
5150     wchar_t* wbe;
5151     mbstate_t mb = {0};
5152     // __weeks_
5153     for (int i = 0; i < 7; ++i)
5154     {
5155         t.tm_wday = i;
5156         strftime_l(buf, countof(buf), "%A", &t, __loc_);
5157         mb = mbstate_t();
5158         const char* bb = buf;
5159 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5160         size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5161 #else
5162         size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5163 #endif
5164         if (j == size_t(-1))
5165             __throw_runtime_error("locale not supported");
5166         wbe = wbuf + j;
5167         __weeks_[i].assign(wbuf, wbe);
5168         strftime_l(buf, countof(buf), "%a", &t, __loc_);
5169         mb = mbstate_t();
5170         bb = buf;
5171 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5172         j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5173 #else
5174         j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5175 #endif
5176         if (j == size_t(-1))
5177             __throw_runtime_error("locale not supported");
5178         wbe = wbuf + j;
5179         __weeks_[i+7].assign(wbuf, wbe);
5180     }
5181     // __months_
5182     for (int i = 0; i < 12; ++i)
5183     {
5184         t.tm_mon = i;
5185         strftime_l(buf, countof(buf), "%B", &t, __loc_);
5186         mb = mbstate_t();
5187         const char* bb = buf;
5188 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5189         size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5190 #else
5191         size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5192 #endif
5193         if (j == size_t(-1))
5194             __throw_runtime_error("locale not supported");
5195         wbe = wbuf + j;
5196         __months_[i].assign(wbuf, wbe);
5197         strftime_l(buf, countof(buf), "%b", &t, __loc_);
5198         mb = mbstate_t();
5199         bb = buf;
5200 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5201         j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5202 #else
5203         j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5204 #endif
5205         if (j == size_t(-1))
5206             __throw_runtime_error("locale not supported");
5207         wbe = wbuf + j;
5208         __months_[i+12].assign(wbuf, wbe);
5209     }
5210     // __am_pm_
5211     t.tm_hour = 1;
5212     strftime_l(buf, countof(buf), "%p", &t, __loc_);
5213     mb = mbstate_t();
5214     const char* bb = buf;
5215 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5216     size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5217 #else
5218     size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5219 #endif
5220     if (j == size_t(-1))
5221         __throw_runtime_error("locale not supported");
5222     wbe = wbuf + j;
5223     __am_pm_[0].assign(wbuf, wbe);
5224     t.tm_hour = 13;
5225     strftime_l(buf, countof(buf), "%p", &t, __loc_);
5226     mb = mbstate_t();
5227     bb = buf;
5228 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5229     j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5230 #else
5231     j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5232 #endif
5233     if (j == size_t(-1))
5234         __throw_runtime_error("locale not supported");
5235     wbe = wbuf + j;
5236     __am_pm_[1].assign(wbuf, wbe);
5237     __c_ = __analyze('c', ct);
5238     __r_ = __analyze('r', ct);
5239     __x_ = __analyze('x', ct);
5240     __X_ = __analyze('X', ct);
5241 }
5242 
5243 template <class CharT>
5244 struct _LIBCPP_HIDDEN __time_get_temp
5245     : public ctype_byname<CharT>
5246 {
5247     explicit __time_get_temp(const char* nm)
5248         : ctype_byname<CharT>(nm, 1) {}
5249     explicit __time_get_temp(const string& nm)
5250         : ctype_byname<CharT>(nm, 1) {}
5251 };
5252 
5253 template <>
5254 __time_get_storage<char>::__time_get_storage(const char* __nm)
5255     : __time_get(__nm)
5256 {
5257     const __time_get_temp<char> ct(__nm);
5258     init(ct);
5259 }
5260 
5261 template <>
5262 __time_get_storage<char>::__time_get_storage(const string& __nm)
5263     : __time_get(__nm)
5264 {
5265     const __time_get_temp<char> ct(__nm);
5266     init(ct);
5267 }
5268 
5269 template <>
5270 __time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5271     : __time_get(__nm)
5272 {
5273     const __time_get_temp<wchar_t> ct(__nm);
5274     init(ct);
5275 }
5276 
5277 template <>
5278 __time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5279     : __time_get(__nm)
5280 {
5281     const __time_get_temp<wchar_t> ct(__nm);
5282     init(ct);
5283 }
5284 
5285 template <>
5286 time_base::dateorder
5287 __time_get_storage<char>::__do_date_order() const
5288 {
5289     unsigned i;
5290     for (i = 0; i < __x_.size(); ++i)
5291         if (__x_[i] == '%')
5292             break;
5293     ++i;
5294     switch (__x_[i])
5295     {
5296     case 'y':
5297     case 'Y':
5298         for (++i; i < __x_.size(); ++i)
5299             if (__x_[i] == '%')
5300                 break;
5301         if (i == __x_.size())
5302             break;
5303         ++i;
5304         switch (__x_[i])
5305         {
5306         case 'm':
5307             for (++i; i < __x_.size(); ++i)
5308                 if (__x_[i] == '%')
5309                     break;
5310             if (i == __x_.size())
5311                 break;
5312             ++i;
5313             if (__x_[i] == 'd')
5314                 return time_base::ymd;
5315             break;
5316         case 'd':
5317             for (++i; i < __x_.size(); ++i)
5318                 if (__x_[i] == '%')
5319                     break;
5320             if (i == __x_.size())
5321                 break;
5322             ++i;
5323             if (__x_[i] == 'm')
5324                 return time_base::ydm;
5325             break;
5326         }
5327         break;
5328     case 'm':
5329         for (++i; i < __x_.size(); ++i)
5330             if (__x_[i] == '%')
5331                 break;
5332         if (i == __x_.size())
5333             break;
5334         ++i;
5335         if (__x_[i] == 'd')
5336         {
5337             for (++i; i < __x_.size(); ++i)
5338                 if (__x_[i] == '%')
5339                     break;
5340             if (i == __x_.size())
5341                 break;
5342             ++i;
5343             if (__x_[i] == 'y' || __x_[i] == 'Y')
5344                 return time_base::mdy;
5345             break;
5346         }
5347         break;
5348     case 'd':
5349         for (++i; i < __x_.size(); ++i)
5350             if (__x_[i] == '%')
5351                 break;
5352         if (i == __x_.size())
5353             break;
5354         ++i;
5355         if (__x_[i] == 'm')
5356         {
5357             for (++i; i < __x_.size(); ++i)
5358                 if (__x_[i] == '%')
5359                     break;
5360             if (i == __x_.size())
5361                 break;
5362             ++i;
5363             if (__x_[i] == 'y' || __x_[i] == 'Y')
5364                 return time_base::dmy;
5365             break;
5366         }
5367         break;
5368     }
5369     return time_base::no_order;
5370 }
5371 
5372 template <>
5373 time_base::dateorder
5374 __time_get_storage<wchar_t>::__do_date_order() const
5375 {
5376     unsigned i;
5377     for (i = 0; i < __x_.size(); ++i)
5378         if (__x_[i] == L'%')
5379             break;
5380     ++i;
5381     switch (__x_[i])
5382     {
5383     case L'y':
5384     case L'Y':
5385         for (++i; i < __x_.size(); ++i)
5386             if (__x_[i] == L'%')
5387                 break;
5388         if (i == __x_.size())
5389             break;
5390         ++i;
5391         switch (__x_[i])
5392         {
5393         case L'm':
5394             for (++i; i < __x_.size(); ++i)
5395                 if (__x_[i] == L'%')
5396                     break;
5397             if (i == __x_.size())
5398                 break;
5399             ++i;
5400             if (__x_[i] == L'd')
5401                 return time_base::ymd;
5402             break;
5403         case L'd':
5404             for (++i; i < __x_.size(); ++i)
5405                 if (__x_[i] == L'%')
5406                     break;
5407             if (i == __x_.size())
5408                 break;
5409             ++i;
5410             if (__x_[i] == L'm')
5411                 return time_base::ydm;
5412             break;
5413         }
5414         break;
5415     case L'm':
5416         for (++i; i < __x_.size(); ++i)
5417             if (__x_[i] == L'%')
5418                 break;
5419         if (i == __x_.size())
5420             break;
5421         ++i;
5422         if (__x_[i] == L'd')
5423         {
5424             for (++i; i < __x_.size(); ++i)
5425                 if (__x_[i] == L'%')
5426                     break;
5427             if (i == __x_.size())
5428                 break;
5429             ++i;
5430             if (__x_[i] == L'y' || __x_[i] == L'Y')
5431                 return time_base::mdy;
5432             break;
5433         }
5434         break;
5435     case L'd':
5436         for (++i; i < __x_.size(); ++i)
5437             if (__x_[i] == L'%')
5438                 break;
5439         if (i == __x_.size())
5440             break;
5441         ++i;
5442         if (__x_[i] == L'm')
5443         {
5444             for (++i; i < __x_.size(); ++i)
5445                 if (__x_[i] == L'%')
5446                     break;
5447             if (i == __x_.size())
5448                 break;
5449             ++i;
5450             if (__x_[i] == L'y' || __x_[i] == L'Y')
5451                 return time_base::dmy;
5452             break;
5453         }
5454         break;
5455     }
5456     return time_base::no_order;
5457 }
5458 
5459 // time_put
5460 
5461 __time_put::__time_put(const char* nm)
5462     : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5463 {
5464 #ifndef _LIBCPP_NO_EXCEPTIONS
5465     if (__loc_ == 0)
5466         throw runtime_error("time_put_byname"
5467                             " failed to construct for " + string(nm));
5468 #endif  // _LIBCPP_NO_EXCEPTIONS
5469 }
5470 
5471 __time_put::__time_put(const string& nm)
5472     : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5473 {
5474 #ifndef _LIBCPP_NO_EXCEPTIONS
5475     if (__loc_ == 0)
5476         throw runtime_error("time_put_byname"
5477                             " failed to construct for " + nm);
5478 #endif  // _LIBCPP_NO_EXCEPTIONS
5479 }
5480 
5481 __time_put::~__time_put()
5482 {
5483     if (__loc_ != _LIBCPP_GET_C_LOCALE)
5484         freelocale(__loc_);
5485 }
5486 
5487 void
5488 __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5489                      char __fmt, char __mod) const
5490 {
5491     char fmt[] = {'%', __fmt, __mod, 0};
5492     if (__mod != 0)
5493         swap(fmt[1], fmt[2]);
5494     size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
5495     __ne = __nb + n;
5496 }
5497 
5498 void
5499 __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5500                      char __fmt, char __mod) const
5501 {
5502     char __nar[100];
5503     char* __ne = __nar + 100;
5504     __do_put(__nar, __ne, __tm, __fmt, __mod);
5505     mbstate_t mb = {0};
5506     const char* __nb = __nar;
5507 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5508     size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5509 #else
5510     size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5511 #endif
5512     if (j == size_t(-1))
5513         __throw_runtime_error("locale not supported");
5514     __we = __wb + j;
5515 }
5516 
5517 // moneypunct_byname
5518 
5519 template <class charT>
5520 static
5521 void
5522 __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5523            bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5524            charT space_char)
5525 {
5526     const char sign = static_cast<char>(money_base::sign);
5527     const char space = static_cast<char>(money_base::space);
5528     const char none = static_cast<char>(money_base::none);
5529     const char symbol = static_cast<char>(money_base::symbol);
5530     const char value = static_cast<char>(money_base::value);
5531     const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5532 
5533     // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5534     // function'. "Space between sign and symbol or value" means that
5535     // if the sign is adjacent to the symbol, there's a space between
5536     // them, and otherwise there's a space between the sign and value.
5537     //
5538     // C11's localeconv specifies that the fourth character of an
5539     // international curr_symbol is used to separate the sign and
5540     // value when sep_by_space says to do so. C++ can't represent
5541     // that, so we just use a space.  When sep_by_space says to
5542     // separate the symbol and value-or-sign with a space, we rearrange the
5543     // curr_symbol to put its spacing character on the correct side of
5544     // the symbol.
5545     //
5546     // We also need to avoid adding an extra space between the sign
5547     // and value when the currency symbol is suppressed (by not
5548     // setting showbase).  We match glibc's strfmon by interpreting
5549     // sep_by_space==1 as "omit the space when the currency symbol is
5550     // absent".
5551     //
5552     // Users who want to get this right should use ICU instead.
5553 
5554     switch (cs_precedes)
5555     {
5556     case 0:  // value before curr_symbol
5557         if (symbol_contains_sep) {
5558             // Move the separator to before the symbol, to place it
5559             // between the value and symbol.
5560             rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5561                    __curr_symbol_.end());
5562         }
5563         switch (sign_posn)
5564         {
5565         case 0:  // Parentheses surround the quantity and currency symbol.
5566             pat.field[0] = sign;
5567             pat.field[1] = value;
5568             pat.field[2] = none;  // Any space appears in the symbol.
5569             pat.field[3] = symbol;
5570             switch (sep_by_space)
5571             {
5572             case 0:  // No space separates the currency symbol and value.
5573                 // This case may have changed between C99 and C11;
5574                 // assume the currency symbol matches the intention.
5575             case 2:  // Space between sign and currency or value.
5576                 // The "sign" is two parentheses, so no space here either.
5577                 return;
5578             case 1:  // Space between currency-and-sign or currency and value.
5579                 if (!symbol_contains_sep) {
5580                     // We insert the space into the symbol instead of
5581                     // setting pat.field[2]=space so that when
5582                     // showbase is not set, the space goes away too.
5583                     __curr_symbol_.insert(0, 1, space_char);
5584                 }
5585                 return;
5586             default:
5587                 break;
5588             }
5589             break;
5590         case 1:  // The sign string precedes the quantity and currency symbol.
5591             pat.field[0] = sign;
5592             pat.field[3] = symbol;
5593             switch (sep_by_space)
5594             {
5595             case 0:  // No space separates the currency symbol and value.
5596                 pat.field[1] = value;
5597                 pat.field[2] = none;
5598                 return;
5599             case 1:  // Space between currency-and-sign or currency and value.
5600                 pat.field[1] = value;
5601                 pat.field[2] = none;
5602                 if (!symbol_contains_sep) {
5603                     // We insert the space into the symbol instead of
5604                     // setting pat.field[2]=space so that when
5605                     // showbase is not set, the space goes away too.
5606                     __curr_symbol_.insert(0, 1, space_char);
5607                 }
5608                 return;
5609             case 2:  // Space between sign and currency or value.
5610                 pat.field[1] = space;
5611                 pat.field[2] = value;
5612                 if (symbol_contains_sep) {
5613                     // Remove the separator from the symbol, since it
5614                     // has already appeared after the sign.
5615                     __curr_symbol_.erase(__curr_symbol_.begin());
5616                 }
5617                 return;
5618             default:
5619                 break;
5620             }
5621             break;
5622         case 2:  // The sign string succeeds the quantity and currency symbol.
5623             pat.field[0] = value;
5624             pat.field[3] = sign;
5625             switch (sep_by_space)
5626             {
5627             case 0:  // No space separates the currency symbol and value.
5628                 pat.field[1] = none;
5629                 pat.field[2] = symbol;
5630                 return;
5631             case 1:  // Space between currency-and-sign or currency and value.
5632                 if (!symbol_contains_sep) {
5633                     // We insert the space into the symbol instead of
5634                     // setting pat.field[1]=space so that when
5635                     // showbase is not set, the space goes away too.
5636                     __curr_symbol_.insert(0, 1, space_char);
5637                 }
5638                 pat.field[1] = none;
5639                 pat.field[2] = symbol;
5640                 return;
5641             case 2:  // Space between sign and currency or value.
5642                 pat.field[1] = symbol;
5643                 pat.field[2] = space;
5644                 if (symbol_contains_sep) {
5645                     // Remove the separator from the symbol, since it
5646                     // should not be removed if showbase is absent.
5647                     __curr_symbol_.erase(__curr_symbol_.begin());
5648                 }
5649                 return;
5650             default:
5651                 break;
5652             }
5653             break;
5654         case 3:  // The sign string immediately precedes the currency symbol.
5655             pat.field[0] = value;
5656             pat.field[3] = symbol;
5657             switch (sep_by_space)
5658             {
5659             case 0:  // No space separates the currency symbol and value.
5660                 pat.field[1] = none;
5661                 pat.field[2] = sign;
5662                 return;
5663             case 1:  // Space between currency-and-sign or currency and value.
5664                 pat.field[1] = space;
5665                 pat.field[2] = sign;
5666                 if (symbol_contains_sep) {
5667                     // Remove the separator from the symbol, since it
5668                     // has already appeared before the sign.
5669                     __curr_symbol_.erase(__curr_symbol_.begin());
5670                 }
5671                 return;
5672             case 2:  // Space between sign and currency or value.
5673                 pat.field[1] = sign;
5674                 pat.field[2] = none;
5675                 if (!symbol_contains_sep) {
5676                     // We insert the space into the symbol instead of
5677                     // setting pat.field[2]=space so that when
5678                     // showbase is not set, the space goes away too.
5679                     __curr_symbol_.insert(0, 1, space_char);
5680                 }
5681                 return;
5682             default:
5683                 break;
5684             }
5685             break;
5686         case 4:  // The sign string immediately succeeds the currency symbol.
5687             pat.field[0] = value;
5688             pat.field[3] = sign;
5689             switch (sep_by_space)
5690             {
5691             case 0:  // No space separates the currency symbol and value.
5692                 pat.field[1] = none;
5693                 pat.field[2] = symbol;
5694                 return;
5695             case 1:  // Space between currency-and-sign or currency and value.
5696                 pat.field[1] = none;
5697                 pat.field[2] = symbol;
5698                 if (!symbol_contains_sep) {
5699                     // We insert the space into the symbol instead of
5700                     // setting pat.field[1]=space so that when
5701                     // showbase is not set, the space goes away too.
5702                     __curr_symbol_.insert(0, 1, space_char);
5703                 }
5704                 return;
5705             case 2:  // Space between sign and currency or value.
5706                 pat.field[1] = symbol;
5707                 pat.field[2] = space;
5708                 if (symbol_contains_sep) {
5709                     // Remove the separator from the symbol, since it
5710                     // should not disappear when showbase is absent.
5711                     __curr_symbol_.erase(__curr_symbol_.begin());
5712                 }
5713                 return;
5714             default:
5715                 break;
5716             }
5717             break;
5718         default:
5719             break;
5720         }
5721         break;
5722     case 1:  // curr_symbol before value
5723         switch (sign_posn)
5724         {
5725         case 0:  // Parentheses surround the quantity and currency symbol.
5726             pat.field[0] = sign;
5727             pat.field[1] = symbol;
5728             pat.field[2] = none;  // Any space appears in the symbol.
5729             pat.field[3] = value;
5730             switch (sep_by_space)
5731             {
5732             case 0:  // No space separates the currency symbol and value.
5733                 // This case may have changed between C99 and C11;
5734                 // assume the currency symbol matches the intention.
5735             case 2:  // Space between sign and currency or value.
5736                 // The "sign" is two parentheses, so no space here either.
5737                 return;
5738             case 1:  // Space between currency-and-sign or currency and value.
5739                 if (!symbol_contains_sep) {
5740                     // We insert the space into the symbol instead of
5741                     // setting pat.field[2]=space so that when
5742                     // showbase is not set, the space goes away too.
5743                     __curr_symbol_.insert(0, 1, space_char);
5744                 }
5745                 return;
5746             default:
5747                 break;
5748             }
5749             break;
5750         case 1:  // The sign string precedes the quantity and currency symbol.
5751             pat.field[0] = sign;
5752             pat.field[3] = value;
5753             switch (sep_by_space)
5754             {
5755             case 0:  // No space separates the currency symbol and value.
5756                 pat.field[1] = symbol;
5757                 pat.field[2] = none;
5758                 return;
5759             case 1:  // Space between currency-and-sign or currency and value.
5760                 pat.field[1] = symbol;
5761                 pat.field[2] = none;
5762                 if (!symbol_contains_sep) {
5763                     // We insert the space into the symbol instead of
5764                     // setting pat.field[2]=space so that when
5765                     // showbase is not set, the space goes away too.
5766                     __curr_symbol_.push_back(space_char);
5767                 }
5768                 return;
5769             case 2:  // Space between sign and currency or value.
5770                 pat.field[1] = space;
5771                 pat.field[2] = symbol;
5772                 if (symbol_contains_sep) {
5773                     // Remove the separator from the symbol, since it
5774                     // has already appeared after the sign.
5775                     __curr_symbol_.pop_back();
5776                 }
5777                 return;
5778             default:
5779                 break;
5780             }
5781             break;
5782         case 2:  // The sign string succeeds the quantity and currency symbol.
5783             pat.field[0] = symbol;
5784             pat.field[3] = sign;
5785             switch (sep_by_space)
5786             {
5787             case 0:  // No space separates the currency symbol and value.
5788                 pat.field[1] = none;
5789                 pat.field[2] = value;
5790                 return;
5791             case 1:  // Space between currency-and-sign or currency and value.
5792                 pat.field[1] = none;
5793                 pat.field[2] = value;
5794                 if (!symbol_contains_sep) {
5795                     // We insert the space into the symbol instead of
5796                     // setting pat.field[1]=space so that when
5797                     // showbase is not set, the space goes away too.
5798                     __curr_symbol_.push_back(space_char);
5799                 }
5800                 return;
5801             case 2:  // Space between sign and currency or value.
5802                 pat.field[1] = value;
5803                 pat.field[2] = space;
5804                 if (symbol_contains_sep) {
5805                     // Remove the separator from the symbol, since it
5806                     // will appear before the sign.
5807                     __curr_symbol_.pop_back();
5808                 }
5809                 return;
5810             default:
5811                 break;
5812             }
5813             break;
5814         case 3:  // The sign string immediately precedes the currency symbol.
5815             pat.field[0] = sign;
5816             pat.field[3] = value;
5817             switch (sep_by_space)
5818             {
5819             case 0:  // No space separates the currency symbol and value.
5820                 pat.field[1] = symbol;
5821                 pat.field[2] = none;
5822                 return;
5823             case 1:  // Space between currency-and-sign or currency and value.
5824                 pat.field[1] = symbol;
5825                 pat.field[2] = none;
5826                 if (!symbol_contains_sep) {
5827                     // We insert the space into the symbol instead of
5828                     // setting pat.field[2]=space so that when
5829                     // showbase is not set, the space goes away too.
5830                     __curr_symbol_.push_back(space_char);
5831                 }
5832                 return;
5833             case 2:  // Space between sign and currency or value.
5834                 pat.field[1] = space;
5835                 pat.field[2] = symbol;
5836                 if (symbol_contains_sep) {
5837                     // Remove the separator from the symbol, since it
5838                     // has already appeared after the sign.
5839                     __curr_symbol_.pop_back();
5840                 }
5841                 return;
5842             default:
5843                 break;
5844             }
5845             break;
5846         case 4:  // The sign string immediately succeeds the currency symbol.
5847             pat.field[0] = symbol;
5848             pat.field[3] = value;
5849             switch (sep_by_space)
5850             {
5851             case 0:  // No space separates the currency symbol and value.
5852                 pat.field[1] = sign;
5853                 pat.field[2] = none;
5854                 return;
5855             case 1:  // Space between currency-and-sign or currency and value.
5856                 pat.field[1] = sign;
5857                 pat.field[2] = space;
5858                 if (symbol_contains_sep) {
5859                     // Remove the separator from the symbol, since it
5860                     // should not disappear when showbase is absent.
5861                     __curr_symbol_.pop_back();
5862                 }
5863                 return;
5864             case 2:  // Space between sign and currency or value.
5865                 pat.field[1] = none;
5866                 pat.field[2] = sign;
5867                 if (!symbol_contains_sep) {
5868                     // We insert the space into the symbol instead of
5869                     // setting pat.field[1]=space so that when
5870                     // showbase is not set, the space goes away too.
5871                     __curr_symbol_.push_back(space_char);
5872                 }
5873                 return;
5874            default:
5875                 break;
5876             }
5877             break;
5878         default:
5879             break;
5880         }
5881         break;
5882     default:
5883         break;
5884     }
5885     pat.field[0] = symbol;
5886     pat.field[1] = sign;
5887     pat.field[2] = none;
5888     pat.field[3] = value;
5889 }
5890 
5891 template<>
5892 void
5893 moneypunct_byname<char, false>::init(const char* nm)
5894 {
5895     typedef moneypunct<char, false> base;
5896     __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5897 #ifndef _LIBCPP_NO_EXCEPTIONS
5898     if (loc == nullptr)
5899         throw runtime_error("moneypunct_byname"
5900                             " failed to construct for " + string(nm));
5901 #endif  // _LIBCPP_NO_EXCEPTIONS
5902 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5903     lconv* lc = localeconv_l(loc.get());
5904 #else
5905     lconv* lc = __localeconv_l(loc.get());
5906 #endif
5907     if (*lc->mon_decimal_point)
5908         __decimal_point_ = *lc->mon_decimal_point;
5909     else
5910         __decimal_point_ = base::do_decimal_point();
5911     if (*lc->mon_thousands_sep)
5912         __thousands_sep_ = *lc->mon_thousands_sep;
5913     else
5914         __thousands_sep_ = base::do_thousands_sep();
5915     __grouping_ = lc->mon_grouping;
5916     __curr_symbol_ = lc->currency_symbol;
5917     if (lc->frac_digits != CHAR_MAX)
5918         __frac_digits_ = lc->frac_digits;
5919     else
5920         __frac_digits_ = base::do_frac_digits();
5921     if (lc->p_sign_posn == 0)
5922         __positive_sign_ = "()";
5923     else
5924         __positive_sign_ = lc->positive_sign;
5925     if (lc->n_sign_posn == 0)
5926         __negative_sign_ = "()";
5927     else
5928         __negative_sign_ = lc->negative_sign;
5929     // Assume the positive and negative formats will want spaces in
5930     // the same places in curr_symbol since there's no way to
5931     // represent anything else.
5932     string_type __dummy_curr_symbol = __curr_symbol_;
5933     __init_pat(__pos_format_, __dummy_curr_symbol, false,
5934                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5935     __init_pat(__neg_format_, __curr_symbol_, false,
5936                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
5937 }
5938 
5939 template<>
5940 void
5941 moneypunct_byname<char, true>::init(const char* nm)
5942 {
5943     typedef moneypunct<char, true> base;
5944     __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
5945 #ifndef _LIBCPP_NO_EXCEPTIONS
5946     if (loc == nullptr)
5947         throw runtime_error("moneypunct_byname"
5948                             " failed to construct for " + string(nm));
5949 #endif  // _LIBCPP_NO_EXCEPTIONS
5950 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
5951     lconv* lc = localeconv_l(loc.get());
5952 #else
5953     lconv* lc = __localeconv_l(loc.get());
5954 #endif
5955     if (*lc->mon_decimal_point)
5956         __decimal_point_ = *lc->mon_decimal_point;
5957     else
5958         __decimal_point_ = base::do_decimal_point();
5959     if (*lc->mon_thousands_sep)
5960         __thousands_sep_ = *lc->mon_thousands_sep;
5961     else
5962         __thousands_sep_ = base::do_thousands_sep();
5963     __grouping_ = lc->mon_grouping;
5964     __curr_symbol_ = lc->int_curr_symbol;
5965     if (lc->int_frac_digits != CHAR_MAX)
5966         __frac_digits_ = lc->int_frac_digits;
5967     else
5968         __frac_digits_ = base::do_frac_digits();
5969 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5970     if (lc->p_sign_posn == 0)
5971 #else // _LIBCPP_MSVCRT
5972     if (lc->int_p_sign_posn == 0)
5973 #endif // !_LIBCPP_MSVCRT
5974         __positive_sign_ = "()";
5975     else
5976         __positive_sign_ = lc->positive_sign;
5977 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5978     if(lc->n_sign_posn == 0)
5979 #else // _LIBCPP_MSVCRT
5980     if (lc->int_n_sign_posn == 0)
5981 #endif // !_LIBCPP_MSVCRT
5982         __negative_sign_ = "()";
5983     else
5984         __negative_sign_ = lc->negative_sign;
5985     // Assume the positive and negative formats will want spaces in
5986     // the same places in curr_symbol since there's no way to
5987     // represent anything else.
5988     string_type __dummy_curr_symbol = __curr_symbol_;
5989 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5990     __init_pat(__pos_format_, __dummy_curr_symbol, true,
5991                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5992     __init_pat(__neg_format_, __curr_symbol_, true,
5993                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
5994 #else // _LIBCPP_MSVCRT
5995     __init_pat(__pos_format_, __dummy_curr_symbol, true,
5996                lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5997                lc->int_p_sign_posn, ' ');
5998     __init_pat(__neg_format_, __curr_symbol_, true,
5999                lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6000                lc->int_n_sign_posn, ' ');
6001 #endif // !_LIBCPP_MSVCRT
6002 }
6003 
6004 template<>
6005 void
6006 moneypunct_byname<wchar_t, false>::init(const char* nm)
6007 {
6008     typedef moneypunct<wchar_t, false> base;
6009     __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
6010 #ifndef _LIBCPP_NO_EXCEPTIONS
6011     if (loc == nullptr)
6012         throw runtime_error("moneypunct_byname"
6013                             " failed to construct for " + string(nm));
6014 #endif  // _LIBCPP_NO_EXCEPTIONS
6015 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6016     lconv* lc = localeconv_l(loc.get());
6017 #else
6018     lconv* lc = __localeconv_l(loc.get());
6019 #endif
6020     if (*lc->mon_decimal_point)
6021         __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6022     else
6023         __decimal_point_ = base::do_decimal_point();
6024     if (*lc->mon_thousands_sep)
6025         __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6026     else
6027         __thousands_sep_ = base::do_thousands_sep();
6028     __grouping_ = lc->mon_grouping;
6029     wchar_t wbuf[100];
6030     mbstate_t mb = {0};
6031     const char* bb = lc->currency_symbol;
6032 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6033     size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6034 #else
6035     size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6036 #endif
6037     if (j == size_t(-1))
6038         __throw_runtime_error("locale not supported");
6039     wchar_t* wbe = wbuf + j;
6040     __curr_symbol_.assign(wbuf, wbe);
6041     if (lc->frac_digits != CHAR_MAX)
6042         __frac_digits_ = lc->frac_digits;
6043     else
6044         __frac_digits_ = base::do_frac_digits();
6045     if (lc->p_sign_posn == 0)
6046         __positive_sign_ = L"()";
6047     else
6048     {
6049         mb = mbstate_t();
6050         bb = lc->positive_sign;
6051 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6052         j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6053 #else
6054         j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6055 #endif
6056         if (j == size_t(-1))
6057             __throw_runtime_error("locale not supported");
6058         wbe = wbuf + j;
6059         __positive_sign_.assign(wbuf, wbe);
6060     }
6061     if (lc->n_sign_posn == 0)
6062         __negative_sign_ = L"()";
6063     else
6064     {
6065         mb = mbstate_t();
6066         bb = lc->negative_sign;
6067 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6068         j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6069 #else
6070         j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6071 #endif
6072         if (j == size_t(-1))
6073             __throw_runtime_error("locale not supported");
6074         wbe = wbuf + j;
6075         __negative_sign_.assign(wbuf, wbe);
6076     }
6077     // Assume the positive and negative formats will want spaces in
6078     // the same places in curr_symbol since there's no way to
6079     // represent anything else.
6080     string_type __dummy_curr_symbol = __curr_symbol_;
6081     __init_pat(__pos_format_, __dummy_curr_symbol, false,
6082                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6083     __init_pat(__neg_format_, __curr_symbol_, false,
6084                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6085 }
6086 
6087 template<>
6088 void
6089 moneypunct_byname<wchar_t, true>::init(const char* nm)
6090 {
6091     typedef moneypunct<wchar_t, true> base;
6092     __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
6093 #ifndef _LIBCPP_NO_EXCEPTIONS
6094     if (loc == nullptr)
6095         throw runtime_error("moneypunct_byname"
6096                             " failed to construct for " + string(nm));
6097 #endif  // _LIBCPP_NO_EXCEPTIONS
6098 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6099     lconv* lc = localeconv_l(loc.get());
6100 #else
6101     lconv* lc = __localeconv_l(loc.get());
6102 #endif
6103     if (*lc->mon_decimal_point)
6104         __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6105     else
6106         __decimal_point_ = base::do_decimal_point();
6107     if (*lc->mon_thousands_sep)
6108         __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6109     else
6110         __thousands_sep_ = base::do_thousands_sep();
6111     __grouping_ = lc->mon_grouping;
6112     wchar_t wbuf[100];
6113     mbstate_t mb = {0};
6114     const char* bb = lc->int_curr_symbol;
6115 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6116     size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6117 #else
6118     size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6119 #endif
6120     if (j == size_t(-1))
6121         __throw_runtime_error("locale not supported");
6122     wchar_t* wbe = wbuf + j;
6123     __curr_symbol_.assign(wbuf, wbe);
6124     if (lc->int_frac_digits != CHAR_MAX)
6125         __frac_digits_ = lc->int_frac_digits;
6126     else
6127         __frac_digits_ = base::do_frac_digits();
6128 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6129     if (lc->p_sign_posn == 0)
6130 #else // _LIBCPP_MSVCRT
6131     if (lc->int_p_sign_posn == 0)
6132 #endif // !_LIBCPP_MSVCRT
6133         __positive_sign_ = L"()";
6134     else
6135     {
6136         mb = mbstate_t();
6137         bb = lc->positive_sign;
6138 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6139         j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6140 #else
6141         j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6142 #endif
6143         if (j == size_t(-1))
6144             __throw_runtime_error("locale not supported");
6145         wbe = wbuf + j;
6146         __positive_sign_.assign(wbuf, wbe);
6147     }
6148 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6149     if (lc->n_sign_posn == 0)
6150 #else // _LIBCPP_MSVCRT
6151     if (lc->int_n_sign_posn == 0)
6152 #endif // !_LIBCPP_MSVCRT
6153         __negative_sign_ = L"()";
6154     else
6155     {
6156         mb = mbstate_t();
6157         bb = lc->negative_sign;
6158 #ifdef _LIBCPP_LOCALE__L_EXTENSIONS
6159         j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6160 #else
6161         j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6162 #endif
6163         if (j == size_t(-1))
6164             __throw_runtime_error("locale not supported");
6165         wbe = wbuf + j;
6166         __negative_sign_.assign(wbuf, wbe);
6167     }
6168     // Assume the positive and negative formats will want spaces in
6169     // the same places in curr_symbol since there's no way to
6170     // represent anything else.
6171     string_type __dummy_curr_symbol = __curr_symbol_;
6172 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6173     __init_pat(__pos_format_, __dummy_curr_symbol, true,
6174                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6175     __init_pat(__neg_format_, __curr_symbol_, true,
6176                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6177 #else // _LIBCPP_MSVCRT
6178     __init_pat(__pos_format_, __dummy_curr_symbol, true,
6179                lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6180                lc->int_p_sign_posn, L' ');
6181     __init_pat(__neg_format_, __curr_symbol_, true,
6182                lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6183                lc->int_n_sign_posn, L' ');
6184 #endif // !_LIBCPP_MSVCRT
6185 }
6186 
6187 void __do_nothing(void*) {}
6188 
6189 void __throw_runtime_error(const char* msg)
6190 {
6191 #ifndef _LIBCPP_NO_EXCEPTIONS
6192     throw runtime_error(msg);
6193 #else
6194     (void)msg;
6195 #endif
6196 }
6197 
6198 template class collate<char>;
6199 template class collate<wchar_t>;
6200 
6201 template class num_get<char>;
6202 template class num_get<wchar_t>;
6203 
6204 template struct __num_get<char>;
6205 template struct __num_get<wchar_t>;
6206 
6207 template class num_put<char>;
6208 template class num_put<wchar_t>;
6209 
6210 template struct __num_put<char>;
6211 template struct __num_put<wchar_t>;
6212 
6213 template class time_get<char>;
6214 template class time_get<wchar_t>;
6215 
6216 template class time_get_byname<char>;
6217 template class time_get_byname<wchar_t>;
6218 
6219 template class time_put<char>;
6220 template class time_put<wchar_t>;
6221 
6222 template class time_put_byname<char>;
6223 template class time_put_byname<wchar_t>;
6224 
6225 template class moneypunct<char, false>;
6226 template class moneypunct<char, true>;
6227 template class moneypunct<wchar_t, false>;
6228 template class moneypunct<wchar_t, true>;
6229 
6230 template class moneypunct_byname<char, false>;
6231 template class moneypunct_byname<char, true>;
6232 template class moneypunct_byname<wchar_t, false>;
6233 template class moneypunct_byname<wchar_t, true>;
6234 
6235 template class money_get<char>;
6236 template class money_get<wchar_t>;
6237 
6238 template class __money_get<char>;
6239 template class __money_get<wchar_t>;
6240 
6241 template class money_put<char>;
6242 template class money_put<wchar_t>;
6243 
6244 template class __money_put<char>;
6245 template class __money_put<wchar_t>;
6246 
6247 template class messages<char>;
6248 template class messages<wchar_t>;
6249 
6250 template class messages_byname<char>;
6251 template class messages_byname<wchar_t>;
6252 
6253 template class codecvt_byname<char, char, mbstate_t>;
6254 template class codecvt_byname<wchar_t, char, mbstate_t>;
6255 template class codecvt_byname<char16_t, char, mbstate_t>;
6256 template class codecvt_byname<char32_t, char, mbstate_t>;
6257 
6258 template class __vector_base_common<true>;
6259 
6260 _LIBCPP_END_NAMESPACE_STD
6261