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