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