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