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