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