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