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