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