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