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