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