1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// On Solaris, we need to define something to make the C99 parts of localeconv
10// visible.
11#ifdef __sun__
12#define _LCONV_C99
13#endif
14
15#include <__utility/unreachable.h>
16#include <algorithm>
17#include <clocale>
18#include <codecvt>
19#include <cstdio>
20#include <cstdlib>
21#include <cstring>
22#include <locale>
23#include <string>
24#include <type_traits>
25#include <typeinfo>
26#include <vector>
27
28#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
29#   include <cwctype>
30#endif
31
32#if defined(_AIX)
33#   include <sys/localedef.h> // for __lc_ctype_ptr
34#endif
35
36#if defined(_LIBCPP_MSVCRT)
37#   define _CTYPE_DISABLE_MACROS
38#endif
39
40#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
41#   include "__support/win32/locale_win32.h"
42#elif !defined(__BIONIC__) && !defined(__NuttX__)
43#   include <langinfo.h>
44#endif
45
46#include "include/atomic_support.h"
47#include "include/sso_allocator.h"
48
49// On Linux, wint_t and wchar_t have different signed-ness, and this causes
50// lots of noise in the build log, but no bugs that I know of.
51_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion")
52
53_LIBCPP_PUSH_MACROS
54#include <__undef_macros>
55
56_LIBCPP_BEGIN_NAMESPACE_STD
57
58struct __libcpp_unique_locale {
59  __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
60
61  ~__libcpp_unique_locale() {
62    if (__loc_)
63      freelocale(__loc_);
64  }
65
66  explicit operator bool() const { return __loc_; }
67
68  locale_t& get() { return __loc_; }
69
70  locale_t __loc_;
71private:
72  __libcpp_unique_locale(__libcpp_unique_locale const&);
73  __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
74};
75
76#ifdef __cloc_defined
77locale_t __cloc() {
78  // In theory this could create a race condition. In practice
79  // the race condition is non-fatal since it will just create
80  // a little resource leak. Better approach would be appreciated.
81  static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
82  return result;
83}
84#endif // __cloc_defined
85
86namespace {
87
88struct release
89{
90    void operator()(locale::facet* p) {p->__release_shared();}
91};
92
93template <class T, class ...Args>
94T& make(Args ...args)
95{
96    static typename aligned_storage<sizeof(T)>::type buf;
97    auto *obj = ::new (&buf) T(args...);
98    return *obj;
99}
100
101template <typename T, size_t N>
102inline
103_LIBCPP_CONSTEXPR
104size_t
105countof(const T (&)[N])
106{
107    return N;
108}
109
110template <typename T>
111inline
112_LIBCPP_CONSTEXPR
113size_t
114countof(const T * const begin, const T * const end)
115{
116    return static_cast<size_t>(end - begin);
117}
118
119_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
120{
121#ifndef _LIBCPP_NO_EXCEPTIONS
122    throw runtime_error(msg);
123#else
124    (void)msg;
125    _VSTD::abort();
126#endif
127}
128
129}
130
131const locale::category locale::none;
132const locale::category locale::collate;
133const locale::category locale::ctype;
134const locale::category locale::monetary;
135const locale::category locale::numeric;
136const locale::category locale::time;
137const locale::category locale::messages;
138const locale::category locale::all;
139
140class _LIBCPP_HIDDEN locale::__imp
141    : public facet
142{
143    enum {N = 30};
144    vector<facet*, __sso_allocator<facet*, N> > facets_;
145    string         name_;
146public:
147    explicit __imp(size_t refs = 0);
148    explicit __imp(const string& name, size_t refs = 0);
149    __imp(const __imp&);
150    __imp(const __imp&, const string&, locale::category c);
151    __imp(const __imp& other, const __imp& one, locale::category c);
152    __imp(const __imp&, facet* f, long id);
153    ~__imp();
154
155    const string& name() const {return name_;}
156    bool has_facet(long id) const
157        {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
158    const locale::facet* use_facet(long id) const;
159
160    static const locale& make_classic();
161    static       locale& make_global();
162private:
163    void install(facet* f, long id);
164    template <class F> void install(F* f) {install(f, f->id.__get());}
165    template <class F> void install_from(const __imp& other);
166};
167
168locale::__imp::__imp(size_t refs)
169    : facet(refs),
170      facets_(N),
171      name_("C")
172{
173    facets_.clear();
174    install(&make<_VSTD::collate<char> >(1u));
175#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
176    install(&make<_VSTD::collate<wchar_t> >(1u));
177#endif
178    install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
179#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
180    install(&make<_VSTD::ctype<wchar_t> >(1u));
181#endif
182    install(&make<codecvt<char, char, mbstate_t> >(1u));
183#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
184    install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
185#endif
186_LIBCPP_SUPPRESS_DEPRECATED_PUSH
187    install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
188    install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
189_LIBCPP_SUPPRESS_DEPRECATED_POP
190#ifndef _LIBCPP_HAS_NO_CHAR8_T
191    install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
192    install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
193#endif
194    install(&make<numpunct<char> >(1u));
195#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
196    install(&make<numpunct<wchar_t> >(1u));
197#endif
198    install(&make<num_get<char> >(1u));
199#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
200    install(&make<num_get<wchar_t> >(1u));
201#endif
202    install(&make<num_put<char> >(1u));
203#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
204    install(&make<num_put<wchar_t> >(1u));
205#endif
206    install(&make<moneypunct<char, false> >(1u));
207    install(&make<moneypunct<char, true> >(1u));
208#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
209    install(&make<moneypunct<wchar_t, false> >(1u));
210    install(&make<moneypunct<wchar_t, true> >(1u));
211#endif
212    install(&make<money_get<char> >(1u));
213#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
214    install(&make<money_get<wchar_t> >(1u));
215#endif
216    install(&make<money_put<char> >(1u));
217#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
218    install(&make<money_put<wchar_t> >(1u));
219#endif
220    install(&make<time_get<char> >(1u));
221#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
222    install(&make<time_get<wchar_t> >(1u));
223#endif
224    install(&make<time_put<char> >(1u));
225#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
226    install(&make<time_put<wchar_t> >(1u));
227#endif
228    install(&make<_VSTD::messages<char> >(1u));
229#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
230    install(&make<_VSTD::messages<wchar_t> >(1u));
231#endif
232}
233
234locale::__imp::__imp(const string& name, size_t refs)
235    : facet(refs),
236      facets_(N),
237      name_(name)
238{
239#ifndef _LIBCPP_NO_EXCEPTIONS
240    try
241    {
242#endif // _LIBCPP_NO_EXCEPTIONS
243        facets_ = locale::classic().__locale_->facets_;
244        for (unsigned i = 0; i < facets_.size(); ++i)
245            if (facets_[i])
246                facets_[i]->__add_shared();
247        install(new collate_byname<char>(name_));
248#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
249        install(new collate_byname<wchar_t>(name_));
250#endif
251        install(new ctype_byname<char>(name_));
252#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
253        install(new ctype_byname<wchar_t>(name_));
254#endif
255        install(new codecvt_byname<char, char, mbstate_t>(name_));
256#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
257        install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
258#endif
259_LIBCPP_SUPPRESS_DEPRECATED_PUSH
260        install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
261        install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
262_LIBCPP_SUPPRESS_DEPRECATED_POP
263#ifndef _LIBCPP_HAS_NO_CHAR8_T
264        install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
265        install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
266#endif
267        install(new numpunct_byname<char>(name_));
268#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
269        install(new numpunct_byname<wchar_t>(name_));
270#endif
271        install(new moneypunct_byname<char, false>(name_));
272        install(new moneypunct_byname<char, true>(name_));
273#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
274        install(new moneypunct_byname<wchar_t, false>(name_));
275        install(new moneypunct_byname<wchar_t, true>(name_));
276#endif
277        install(new time_get_byname<char>(name_));
278#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
279        install(new time_get_byname<wchar_t>(name_));
280#endif
281        install(new time_put_byname<char>(name_));
282#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
283        install(new time_put_byname<wchar_t>(name_));
284#endif
285        install(new messages_byname<char>(name_));
286#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
287        install(new messages_byname<wchar_t>(name_));
288#endif
289#ifndef _LIBCPP_NO_EXCEPTIONS
290    }
291    catch (...)
292    {
293        for (unsigned i = 0; i < facets_.size(); ++i)
294            if (facets_[i])
295                facets_[i]->__release_shared();
296        throw;
297    }
298#endif // _LIBCPP_NO_EXCEPTIONS
299}
300
301locale::__imp::__imp(const __imp& other)
302    : facets_(max<size_t>(N, other.facets_.size())),
303      name_(other.name_)
304{
305    facets_ = other.facets_;
306    for (unsigned i = 0; i < facets_.size(); ++i)
307        if (facets_[i])
308            facets_[i]->__add_shared();
309}
310
311locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
312    : facets_(N),
313      name_("*")
314{
315    facets_ = other.facets_;
316    for (unsigned i = 0; i < facets_.size(); ++i)
317        if (facets_[i])
318            facets_[i]->__add_shared();
319#ifndef _LIBCPP_NO_EXCEPTIONS
320    try
321    {
322#endif // _LIBCPP_NO_EXCEPTIONS
323        if (c & locale::collate)
324        {
325            install(new collate_byname<char>(name));
326#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
327            install(new collate_byname<wchar_t>(name));
328#endif
329        }
330        if (c & locale::ctype)
331        {
332            install(new ctype_byname<char>(name));
333#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
334            install(new ctype_byname<wchar_t>(name));
335#endif
336            install(new codecvt_byname<char, char, mbstate_t>(name));
337#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
338            install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
339#endif
340_LIBCPP_SUPPRESS_DEPRECATED_PUSH
341            install(new codecvt_byname<char16_t, char, mbstate_t>(name));
342            install(new codecvt_byname<char32_t, char, mbstate_t>(name));
343_LIBCPP_SUPPRESS_DEPRECATED_POP
344#ifndef _LIBCPP_HAS_NO_CHAR8_T
345            install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
346            install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
347#endif
348        }
349        if (c & locale::monetary)
350        {
351            install(new moneypunct_byname<char, false>(name));
352            install(new moneypunct_byname<char, true>(name));
353#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
354            install(new moneypunct_byname<wchar_t, false>(name));
355            install(new moneypunct_byname<wchar_t, true>(name));
356#endif
357        }
358        if (c & locale::numeric)
359        {
360            install(new numpunct_byname<char>(name));
361#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
362            install(new numpunct_byname<wchar_t>(name));
363#endif
364        }
365        if (c & locale::time)
366        {
367            install(new time_get_byname<char>(name));
368#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
369            install(new time_get_byname<wchar_t>(name));
370#endif
371            install(new time_put_byname<char>(name));
372#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
373            install(new time_put_byname<wchar_t>(name));
374#endif
375        }
376        if (c & locale::messages)
377        {
378            install(new messages_byname<char>(name));
379#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
380            install(new messages_byname<wchar_t>(name));
381#endif
382        }
383#ifndef _LIBCPP_NO_EXCEPTIONS
384    }
385    catch (...)
386    {
387        for (unsigned i = 0; i < facets_.size(); ++i)
388            if (facets_[i])
389                facets_[i]->__release_shared();
390        throw;
391    }
392#endif // _LIBCPP_NO_EXCEPTIONS
393}
394
395template<class F>
396inline
397void
398locale::__imp::install_from(const locale::__imp& one)
399{
400    long id = F::id.__get();
401    install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
402}
403
404locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
405    : facets_(N),
406      name_("*")
407{
408    facets_ = other.facets_;
409    for (unsigned i = 0; i < facets_.size(); ++i)
410        if (facets_[i])
411            facets_[i]->__add_shared();
412#ifndef _LIBCPP_NO_EXCEPTIONS
413    try
414    {
415#endif // _LIBCPP_NO_EXCEPTIONS
416        if (c & locale::collate)
417        {
418            install_from<_VSTD::collate<char> >(one);
419#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
420            install_from<_VSTD::collate<wchar_t> >(one);
421#endif
422        }
423        if (c & locale::ctype)
424        {
425            install_from<_VSTD::ctype<char> >(one);
426#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
427            install_from<_VSTD::ctype<wchar_t> >(one);
428#endif
429            install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
430_LIBCPP_SUPPRESS_DEPRECATED_PUSH
431            install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
432            install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
433_LIBCPP_SUPPRESS_DEPRECATED_POP
434#ifndef _LIBCPP_HAS_NO_CHAR8_T
435            install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
436            install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
437#endif
438#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
439            install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
440#endif
441        }
442        if (c & locale::monetary)
443        {
444            install_from<moneypunct<char, false> >(one);
445            install_from<moneypunct<char, true> >(one);
446#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
447            install_from<moneypunct<wchar_t, false> >(one);
448            install_from<moneypunct<wchar_t, true> >(one);
449#endif
450            install_from<money_get<char> >(one);
451#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
452            install_from<money_get<wchar_t> >(one);
453#endif
454            install_from<money_put<char> >(one);
455#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
456            install_from<money_put<wchar_t> >(one);
457#endif
458        }
459        if (c & locale::numeric)
460        {
461            install_from<numpunct<char> >(one);
462#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
463            install_from<numpunct<wchar_t> >(one);
464#endif
465            install_from<num_get<char> >(one);
466#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
467            install_from<num_get<wchar_t> >(one);
468#endif
469            install_from<num_put<char> >(one);
470#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
471            install_from<num_put<wchar_t> >(one);
472#endif
473        }
474        if (c & locale::time)
475        {
476            install_from<time_get<char> >(one);
477#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
478            install_from<time_get<wchar_t> >(one);
479#endif
480            install_from<time_put<char> >(one);
481#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
482            install_from<time_put<wchar_t> >(one);
483#endif
484        }
485        if (c & locale::messages)
486        {
487            install_from<_VSTD::messages<char> >(one);
488#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
489            install_from<_VSTD::messages<wchar_t> >(one);
490#endif
491        }
492#ifndef _LIBCPP_NO_EXCEPTIONS
493    }
494    catch (...)
495    {
496        for (unsigned i = 0; i < facets_.size(); ++i)
497            if (facets_[i])
498                facets_[i]->__release_shared();
499        throw;
500    }
501#endif // _LIBCPP_NO_EXCEPTIONS
502}
503
504locale::__imp::__imp(const __imp& other, facet* f, long id)
505    : facets_(max<size_t>(N, other.facets_.size()+1)),
506      name_("*")
507{
508    f->__add_shared();
509    unique_ptr<facet, release> hold(f);
510    facets_ = other.facets_;
511    for (unsigned i = 0; i < other.facets_.size(); ++i)
512        if (facets_[i])
513            facets_[i]->__add_shared();
514    install(hold.get(), id);
515}
516
517locale::__imp::~__imp()
518{
519    for (unsigned i = 0; i < facets_.size(); ++i)
520        if (facets_[i])
521            facets_[i]->__release_shared();
522}
523
524void
525locale::__imp::install(facet* f, long id)
526{
527    f->__add_shared();
528    unique_ptr<facet, release> hold(f);
529    if (static_cast<size_t>(id) >= facets_.size())
530        facets_.resize(static_cast<size_t>(id+1));
531    if (facets_[static_cast<size_t>(id)])
532        facets_[static_cast<size_t>(id)]->__release_shared();
533    facets_[static_cast<size_t>(id)] = hold.release();
534}
535
536const locale::facet*
537locale::__imp::use_facet(long id) const
538{
539    if (!has_facet(id))
540        __throw_bad_cast();
541    return facets_[static_cast<size_t>(id)];
542}
543
544// locale
545
546const locale&
547locale::__imp::make_classic()
548{
549    // only one thread can get in here and it only gets in once
550    static aligned_storage<sizeof(locale)>::type buf;
551    locale* c = reinterpret_cast<locale*>(&buf);
552    c->__locale_ = &make<__imp>(1u);
553    return *c;
554}
555
556const locale&
557locale::classic()
558{
559    static const locale& c = __imp::make_classic();
560    return c;
561}
562
563locale&
564locale::__imp::make_global()
565{
566    // only one thread can get in here and it only gets in once
567    static aligned_storage<sizeof(locale)>::type buf;
568    auto *obj = ::new (&buf) locale(locale::classic());
569    return *obj;
570}
571
572locale&
573locale::__global()
574{
575    static locale& g = __imp::make_global();
576    return g;
577}
578
579locale::locale() noexcept
580    : __locale_(__global().__locale_)
581{
582    __locale_->__add_shared();
583}
584
585locale::locale(const locale& l) noexcept
586    : __locale_(l.__locale_)
587{
588    __locale_->__add_shared();
589}
590
591locale::~locale()
592{
593    __locale_->__release_shared();
594}
595
596const locale&
597locale::operator=(const locale& other) noexcept
598{
599    other.__locale_->__add_shared();
600    __locale_->__release_shared();
601    __locale_ = other.__locale_;
602    return *this;
603}
604
605locale::locale(const char* name)
606    : __locale_(name ? new __imp(name)
607                     : (__throw_runtime_error("locale constructed with null"), nullptr))
608{
609    __locale_->__add_shared();
610}
611
612locale::locale(const string& name)
613    : __locale_(new __imp(name))
614{
615    __locale_->__add_shared();
616}
617
618locale::locale(const locale& other, const char* name, category c)
619    : __locale_(name ? new __imp(*other.__locale_, name, c)
620                     : (__throw_runtime_error("locale constructed with null"), nullptr))
621{
622    __locale_->__add_shared();
623}
624
625locale::locale(const locale& other, const string& name, category c)
626    : __locale_(new __imp(*other.__locale_, name, c))
627{
628    __locale_->__add_shared();
629}
630
631locale::locale(const locale& other, const locale& one, category c)
632    : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
633{
634    __locale_->__add_shared();
635}
636
637string
638locale::name() const
639{
640    return __locale_->name();
641}
642
643void
644locale::__install_ctor(const locale& other, facet* f, long id)
645{
646    if (f)
647        __locale_ = new __imp(*other.__locale_, f, id);
648    else
649        __locale_ = other.__locale_;
650    __locale_->__add_shared();
651}
652
653locale
654locale::global(const locale& loc)
655{
656    locale& g = __global();
657    locale r = g;
658    g = loc;
659    if (g.name() != "*")
660        setlocale(LC_ALL, g.name().c_str());
661    return r;
662}
663
664bool
665locale::has_facet(id& x) const
666{
667    return __locale_->has_facet(x.__get());
668}
669
670const locale::facet*
671locale::use_facet(id& x) const
672{
673    return __locale_->use_facet(x.__get());
674}
675
676bool
677locale::operator==(const locale& y) const
678{
679    return (__locale_ == y.__locale_)
680        || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
681}
682
683// locale::facet
684
685locale::facet::~facet()
686{
687}
688
689void
690locale::facet::__on_zero_shared() noexcept
691{
692    delete this;
693}
694
695// locale::id
696
697int32_t locale::id::__next_id = 0;
698
699namespace
700{
701
702class __fake_bind
703{
704    locale::id* id_;
705    void (locale::id::* pmf_)();
706public:
707    __fake_bind(void (locale::id::* pmf)(), locale::id* id)
708        : id_(id), pmf_(pmf) {}
709
710    void operator()() const
711    {
712        (id_->*pmf_)();
713    }
714};
715
716}
717
718long
719locale::id::__get()
720{
721    call_once(__flag_, __fake_bind(&locale::id::__init, this));
722    return __id_ - 1;
723}
724
725void
726locale::id::__init()
727{
728    __id_ = __libcpp_atomic_add(&__next_id, 1);
729}
730
731// template <> class collate_byname<char>
732
733collate_byname<char>::collate_byname(const char* n, size_t refs)
734    : collate<char>(refs),
735      __l_(newlocale(LC_ALL_MASK, n, 0))
736{
737    if (__l_ == 0)
738        __throw_runtime_error("collate_byname<char>::collate_byname"
739                            " failed to construct for " + string(n));
740}
741
742collate_byname<char>::collate_byname(const string& name, size_t refs)
743    : collate<char>(refs),
744      __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
745{
746    if (__l_ == 0)
747        __throw_runtime_error("collate_byname<char>::collate_byname"
748                            " failed to construct for " + name);
749}
750
751collate_byname<char>::~collate_byname()
752{
753    freelocale(__l_);
754}
755
756int
757collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
758                                 const char_type* __lo2, const char_type* __hi2) const
759{
760    string_type lhs(__lo1, __hi1);
761    string_type rhs(__lo2, __hi2);
762    int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l_);
763    if (r < 0)
764        return -1;
765    if (r > 0)
766        return 1;
767    return r;
768}
769
770collate_byname<char>::string_type
771collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
772{
773    const string_type in(lo, hi);
774    string_type out(strxfrm_l(0, in.c_str(), 0, __l_), char());
775    strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l_);
776    return out;
777}
778
779// template <> class collate_byname<wchar_t>
780
781#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
782collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
783    : collate<wchar_t>(refs),
784      __l_(newlocale(LC_ALL_MASK, n, 0))
785{
786    if (__l_ == 0)
787        __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
788                            " failed to construct for " + string(n));
789}
790
791collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
792    : collate<wchar_t>(refs),
793      __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
794{
795    if (__l_ == 0)
796        __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
797                            " failed to construct for " + name);
798}
799
800collate_byname<wchar_t>::~collate_byname()
801{
802    freelocale(__l_);
803}
804
805int
806collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
807                                 const char_type* __lo2, const char_type* __hi2) const
808{
809    string_type lhs(__lo1, __hi1);
810    string_type rhs(__lo2, __hi2);
811    int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l_);
812    if (r < 0)
813        return -1;
814    if (r > 0)
815        return 1;
816    return r;
817}
818
819collate_byname<wchar_t>::string_type
820collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
821{
822    const string_type in(lo, hi);
823    string_type out(wcsxfrm_l(0, in.c_str(), 0, __l_), wchar_t());
824    wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l_);
825    return out;
826}
827#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
828
829const ctype_base::mask ctype_base::space;
830const ctype_base::mask ctype_base::print;
831const ctype_base::mask ctype_base::cntrl;
832const ctype_base::mask ctype_base::upper;
833const ctype_base::mask ctype_base::lower;
834const ctype_base::mask ctype_base::alpha;
835const ctype_base::mask ctype_base::digit;
836const ctype_base::mask ctype_base::punct;
837const ctype_base::mask ctype_base::xdigit;
838const ctype_base::mask ctype_base::blank;
839const ctype_base::mask ctype_base::alnum;
840const ctype_base::mask ctype_base::graph;
841
842// template <> class ctype<wchar_t>;
843
844#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
845locale::id ctype<wchar_t>::id;
846
847ctype<wchar_t>::~ctype()
848{
849}
850
851bool
852ctype<wchar_t>::do_is(mask m, char_type c) const
853{
854    return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
855}
856
857const wchar_t*
858ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
859{
860    for (; low != high; ++low, ++vec)
861        *vec = static_cast<mask>(isascii(*low) ?
862                                   ctype<char>::classic_table()[*low] : 0);
863    return low;
864}
865
866const wchar_t*
867ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
868{
869    for (; low != high; ++low)
870        if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
871            break;
872    return low;
873}
874
875const wchar_t*
876ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
877{
878    for (; low != high; ++low)
879        if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
880            break;
881    return low;
882}
883
884wchar_t
885ctype<wchar_t>::do_toupper(char_type c) const
886{
887#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
888    return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
889#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
890      defined(__NetBSD__) || defined(__MVS__)
891    return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
892#else
893    return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
894#endif
895}
896
897const wchar_t*
898ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
899{
900    for (; low != high; ++low)
901#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
902        *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
903#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
904      defined(__NetBSD__) || defined(__MVS__)
905        *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
906                             : *low;
907#else
908        *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
909#endif
910    return low;
911}
912
913wchar_t
914ctype<wchar_t>::do_tolower(char_type c) const
915{
916#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
917    return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
918#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
919      defined(__NetBSD__) || defined(__MVS__)
920    return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
921#else
922    return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
923#endif
924}
925
926const wchar_t*
927ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
928{
929    for (; low != high; ++low)
930#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
931        *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
932#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
933      defined(__NetBSD__) || defined(__MVS__)
934        *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
935                             : *low;
936#else
937        *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
938#endif
939    return low;
940}
941
942wchar_t
943ctype<wchar_t>::do_widen(char c) const
944{
945    return c;
946}
947
948const char*
949ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
950{
951    for (; low != high; ++low, ++dest)
952        *dest = *low;
953    return low;
954}
955
956char
957ctype<wchar_t>::do_narrow(char_type c, char dfault) const
958{
959    if (isascii(c))
960        return static_cast<char>(c);
961    return dfault;
962}
963
964const wchar_t*
965ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
966{
967    for (; low != high; ++low, ++dest)
968        if (isascii(*low))
969            *dest = static_cast<char>(*low);
970        else
971            *dest = dfault;
972    return low;
973}
974#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
975
976// template <> class ctype<char>;
977
978locale::id ctype<char>::id;
979
980const size_t ctype<char>::table_size;
981
982ctype<char>::ctype(const mask* tab, bool del, size_t refs)
983    : locale::facet(refs),
984      __tab_(tab),
985      __del_(del)
986{
987  if (__tab_ == 0)
988      __tab_ = classic_table();
989}
990
991ctype<char>::~ctype()
992{
993    if (__tab_ && __del_)
994        delete [] __tab_;
995}
996
997char
998ctype<char>::do_toupper(char_type c) const
999{
1000#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1001    return isascii(c) ?
1002      static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
1003#elif defined(__NetBSD__)
1004    return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
1005#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1006    return isascii(c) ?
1007      static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
1008#else
1009    return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
1010#endif
1011}
1012
1013const char*
1014ctype<char>::do_toupper(char_type* low, const char_type* high) const
1015{
1016    for (; low != high; ++low)
1017#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1018        *low = isascii(*low) ?
1019          static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
1020#elif defined(__NetBSD__)
1021        *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
1022#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1023        *low = isascii(*low) ?
1024          static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
1025#else
1026        *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
1027#endif
1028    return low;
1029}
1030
1031char
1032ctype<char>::do_tolower(char_type c) const
1033{
1034#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1035    return isascii(c) ?
1036      static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
1037#elif defined(__NetBSD__)
1038    return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
1039#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1040    return isascii(c) ?
1041      static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
1042#else
1043    return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
1044#endif
1045}
1046
1047const char*
1048ctype<char>::do_tolower(char_type* low, const char_type* high) const
1049{
1050    for (; low != high; ++low)
1051#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1052        *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
1053#elif defined(__NetBSD__)
1054        *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
1055#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1056        *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
1057#else
1058        *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
1059#endif
1060    return low;
1061}
1062
1063char
1064ctype<char>::do_widen(char c) const
1065{
1066    return c;
1067}
1068
1069const char*
1070ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1071{
1072    for (; low != high; ++low, ++dest)
1073        *dest = *low;
1074    return low;
1075}
1076
1077char
1078ctype<char>::do_narrow(char_type c, char dfault) const
1079{
1080    if (isascii(c))
1081        return static_cast<char>(c);
1082    return dfault;
1083}
1084
1085const char*
1086ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1087{
1088    for (; low != high; ++low, ++dest)
1089        if (isascii(*low))
1090            *dest = *low;
1091        else
1092            *dest = dfault;
1093    return low;
1094}
1095
1096#if defined(__EMSCRIPTEN__)
1097extern "C" const unsigned short ** __ctype_b_loc();
1098extern "C" const int ** __ctype_tolower_loc();
1099extern "C" const int ** __ctype_toupper_loc();
1100#endif
1101
1102#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
1103const ctype<char>::mask*
1104ctype<char>::classic_table() noexcept
1105{
1106    static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1107        cntrl,                          cntrl,
1108        cntrl,                          cntrl,
1109        cntrl,                          cntrl,
1110        cntrl,                          cntrl,
1111        cntrl,                          cntrl | space | blank,
1112        cntrl | space,                  cntrl | space,
1113        cntrl | space,                  cntrl | space,
1114        cntrl,                          cntrl,
1115        cntrl,                          cntrl,
1116        cntrl,                          cntrl,
1117        cntrl,                          cntrl,
1118        cntrl,                          cntrl,
1119        cntrl,                          cntrl,
1120        cntrl,                          cntrl,
1121        cntrl,                          cntrl,
1122        cntrl,                          cntrl,
1123        space | blank | print,          punct | print,
1124        punct | print,                  punct | print,
1125        punct | print,                  punct | print,
1126        punct | print,                  punct | print,
1127        punct | print,                  punct | print,
1128        punct | print,                  punct | print,
1129        punct | print,                  punct | print,
1130        punct | print,                  punct | print,
1131        digit | print | xdigit,         digit | print | xdigit,
1132        digit | print | xdigit,         digit | print | xdigit,
1133        digit | print | xdigit,         digit | print | xdigit,
1134        digit | print | xdigit,         digit | print | xdigit,
1135        digit | print | xdigit,         digit | print | xdigit,
1136        punct | print,                  punct | print,
1137        punct | print,                  punct | print,
1138        punct | print,                  punct | print,
1139        punct | print,                  upper | xdigit | print | alpha,
1140        upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1141        upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1142        upper | xdigit | print | alpha, upper | print | alpha,
1143        upper | print | alpha,          upper | print | alpha,
1144        upper | print | alpha,          upper | print | alpha,
1145        upper | print | alpha,          upper | print | alpha,
1146        upper | 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,          punct | print,
1153        punct | print,                  punct | print,
1154        punct | print,                  punct | print,
1155        punct | print,                  lower | xdigit | print | alpha,
1156        lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1157        lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1158        lower | xdigit | print | alpha, lower | print | alpha,
1159        lower | print | alpha,          lower | print | alpha,
1160        lower | print | alpha,          lower | print | alpha,
1161        lower | print | alpha,          lower | print | alpha,
1162        lower | 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,          punct | print,
1169        punct | print,                  punct | print,
1170        punct | print,                  cntrl,
1171        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1172        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1173        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1174        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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    };
1180    return builtin_table;
1181}
1182#else
1183const ctype<char>::mask*
1184ctype<char>::classic_table() noexcept
1185{
1186#if defined(__APPLE__) || defined(__FreeBSD__)
1187    return _DefaultRuneLocale.__runetype;
1188#elif defined(__NetBSD__)
1189    return _C_ctype_tab_ + 1;
1190#elif defined(__GLIBC__)
1191    return _LIBCPP_GET_C_LOCALE->__ctype_b;
1192#elif defined(__sun__)
1193    return __ctype_mask;
1194#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
1195    return __pctype_func();
1196#elif defined(__EMSCRIPTEN__)
1197    return *__ctype_b_loc();
1198#elif defined(_NEWLIB_VERSION)
1199    // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1200    return _ctype_ + 1;
1201#elif defined(_AIX)
1202    return (const unsigned int *)__lc_ctype_ptr->obj->mask;
1203#elif defined(__MVS__)
1204# if defined(__NATIVE_ASCII_F)
1205    return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1206# else
1207    return const_cast<const ctype<char>::mask*> (__ctypec);
1208# endif
1209#else
1210    // Platform not supported: abort so the person doing the port knows what to
1211    // fix
1212# warning  ctype<char>::classic_table() is not implemented
1213    printf("ctype<char>::classic_table() is not implemented\n");
1214    abort();
1215    return NULL;
1216#endif
1217}
1218#endif
1219
1220#if defined(__GLIBC__)
1221const int*
1222ctype<char>::__classic_lower_table() noexcept
1223{
1224    return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
1225}
1226
1227const int*
1228ctype<char>::__classic_upper_table() noexcept
1229{
1230    return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
1231}
1232#elif defined(__NetBSD__)
1233const short*
1234ctype<char>::__classic_lower_table() noexcept
1235{
1236    return _C_tolower_tab_ + 1;
1237}
1238
1239const short*
1240ctype<char>::__classic_upper_table() noexcept
1241{
1242    return _C_toupper_tab_ + 1;
1243}
1244
1245#elif defined(__EMSCRIPTEN__)
1246const int*
1247ctype<char>::__classic_lower_table() noexcept
1248{
1249    return *__ctype_tolower_loc();
1250}
1251
1252const int*
1253ctype<char>::__classic_upper_table() noexcept
1254{
1255    return *__ctype_toupper_loc();
1256}
1257#elif defined(__MVS__)
1258const unsigned short*
1259ctype<char>::__classic_lower_table() _NOEXCEPT
1260{
1261# if defined(__NATIVE_ASCII_F)
1262  return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1263# else
1264  return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1265# endif
1266}
1267const unsigned short *
1268ctype<char>::__classic_upper_table() _NOEXCEPT
1269{
1270# if defined(__NATIVE_ASCII_F)
1271  return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1272# else
1273  return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1274# endif
1275}
1276#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
1277
1278// template <> class ctype_byname<char>
1279
1280ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1281    : ctype<char>(0, false, refs),
1282      __l_(newlocale(LC_ALL_MASK, name, 0))
1283{
1284    if (__l_ == 0)
1285        __throw_runtime_error("ctype_byname<char>::ctype_byname"
1286                            " failed to construct for " + string(name));
1287}
1288
1289ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1290    : ctype<char>(0, false, refs),
1291      __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1292{
1293    if (__l_ == 0)
1294        __throw_runtime_error("ctype_byname<char>::ctype_byname"
1295                            " failed to construct for " + name);
1296}
1297
1298ctype_byname<char>::~ctype_byname()
1299{
1300    freelocale(__l_);
1301}
1302
1303char
1304ctype_byname<char>::do_toupper(char_type c) const
1305{
1306    return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l_));
1307}
1308
1309const char*
1310ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1311{
1312    for (; low != high; ++low)
1313        *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l_));
1314    return low;
1315}
1316
1317char
1318ctype_byname<char>::do_tolower(char_type c) const
1319{
1320    return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l_));
1321}
1322
1323const char*
1324ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1325{
1326    for (; low != high; ++low)
1327        *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l_));
1328    return low;
1329}
1330
1331// template <> class ctype_byname<wchar_t>
1332
1333#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1334ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1335    : ctype<wchar_t>(refs),
1336      __l_(newlocale(LC_ALL_MASK, name, 0))
1337{
1338    if (__l_ == 0)
1339        __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
1340                            " failed to construct for " + string(name));
1341}
1342
1343ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1344    : ctype<wchar_t>(refs),
1345      __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1346{
1347    if (__l_ == 0)
1348        __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
1349                            " failed to construct for " + name);
1350}
1351
1352ctype_byname<wchar_t>::~ctype_byname()
1353{
1354    freelocale(__l_);
1355}
1356
1357bool
1358ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1359{
1360#ifdef _LIBCPP_WCTYPE_IS_MASK
1361    return static_cast<bool>(iswctype_l(c, m, __l_));
1362#else
1363    bool result = false;
1364    wint_t ch = static_cast<wint_t>(c);
1365    if ((m & space) == space) result |= (iswspace_l(ch, __l_) != 0);
1366    if ((m & print) == print) result |= (iswprint_l(ch, __l_) != 0);
1367    if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l_) != 0);
1368    if ((m & upper) == upper) result |= (iswupper_l(ch, __l_) != 0);
1369    if ((m & lower) == lower) result |= (iswlower_l(ch, __l_) != 0);
1370    if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l_) != 0);
1371    if ((m & digit) == digit) result |= (iswdigit_l(ch, __l_) != 0);
1372    if ((m & punct) == punct) result |= (iswpunct_l(ch, __l_) != 0);
1373    if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l_) != 0);
1374    if ((m & blank) == blank) result |= (iswblank_l(ch, __l_) != 0);
1375    return result;
1376#endif
1377}
1378
1379const wchar_t*
1380ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1381{
1382    for (; low != high; ++low, ++vec)
1383    {
1384        if (isascii(*low))
1385            *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
1386        else
1387        {
1388            *vec = 0;
1389            wint_t ch = static_cast<wint_t>(*low);
1390            if (iswspace_l(ch, __l_))
1391                *vec |= space;
1392#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
1393            if (iswprint_l(ch, __l_))
1394                *vec |= print;
1395#endif
1396            if (iswcntrl_l(ch, __l_))
1397                *vec |= cntrl;
1398            if (iswupper_l(ch, __l_))
1399                *vec |= upper;
1400            if (iswlower_l(ch, __l_))
1401                *vec |= lower;
1402#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
1403            if (iswalpha_l(ch, __l_))
1404                *vec |= alpha;
1405#endif
1406            if (iswdigit_l(ch, __l_))
1407                *vec |= digit;
1408            if (iswpunct_l(ch, __l_))
1409                *vec |= punct;
1410#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
1411            if (iswxdigit_l(ch, __l_))
1412                *vec |= xdigit;
1413#endif
1414#if !defined(__sun__)
1415            if (iswblank_l(ch, __l_))
1416                *vec |= blank;
1417#endif
1418        }
1419    }
1420    return low;
1421}
1422
1423const wchar_t*
1424ctype_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
1448const wchar_t*
1449ctype_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
1474wchar_t
1475ctype_byname<wchar_t>::do_toupper(char_type c) const
1476{
1477    return towupper_l(c, __l_);
1478}
1479
1480const wchar_t*
1481ctype_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
1488wchar_t
1489ctype_byname<wchar_t>::do_tolower(char_type c) const
1490{
1491    return towlower_l(c, __l_);
1492}
1493
1494const wchar_t*
1495ctype_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
1502wchar_t
1503ctype_byname<wchar_t>::do_widen(char c) const
1504{
1505    return __libcpp_btowc_l(c, __l_);
1506}
1507
1508const char*
1509ctype_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
1516char
1517ctype_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
1523const wchar_t*
1524ctype_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
1537locale::id codecvt<char, char, mbstate_t>::id;
1538
1539codecvt<char, char, mbstate_t>::~codecvt()
1540{
1541}
1542
1543codecvt<char, char, mbstate_t>::result
1544codecvt<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
1553codecvt<char, char, mbstate_t>::result
1554codecvt<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
1563codecvt<char, char, mbstate_t>::result
1564codecvt<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
1571int
1572codecvt<char, char, mbstate_t>::do_encoding() const noexcept
1573{
1574    return 1;
1575}
1576
1577bool
1578codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
1579{
1580    return true;
1581}
1582
1583int
1584codecvt<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
1590int
1591codecvt<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
1599locale::id codecvt<wchar_t, char, mbstate_t>::id;
1600
1601codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1602    : locale::facet(refs),
1603      __l_(_LIBCPP_GET_C_LOCALE)
1604{
1605}
1606
1607codecvt<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
1616codecvt<wchar_t, char, mbstate_t>::~codecvt()
1617{
1618    if (__l_ != _LIBCPP_GET_C_LOCALE)
1619        freelocale(__l_);
1620}
1621
1622codecvt<wchar_t, char, mbstate_t>::result
1623codecvt<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
1679codecvt<wchar_t, char, mbstate_t>::result
1680codecvt<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
1745codecvt<wchar_t, char, mbstate_t>::result
1746codecvt<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
1762int
1763codecvt<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
1774bool
1775codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
1776{
1777    return false;
1778}
1779
1780int
1781codecvt<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
1806int
1807codecvt<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
1828static
1829codecvt_base::result
1830utf16_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
1905static
1906codecvt_base::result
1907utf16_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
1982static
1983codecvt_base::result
1984utf8_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
2103static
2104codecvt_base::result
2105utf8_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
2224static
2225int
2226utf8_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
2325static
2326codecvt_base::result
2327ucs4_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
2380static
2381codecvt_base::result
2382utf8_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
2494static
2495int
2496utf8_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
2592static
2593codecvt_base::result
2594ucs2_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
2638static
2639codecvt_base::result
2640utf8_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
2719static
2720int
2721utf8_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
2788static
2789codecvt_base::result
2790ucs4_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
2833static
2834codecvt_base::result
2835utf16be_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
2878static
2879int
2880utf16be_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
2920static
2921codecvt_base::result
2922ucs4_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
2965static
2966codecvt_base::result
2967utf16le_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
3010static
3011int
3012utf16le_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
3052static
3053codecvt_base::result
3054ucs2_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
3080static
3081codecvt_base::result
3082utf16be_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
3104static
3105int
3106utf16be_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
3126static
3127codecvt_base::result
3128ucs2_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
3154static
3155codecvt_base::result
3156utf16le_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
3178static
3179int
3180utf16le_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
3205locale::id codecvt<char16_t, char, mbstate_t>::id;
3206
3207codecvt<char16_t, char, mbstate_t>::~codecvt()
3208{
3209}
3210
3211codecvt<char16_t, char, mbstate_t>::result
3212codecvt<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
3228codecvt<char16_t, char, mbstate_t>::result
3229codecvt<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
3245codecvt<char16_t, char, mbstate_t>::result
3246codecvt<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
3253int
3254codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
3255{
3256    return 0;
3257}
3258
3259bool
3260codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
3261{
3262    return false;
3263}
3264
3265int
3266codecvt<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
3274int
3275codecvt<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
3284locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3285
3286codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3287{
3288}
3289
3290codecvt<char16_t, char8_t, mbstate_t>::result
3291codecvt<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
3307codecvt<char16_t, char8_t, mbstate_t>::result
3308codecvt<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
3324codecvt<char16_t, char8_t, mbstate_t>::result
3325codecvt<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
3332int
3333codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
3334{
3335    return 0;
3336}
3337
3338bool
3339codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3340{
3341    return false;
3342}
3343
3344int
3345codecvt<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
3353int
3354codecvt<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
3363locale::id codecvt<char32_t, char, mbstate_t>::id;
3364
3365codecvt<char32_t, char, mbstate_t>::~codecvt()
3366{
3367}
3368
3369codecvt<char32_t, char, mbstate_t>::result
3370codecvt<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
3386codecvt<char32_t, char, mbstate_t>::result
3387codecvt<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
3403codecvt<char32_t, char, mbstate_t>::result
3404codecvt<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
3411int
3412codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
3413{
3414    return 0;
3415}
3416
3417bool
3418codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
3419{
3420    return false;
3421}
3422
3423int
3424codecvt<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
3432int
3433codecvt<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
3442locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3443
3444codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3445{
3446}
3447
3448codecvt<char32_t, char8_t, mbstate_t>::result
3449codecvt<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
3465codecvt<char32_t, char8_t, mbstate_t>::result
3466codecvt<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
3482codecvt<char32_t, char8_t, mbstate_t>::result
3483codecvt<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
3490int
3491codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
3492{
3493    return 0;
3494}
3495
3496bool
3497codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3498{
3499    return false;
3500}
3501
3502int
3503codecvt<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
3511int
3512codecvt<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
3585int
3586__codecvt_utf8<wchar_t>::do_encoding() const noexcept
3587{
3588    return 0;
3589}
3590
3591bool
3592__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
3593{
3594    return false;
3595}
3596
3597int
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
3611int
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
3672int
3673__codecvt_utf8<char16_t>::do_encoding() const noexcept
3674{
3675    return 0;
3676}
3677
3678bool
3679__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
3680{
3681    return false;
3682}
3683
3684int
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
3694int
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
3749int
3750__codecvt_utf8<char32_t>::do_encoding() const noexcept
3751{
3752    return 0;
3753}
3754
3755bool
3756__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
3757{
3758    return false;
3759}
3760
3761int
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
3771int
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
3846int
3847__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
3848{
3849    return 0;
3850}
3851
3852bool
3853__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
3854{
3855    return false;
3856}
3857
3858int
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
3871int
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
3950int
3951__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
3952{
3953    return 0;
3954}
3955
3956bool
3957__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
3958{
3959    return false;
3960}
3961
3962int
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
3975int
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
4036int
4037__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
4038{
4039    return 0;
4040}
4041
4042bool
4043__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
4044{
4045    return false;
4046}
4047
4048int
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
4058int
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
4113int
4114__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
4115{
4116    return 0;
4117}
4118
4119bool
4120__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
4121{
4122    return false;
4123}
4124
4125int
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
4135int
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
4190int
4191__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
4192{
4193    return 0;
4194}
4195
4196bool
4197__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
4198{
4199    return false;
4200}
4201
4202int
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
4212int
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
4267int
4268__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
4269{
4270    return 0;
4271}
4272
4273bool
4274__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
4275{
4276    return false;
4277}
4278
4279int
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
4289int
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
4357int
4358__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
4359{
4360    return 0;
4361}
4362
4363bool
4364__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
4365{
4366    return false;
4367}
4368
4369int
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
4378int
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
4433int
4434__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
4435{
4436    return 0;
4437}
4438
4439bool
4440__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
4441{
4442    return false;
4443}
4444
4445int
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
4455int
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
4510int
4511__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
4512{
4513    return 0;
4514}
4515
4516bool
4517__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
4518{
4519    return false;
4520}
4521
4522int
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
4532int
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
4566static 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
4583static 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
4588static 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
4594static 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
4641locale::id numpunct< char  >::id;
4642#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4643locale::id numpunct<wchar_t>::id;
4644#endif
4645
4646numpunct<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
4654numpunct<wchar_t>::numpunct(size_t refs)
4655    : locale::facet(refs),
4656      __decimal_point_(L'.'),
4657      __thousands_sep_(L',')
4658{
4659}
4660#endif
4661
4662numpunct<char>::~numpunct()
4663{
4664}
4665
4666#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4667numpunct<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
4674wchar_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
4679wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4680#endif
4681
4682string numpunct< char  >::do_grouping() const {return __grouping_;}
4683#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4684string 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
4689wstring 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
4694wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4695#endif
4696
4697// numpunct_byname<char>
4698
4699numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4700    : numpunct<char>(refs)
4701{
4702    __init(nm);
4703}
4704
4705numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4706    : numpunct<char>(refs)
4707{
4708    __init(nm.c_str());
4709}
4710
4711numpunct_byname<char>::~numpunct_byname()
4712{
4713}
4714
4715void
4716numpunct_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
4741numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4742    : numpunct<wchar_t>(refs)
4743{
4744    __init(nm);
4745}
4746
4747numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4748    : numpunct<wchar_t>(refs)
4749{
4750    __init(nm.c_str());
4751}
4752
4753numpunct_byname<wchar_t>::~numpunct_byname()
4754{
4755}
4756
4757void
4758numpunct_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
4780int
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
4793const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4794
4795void
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
4827void
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
4855bool
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
4906char*
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
4930static
4931string*
4932init_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
4953static
4954wstring*
4955init_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
4976template <>
4977const 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
4985template <>
4986const 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
4994static
4995string*
4996init_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
5027static
5028wstring*
5029init_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
5060template <>
5061const 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
5069template <>
5070const 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
5078static
5079string*
5080init_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
5089static
5090wstring*
5091init_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
5100template <>
5101const 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
5109template <>
5110const 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
5118template <>
5119const 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
5127template <>
5128const 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
5136template <>
5137const 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
5145template <>
5146const 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
5154template <>
5155const 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
5163template <>
5164const 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
5172template <>
5173const 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
5181template <>
5182const 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
5215template <>
5216string
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
5362template <>
5363wstring
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
5513template <>
5514void
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
5551template <>
5552void
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
5628template <class CharT>
5629struct _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
5638template <>
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
5646template <>
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
5655template <>
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
5663template <>
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
5672template <>
5673time_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
5760template <>
5761time_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
5872void
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
5884void
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
5902template <class charT>
5903static
5904void
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
6274template<>
6275void
6276moneypunct_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
6318template<>
6319void
6320moneypunct_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
6379template<>
6380void
6381moneypunct_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
6444template<>
6445void
6446moneypunct_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
6528void __do_nothing(void*) {}
6529
6530void __throw_runtime_error(const char* msg)
6531{
6532#ifndef _LIBCPP_NO_EXCEPTIONS
6533    throw runtime_error(msg);
6534#else
6535    (void)msg;
6536    _VSTD::abort();
6537#endif
6538}
6539
6540                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6541_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
6542
6543                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6544_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
6545
6546                           template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6547_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
6548
6549                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6550_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
6551
6552                           template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6553_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
6554
6555                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6556_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
6557
6558                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6559_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
6560
6561                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6562_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
6563
6564                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6565_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
6566
6567                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6568                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6569_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6570_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
6571
6572                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6573                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6574_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6575_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
6576
6577                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6578_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
6579
6580                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6581_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
6582
6583                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6584_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
6585
6586                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6587_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
6588
6589                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6590_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
6591
6592                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6593_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
6594
6595                           template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6596_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;)
6597template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6598template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
6599#ifndef _LIBCPP_HAS_NO_CHAR8_T
6600template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6601template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6602#endif
6603
6604_LIBCPP_END_NAMESPACE_STD
6605
6606_LIBCPP_POP_MACROS
6607