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