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