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