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