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