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