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