xref: /freebsd-12.1/contrib/libc++/src/locale.cpp (revision 4ba319b5)
17a984708SDavid Chisnall //===------------------------- locale.cpp ---------------------------------===//
27a984708SDavid Chisnall //
37a984708SDavid Chisnall //                     The LLVM Compiler Infrastructure
47a984708SDavid Chisnall //
57a984708SDavid Chisnall // This file is dual licensed under the MIT and the University of Illinois Open
67a984708SDavid Chisnall // Source Licenses. See LICENSE.TXT for details.
77a984708SDavid Chisnall //
87a984708SDavid Chisnall //===----------------------------------------------------------------------===//
97a984708SDavid Chisnall 
1094e3ee44SDavid Chisnall // On Solaris, we need to define something to make the C99 parts of localeconv
1194e3ee44SDavid Chisnall // visible.
1294e3ee44SDavid Chisnall #ifdef __sun__
1394e3ee44SDavid Chisnall #define _LCONV_C99
1494e3ee44SDavid Chisnall #endif
1594e3ee44SDavid Chisnall 
167a984708SDavid Chisnall #include "string"
177a984708SDavid Chisnall #include "locale"
187a984708SDavid Chisnall #include "codecvt"
197a984708SDavid Chisnall #include "vector"
207a984708SDavid Chisnall #include "algorithm"
217a984708SDavid Chisnall #include "typeinfo"
224f7ab58eSDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
237a984708SDavid Chisnall #  include "type_traits"
244f7ab58eSDimitry Andric #endif
257a984708SDavid Chisnall #include "clocale"
267a984708SDavid Chisnall #include "cstring"
27aed8d94eSDimitry Andric #if defined(_LIBCPP_MSVCRT)
28aed8d94eSDimitry Andric #define _CTYPE_DISABLE_MACROS
29aed8d94eSDimitry Andric #endif
307a984708SDavid Chisnall #include "cwctype"
317a984708SDavid Chisnall #include "__sso_allocator"
324f7ab58eSDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
33854fa44bSDimitry Andric #include "support/win32/locale_win32.h"
34aed8d94eSDimitry Andric #elif !defined(__BIONIC__)
357a984708SDavid Chisnall #include <langinfo.h>
36d72607e9SDimitry Andric #endif
377a984708SDavid Chisnall #include <stdlib.h>
384f7ab58eSDimitry Andric #include <stdio.h>
39b2c7081bSDimitry Andric #include "include/atomic_support.h"
40f9448bf3SDimitry Andric #include "__undef_macros"
417a984708SDavid Chisnall 
421bf9f7c1SDimitry Andric // On Linux, wint_t and wchar_t have different signed-ness, and this causes
431bf9f7c1SDimitry Andric // lots of noise in the build log, but no bugs that I know of.
444f7ab58eSDimitry Andric #if defined(__clang__)
451bf9f7c1SDimitry Andric #pragma clang diagnostic ignored "-Wsign-conversion"
464f7ab58eSDimitry Andric #endif
471bf9f7c1SDimitry Andric 
487a984708SDavid Chisnall _LIBCPP_BEGIN_NAMESPACE_STD
497a984708SDavid Chisnall 
505517e702SDimitry Andric struct __libcpp_unique_locale {
__libcpp_unique_locale__libcpp_unique_locale515517e702SDimitry Andric   __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
525517e702SDimitry Andric 
~__libcpp_unique_locale__libcpp_unique_locale535517e702SDimitry Andric   ~__libcpp_unique_locale() {
545517e702SDimitry Andric     if (__loc_)
555517e702SDimitry Andric       freelocale(__loc_);
565517e702SDimitry Andric   }
575517e702SDimitry Andric 
operator bool__libcpp_unique_locale585517e702SDimitry Andric   explicit operator bool() const { return __loc_; }
595517e702SDimitry Andric 
get__libcpp_unique_locale605517e702SDimitry Andric   locale_t& get() { return __loc_; }
615517e702SDimitry Andric 
625517e702SDimitry Andric   locale_t __loc_;
635517e702SDimitry Andric private:
645517e702SDimitry Andric   __libcpp_unique_locale(__libcpp_unique_locale const&);
655517e702SDimitry Andric   __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
665517e702SDimitry Andric };
675517e702SDimitry Andric 
687a984708SDavid Chisnall #ifdef __cloc_defined
__cloc()697a984708SDavid Chisnall locale_t __cloc() {
707a984708SDavid Chisnall   // In theory this could create a race condition. In practice
717a984708SDavid Chisnall   // the race condition is non-fatal since it will just create
727a984708SDavid Chisnall   // a little resource leak. Better approach would be appreciated.
737a984708SDavid Chisnall   static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
747a984708SDavid Chisnall   return result;
757a984708SDavid Chisnall }
767a984708SDavid Chisnall #endif // __cloc_defined
777a984708SDavid Chisnall 
787a984708SDavid Chisnall namespace {
797a984708SDavid Chisnall 
807a984708SDavid Chisnall struct release
817a984708SDavid Chisnall {
operator ()__anonf1c1b2eb0111::release827a984708SDavid Chisnall     void operator()(locale::facet* p) {p->__release_shared();}
837a984708SDavid Chisnall };
847a984708SDavid Chisnall 
857a984708SDavid Chisnall template <class T, class A0>
867a984708SDavid Chisnall inline
877a984708SDavid Chisnall T&
make(A0 a0)887a984708SDavid Chisnall make(A0 a0)
897a984708SDavid Chisnall {
907a984708SDavid Chisnall     static typename aligned_storage<sizeof(T)>::type buf;
910f5676f4SDimitry Andric     auto *obj = ::new (&buf) T(a0);
920f5676f4SDimitry Andric     return *obj;
937a984708SDavid Chisnall }
947a984708SDavid Chisnall 
957a984708SDavid Chisnall template <class T, class A0, class A1>
967a984708SDavid Chisnall inline
977a984708SDavid Chisnall T&
make(A0 a0,A1 a1)987a984708SDavid Chisnall make(A0 a0, A1 a1)
997a984708SDavid Chisnall {
1007a984708SDavid Chisnall     static typename aligned_storage<sizeof(T)>::type buf;
1017a984708SDavid Chisnall     ::new (&buf) T(a0, a1);
102d72607e9SDimitry Andric     return *reinterpret_cast<T*>(&buf);
1037a984708SDavid Chisnall }
1047a984708SDavid Chisnall 
1057a984708SDavid Chisnall template <class T, class A0, class A1, class A2>
1067a984708SDavid Chisnall inline
1077a984708SDavid Chisnall T&
make(A0 a0,A1 a1,A2 a2)1087a984708SDavid Chisnall make(A0 a0, A1 a1, A2 a2)
1097a984708SDavid Chisnall {
1107a984708SDavid Chisnall     static typename aligned_storage<sizeof(T)>::type buf;
1110f5676f4SDimitry Andric     auto *obj = ::new (&buf) T(a0, a1, a2);
1120f5676f4SDimitry Andric     return *obj;
1137a984708SDavid Chisnall }
1147a984708SDavid Chisnall 
115cfdf2879SDavid Chisnall template <typename T, size_t N>
116cfdf2879SDavid Chisnall inline
117cfdf2879SDavid Chisnall _LIBCPP_CONSTEXPR
118cfdf2879SDavid Chisnall size_t
countof(const T (&)[N])119cfdf2879SDavid Chisnall countof(const T (&)[N])
120cfdf2879SDavid Chisnall {
121cfdf2879SDavid Chisnall     return N;
1227a984708SDavid Chisnall }
1237a984708SDavid Chisnall 
124cfdf2879SDavid Chisnall template <typename T>
125cfdf2879SDavid Chisnall inline
126cfdf2879SDavid Chisnall _LIBCPP_CONSTEXPR
127cfdf2879SDavid Chisnall size_t
countof(const T * const begin,const T * const end)128cfdf2879SDavid Chisnall countof(const T * const begin, const T * const end)
129cfdf2879SDavid Chisnall {
130cfdf2879SDavid Chisnall     return static_cast<size_t>(end - begin);
131cfdf2879SDavid Chisnall }
132cfdf2879SDavid Chisnall 
__throw_runtime_error(const string & msg)133aed8d94eSDimitry Andric _LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
134aed8d94eSDimitry Andric {
135aed8d94eSDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
136aed8d94eSDimitry Andric     throw runtime_error(msg);
137aed8d94eSDimitry Andric #else
138aed8d94eSDimitry Andric     (void)msg;
139aed8d94eSDimitry Andric     _VSTD::abort();
140aed8d94eSDimitry Andric #endif
141aed8d94eSDimitry Andric }
142aed8d94eSDimitry Andric 
143cfdf2879SDavid Chisnall }
144cfdf2879SDavid Chisnall 
1454f7ab58eSDimitry Andric #if defined(_AIX)
1464f7ab58eSDimitry Andric // Set priority to INT_MIN + 256 + 150
1474f7ab58eSDimitry Andric # pragma priority ( -2147483242 )
1484f7ab58eSDimitry Andric #endif
1494f7ab58eSDimitry Andric 
150cfdf2879SDavid Chisnall const locale::category locale::none;
151cfdf2879SDavid Chisnall const locale::category locale::collate;
152cfdf2879SDavid Chisnall const locale::category locale::ctype;
153cfdf2879SDavid Chisnall const locale::category locale::monetary;
154cfdf2879SDavid Chisnall const locale::category locale::numeric;
155cfdf2879SDavid Chisnall const locale::category locale::time;
156cfdf2879SDavid Chisnall const locale::category locale::messages;
157cfdf2879SDavid Chisnall const locale::category locale::all;
158cfdf2879SDavid Chisnall 
1597a984708SDavid Chisnall class _LIBCPP_HIDDEN locale::__imp
1607a984708SDavid Chisnall     : public facet
1617a984708SDavid Chisnall {
1627a984708SDavid Chisnall     enum {N = 28};
16380779b37SDimitry Andric #if defined(_LIBCPP_COMPILER_MSVC)
1644f7ab58eSDimitry Andric // FIXME: MSVC doesn't support aligned parameters by value.
1654f7ab58eSDimitry Andric // I can't get the __sso_allocator to work here
1664f7ab58eSDimitry Andric // for MSVC I think for this reason.
1674f7ab58eSDimitry Andric     vector<facet*> facets_;
1684f7ab58eSDimitry Andric #else
1697a984708SDavid Chisnall     vector<facet*, __sso_allocator<facet*, N> > facets_;
1704f7ab58eSDimitry Andric #endif
17194e3ee44SDavid Chisnall     string         name_;
1727a984708SDavid Chisnall public:
1737a984708SDavid Chisnall     explicit __imp(size_t refs = 0);
1747a984708SDavid Chisnall     explicit __imp(const string& name, size_t refs = 0);
1757a984708SDavid Chisnall     __imp(const __imp&);
1767a984708SDavid Chisnall     __imp(const __imp&, const string&, locale::category c);
1777a984708SDavid Chisnall     __imp(const __imp& other, const __imp& one, locale::category c);
1787a984708SDavid Chisnall     __imp(const __imp&, facet* f, long id);
1797a984708SDavid Chisnall     ~__imp();
1807a984708SDavid Chisnall 
name() const1817a984708SDavid Chisnall     const string& name() const {return name_;}
has_facet(long id) const18294e3ee44SDavid Chisnall     bool has_facet(long id) const
18394e3ee44SDavid Chisnall         {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
1847a984708SDavid Chisnall     const locale::facet* use_facet(long id) const;
1857a984708SDavid Chisnall 
1867a984708SDavid Chisnall     static const locale& make_classic();
1877a984708SDavid Chisnall     static       locale& make_global();
1887a984708SDavid Chisnall private:
1897a984708SDavid Chisnall     void install(facet* f, long id);
install(F * f)1907a984708SDavid Chisnall     template <class F> void install(F* f) {install(f, f->id.__get());}
1917a984708SDavid Chisnall     template <class F> void install_from(const __imp& other);
1927a984708SDavid Chisnall };
1937a984708SDavid Chisnall 
__imp(size_t refs)1947a984708SDavid Chisnall locale::__imp::__imp(size_t refs)
1957a984708SDavid Chisnall     : facet(refs),
19694e3ee44SDavid Chisnall       facets_(N),
19794e3ee44SDavid Chisnall       name_("C")
1987a984708SDavid Chisnall {
1997a984708SDavid Chisnall     facets_.clear();
20094e3ee44SDavid Chisnall     install(&make<_VSTD::collate<char> >(1u));
20194e3ee44SDavid Chisnall     install(&make<_VSTD::collate<wchar_t> >(1u));
202d72607e9SDimitry Andric     install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
20394e3ee44SDavid Chisnall     install(&make<_VSTD::ctype<wchar_t> >(1u));
20494e3ee44SDavid Chisnall     install(&make<codecvt<char, char, mbstate_t> >(1u));
20594e3ee44SDavid Chisnall     install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
20694e3ee44SDavid Chisnall     install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
20794e3ee44SDavid Chisnall     install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
20894e3ee44SDavid Chisnall     install(&make<numpunct<char> >(1u));
20994e3ee44SDavid Chisnall     install(&make<numpunct<wchar_t> >(1u));
21094e3ee44SDavid Chisnall     install(&make<num_get<char> >(1u));
21194e3ee44SDavid Chisnall     install(&make<num_get<wchar_t> >(1u));
21294e3ee44SDavid Chisnall     install(&make<num_put<char> >(1u));
21394e3ee44SDavid Chisnall     install(&make<num_put<wchar_t> >(1u));
21494e3ee44SDavid Chisnall     install(&make<moneypunct<char, false> >(1u));
21594e3ee44SDavid Chisnall     install(&make<moneypunct<char, true> >(1u));
21694e3ee44SDavid Chisnall     install(&make<moneypunct<wchar_t, false> >(1u));
21794e3ee44SDavid Chisnall     install(&make<moneypunct<wchar_t, true> >(1u));
21894e3ee44SDavid Chisnall     install(&make<money_get<char> >(1u));
21994e3ee44SDavid Chisnall     install(&make<money_get<wchar_t> >(1u));
22094e3ee44SDavid Chisnall     install(&make<money_put<char> >(1u));
22194e3ee44SDavid Chisnall     install(&make<money_put<wchar_t> >(1u));
22294e3ee44SDavid Chisnall     install(&make<time_get<char> >(1u));
22394e3ee44SDavid Chisnall     install(&make<time_get<wchar_t> >(1u));
22494e3ee44SDavid Chisnall     install(&make<time_put<char> >(1u));
22594e3ee44SDavid Chisnall     install(&make<time_put<wchar_t> >(1u));
22694e3ee44SDavid Chisnall     install(&make<_VSTD::messages<char> >(1u));
22794e3ee44SDavid Chisnall     install(&make<_VSTD::messages<wchar_t> >(1u));
2287a984708SDavid Chisnall }
2297a984708SDavid Chisnall 
__imp(const string & name,size_t refs)2307a984708SDavid Chisnall locale::__imp::__imp(const string& name, size_t refs)
2317a984708SDavid Chisnall     : facet(refs),
23294e3ee44SDavid Chisnall       facets_(N),
23394e3ee44SDavid Chisnall       name_(name)
2347a984708SDavid Chisnall {
2357a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
2367a984708SDavid Chisnall     try
2377a984708SDavid Chisnall     {
2387a984708SDavid Chisnall #endif  // _LIBCPP_NO_EXCEPTIONS
2397a984708SDavid Chisnall         facets_ = locale::classic().__locale_->facets_;
2407a984708SDavid Chisnall         for (unsigned i = 0; i < facets_.size(); ++i)
2417a984708SDavid Chisnall             if (facets_[i])
2427a984708SDavid Chisnall                 facets_[i]->__add_shared();
2437a984708SDavid Chisnall         install(new collate_byname<char>(name_));
2447a984708SDavid Chisnall         install(new collate_byname<wchar_t>(name_));
2457a984708SDavid Chisnall         install(new ctype_byname<char>(name_));
2467a984708SDavid Chisnall         install(new ctype_byname<wchar_t>(name_));
2477a984708SDavid Chisnall         install(new codecvt_byname<char, char, mbstate_t>(name_));
2487a984708SDavid Chisnall         install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
2497a984708SDavid Chisnall         install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
2507a984708SDavid Chisnall         install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
2517a984708SDavid Chisnall         install(new numpunct_byname<char>(name_));
2527a984708SDavid Chisnall         install(new numpunct_byname<wchar_t>(name_));
2537a984708SDavid Chisnall         install(new moneypunct_byname<char, false>(name_));
2547a984708SDavid Chisnall         install(new moneypunct_byname<char, true>(name_));
2557a984708SDavid Chisnall         install(new moneypunct_byname<wchar_t, false>(name_));
2567a984708SDavid Chisnall         install(new moneypunct_byname<wchar_t, true>(name_));
2577a984708SDavid Chisnall         install(new time_get_byname<char>(name_));
2587a984708SDavid Chisnall         install(new time_get_byname<wchar_t>(name_));
2597a984708SDavid Chisnall         install(new time_put_byname<char>(name_));
2607a984708SDavid Chisnall         install(new time_put_byname<wchar_t>(name_));
2617a984708SDavid Chisnall         install(new messages_byname<char>(name_));
2627a984708SDavid Chisnall         install(new messages_byname<wchar_t>(name_));
2637a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
2647a984708SDavid Chisnall     }
2657a984708SDavid Chisnall     catch (...)
2667a984708SDavid Chisnall     {
2677a984708SDavid Chisnall         for (unsigned i = 0; i < facets_.size(); ++i)
2687a984708SDavid Chisnall             if (facets_[i])
2697a984708SDavid Chisnall                 facets_[i]->__release_shared();
2707a984708SDavid Chisnall         throw;
2717a984708SDavid Chisnall     }
2727a984708SDavid Chisnall #endif  // _LIBCPP_NO_EXCEPTIONS
2737a984708SDavid Chisnall }
2747a984708SDavid Chisnall 
275cfdf2879SDavid Chisnall // NOTE avoid the `base class should be explicitly initialized in the
276cfdf2879SDavid Chisnall // copy constructor` warning emitted by GCC
2774bab9fd9SDavid Chisnall #if defined(__clang__) || _GNUC_VER >= 406
278cfdf2879SDavid Chisnall #pragma GCC diagnostic push
279cfdf2879SDavid Chisnall #pragma GCC diagnostic ignored "-Wextra"
2804bab9fd9SDavid Chisnall #endif
281cfdf2879SDavid Chisnall 
__imp(const __imp & other)2827a984708SDavid Chisnall locale::__imp::__imp(const __imp& other)
28394e3ee44SDavid Chisnall     : facets_(max<size_t>(N, other.facets_.size())),
28494e3ee44SDavid Chisnall       name_(other.name_)
2857a984708SDavid Chisnall {
2867a984708SDavid Chisnall     facets_ = other.facets_;
2877a984708SDavid Chisnall     for (unsigned i = 0; i < facets_.size(); ++i)
2887a984708SDavid Chisnall         if (facets_[i])
2897a984708SDavid Chisnall             facets_[i]->__add_shared();
2907a984708SDavid Chisnall }
2917a984708SDavid Chisnall 
2924bab9fd9SDavid Chisnall #if defined(__clang__) || _GNUC_VER >= 406
293cfdf2879SDavid Chisnall #pragma GCC diagnostic pop
2944bab9fd9SDavid Chisnall #endif
295cfdf2879SDavid Chisnall 
__imp(const __imp & other,const string & name,locale::category c)2967a984708SDavid Chisnall locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
29794e3ee44SDavid Chisnall     : facets_(N),
29894e3ee44SDavid Chisnall       name_("*")
2997a984708SDavid Chisnall {
3007a984708SDavid Chisnall     facets_ = other.facets_;
3017a984708SDavid Chisnall     for (unsigned i = 0; i < facets_.size(); ++i)
3027a984708SDavid Chisnall         if (facets_[i])
3037a984708SDavid Chisnall             facets_[i]->__add_shared();
3047a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
3057a984708SDavid Chisnall     try
3067a984708SDavid Chisnall     {
3077a984708SDavid Chisnall #endif  // _LIBCPP_NO_EXCEPTIONS
3087a984708SDavid Chisnall         if (c & locale::collate)
3097a984708SDavid Chisnall         {
3107a984708SDavid Chisnall             install(new collate_byname<char>(name));
3117a984708SDavid Chisnall             install(new collate_byname<wchar_t>(name));
3127a984708SDavid Chisnall         }
3137a984708SDavid Chisnall         if (c & locale::ctype)
3147a984708SDavid Chisnall         {
3157a984708SDavid Chisnall             install(new ctype_byname<char>(name));
3167a984708SDavid Chisnall             install(new ctype_byname<wchar_t>(name));
3177a984708SDavid Chisnall             install(new codecvt_byname<char, char, mbstate_t>(name));
3187a984708SDavid Chisnall             install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
3197a984708SDavid Chisnall             install(new codecvt_byname<char16_t, char, mbstate_t>(name));
3207a984708SDavid Chisnall             install(new codecvt_byname<char32_t, char, mbstate_t>(name));
3217a984708SDavid Chisnall         }
3227a984708SDavid Chisnall         if (c & locale::monetary)
3237a984708SDavid Chisnall         {
3247a984708SDavid Chisnall             install(new moneypunct_byname<char, false>(name));
3257a984708SDavid Chisnall             install(new moneypunct_byname<char, true>(name));
3267a984708SDavid Chisnall             install(new moneypunct_byname<wchar_t, false>(name));
3277a984708SDavid Chisnall             install(new moneypunct_byname<wchar_t, true>(name));
3287a984708SDavid Chisnall         }
3297a984708SDavid Chisnall         if (c & locale::numeric)
3307a984708SDavid Chisnall         {
3317a984708SDavid Chisnall             install(new numpunct_byname<char>(name));
3327a984708SDavid Chisnall             install(new numpunct_byname<wchar_t>(name));
3337a984708SDavid Chisnall         }
3347a984708SDavid Chisnall         if (c & locale::time)
3357a984708SDavid Chisnall         {
3367a984708SDavid Chisnall             install(new time_get_byname<char>(name));
3377a984708SDavid Chisnall             install(new time_get_byname<wchar_t>(name));
3387a984708SDavid Chisnall             install(new time_put_byname<char>(name));
3397a984708SDavid Chisnall             install(new time_put_byname<wchar_t>(name));
3407a984708SDavid Chisnall         }
3417a984708SDavid Chisnall         if (c & locale::messages)
3427a984708SDavid Chisnall         {
3437a984708SDavid Chisnall             install(new messages_byname<char>(name));
3447a984708SDavid Chisnall             install(new messages_byname<wchar_t>(name));
3457a984708SDavid Chisnall         }
3467a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
3477a984708SDavid Chisnall     }
3487a984708SDavid Chisnall     catch (...)
3497a984708SDavid Chisnall     {
3507a984708SDavid Chisnall         for (unsigned i = 0; i < facets_.size(); ++i)
3517a984708SDavid Chisnall             if (facets_[i])
3527a984708SDavid Chisnall                 facets_[i]->__release_shared();
3537a984708SDavid Chisnall         throw;
3547a984708SDavid Chisnall     }
3557a984708SDavid Chisnall #endif  // _LIBCPP_NO_EXCEPTIONS
3567a984708SDavid Chisnall }
3577a984708SDavid Chisnall 
3587a984708SDavid Chisnall template<class F>
3597a984708SDavid Chisnall inline
3607a984708SDavid Chisnall void
install_from(const locale::__imp & one)3617a984708SDavid Chisnall locale::__imp::install_from(const locale::__imp& one)
3627a984708SDavid Chisnall {
3637a984708SDavid Chisnall     long id = F::id.__get();
3647a984708SDavid Chisnall     install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
3657a984708SDavid Chisnall }
3667a984708SDavid Chisnall 
__imp(const __imp & other,const __imp & one,locale::category c)3677a984708SDavid Chisnall locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
36894e3ee44SDavid Chisnall     : facets_(N),
36994e3ee44SDavid Chisnall       name_("*")
3707a984708SDavid Chisnall {
3717a984708SDavid Chisnall     facets_ = other.facets_;
3727a984708SDavid Chisnall     for (unsigned i = 0; i < facets_.size(); ++i)
3737a984708SDavid Chisnall         if (facets_[i])
3747a984708SDavid Chisnall             facets_[i]->__add_shared();
3757a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
3767a984708SDavid Chisnall     try
3777a984708SDavid Chisnall     {
3787a984708SDavid Chisnall #endif  // _LIBCPP_NO_EXCEPTIONS
3797a984708SDavid Chisnall         if (c & locale::collate)
3807a984708SDavid Chisnall         {
3817a984708SDavid Chisnall             install_from<_VSTD::collate<char> >(one);
3827a984708SDavid Chisnall             install_from<_VSTD::collate<wchar_t> >(one);
3837a984708SDavid Chisnall         }
3847a984708SDavid Chisnall         if (c & locale::ctype)
3857a984708SDavid Chisnall         {
3867a984708SDavid Chisnall             install_from<_VSTD::ctype<char> >(one);
3877a984708SDavid Chisnall             install_from<_VSTD::ctype<wchar_t> >(one);
3887a984708SDavid Chisnall             install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
3897a984708SDavid Chisnall             install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
3907a984708SDavid Chisnall             install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
3917a984708SDavid Chisnall             install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
3927a984708SDavid Chisnall         }
3937a984708SDavid Chisnall         if (c & locale::monetary)
3947a984708SDavid Chisnall         {
3957a984708SDavid Chisnall             install_from<moneypunct<char, false> >(one);
3967a984708SDavid Chisnall             install_from<moneypunct<char, true> >(one);
3977a984708SDavid Chisnall             install_from<moneypunct<wchar_t, false> >(one);
3987a984708SDavid Chisnall             install_from<moneypunct<wchar_t, true> >(one);
3997a984708SDavid Chisnall             install_from<money_get<char> >(one);
4007a984708SDavid Chisnall             install_from<money_get<wchar_t> >(one);
4017a984708SDavid Chisnall             install_from<money_put<char> >(one);
4027a984708SDavid Chisnall             install_from<money_put<wchar_t> >(one);
4037a984708SDavid Chisnall         }
4047a984708SDavid Chisnall         if (c & locale::numeric)
4057a984708SDavid Chisnall         {
4067a984708SDavid Chisnall             install_from<numpunct<char> >(one);
4077a984708SDavid Chisnall             install_from<numpunct<wchar_t> >(one);
4087a984708SDavid Chisnall             install_from<num_get<char> >(one);
4097a984708SDavid Chisnall             install_from<num_get<wchar_t> >(one);
4107a984708SDavid Chisnall             install_from<num_put<char> >(one);
4117a984708SDavid Chisnall             install_from<num_put<wchar_t> >(one);
4127a984708SDavid Chisnall         }
4137a984708SDavid Chisnall         if (c & locale::time)
4147a984708SDavid Chisnall         {
4157a984708SDavid Chisnall             install_from<time_get<char> >(one);
4167a984708SDavid Chisnall             install_from<time_get<wchar_t> >(one);
4177a984708SDavid Chisnall             install_from<time_put<char> >(one);
4187a984708SDavid Chisnall             install_from<time_put<wchar_t> >(one);
4197a984708SDavid Chisnall         }
4207a984708SDavid Chisnall         if (c & locale::messages)
4217a984708SDavid Chisnall         {
4227a984708SDavid Chisnall             install_from<_VSTD::messages<char> >(one);
4237a984708SDavid Chisnall             install_from<_VSTD::messages<wchar_t> >(one);
4247a984708SDavid Chisnall         }
4257a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
4267a984708SDavid Chisnall     }
4277a984708SDavid Chisnall     catch (...)
4287a984708SDavid Chisnall     {
4297a984708SDavid Chisnall         for (unsigned i = 0; i < facets_.size(); ++i)
4307a984708SDavid Chisnall             if (facets_[i])
4317a984708SDavid Chisnall                 facets_[i]->__release_shared();
4327a984708SDavid Chisnall         throw;
4337a984708SDavid Chisnall     }
4347a984708SDavid Chisnall #endif  // _LIBCPP_NO_EXCEPTIONS
4357a984708SDavid Chisnall }
4367a984708SDavid Chisnall 
__imp(const __imp & other,facet * f,long id)4377a984708SDavid Chisnall locale::__imp::__imp(const __imp& other, facet* f, long id)
43894e3ee44SDavid Chisnall     : facets_(max<size_t>(N, other.facets_.size()+1)),
43994e3ee44SDavid Chisnall       name_("*")
4407a984708SDavid Chisnall {
4417a984708SDavid Chisnall     f->__add_shared();
4427a984708SDavid Chisnall     unique_ptr<facet, release> hold(f);
4437a984708SDavid Chisnall     facets_ = other.facets_;
4447a984708SDavid Chisnall     for (unsigned i = 0; i < other.facets_.size(); ++i)
4457a984708SDavid Chisnall         if (facets_[i])
4467a984708SDavid Chisnall             facets_[i]->__add_shared();
4477a984708SDavid Chisnall     install(hold.get(), id);
4487a984708SDavid Chisnall }
4497a984708SDavid Chisnall 
~__imp()4507a984708SDavid Chisnall locale::__imp::~__imp()
4517a984708SDavid Chisnall {
4527a984708SDavid Chisnall     for (unsigned i = 0; i < facets_.size(); ++i)
4537a984708SDavid Chisnall         if (facets_[i])
4547a984708SDavid Chisnall             facets_[i]->__release_shared();
4557a984708SDavid Chisnall }
4567a984708SDavid Chisnall 
4577a984708SDavid Chisnall void
install(facet * f,long id)4587a984708SDavid Chisnall locale::__imp::install(facet* f, long id)
4597a984708SDavid Chisnall {
4607a984708SDavid Chisnall     f->__add_shared();
4617a984708SDavid Chisnall     unique_ptr<facet, release> hold(f);
46294e3ee44SDavid Chisnall     if (static_cast<size_t>(id) >= facets_.size())
46394e3ee44SDavid Chisnall         facets_.resize(static_cast<size_t>(id+1));
46494e3ee44SDavid Chisnall     if (facets_[static_cast<size_t>(id)])
46594e3ee44SDavid Chisnall         facets_[static_cast<size_t>(id)]->__release_shared();
46694e3ee44SDavid Chisnall     facets_[static_cast<size_t>(id)] = hold.release();
4677a984708SDavid Chisnall }
4687a984708SDavid Chisnall 
4697a984708SDavid Chisnall const locale::facet*
use_facet(long id) const4707a984708SDavid Chisnall locale::__imp::use_facet(long id) const
4717a984708SDavid Chisnall {
4727a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
4737a984708SDavid Chisnall     if (!has_facet(id))
4747a984708SDavid Chisnall         throw bad_cast();
4757a984708SDavid Chisnall #endif  // _LIBCPP_NO_EXCEPTIONS
47694e3ee44SDavid Chisnall     return facets_[static_cast<size_t>(id)];
4777a984708SDavid Chisnall }
4787a984708SDavid Chisnall 
4797a984708SDavid Chisnall // locale
4807a984708SDavid Chisnall 
4817a984708SDavid Chisnall const locale&
make_classic()4827a984708SDavid Chisnall locale::__imp::make_classic()
4837a984708SDavid Chisnall {
4847a984708SDavid Chisnall     // only one thread can get in here and it only gets in once
4857a984708SDavid Chisnall     static aligned_storage<sizeof(locale)>::type buf;
486d72607e9SDimitry Andric     locale* c = reinterpret_cast<locale*>(&buf);
48794e3ee44SDavid Chisnall     c->__locale_ = &make<__imp>(1u);
4887a984708SDavid Chisnall     return *c;
4897a984708SDavid Chisnall }
4907a984708SDavid Chisnall 
4917a984708SDavid Chisnall const locale&
classic()4927a984708SDavid Chisnall locale::classic()
4937a984708SDavid Chisnall {
4947a984708SDavid Chisnall     static const locale& c = __imp::make_classic();
4957a984708SDavid Chisnall     return c;
4967a984708SDavid Chisnall }
4977a984708SDavid Chisnall 
4987a984708SDavid Chisnall locale&
make_global()4997a984708SDavid Chisnall locale::__imp::make_global()
5007a984708SDavid Chisnall {
5017a984708SDavid Chisnall     // only one thread can get in here and it only gets in once
5027a984708SDavid Chisnall     static aligned_storage<sizeof(locale)>::type buf;
5030f5676f4SDimitry Andric     auto *obj = ::new (&buf) locale(locale::classic());
5040f5676f4SDimitry Andric     return *obj;
5057a984708SDavid Chisnall }
5067a984708SDavid Chisnall 
5077a984708SDavid Chisnall locale&
__global()5087a984708SDavid Chisnall locale::__global()
5097a984708SDavid Chisnall {
5107a984708SDavid Chisnall     static locale& g = __imp::make_global();
5117a984708SDavid Chisnall     return g;
5127a984708SDavid Chisnall }
5137a984708SDavid Chisnall 
locale()5147a984708SDavid Chisnall locale::locale()  _NOEXCEPT
5157a984708SDavid Chisnall     : __locale_(__global().__locale_)
5167a984708SDavid Chisnall {
5177a984708SDavid Chisnall     __locale_->__add_shared();
5187a984708SDavid Chisnall }
5197a984708SDavid Chisnall 
locale(const locale & l)5207a984708SDavid Chisnall locale::locale(const locale& l)  _NOEXCEPT
5217a984708SDavid Chisnall     : __locale_(l.__locale_)
5227a984708SDavid Chisnall {
5237a984708SDavid Chisnall     __locale_->__add_shared();
5247a984708SDavid Chisnall }
5257a984708SDavid Chisnall 
~locale()5267a984708SDavid Chisnall locale::~locale()
5277a984708SDavid Chisnall {
5287a984708SDavid Chisnall     __locale_->__release_shared();
5297a984708SDavid Chisnall }
5307a984708SDavid Chisnall 
5317a984708SDavid Chisnall const locale&
operator =(const locale & other)5327a984708SDavid Chisnall locale::operator=(const locale& other)  _NOEXCEPT
5337a984708SDavid Chisnall {
5347a984708SDavid Chisnall     other.__locale_->__add_shared();
5357a984708SDavid Chisnall     __locale_->__release_shared();
5367a984708SDavid Chisnall     __locale_ = other.__locale_;
5377a984708SDavid Chisnall     return *this;
5387a984708SDavid Chisnall }
5397a984708SDavid Chisnall 
locale(const char * name)5407a984708SDavid Chisnall locale::locale(const char* name)
5417a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
5427a984708SDavid Chisnall     : __locale_(name ? new __imp(name)
5437a984708SDavid Chisnall                      : throw runtime_error("locale constructed with null"))
5447a984708SDavid Chisnall #else  // _LIBCPP_NO_EXCEPTIONS
5457a984708SDavid Chisnall     : __locale_(new __imp(name))
5467a984708SDavid Chisnall #endif
5477a984708SDavid Chisnall {
5487a984708SDavid Chisnall     __locale_->__add_shared();
5497a984708SDavid Chisnall }
5507a984708SDavid Chisnall 
locale(const string & name)5517a984708SDavid Chisnall locale::locale(const string& name)
5527a984708SDavid Chisnall     : __locale_(new __imp(name))
5537a984708SDavid Chisnall {
5547a984708SDavid Chisnall     __locale_->__add_shared();
5557a984708SDavid Chisnall }
5567a984708SDavid Chisnall 
locale(const locale & other,const char * name,category c)5577a984708SDavid Chisnall locale::locale(const locale& other, const char* name, category c)
5587a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
5597a984708SDavid Chisnall     : __locale_(name ? new __imp(*other.__locale_, name, c)
5607a984708SDavid Chisnall                      : throw runtime_error("locale constructed with null"))
5617a984708SDavid Chisnall #else  // _LIBCPP_NO_EXCEPTIONS
5627a984708SDavid Chisnall     : __locale_(new __imp(*other.__locale_, name, c))
5637a984708SDavid Chisnall #endif
5647a984708SDavid Chisnall {
5657a984708SDavid Chisnall     __locale_->__add_shared();
5667a984708SDavid Chisnall }
5677a984708SDavid Chisnall 
locale(const locale & other,const string & name,category c)5687a984708SDavid Chisnall locale::locale(const locale& other, const string& name, category c)
5697a984708SDavid Chisnall     : __locale_(new __imp(*other.__locale_, name, c))
5707a984708SDavid Chisnall {
5717a984708SDavid Chisnall     __locale_->__add_shared();
5727a984708SDavid Chisnall }
5737a984708SDavid Chisnall 
locale(const locale & other,const locale & one,category c)5747a984708SDavid Chisnall locale::locale(const locale& other, const locale& one, category c)
5757a984708SDavid Chisnall     : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
5767a984708SDavid Chisnall {
5777a984708SDavid Chisnall     __locale_->__add_shared();
5787a984708SDavid Chisnall }
5797a984708SDavid Chisnall 
5807a984708SDavid Chisnall string
name() const5817a984708SDavid Chisnall locale::name() const
5827a984708SDavid Chisnall {
5837a984708SDavid Chisnall     return __locale_->name();
5847a984708SDavid Chisnall }
5857a984708SDavid Chisnall 
5867a984708SDavid Chisnall void
__install_ctor(const locale & other,facet * f,long id)5877a984708SDavid Chisnall locale::__install_ctor(const locale& other, facet* f, long id)
5887a984708SDavid Chisnall {
5897a984708SDavid Chisnall     if (f)
5907a984708SDavid Chisnall         __locale_ = new __imp(*other.__locale_, f, id);
5917a984708SDavid Chisnall     else
5927a984708SDavid Chisnall         __locale_ = other.__locale_;
5937a984708SDavid Chisnall     __locale_->__add_shared();
5947a984708SDavid Chisnall }
5957a984708SDavid Chisnall 
5967a984708SDavid Chisnall locale
global(const locale & loc)5977a984708SDavid Chisnall locale::global(const locale& loc)
5987a984708SDavid Chisnall {
5997a984708SDavid Chisnall     locale& g = __global();
6007a984708SDavid Chisnall     locale r = g;
6017a984708SDavid Chisnall     g = loc;
6027a984708SDavid Chisnall     if (g.name() != "*")
6037a984708SDavid Chisnall         setlocale(LC_ALL, g.name().c_str());
6047a984708SDavid Chisnall     return r;
6057a984708SDavid Chisnall }
6067a984708SDavid Chisnall 
6077a984708SDavid Chisnall bool
has_facet(id & x) const6087a984708SDavid Chisnall locale::has_facet(id& x) const
6097a984708SDavid Chisnall {
6107a984708SDavid Chisnall     return __locale_->has_facet(x.__get());
6117a984708SDavid Chisnall }
6127a984708SDavid Chisnall 
6137a984708SDavid Chisnall const locale::facet*
use_facet(id & x) const6147a984708SDavid Chisnall locale::use_facet(id& x) const
6157a984708SDavid Chisnall {
6167a984708SDavid Chisnall     return __locale_->use_facet(x.__get());
6177a984708SDavid Chisnall }
6187a984708SDavid Chisnall 
6197a984708SDavid Chisnall bool
operator ==(const locale & y) const6207a984708SDavid Chisnall locale::operator==(const locale& y) const
6217a984708SDavid Chisnall {
6227a984708SDavid Chisnall     return (__locale_ == y.__locale_)
6237a984708SDavid Chisnall         || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
6247a984708SDavid Chisnall }
6257a984708SDavid Chisnall 
6267a984708SDavid Chisnall // locale::facet
6277a984708SDavid Chisnall 
~facet()6287a984708SDavid Chisnall locale::facet::~facet()
6297a984708SDavid Chisnall {
6307a984708SDavid Chisnall }
6317a984708SDavid Chisnall 
6327a984708SDavid Chisnall void
__on_zero_shared()6337a984708SDavid Chisnall locale::facet::__on_zero_shared() _NOEXCEPT
6347a984708SDavid Chisnall {
6357a984708SDavid Chisnall     delete this;
6367a984708SDavid Chisnall }
6377a984708SDavid Chisnall 
6387a984708SDavid Chisnall // locale::id
6397a984708SDavid Chisnall 
6407a984708SDavid Chisnall int32_t locale::id::__next_id = 0;
6417a984708SDavid Chisnall 
6427a984708SDavid Chisnall namespace
6437a984708SDavid Chisnall {
6447a984708SDavid Chisnall 
6457a984708SDavid Chisnall class __fake_bind
6467a984708SDavid Chisnall {
6477a984708SDavid Chisnall     locale::id* id_;
6487a984708SDavid Chisnall     void (locale::id::* pmf_)();
6497a984708SDavid Chisnall public:
__fake_bind(void (locale::id::* pmf)(),locale::id * id)6507a984708SDavid Chisnall     __fake_bind(void (locale::id::* pmf)(), locale::id* id)
6517a984708SDavid Chisnall         : id_(id), pmf_(pmf) {}
6527a984708SDavid Chisnall 
operator ()() const6537a984708SDavid Chisnall     void operator()() const
6547a984708SDavid Chisnall     {
6557a984708SDavid Chisnall         (id_->*pmf_)();
6567a984708SDavid Chisnall     }
6577a984708SDavid Chisnall };
6587a984708SDavid Chisnall 
6597a984708SDavid Chisnall }
6607a984708SDavid Chisnall 
6617a984708SDavid Chisnall long
__get()6627a984708SDavid Chisnall locale::id::__get()
6637a984708SDavid Chisnall {
6647a984708SDavid Chisnall     call_once(__flag_, __fake_bind(&locale::id::__init, this));
6657a984708SDavid Chisnall     return __id_ - 1;
6667a984708SDavid Chisnall }
6677a984708SDavid Chisnall 
6687a984708SDavid Chisnall void
__init()6697a984708SDavid Chisnall locale::id::__init()
6707a984708SDavid Chisnall {
671b2c7081bSDimitry Andric     __id_ = __libcpp_atomic_add(&__next_id, 1);
6727a984708SDavid Chisnall }
6737a984708SDavid Chisnall 
6747a984708SDavid Chisnall // template <> class collate_byname<char>
6757a984708SDavid Chisnall 
collate_byname(const char * n,size_t refs)6767a984708SDavid Chisnall collate_byname<char>::collate_byname(const char* n, size_t refs)
6777a984708SDavid Chisnall     : collate<char>(refs),
6787a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, n, 0))
6797a984708SDavid Chisnall {
6807a984708SDavid Chisnall     if (__l == 0)
681aed8d94eSDimitry Andric         __throw_runtime_error("collate_byname<char>::collate_byname"
6827a984708SDavid Chisnall                             " failed to construct for " + string(n));
6837a984708SDavid Chisnall }
6847a984708SDavid Chisnall 
collate_byname(const string & name,size_t refs)6857a984708SDavid Chisnall collate_byname<char>::collate_byname(const string& name, size_t refs)
6867a984708SDavid Chisnall     : collate<char>(refs),
6877a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
6887a984708SDavid Chisnall {
6897a984708SDavid Chisnall     if (__l == 0)
690aed8d94eSDimitry Andric         __throw_runtime_error("collate_byname<char>::collate_byname"
6917a984708SDavid Chisnall                             " failed to construct for " + name);
6927a984708SDavid Chisnall }
6937a984708SDavid Chisnall 
~collate_byname()6947a984708SDavid Chisnall collate_byname<char>::~collate_byname()
6957a984708SDavid Chisnall {
6967a984708SDavid Chisnall     freelocale(__l);
6977a984708SDavid Chisnall }
6987a984708SDavid Chisnall 
6997a984708SDavid Chisnall int
do_compare(const char_type * __lo1,const char_type * __hi1,const char_type * __lo2,const char_type * __hi2) const7007a984708SDavid Chisnall collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
7017a984708SDavid Chisnall                                  const char_type* __lo2, const char_type* __hi2) const
7027a984708SDavid Chisnall {
7037a984708SDavid Chisnall     string_type lhs(__lo1, __hi1);
7047a984708SDavid Chisnall     string_type rhs(__lo2, __hi2);
7057a984708SDavid Chisnall     int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
7067a984708SDavid Chisnall     if (r < 0)
7077a984708SDavid Chisnall         return -1;
7087a984708SDavid Chisnall     if (r > 0)
7097a984708SDavid Chisnall         return 1;
7107a984708SDavid Chisnall     return r;
7117a984708SDavid Chisnall }
7127a984708SDavid Chisnall 
7137a984708SDavid Chisnall collate_byname<char>::string_type
do_transform(const char_type * lo,const char_type * hi) const7147a984708SDavid Chisnall collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
7157a984708SDavid Chisnall {
7167a984708SDavid Chisnall     const string_type in(lo, hi);
7177a984708SDavid Chisnall     string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
7187a984708SDavid Chisnall     strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
7197a984708SDavid Chisnall     return out;
7207a984708SDavid Chisnall }
7217a984708SDavid Chisnall 
7227a984708SDavid Chisnall // template <> class collate_byname<wchar_t>
7237a984708SDavid Chisnall 
collate_byname(const char * n,size_t refs)7247a984708SDavid Chisnall collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
7257a984708SDavid Chisnall     : collate<wchar_t>(refs),
7267a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, n, 0))
7277a984708SDavid Chisnall {
7287a984708SDavid Chisnall     if (__l == 0)
729aed8d94eSDimitry Andric         __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
7307a984708SDavid Chisnall                             " failed to construct for " + string(n));
7317a984708SDavid Chisnall }
7327a984708SDavid Chisnall 
collate_byname(const string & name,size_t refs)7337a984708SDavid Chisnall collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
7347a984708SDavid Chisnall     : collate<wchar_t>(refs),
7357a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
7367a984708SDavid Chisnall {
7377a984708SDavid Chisnall     if (__l == 0)
738aed8d94eSDimitry Andric         __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
7397a984708SDavid Chisnall                             " failed to construct for " + name);
7407a984708SDavid Chisnall }
7417a984708SDavid Chisnall 
~collate_byname()7427a984708SDavid Chisnall collate_byname<wchar_t>::~collate_byname()
7437a984708SDavid Chisnall {
7447a984708SDavid Chisnall     freelocale(__l);
7457a984708SDavid Chisnall }
7467a984708SDavid Chisnall 
7477a984708SDavid Chisnall int
do_compare(const char_type * __lo1,const char_type * __hi1,const char_type * __lo2,const char_type * __hi2) const7487a984708SDavid Chisnall collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
7497a984708SDavid Chisnall                                  const char_type* __lo2, const char_type* __hi2) const
7507a984708SDavid Chisnall {
7517a984708SDavid Chisnall     string_type lhs(__lo1, __hi1);
7527a984708SDavid Chisnall     string_type rhs(__lo2, __hi2);
7537a984708SDavid Chisnall     int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
7547a984708SDavid Chisnall     if (r < 0)
7557a984708SDavid Chisnall         return -1;
7567a984708SDavid Chisnall     if (r > 0)
7577a984708SDavid Chisnall         return 1;
7587a984708SDavid Chisnall     return r;
7597a984708SDavid Chisnall }
7607a984708SDavid Chisnall 
7617a984708SDavid Chisnall collate_byname<wchar_t>::string_type
do_transform(const char_type * lo,const char_type * hi) const7627a984708SDavid Chisnall collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
7637a984708SDavid Chisnall {
7647a984708SDavid Chisnall     const string_type in(lo, hi);
7657a984708SDavid Chisnall     string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
7667a984708SDavid Chisnall     wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
7677a984708SDavid Chisnall     return out;
7687a984708SDavid Chisnall }
7697a984708SDavid Chisnall 
7707a984708SDavid Chisnall // template <> class ctype<wchar_t>;
7717a984708SDavid Chisnall 
772cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::space;
773cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::print;
774cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::cntrl;
775cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::upper;
776cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::lower;
777cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::alpha;
778cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::digit;
779cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::punct;
780cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::xdigit;
781cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::blank;
782cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::alnum;
783cfdf2879SDavid Chisnall const ctype_base::mask ctype_base::graph;
784cfdf2879SDavid Chisnall 
7857a984708SDavid Chisnall locale::id ctype<wchar_t>::id;
7867a984708SDavid Chisnall 
~ctype()7877a984708SDavid Chisnall ctype<wchar_t>::~ctype()
7887a984708SDavid Chisnall {
7897a984708SDavid Chisnall }
7907a984708SDavid Chisnall 
7917a984708SDavid Chisnall bool
do_is(mask m,char_type c) const7927a984708SDavid Chisnall ctype<wchar_t>::do_is(mask m, char_type c) const
7937a984708SDavid Chisnall {
7944f7ab58eSDimitry Andric     return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
7957a984708SDavid Chisnall }
7967a984708SDavid Chisnall 
7977a984708SDavid Chisnall const wchar_t*
do_is(const char_type * low,const char_type * high,mask * vec) const7987a984708SDavid Chisnall ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
7997a984708SDavid Chisnall {
8007a984708SDavid Chisnall     for (; low != high; ++low, ++vec)
8017a984708SDavid Chisnall         *vec = static_cast<mask>(isascii(*low) ?
8027a984708SDavid Chisnall                                    ctype<char>::classic_table()[*low] : 0);
8037a984708SDavid Chisnall     return low;
8047a984708SDavid Chisnall }
8057a984708SDavid Chisnall 
8067a984708SDavid Chisnall const wchar_t*
do_scan_is(mask m,const char_type * low,const char_type * high) const8077a984708SDavid Chisnall ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
8087a984708SDavid Chisnall {
8097a984708SDavid Chisnall     for (; low != high; ++low)
8107a984708SDavid Chisnall         if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
8117a984708SDavid Chisnall             break;
8127a984708SDavid Chisnall     return low;
8137a984708SDavid Chisnall }
8147a984708SDavid Chisnall 
8157a984708SDavid Chisnall const wchar_t*
do_scan_not(mask m,const char_type * low,const char_type * high) const8167a984708SDavid Chisnall ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
8177a984708SDavid Chisnall {
8187a984708SDavid Chisnall     for (; low != high; ++low)
8197a984708SDavid Chisnall         if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
8207a984708SDavid Chisnall             break;
8217a984708SDavid Chisnall     return low;
8227a984708SDavid Chisnall }
8237a984708SDavid Chisnall 
8247a984708SDavid Chisnall wchar_t
do_toupper(char_type c) const8257a984708SDavid Chisnall ctype<wchar_t>::do_toupper(char_type c) const
8267a984708SDavid Chisnall {
8277a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8287a984708SDavid Chisnall     return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
8299729cf09SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8309729cf09SDimitry Andric       defined(__NetBSD__)
8317a984708SDavid Chisnall     return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
8327a984708SDavid Chisnall #else
833854fa44bSDimitry Andric     return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
8347a984708SDavid Chisnall #endif
8357a984708SDavid Chisnall }
8367a984708SDavid Chisnall 
8377a984708SDavid Chisnall const wchar_t*
do_toupper(char_type * low,const char_type * high) const8387a984708SDavid Chisnall ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
8397a984708SDavid Chisnall {
8407a984708SDavid Chisnall     for (; low != high; ++low)
8417a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8427a984708SDavid Chisnall         *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
8439729cf09SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8449729cf09SDimitry Andric       defined(__NetBSD__)
8457a984708SDavid Chisnall         *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
8467a984708SDavid Chisnall                              : *low;
8477a984708SDavid Chisnall #else
848854fa44bSDimitry Andric         *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
8497a984708SDavid Chisnall #endif
8507a984708SDavid Chisnall     return low;
8517a984708SDavid Chisnall }
8527a984708SDavid Chisnall 
8537a984708SDavid Chisnall wchar_t
do_tolower(char_type c) const8547a984708SDavid Chisnall ctype<wchar_t>::do_tolower(char_type c) const
8557a984708SDavid Chisnall {
8567a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8577a984708SDavid Chisnall     return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
8589729cf09SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8599729cf09SDimitry Andric       defined(__NetBSD__)
8607a984708SDavid Chisnall     return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
8617a984708SDavid Chisnall #else
862854fa44bSDimitry Andric     return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
8637a984708SDavid Chisnall #endif
8647a984708SDavid Chisnall }
8657a984708SDavid Chisnall 
8667a984708SDavid Chisnall const wchar_t*
do_tolower(char_type * low,const char_type * high) const8677a984708SDavid Chisnall ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
8687a984708SDavid Chisnall {
8697a984708SDavid Chisnall     for (; low != high; ++low)
8707a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8717a984708SDavid Chisnall         *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
8729729cf09SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8739729cf09SDimitry Andric       defined(__NetBSD__)
8747a984708SDavid Chisnall         *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
8757a984708SDavid Chisnall                              : *low;
8767a984708SDavid Chisnall #else
877854fa44bSDimitry Andric         *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
8787a984708SDavid Chisnall #endif
8797a984708SDavid Chisnall     return low;
8807a984708SDavid Chisnall }
8817a984708SDavid Chisnall 
8827a984708SDavid Chisnall wchar_t
do_widen(char c) const8837a984708SDavid Chisnall ctype<wchar_t>::do_widen(char c) const
8847a984708SDavid Chisnall {
8857a984708SDavid Chisnall     return c;
8867a984708SDavid Chisnall }
8877a984708SDavid Chisnall 
8887a984708SDavid Chisnall const char*
do_widen(const char * low,const char * high,char_type * dest) const8897a984708SDavid Chisnall ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
8907a984708SDavid Chisnall {
8917a984708SDavid Chisnall     for (; low != high; ++low, ++dest)
8927a984708SDavid Chisnall         *dest = *low;
8937a984708SDavid Chisnall     return low;
8947a984708SDavid Chisnall }
8957a984708SDavid Chisnall 
8967a984708SDavid Chisnall char
do_narrow(char_type c,char dfault) const8977a984708SDavid Chisnall ctype<wchar_t>::do_narrow(char_type c, char dfault) const
8987a984708SDavid Chisnall {
8997a984708SDavid Chisnall     if (isascii(c))
9007a984708SDavid Chisnall         return static_cast<char>(c);
9017a984708SDavid Chisnall     return dfault;
9027a984708SDavid Chisnall }
9037a984708SDavid Chisnall 
9047a984708SDavid Chisnall const wchar_t*
do_narrow(const char_type * low,const char_type * high,char dfault,char * dest) const9057a984708SDavid Chisnall ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
9067a984708SDavid Chisnall {
9077a984708SDavid Chisnall     for (; low != high; ++low, ++dest)
9087a984708SDavid Chisnall         if (isascii(*low))
90994e3ee44SDavid Chisnall             *dest = static_cast<char>(*low);
9107a984708SDavid Chisnall         else
9117a984708SDavid Chisnall             *dest = dfault;
9127a984708SDavid Chisnall     return low;
9137a984708SDavid Chisnall }
9147a984708SDavid Chisnall 
9157a984708SDavid Chisnall // template <> class ctype<char>;
9167a984708SDavid Chisnall 
9177a984708SDavid Chisnall locale::id ctype<char>::id;
9187a984708SDavid Chisnall 
ctype(const mask * tab,bool del,size_t refs)9197a984708SDavid Chisnall ctype<char>::ctype(const mask* tab, bool del, size_t refs)
9207a984708SDavid Chisnall     : locale::facet(refs),
9217a984708SDavid Chisnall       __tab_(tab),
9227a984708SDavid Chisnall       __del_(del)
9237a984708SDavid Chisnall {
9247a984708SDavid Chisnall   if (__tab_ == 0)
9257a984708SDavid Chisnall       __tab_ = classic_table();
9267a984708SDavid Chisnall }
9277a984708SDavid Chisnall 
~ctype()9287a984708SDavid Chisnall ctype<char>::~ctype()
9297a984708SDavid Chisnall {
9307a984708SDavid Chisnall     if (__tab_ && __del_)
9317a984708SDavid Chisnall         delete [] __tab_;
9327a984708SDavid Chisnall }
9337a984708SDavid Chisnall 
9347a984708SDavid Chisnall char
do_toupper(char_type c) const9357a984708SDavid Chisnall ctype<char>::do_toupper(char_type c) const
9367a984708SDavid Chisnall {
9377a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
93894e3ee44SDavid Chisnall     return isascii(c) ?
93994e3ee44SDavid Chisnall       static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
9404bab9fd9SDavid Chisnall #elif defined(__NetBSD__)
9414bab9fd9SDavid Chisnall     return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
9424f7ab58eSDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
9431bf9f7c1SDimitry Andric     return isascii(c) ?
9444bab9fd9SDavid Chisnall       static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
9457a984708SDavid Chisnall #else
946854fa44bSDimitry Andric     return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
9477a984708SDavid Chisnall #endif
9487a984708SDavid Chisnall }
9497a984708SDavid Chisnall 
9507a984708SDavid Chisnall const char*
do_toupper(char_type * low,const char_type * high) const9517a984708SDavid Chisnall ctype<char>::do_toupper(char_type* low, const char_type* high) const
9527a984708SDavid Chisnall {
9537a984708SDavid Chisnall     for (; low != high; ++low)
9547a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
95594e3ee44SDavid Chisnall         *low = isascii(*low) ?
95694e3ee44SDavid Chisnall           static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
9574bab9fd9SDavid Chisnall #elif defined(__NetBSD__)
9584bab9fd9SDavid Chisnall         *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
9594f7ab58eSDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
9601bf9f7c1SDimitry Andric         *low = isascii(*low) ?
9611bf9f7c1SDimitry Andric           static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
9627a984708SDavid Chisnall #else
963854fa44bSDimitry Andric         *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
9647a984708SDavid Chisnall #endif
9657a984708SDavid Chisnall     return low;
9667a984708SDavid Chisnall }
9677a984708SDavid Chisnall 
9687a984708SDavid Chisnall char
do_tolower(char_type c) const9697a984708SDavid Chisnall ctype<char>::do_tolower(char_type c) const
9707a984708SDavid Chisnall {
9717a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
97294e3ee44SDavid Chisnall     return isascii(c) ?
97394e3ee44SDavid Chisnall       static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
9744bab9fd9SDavid Chisnall #elif defined(__NetBSD__)
9754bab9fd9SDavid Chisnall     return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
9769729cf09SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
9771bf9f7c1SDimitry Andric     return isascii(c) ?
9781bf9f7c1SDimitry Andric       static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
9797a984708SDavid Chisnall #else
980854fa44bSDimitry Andric     return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
9817a984708SDavid Chisnall #endif
9827a984708SDavid Chisnall }
9837a984708SDavid Chisnall 
9847a984708SDavid Chisnall const char*
do_tolower(char_type * low,const char_type * high) const9857a984708SDavid Chisnall ctype<char>::do_tolower(char_type* low, const char_type* high) const
9867a984708SDavid Chisnall {
9877a984708SDavid Chisnall     for (; low != high; ++low)
9887a984708SDavid Chisnall #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
98994e3ee44SDavid Chisnall         *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
9904bab9fd9SDavid Chisnall #elif defined(__NetBSD__)
9914bab9fd9SDavid Chisnall         *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
9924f7ab58eSDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
9931bf9f7c1SDimitry Andric         *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
9947a984708SDavid Chisnall #else
995854fa44bSDimitry Andric         *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
9967a984708SDavid Chisnall #endif
9977a984708SDavid Chisnall     return low;
9987a984708SDavid Chisnall }
9997a984708SDavid Chisnall 
10007a984708SDavid Chisnall char
do_widen(char c) const10017a984708SDavid Chisnall ctype<char>::do_widen(char c) const
10027a984708SDavid Chisnall {
10037a984708SDavid Chisnall     return c;
10047a984708SDavid Chisnall }
10057a984708SDavid Chisnall 
10067a984708SDavid Chisnall const char*
do_widen(const char * low,const char * high,char_type * dest) const10077a984708SDavid Chisnall ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
10087a984708SDavid Chisnall {
10097a984708SDavid Chisnall     for (; low != high; ++low, ++dest)
10107a984708SDavid Chisnall         *dest = *low;
10117a984708SDavid Chisnall     return low;
10127a984708SDavid Chisnall }
10137a984708SDavid Chisnall 
10147a984708SDavid Chisnall char
do_narrow(char_type c,char dfault) const10157a984708SDavid Chisnall ctype<char>::do_narrow(char_type c, char dfault) const
10167a984708SDavid Chisnall {
10177a984708SDavid Chisnall     if (isascii(c))
10187a984708SDavid Chisnall         return static_cast<char>(c);
10197a984708SDavid Chisnall     return dfault;
10207a984708SDavid Chisnall }
10217a984708SDavid Chisnall 
10227a984708SDavid Chisnall const char*
do_narrow(const char_type * low,const char_type * high,char dfault,char * dest) const10237a984708SDavid Chisnall ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
10247a984708SDavid Chisnall {
10257a984708SDavid Chisnall     for (; low != high; ++low, ++dest)
10267a984708SDavid Chisnall         if (isascii(*low))
10277a984708SDavid Chisnall             *dest = *low;
10287a984708SDavid Chisnall         else
10297a984708SDavid Chisnall             *dest = dfault;
10307a984708SDavid Chisnall     return low;
10317a984708SDavid Chisnall }
10327a984708SDavid Chisnall 
10339729cf09SDimitry Andric #if defined(__EMSCRIPTEN__)
10341bf9f7c1SDimitry Andric extern "C" const unsigned short ** __ctype_b_loc();
10351bf9f7c1SDimitry Andric extern "C" const int ** __ctype_tolower_loc();
10361bf9f7c1SDimitry Andric extern "C" const int ** __ctype_toupper_loc();
10371bf9f7c1SDimitry Andric #endif
10381bf9f7c1SDimitry Andric 
1039854fa44bSDimitry Andric #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
1040854fa44bSDimitry Andric const ctype<char>::mask*
classic_table()1041854fa44bSDimitry Andric ctype<char>::classic_table()  _NOEXCEPT
1042854fa44bSDimitry Andric {
1043854fa44bSDimitry Andric     static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1044854fa44bSDimitry Andric         cntrl,                          cntrl,
1045854fa44bSDimitry Andric         cntrl,                          cntrl,
1046854fa44bSDimitry Andric         cntrl,                          cntrl,
1047854fa44bSDimitry Andric         cntrl,                          cntrl,
1048854fa44bSDimitry Andric         cntrl,                          cntrl | space | blank,
1049854fa44bSDimitry Andric         cntrl | space,                  cntrl | space,
1050854fa44bSDimitry Andric         cntrl | space,                  cntrl | space,
1051854fa44bSDimitry Andric         cntrl,                          cntrl,
1052854fa44bSDimitry Andric         cntrl,                          cntrl,
1053854fa44bSDimitry Andric         cntrl,                          cntrl,
1054854fa44bSDimitry Andric         cntrl,                          cntrl,
1055854fa44bSDimitry Andric         cntrl,                          cntrl,
1056854fa44bSDimitry Andric         cntrl,                          cntrl,
1057854fa44bSDimitry Andric         cntrl,                          cntrl,
1058854fa44bSDimitry Andric         cntrl,                          cntrl,
1059854fa44bSDimitry Andric         cntrl,                          cntrl,
1060854fa44bSDimitry Andric         space | blank | print,          punct | print,
1061854fa44bSDimitry Andric         punct | print,                  punct | print,
1062854fa44bSDimitry Andric         punct | print,                  punct | print,
1063854fa44bSDimitry Andric         punct | print,                  punct | print,
1064854fa44bSDimitry Andric         punct | print,                  punct | print,
1065854fa44bSDimitry Andric         punct | print,                  punct | print,
1066854fa44bSDimitry Andric         punct | print,                  punct | print,
1067854fa44bSDimitry Andric         punct | print,                  punct | print,
1068854fa44bSDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
1069854fa44bSDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
1070854fa44bSDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
1071854fa44bSDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
1072854fa44bSDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
1073854fa44bSDimitry Andric         punct | print,                  punct | print,
1074854fa44bSDimitry Andric         punct | print,                  punct | print,
1075854fa44bSDimitry Andric         punct | print,                  punct | print,
1076854fa44bSDimitry Andric         punct | print,                  upper | xdigit | print | alpha,
1077854fa44bSDimitry Andric         upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1078854fa44bSDimitry Andric         upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1079854fa44bSDimitry Andric         upper | xdigit | print | alpha, upper | print | alpha,
1080854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1081854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1082854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1083854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1084854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1085854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1086854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1087854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1088854fa44bSDimitry Andric         upper | print | alpha,          upper | print | alpha,
1089854fa44bSDimitry Andric         upper | print | alpha,          punct | print,
1090854fa44bSDimitry Andric         punct | print,                  punct | print,
1091854fa44bSDimitry Andric         punct | print,                  punct | print,
1092854fa44bSDimitry Andric         punct | print,                  lower | xdigit | print | alpha,
1093854fa44bSDimitry Andric         lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1094854fa44bSDimitry Andric         lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1095854fa44bSDimitry Andric         lower | xdigit | print | alpha, lower | print | alpha,
1096854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1097854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1098854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1099854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1100854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1101854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1102854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1103854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1104854fa44bSDimitry Andric         lower | print | alpha,          lower | print | alpha,
1105854fa44bSDimitry Andric         lower | print | alpha,          punct | print,
1106854fa44bSDimitry Andric         punct | print,                  punct | print,
1107854fa44bSDimitry Andric         punct | print,                  cntrl,
1108854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1109854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1110854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1111854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1112854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1113854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1114854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1115854fa44bSDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1116854fa44bSDimitry Andric     };
1117854fa44bSDimitry Andric     return builtin_table;
1118854fa44bSDimitry Andric }
1119854fa44bSDimitry Andric #else
11207a984708SDavid Chisnall const ctype<char>::mask*
classic_table()11217a984708SDavid Chisnall ctype<char>::classic_table()  _NOEXCEPT
11227a984708SDavid Chisnall {
11237a984708SDavid Chisnall #if defined(__APPLE__) || defined(__FreeBSD__)
11247a984708SDavid Chisnall     return _DefaultRuneLocale.__runetype;
11254bab9fd9SDavid Chisnall #elif defined(__NetBSD__)
11264bab9fd9SDavid Chisnall     return _C_ctype_tab_ + 1;
11277a984708SDavid Chisnall #elif defined(__GLIBC__)
1128854fa44bSDimitry Andric     return _LIBCPP_GET_C_LOCALE->__ctype_b;
112994e3ee44SDavid Chisnall #elif __sun__
113094e3ee44SDavid Chisnall     return __ctype_mask;
11314f7ab58eSDimitry Andric #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
1132aed8d94eSDimitry Andric     return __pctype_func();
11334f7ab58eSDimitry Andric #elif defined(__EMSCRIPTEN__)
11341bf9f7c1SDimitry Andric     return *__ctype_b_loc();
1135854fa44bSDimitry Andric #elif defined(_NEWLIB_VERSION)
1136854fa44bSDimitry Andric     // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1137854fa44bSDimitry Andric     return _ctype_ + 1;
11384f7ab58eSDimitry Andric #elif defined(_AIX)
1139d72607e9SDimitry Andric     return (const unsigned int *)__lc_ctype_ptr->obj->mask;
11407a984708SDavid Chisnall #else
114194e3ee44SDavid Chisnall     // Platform not supported: abort so the person doing the port knows what to
114294e3ee44SDavid Chisnall     // fix
114394e3ee44SDavid Chisnall # warning  ctype<char>::classic_table() is not implemented
11444f7ab58eSDimitry Andric     printf("ctype<char>::classic_table() is not implemented\n");
114594e3ee44SDavid Chisnall     abort();
11467a984708SDavid Chisnall     return NULL;
11477a984708SDavid Chisnall #endif
11487a984708SDavid Chisnall }
1149854fa44bSDimitry Andric #endif
11507a984708SDavid Chisnall 
11517a984708SDavid Chisnall #if defined(__GLIBC__)
11527a984708SDavid Chisnall const int*
__classic_lower_table()11537a984708SDavid Chisnall ctype<char>::__classic_lower_table() _NOEXCEPT
11547a984708SDavid Chisnall {
1155854fa44bSDimitry Andric     return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
11567a984708SDavid Chisnall }
11577a984708SDavid Chisnall 
11587a984708SDavid Chisnall const int*
__classic_upper_table()11597a984708SDavid Chisnall ctype<char>::__classic_upper_table() _NOEXCEPT
11607a984708SDavid Chisnall {
1161854fa44bSDimitry Andric     return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
11627a984708SDavid Chisnall }
11634bab9fd9SDavid Chisnall #elif __NetBSD__
11644bab9fd9SDavid Chisnall const short*
__classic_lower_table()11654bab9fd9SDavid Chisnall ctype<char>::__classic_lower_table() _NOEXCEPT
11664bab9fd9SDavid Chisnall {
11674bab9fd9SDavid Chisnall     return _C_tolower_tab_ + 1;
11684bab9fd9SDavid Chisnall }
11697a984708SDavid Chisnall 
11704bab9fd9SDavid Chisnall const short*
__classic_upper_table()11714bab9fd9SDavid Chisnall ctype<char>::__classic_upper_table() _NOEXCEPT
11724bab9fd9SDavid Chisnall {
11734bab9fd9SDavid Chisnall     return _C_toupper_tab_ + 1;
11744bab9fd9SDavid Chisnall }
11754bab9fd9SDavid Chisnall 
11764f7ab58eSDimitry Andric #elif defined(__EMSCRIPTEN__)
11771bf9f7c1SDimitry Andric const int*
__classic_lower_table()11781bf9f7c1SDimitry Andric ctype<char>::__classic_lower_table() _NOEXCEPT
11791bf9f7c1SDimitry Andric {
11801bf9f7c1SDimitry Andric     return *__ctype_tolower_loc();
11811bf9f7c1SDimitry Andric }
11821bf9f7c1SDimitry Andric 
11831bf9f7c1SDimitry Andric const int*
__classic_upper_table()11841bf9f7c1SDimitry Andric ctype<char>::__classic_upper_table() _NOEXCEPT
11851bf9f7c1SDimitry Andric {
11861bf9f7c1SDimitry Andric     return *__ctype_toupper_loc();
11871bf9f7c1SDimitry Andric }
11889729cf09SDimitry Andric #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
11891bf9f7c1SDimitry Andric 
11907a984708SDavid Chisnall // template <> class ctype_byname<char>
11917a984708SDavid Chisnall 
ctype_byname(const char * name,size_t refs)11927a984708SDavid Chisnall ctype_byname<char>::ctype_byname(const char* name, size_t refs)
11937a984708SDavid Chisnall     : ctype<char>(0, false, refs),
11947a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, name, 0))
11957a984708SDavid Chisnall {
11967a984708SDavid Chisnall     if (__l == 0)
1197aed8d94eSDimitry Andric         __throw_runtime_error("ctype_byname<char>::ctype_byname"
11987a984708SDavid Chisnall                             " failed to construct for " + string(name));
11997a984708SDavid Chisnall }
12007a984708SDavid Chisnall 
ctype_byname(const string & name,size_t refs)12017a984708SDavid Chisnall ctype_byname<char>::ctype_byname(const string& name, size_t refs)
12027a984708SDavid Chisnall     : ctype<char>(0, false, refs),
12037a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
12047a984708SDavid Chisnall {
12057a984708SDavid Chisnall     if (__l == 0)
1206aed8d94eSDimitry Andric         __throw_runtime_error("ctype_byname<char>::ctype_byname"
12077a984708SDavid Chisnall                             " failed to construct for " + name);
12087a984708SDavid Chisnall }
12097a984708SDavid Chisnall 
~ctype_byname()12107a984708SDavid Chisnall ctype_byname<char>::~ctype_byname()
12117a984708SDavid Chisnall {
12127a984708SDavid Chisnall     freelocale(__l);
12137a984708SDavid Chisnall }
12147a984708SDavid Chisnall 
12157a984708SDavid Chisnall char
do_toupper(char_type c) const12167a984708SDavid Chisnall ctype_byname<char>::do_toupper(char_type c) const
12177a984708SDavid Chisnall {
12184bab9fd9SDavid Chisnall     return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
12197a984708SDavid Chisnall }
12207a984708SDavid Chisnall 
12217a984708SDavid Chisnall const char*
do_toupper(char_type * low,const char_type * high) const12227a984708SDavid Chisnall ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
12237a984708SDavid Chisnall {
12247a984708SDavid Chisnall     for (; low != high; ++low)
12254bab9fd9SDavid Chisnall         *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
12267a984708SDavid Chisnall     return low;
12277a984708SDavid Chisnall }
12287a984708SDavid Chisnall 
12297a984708SDavid Chisnall char
do_tolower(char_type c) const12307a984708SDavid Chisnall ctype_byname<char>::do_tolower(char_type c) const
12317a984708SDavid Chisnall {
12324bab9fd9SDavid Chisnall     return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
12337a984708SDavid Chisnall }
12347a984708SDavid Chisnall 
12357a984708SDavid Chisnall const char*
do_tolower(char_type * low,const char_type * high) const12367a984708SDavid Chisnall ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
12377a984708SDavid Chisnall {
12387a984708SDavid Chisnall     for (; low != high; ++low)
12394bab9fd9SDavid Chisnall         *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
12407a984708SDavid Chisnall     return low;
12417a984708SDavid Chisnall }
12427a984708SDavid Chisnall 
12437a984708SDavid Chisnall // template <> class ctype_byname<wchar_t>
12447a984708SDavid Chisnall 
ctype_byname(const char * name,size_t refs)12457a984708SDavid Chisnall ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
12467a984708SDavid Chisnall     : ctype<wchar_t>(refs),
12477a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, name, 0))
12487a984708SDavid Chisnall {
12497a984708SDavid Chisnall     if (__l == 0)
1250aed8d94eSDimitry Andric         __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
12517a984708SDavid Chisnall                             " failed to construct for " + string(name));
12527a984708SDavid Chisnall }
12537a984708SDavid Chisnall 
ctype_byname(const string & name,size_t refs)12547a984708SDavid Chisnall ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
12557a984708SDavid Chisnall     : ctype<wchar_t>(refs),
12567a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
12577a984708SDavid Chisnall {
12587a984708SDavid Chisnall     if (__l == 0)
1259aed8d94eSDimitry Andric         __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
12607a984708SDavid Chisnall                             " failed to construct for " + name);
12617a984708SDavid Chisnall }
12627a984708SDavid Chisnall 
~ctype_byname()12637a984708SDavid Chisnall ctype_byname<wchar_t>::~ctype_byname()
12647a984708SDavid Chisnall {
12657a984708SDavid Chisnall     freelocale(__l);
12667a984708SDavid Chisnall }
12677a984708SDavid Chisnall 
12687a984708SDavid Chisnall bool
do_is(mask m,char_type c) const12697a984708SDavid Chisnall ctype_byname<wchar_t>::do_is(mask m, char_type c) const
12707a984708SDavid Chisnall {
12717a984708SDavid Chisnall #ifdef _LIBCPP_WCTYPE_IS_MASK
12727a984708SDavid Chisnall     return static_cast<bool>(iswctype_l(c, m, __l));
12737a984708SDavid Chisnall #else
1274936e9439SDimitry Andric     bool result = false;
12751bf9f7c1SDimitry Andric     wint_t ch = static_cast<wint_t>(c);
1276854fa44bSDimitry Andric     if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1277854fa44bSDimitry Andric     if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1278854fa44bSDimitry Andric     if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1279854fa44bSDimitry Andric     if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1280854fa44bSDimitry Andric     if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1281854fa44bSDimitry Andric     if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1282854fa44bSDimitry Andric     if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1283854fa44bSDimitry Andric     if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1284854fa44bSDimitry Andric     if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1285854fa44bSDimitry Andric     if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
12867a984708SDavid Chisnall     return result;
12877a984708SDavid Chisnall #endif
12887a984708SDavid Chisnall }
12897a984708SDavid Chisnall 
12907a984708SDavid Chisnall const wchar_t*
do_is(const char_type * low,const char_type * high,mask * vec) const12917a984708SDavid Chisnall ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
12927a984708SDavid Chisnall {
12937a984708SDavid Chisnall     for (; low != high; ++low, ++vec)
12947a984708SDavid Chisnall     {
12957a984708SDavid Chisnall         if (isascii(*low))
12967a984708SDavid Chisnall             *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
12977a984708SDavid Chisnall         else
12987a984708SDavid Chisnall         {
12997a984708SDavid Chisnall             *vec = 0;
13001bf9f7c1SDimitry Andric             wint_t ch = static_cast<wint_t>(*low);
13011bf9f7c1SDimitry Andric             if (iswspace_l(ch, __l))
13027a984708SDavid Chisnall                 *vec |= space;
1303854fa44bSDimitry Andric #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
13041bf9f7c1SDimitry Andric             if (iswprint_l(ch, __l))
13057a984708SDavid Chisnall                 *vec |= print;
1306854fa44bSDimitry Andric #endif
13071bf9f7c1SDimitry Andric             if (iswcntrl_l(ch, __l))
13087a984708SDavid Chisnall                 *vec |= cntrl;
13091bf9f7c1SDimitry Andric             if (iswupper_l(ch, __l))
13107a984708SDavid Chisnall                 *vec |= upper;
13111bf9f7c1SDimitry Andric             if (iswlower_l(ch, __l))
13127a984708SDavid Chisnall                 *vec |= lower;
1313854fa44bSDimitry Andric #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
13141bf9f7c1SDimitry Andric             if (iswalpha_l(ch, __l))
13157a984708SDavid Chisnall                 *vec |= alpha;
1316854fa44bSDimitry Andric #endif
13171bf9f7c1SDimitry Andric             if (iswdigit_l(ch, __l))
13187a984708SDavid Chisnall                 *vec |= digit;
13191bf9f7c1SDimitry Andric             if (iswpunct_l(ch, __l))
13207a984708SDavid Chisnall                 *vec |= punct;
1321854fa44bSDimitry Andric #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
13221bf9f7c1SDimitry Andric             if (iswxdigit_l(ch, __l))
13237a984708SDavid Chisnall                 *vec |= xdigit;
1324854fa44bSDimitry Andric #endif
1325854fa44bSDimitry Andric #if !defined(__sun__)
1326854fa44bSDimitry Andric             if (iswblank_l(ch, __l))
1327854fa44bSDimitry Andric                 *vec |= blank;
1328854fa44bSDimitry Andric #endif
13297a984708SDavid Chisnall         }
13307a984708SDavid Chisnall     }
13317a984708SDavid Chisnall     return low;
13327a984708SDavid Chisnall }
13337a984708SDavid Chisnall 
13347a984708SDavid Chisnall const wchar_t*
do_scan_is(mask m,const char_type * low,const char_type * high) const13357a984708SDavid Chisnall ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
13367a984708SDavid Chisnall {
13377a984708SDavid Chisnall     for (; low != high; ++low)
13387a984708SDavid Chisnall     {
13397a984708SDavid Chisnall #ifdef _LIBCPP_WCTYPE_IS_MASK
13407a984708SDavid Chisnall         if (iswctype_l(*low, m, __l))
13417a984708SDavid Chisnall             break;
13427a984708SDavid Chisnall #else
13431bf9f7c1SDimitry Andric         wint_t ch = static_cast<wint_t>(*low);
1344854fa44bSDimitry Andric         if ((m & space) == space && iswspace_l(ch, __l)) break;
1345854fa44bSDimitry Andric         if ((m & print) == print && iswprint_l(ch, __l)) break;
1346854fa44bSDimitry Andric         if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1347854fa44bSDimitry Andric         if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1348854fa44bSDimitry Andric         if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1349854fa44bSDimitry Andric         if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1350854fa44bSDimitry Andric         if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1351854fa44bSDimitry Andric         if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1352854fa44bSDimitry Andric         if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1353854fa44bSDimitry Andric         if ((m & blank) == blank && iswblank_l(ch, __l)) break;
13547a984708SDavid Chisnall #endif
13557a984708SDavid Chisnall     }
13567a984708SDavid Chisnall     return low;
13577a984708SDavid Chisnall }
13587a984708SDavid Chisnall 
13597a984708SDavid Chisnall const wchar_t*
do_scan_not(mask m,const char_type * low,const char_type * high) const13607a984708SDavid Chisnall ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
13617a984708SDavid Chisnall {
13627a984708SDavid Chisnall     for (; low != high; ++low)
13637a984708SDavid Chisnall     {
13647a984708SDavid Chisnall #ifdef _LIBCPP_WCTYPE_IS_MASK
13657a984708SDavid Chisnall         if (!iswctype_l(*low, m, __l))
13667a984708SDavid Chisnall             break;
13677a984708SDavid Chisnall #else
13681bf9f7c1SDimitry Andric         wint_t ch = static_cast<wint_t>(*low);
1369854fa44bSDimitry Andric         if ((m & space) == space && iswspace_l(ch, __l)) continue;
1370854fa44bSDimitry Andric         if ((m & print) == print && iswprint_l(ch, __l)) continue;
1371854fa44bSDimitry Andric         if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1372854fa44bSDimitry Andric         if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1373854fa44bSDimitry Andric         if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1374854fa44bSDimitry Andric         if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1375854fa44bSDimitry Andric         if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1376854fa44bSDimitry Andric         if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1377854fa44bSDimitry Andric         if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1378854fa44bSDimitry Andric         if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
13797a984708SDavid Chisnall         break;
13807a984708SDavid Chisnall #endif
13817a984708SDavid Chisnall     }
13827a984708SDavid Chisnall     return low;
13837a984708SDavid Chisnall }
13847a984708SDavid Chisnall 
13857a984708SDavid Chisnall wchar_t
do_toupper(char_type c) const13867a984708SDavid Chisnall ctype_byname<wchar_t>::do_toupper(char_type c) const
13877a984708SDavid Chisnall {
13887a984708SDavid Chisnall     return towupper_l(c, __l);
13897a984708SDavid Chisnall }
13907a984708SDavid Chisnall 
13917a984708SDavid Chisnall const wchar_t*
do_toupper(char_type * low,const char_type * high) const13927a984708SDavid Chisnall ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
13937a984708SDavid Chisnall {
13947a984708SDavid Chisnall     for (; low != high; ++low)
13957a984708SDavid Chisnall         *low = towupper_l(*low, __l);
13967a984708SDavid Chisnall     return low;
13977a984708SDavid Chisnall }
13987a984708SDavid Chisnall 
13997a984708SDavid Chisnall wchar_t
do_tolower(char_type c) const14007a984708SDavid Chisnall ctype_byname<wchar_t>::do_tolower(char_type c) const
14017a984708SDavid Chisnall {
14027a984708SDavid Chisnall     return towlower_l(c, __l);
14037a984708SDavid Chisnall }
14047a984708SDavid Chisnall 
14057a984708SDavid Chisnall const wchar_t*
do_tolower(char_type * low,const char_type * high) const14067a984708SDavid Chisnall ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
14077a984708SDavid Chisnall {
14087a984708SDavid Chisnall     for (; low != high; ++low)
14097a984708SDavid Chisnall         *low = towlower_l(*low, __l);
14107a984708SDavid Chisnall     return low;
14117a984708SDavid Chisnall }
14127a984708SDavid Chisnall 
14137a984708SDavid Chisnall wchar_t
do_widen(char c) const14147a984708SDavid Chisnall ctype_byname<wchar_t>::do_widen(char c) const
14157a984708SDavid Chisnall {
14167c82a1ecSDimitry Andric     return __libcpp_btowc_l(c, __l);
14177a984708SDavid Chisnall }
14187a984708SDavid Chisnall 
14197a984708SDavid Chisnall const char*
do_widen(const char * low,const char * high,char_type * dest) const14207a984708SDavid Chisnall ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
14217a984708SDavid Chisnall {
14227a984708SDavid Chisnall     for (; low != high; ++low, ++dest)
14237c82a1ecSDimitry Andric         *dest = __libcpp_btowc_l(*low, __l);
14247a984708SDavid Chisnall     return low;
14257a984708SDavid Chisnall }
14267a984708SDavid Chisnall 
14277a984708SDavid Chisnall char
do_narrow(char_type c,char dfault) const14287a984708SDavid Chisnall ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
14297a984708SDavid Chisnall {
14307c82a1ecSDimitry Andric     int r = __libcpp_wctob_l(c, __l);
1431cfdf2879SDavid Chisnall     return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
14327a984708SDavid Chisnall }
14337a984708SDavid Chisnall 
14347a984708SDavid Chisnall const wchar_t*
do_narrow(const char_type * low,const char_type * high,char dfault,char * dest) const14357a984708SDavid Chisnall ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
14367a984708SDavid Chisnall {
14377a984708SDavid Chisnall     for (; low != high; ++low, ++dest)
14387a984708SDavid Chisnall     {
14397c82a1ecSDimitry Andric         int r = __libcpp_wctob_l(*low, __l);
1440cfdf2879SDavid Chisnall         *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
14417a984708SDavid Chisnall     }
14427a984708SDavid Chisnall     return low;
14437a984708SDavid Chisnall }
14447a984708SDavid Chisnall 
14457a984708SDavid Chisnall // template <> class codecvt<char, char, mbstate_t>
14467a984708SDavid Chisnall 
14477a984708SDavid Chisnall locale::id codecvt<char, char, mbstate_t>::id;
14487a984708SDavid Chisnall 
~codecvt()14497a984708SDavid Chisnall codecvt<char, char, mbstate_t>::~codecvt()
14507a984708SDavid Chisnall {
14517a984708SDavid Chisnall }
14527a984708SDavid Chisnall 
14537a984708SDavid Chisnall codecvt<char, char, mbstate_t>::result
do_out(state_type &,const intern_type * frm,const intern_type *,const intern_type * & frm_nxt,extern_type * to,extern_type *,extern_type * & to_nxt) const14547a984708SDavid Chisnall codecvt<char, char, mbstate_t>::do_out(state_type&,
14557a984708SDavid Chisnall     const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
14567a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
14577a984708SDavid Chisnall {
14587a984708SDavid Chisnall     frm_nxt = frm;
14597a984708SDavid Chisnall     to_nxt = to;
14607a984708SDavid Chisnall     return noconv;
14617a984708SDavid Chisnall }
14627a984708SDavid Chisnall 
14637a984708SDavid Chisnall codecvt<char, char, mbstate_t>::result
do_in(state_type &,const extern_type * frm,const extern_type *,const extern_type * & frm_nxt,intern_type * to,intern_type *,intern_type * & to_nxt) const14647a984708SDavid Chisnall codecvt<char, char, mbstate_t>::do_in(state_type&,
14657a984708SDavid Chisnall     const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
14667a984708SDavid Chisnall     intern_type* to, intern_type*, intern_type*& to_nxt) const
14677a984708SDavid Chisnall {
14687a984708SDavid Chisnall     frm_nxt = frm;
14697a984708SDavid Chisnall     to_nxt = to;
14707a984708SDavid Chisnall     return noconv;
14717a984708SDavid Chisnall }
14727a984708SDavid Chisnall 
14737a984708SDavid Chisnall codecvt<char, char, mbstate_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const14747a984708SDavid Chisnall codecvt<char, char, mbstate_t>::do_unshift(state_type&,
14757a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
14767a984708SDavid Chisnall {
14777a984708SDavid Chisnall     to_nxt = to;
14787a984708SDavid Chisnall     return noconv;
14797a984708SDavid Chisnall }
14807a984708SDavid Chisnall 
14817a984708SDavid Chisnall int
do_encoding() const14827a984708SDavid Chisnall codecvt<char, char, mbstate_t>::do_encoding() const  _NOEXCEPT
14837a984708SDavid Chisnall {
14847a984708SDavid Chisnall     return 1;
14857a984708SDavid Chisnall }
14867a984708SDavid Chisnall 
14877a984708SDavid Chisnall bool
do_always_noconv() const14887a984708SDavid Chisnall codecvt<char, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
14897a984708SDavid Chisnall {
14907a984708SDavid Chisnall     return true;
14917a984708SDavid Chisnall }
14927a984708SDavid Chisnall 
14937a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * end,size_t mx) const14947a984708SDavid Chisnall codecvt<char, char, mbstate_t>::do_length(state_type&,
14957a984708SDavid Chisnall     const extern_type* frm, const extern_type* end, size_t mx) const
14967a984708SDavid Chisnall {
149794e3ee44SDavid Chisnall     return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
14987a984708SDavid Chisnall }
14997a984708SDavid Chisnall 
15007a984708SDavid Chisnall int
do_max_length() const15017a984708SDavid Chisnall codecvt<char, char, mbstate_t>::do_max_length() const  _NOEXCEPT
15027a984708SDavid Chisnall {
15037a984708SDavid Chisnall     return 1;
15047a984708SDavid Chisnall }
15057a984708SDavid Chisnall 
15067a984708SDavid Chisnall // template <> class codecvt<wchar_t, char, mbstate_t>
15077a984708SDavid Chisnall 
15087a984708SDavid Chisnall locale::id codecvt<wchar_t, char, mbstate_t>::id;
15097a984708SDavid Chisnall 
codecvt(size_t refs)15107a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
15117a984708SDavid Chisnall     : locale::facet(refs),
15124bab9fd9SDavid Chisnall       __l(_LIBCPP_GET_C_LOCALE)
15137a984708SDavid Chisnall {
15147a984708SDavid Chisnall }
15157a984708SDavid Chisnall 
codecvt(const char * nm,size_t refs)15167a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
15177a984708SDavid Chisnall     : locale::facet(refs),
15187a984708SDavid Chisnall       __l(newlocale(LC_ALL_MASK, nm, 0))
15197a984708SDavid Chisnall {
15207a984708SDavid Chisnall     if (__l == 0)
1521aed8d94eSDimitry Andric         __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
15227a984708SDavid Chisnall                             " failed to construct for " + string(nm));
15237a984708SDavid Chisnall }
15247a984708SDavid Chisnall 
~codecvt()15257a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::~codecvt()
15267a984708SDavid Chisnall {
15274bab9fd9SDavid Chisnall     if (__l != _LIBCPP_GET_C_LOCALE)
15287a984708SDavid Chisnall         freelocale(__l);
15297a984708SDavid Chisnall }
15307a984708SDavid Chisnall 
15317a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::result
do_out(state_type & st,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const15327a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
15337a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
15347a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
15357a984708SDavid Chisnall {
15367a984708SDavid Chisnall     // look for first internal null in frm
15377a984708SDavid Chisnall     const intern_type* fend = frm;
15387a984708SDavid Chisnall     for (; fend != frm_end; ++fend)
15397a984708SDavid Chisnall         if (*fend == 0)
15407a984708SDavid Chisnall             break;
15417a984708SDavid Chisnall     // loop over all null-terminated sequences in frm
15427a984708SDavid Chisnall     to_nxt = to;
15437a984708SDavid Chisnall     for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
15447a984708SDavid Chisnall     {
15451bf9f7c1SDimitry Andric         // save state in case it is needed to recover to_nxt on error
15467a984708SDavid Chisnall         mbstate_t save_state = st;
15477c82a1ecSDimitry Andric         size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
154894e3ee44SDavid Chisnall                                      static_cast<size_t>(to_end-to), &st, __l);
15497a984708SDavid Chisnall         if (n == size_t(-1))
15507a984708SDavid Chisnall         {
15517a984708SDavid Chisnall             // need to recover to_nxt
15527a984708SDavid Chisnall             for (to_nxt = to; frm != frm_nxt; ++frm)
15537a984708SDavid Chisnall             {
15547c82a1ecSDimitry Andric                 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
15557a984708SDavid Chisnall                 if (n == size_t(-1))
15567a984708SDavid Chisnall                     break;
15577a984708SDavid Chisnall                 to_nxt += n;
15587a984708SDavid Chisnall             }
15597a984708SDavid Chisnall             frm_nxt = frm;
15607a984708SDavid Chisnall             return error;
15617a984708SDavid Chisnall         }
15627a984708SDavid Chisnall         if (n == 0)
15637a984708SDavid Chisnall             return partial;
15647a984708SDavid Chisnall         to_nxt += n;
15657a984708SDavid Chisnall         if (to_nxt == to_end)
15667a984708SDavid Chisnall             break;
15677a984708SDavid Chisnall         if (fend != frm_end)  // set up next null terminated sequence
15687a984708SDavid Chisnall         {
15697a984708SDavid Chisnall             // Try to write the terminating null
15707a984708SDavid Chisnall             extern_type tmp[MB_LEN_MAX];
15717c82a1ecSDimitry Andric             n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
15727a984708SDavid Chisnall             if (n == size_t(-1))  // on error
15737a984708SDavid Chisnall                 return error;
157494e3ee44SDavid Chisnall             if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
15757a984708SDavid Chisnall                 return partial;
15767a984708SDavid Chisnall             for (extern_type* p = tmp; n; --n)  // write it
15777a984708SDavid Chisnall                 *to_nxt++ = *p++;
15787a984708SDavid Chisnall             ++frm_nxt;
15797a984708SDavid Chisnall             // look for next null in frm
15807a984708SDavid Chisnall             for (fend = frm_nxt; fend != frm_end; ++fend)
15817a984708SDavid Chisnall                 if (*fend == 0)
15827a984708SDavid Chisnall                     break;
15837a984708SDavid Chisnall         }
15847a984708SDavid Chisnall     }
15857a984708SDavid Chisnall     return frm_nxt == frm_end ? ok : partial;
15867a984708SDavid Chisnall }
15877a984708SDavid Chisnall 
15887a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::result
do_in(state_type & st,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const15897a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
15907a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
15917a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
15927a984708SDavid Chisnall {
15937a984708SDavid Chisnall     // look for first internal null in frm
15947a984708SDavid Chisnall     const extern_type* fend = frm;
15957a984708SDavid Chisnall     for (; fend != frm_end; ++fend)
15967a984708SDavid Chisnall         if (*fend == 0)
15977a984708SDavid Chisnall             break;
15987a984708SDavid Chisnall     // loop over all null-terminated sequences in frm
15997a984708SDavid Chisnall     to_nxt = to;
16007a984708SDavid Chisnall     for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
16017a984708SDavid Chisnall     {
16021bf9f7c1SDimitry Andric         // save state in case it is needed to recover to_nxt on error
16037a984708SDavid Chisnall         mbstate_t save_state = st;
16047c82a1ecSDimitry Andric         size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
160594e3ee44SDavid Chisnall                                      static_cast<size_t>(to_end-to), &st, __l);
16067a984708SDavid Chisnall         if (n == size_t(-1))
16077a984708SDavid Chisnall         {
16087a984708SDavid Chisnall             // need to recover to_nxt
16097a984708SDavid Chisnall             for (to_nxt = to; frm != frm_nxt; ++to_nxt)
16107a984708SDavid Chisnall             {
16117c82a1ecSDimitry Andric                 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
161294e3ee44SDavid Chisnall                                    &save_state, __l);
16137a984708SDavid Chisnall                 switch (n)
16147a984708SDavid Chisnall                 {
16157a984708SDavid Chisnall                 case 0:
16167a984708SDavid Chisnall                     ++frm;
16177a984708SDavid Chisnall                     break;
161894e3ee44SDavid Chisnall                 case size_t(-1):
16197a984708SDavid Chisnall                     frm_nxt = frm;
16207a984708SDavid Chisnall                     return error;
162194e3ee44SDavid Chisnall                 case size_t(-2):
16227a984708SDavid Chisnall                     frm_nxt = frm;
16237a984708SDavid Chisnall                     return partial;
16247a984708SDavid Chisnall                 default:
16257a984708SDavid Chisnall                     frm += n;
16267a984708SDavid Chisnall                     break;
16277a984708SDavid Chisnall                 }
16287a984708SDavid Chisnall             }
16297a984708SDavid Chisnall             frm_nxt = frm;
16307a984708SDavid Chisnall             return frm_nxt == frm_end ? ok : partial;
16317a984708SDavid Chisnall         }
1632854fa44bSDimitry Andric         if (n == size_t(-1))
16337a984708SDavid Chisnall             return error;
16347a984708SDavid Chisnall         to_nxt += n;
16357a984708SDavid Chisnall         if (to_nxt == to_end)
16367a984708SDavid Chisnall             break;
16377a984708SDavid Chisnall         if (fend != frm_end)  // set up next null terminated sequence
16387a984708SDavid Chisnall         {
16397a984708SDavid Chisnall             // Try to write the terminating null
16407c82a1ecSDimitry Andric             n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
16417a984708SDavid Chisnall             if (n != 0)  // on error
16427a984708SDavid Chisnall                 return error;
16437a984708SDavid Chisnall             ++to_nxt;
16447a984708SDavid Chisnall             ++frm_nxt;
16457a984708SDavid Chisnall             // look for next null in frm
16467a984708SDavid Chisnall             for (fend = frm_nxt; fend != frm_end; ++fend)
16477a984708SDavid Chisnall                 if (*fend == 0)
16487a984708SDavid Chisnall                     break;
16497a984708SDavid Chisnall         }
16507a984708SDavid Chisnall     }
16517a984708SDavid Chisnall     return frm_nxt == frm_end ? ok : partial;
16527a984708SDavid Chisnall }
16537a984708SDavid Chisnall 
16547a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::result
do_unshift(state_type & st,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const16557a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
16567a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
16577a984708SDavid Chisnall {
16587a984708SDavid Chisnall     to_nxt = to;
16597a984708SDavid Chisnall     extern_type tmp[MB_LEN_MAX];
16607c82a1ecSDimitry Andric     size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
16617a984708SDavid Chisnall     if (n == size_t(-1) || n == 0)  // on error
16627a984708SDavid Chisnall         return error;
16637a984708SDavid Chisnall     --n;
166494e3ee44SDavid Chisnall     if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
16657a984708SDavid Chisnall         return partial;
16667a984708SDavid Chisnall     for (extern_type* p = tmp; n; --n)  // write it
16677a984708SDavid Chisnall         *to_nxt++ = *p++;
16687a984708SDavid Chisnall     return ok;
16697a984708SDavid Chisnall }
16707a984708SDavid Chisnall 
16717a984708SDavid Chisnall int
do_encoding() const16727a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
16737a984708SDavid Chisnall {
16747c82a1ecSDimitry Andric     if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
1675854fa44bSDimitry Andric         return -1;
1676854fa44bSDimitry Andric 
16777a984708SDavid Chisnall     // stateless encoding
16787c82a1ecSDimitry Andric     if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1)  // there are no known constant length encodings
16797a984708SDavid Chisnall         return 1;                // which take more than 1 char to form a wchar_t
16807a984708SDavid Chisnall     return 0;
16817a984708SDavid Chisnall }
16827a984708SDavid Chisnall 
16837a984708SDavid Chisnall bool
do_always_noconv() const16847a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
16857a984708SDavid Chisnall {
16867a984708SDavid Chisnall     return false;
16877a984708SDavid Chisnall }
16887a984708SDavid Chisnall 
16897a984708SDavid Chisnall int
do_length(state_type & st,const extern_type * frm,const extern_type * frm_end,size_t mx) const16907a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
16917a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
16927a984708SDavid Chisnall {
16937a984708SDavid Chisnall     int nbytes = 0;
16947a984708SDavid Chisnall     for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
16957a984708SDavid Chisnall     {
16967c82a1ecSDimitry Andric         size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
16977a984708SDavid Chisnall         switch (n)
16987a984708SDavid Chisnall         {
16997a984708SDavid Chisnall         case 0:
17007a984708SDavid Chisnall             ++nbytes;
17017a984708SDavid Chisnall             ++frm;
17027a984708SDavid Chisnall             break;
170394e3ee44SDavid Chisnall         case size_t(-1):
170494e3ee44SDavid Chisnall         case size_t(-2):
17057a984708SDavid Chisnall             return nbytes;
17067a984708SDavid Chisnall         default:
17077a984708SDavid Chisnall             nbytes += n;
17087a984708SDavid Chisnall             frm += n;
17097a984708SDavid Chisnall             break;
17107a984708SDavid Chisnall         }
17117a984708SDavid Chisnall     }
17127a984708SDavid Chisnall     return nbytes;
17137a984708SDavid Chisnall }
17147a984708SDavid Chisnall 
17157a984708SDavid Chisnall int
do_max_length() const17167a984708SDavid Chisnall codecvt<wchar_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
17177a984708SDavid Chisnall {
17187c82a1ecSDimitry Andric     return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
17197a984708SDavid Chisnall }
17207a984708SDavid Chisnall 
17217a984708SDavid Chisnall //                                     Valid UTF ranges
17227a984708SDavid Chisnall //     UTF-32               UTF-16                          UTF-8               # of code points
17237a984708SDavid Chisnall //                     first      second       first   second    third   fourth
17247a984708SDavid Chisnall // 000000 - 00007F  0000 - 007F               00 - 7F                                 127
17257a984708SDavid Chisnall // 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920
17267a984708SDavid Chisnall // 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048
17277a984708SDavid Chisnall // 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152
17287a984708SDavid Chisnall // 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048
17297a984708SDavid Chisnall // 00D800 - 00DFFF                invalid
17307a984708SDavid Chisnall // 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192
17317a984708SDavid Chisnall // 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608
17327a984708SDavid Chisnall // 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432
17337a984708SDavid Chisnall // 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536
17347a984708SDavid Chisnall 
17357a984708SDavid Chisnall static
17367a984708SDavid Chisnall codecvt_base::result
utf16_to_utf8(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))17377a984708SDavid Chisnall utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
17387a984708SDavid Chisnall               uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
17397a984708SDavid Chisnall               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
17407a984708SDavid Chisnall {
17417a984708SDavid Chisnall     frm_nxt = frm;
17427a984708SDavid Chisnall     to_nxt = to;
17437a984708SDavid Chisnall     if (mode & generate_header)
17447a984708SDavid Chisnall     {
17457a984708SDavid Chisnall         if (to_end-to_nxt < 3)
17467a984708SDavid Chisnall             return codecvt_base::partial;
17477a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xEF);
17487a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBB);
17497a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBF);
17507a984708SDavid Chisnall     }
17517a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
17527a984708SDavid Chisnall     {
17537a984708SDavid Chisnall         uint16_t wc1 = *frm_nxt;
17547a984708SDavid Chisnall         if (wc1 > Maxcode)
17557a984708SDavid Chisnall             return codecvt_base::error;
17567a984708SDavid Chisnall         if (wc1 < 0x0080)
17577a984708SDavid Chisnall         {
17587a984708SDavid Chisnall             if (to_end-to_nxt < 1)
17597a984708SDavid Chisnall                 return codecvt_base::partial;
17607a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc1);
17617a984708SDavid Chisnall         }
17627a984708SDavid Chisnall         else if (wc1 < 0x0800)
17637a984708SDavid Chisnall         {
17647a984708SDavid Chisnall             if (to_end-to_nxt < 2)
17657a984708SDavid Chisnall                 return codecvt_base::partial;
17667a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
17677a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
17687a984708SDavid Chisnall         }
17697a984708SDavid Chisnall         else if (wc1 < 0xD800)
17707a984708SDavid Chisnall         {
17717a984708SDavid Chisnall             if (to_end-to_nxt < 3)
17727a984708SDavid Chisnall                 return codecvt_base::partial;
17737a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
17747a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
17757a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
17767a984708SDavid Chisnall         }
17777a984708SDavid Chisnall         else if (wc1 < 0xDC00)
17787a984708SDavid Chisnall         {
17797a984708SDavid Chisnall             if (frm_end-frm_nxt < 2)
17807a984708SDavid Chisnall                 return codecvt_base::partial;
17817a984708SDavid Chisnall             uint16_t wc2 = frm_nxt[1];
17827a984708SDavid Chisnall             if ((wc2 & 0xFC00) != 0xDC00)
17837a984708SDavid Chisnall                 return codecvt_base::error;
17847a984708SDavid Chisnall             if (to_end-to_nxt < 4)
17857a984708SDavid Chisnall                 return codecvt_base::partial;
1786d72607e9SDimitry Andric             if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1787d72607e9SDimitry Andric                 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
17887a984708SDavid Chisnall                 return codecvt_base::error;
17897a984708SDavid Chisnall             ++frm_nxt;
17907a984708SDavid Chisnall             uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
17917a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
17927a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
17937a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
17947a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
17957a984708SDavid Chisnall         }
17967a984708SDavid Chisnall         else if (wc1 < 0xE000)
17977a984708SDavid Chisnall         {
17987a984708SDavid Chisnall             return codecvt_base::error;
17997a984708SDavid Chisnall         }
18007a984708SDavid Chisnall         else
18017a984708SDavid Chisnall         {
18027a984708SDavid Chisnall             if (to_end-to_nxt < 3)
18037a984708SDavid Chisnall                 return codecvt_base::partial;
18047a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
18057a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
18067a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
18077a984708SDavid Chisnall         }
18087a984708SDavid Chisnall     }
18097a984708SDavid Chisnall     return codecvt_base::ok;
18107a984708SDavid Chisnall }
18117a984708SDavid Chisnall 
18127a984708SDavid Chisnall static
18137a984708SDavid Chisnall codecvt_base::result
utf16_to_utf8(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))18147a984708SDavid Chisnall utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
18157a984708SDavid Chisnall               uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
18167a984708SDavid Chisnall               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
18177a984708SDavid Chisnall {
18187a984708SDavid Chisnall     frm_nxt = frm;
18197a984708SDavid Chisnall     to_nxt = to;
18207a984708SDavid Chisnall     if (mode & generate_header)
18217a984708SDavid Chisnall     {
18227a984708SDavid Chisnall         if (to_end-to_nxt < 3)
18237a984708SDavid Chisnall             return codecvt_base::partial;
18247a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xEF);
18257a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBB);
18267a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBF);
18277a984708SDavid Chisnall     }
18287a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
18297a984708SDavid Chisnall     {
18307a984708SDavid Chisnall         uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
18317a984708SDavid Chisnall         if (wc1 > Maxcode)
18327a984708SDavid Chisnall             return codecvt_base::error;
18337a984708SDavid Chisnall         if (wc1 < 0x0080)
18347a984708SDavid Chisnall         {
18357a984708SDavid Chisnall             if (to_end-to_nxt < 1)
18367a984708SDavid Chisnall                 return codecvt_base::partial;
18377a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc1);
18387a984708SDavid Chisnall         }
18397a984708SDavid Chisnall         else if (wc1 < 0x0800)
18407a984708SDavid Chisnall         {
18417a984708SDavid Chisnall             if (to_end-to_nxt < 2)
18427a984708SDavid Chisnall                 return codecvt_base::partial;
18437a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
18447a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
18457a984708SDavid Chisnall         }
18467a984708SDavid Chisnall         else if (wc1 < 0xD800)
18477a984708SDavid Chisnall         {
18487a984708SDavid Chisnall             if (to_end-to_nxt < 3)
18497a984708SDavid Chisnall                 return codecvt_base::partial;
18507a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
18517a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
18527a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
18537a984708SDavid Chisnall         }
18547a984708SDavid Chisnall         else if (wc1 < 0xDC00)
18557a984708SDavid Chisnall         {
18567a984708SDavid Chisnall             if (frm_end-frm_nxt < 2)
18577a984708SDavid Chisnall                 return codecvt_base::partial;
18587a984708SDavid Chisnall             uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
18597a984708SDavid Chisnall             if ((wc2 & 0xFC00) != 0xDC00)
18607a984708SDavid Chisnall                 return codecvt_base::error;
18617a984708SDavid Chisnall             if (to_end-to_nxt < 4)
18627a984708SDavid Chisnall                 return codecvt_base::partial;
1863d72607e9SDimitry Andric             if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1864d72607e9SDimitry Andric                 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
18657a984708SDavid Chisnall                 return codecvt_base::error;
18667a984708SDavid Chisnall             ++frm_nxt;
18677a984708SDavid Chisnall             uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
18687a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
18697a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
18707a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
18717a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
18727a984708SDavid Chisnall         }
18737a984708SDavid Chisnall         else if (wc1 < 0xE000)
18747a984708SDavid Chisnall         {
18757a984708SDavid Chisnall             return codecvt_base::error;
18767a984708SDavid Chisnall         }
18777a984708SDavid Chisnall         else
18787a984708SDavid Chisnall         {
18797a984708SDavid Chisnall             if (to_end-to_nxt < 3)
18807a984708SDavid Chisnall                 return codecvt_base::partial;
18817a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
18827a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
18837a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
18847a984708SDavid Chisnall         }
18857a984708SDavid Chisnall     }
18867a984708SDavid Chisnall     return codecvt_base::ok;
18877a984708SDavid Chisnall }
18887a984708SDavid Chisnall 
18897a984708SDavid Chisnall static
18907a984708SDavid Chisnall codecvt_base::result
utf8_to_utf16(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))18917a984708SDavid Chisnall utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
18927a984708SDavid Chisnall               uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
18937a984708SDavid Chisnall               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
18947a984708SDavid Chisnall {
18957a984708SDavid Chisnall     frm_nxt = frm;
18967a984708SDavid Chisnall     to_nxt = to;
18977a984708SDavid Chisnall     if (mode & consume_header)
18987a984708SDavid Chisnall     {
18997a984708SDavid Chisnall         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
19007a984708SDavid Chisnall                                                           frm_nxt[2] == 0xBF)
19017a984708SDavid Chisnall             frm_nxt += 3;
19027a984708SDavid Chisnall     }
19037a984708SDavid Chisnall     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
19047a984708SDavid Chisnall     {
19057a984708SDavid Chisnall         uint8_t c1 = *frm_nxt;
19067a984708SDavid Chisnall         if (c1 > Maxcode)
19077a984708SDavid Chisnall             return codecvt_base::error;
19087a984708SDavid Chisnall         if (c1 < 0x80)
19097a984708SDavid Chisnall         {
19107a984708SDavid Chisnall             *to_nxt = static_cast<uint16_t>(c1);
19117a984708SDavid Chisnall             ++frm_nxt;
19127a984708SDavid Chisnall         }
19137a984708SDavid Chisnall         else if (c1 < 0xC2)
19147a984708SDavid Chisnall         {
19157a984708SDavid Chisnall             return codecvt_base::error;
19167a984708SDavid Chisnall         }
19177a984708SDavid Chisnall         else if (c1 < 0xE0)
19187a984708SDavid Chisnall         {
19197a984708SDavid Chisnall             if (frm_end-frm_nxt < 2)
19207a984708SDavid Chisnall                 return codecvt_base::partial;
19217a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
19227a984708SDavid Chisnall             if ((c2 & 0xC0) != 0x80)
19237a984708SDavid Chisnall                 return codecvt_base::error;
19247a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
19257a984708SDavid Chisnall             if (t > Maxcode)
19267a984708SDavid Chisnall                 return codecvt_base::error;
19277a984708SDavid Chisnall             *to_nxt = t;
19287a984708SDavid Chisnall             frm_nxt += 2;
19297a984708SDavid Chisnall         }
19307a984708SDavid Chisnall         else if (c1 < 0xF0)
19317a984708SDavid Chisnall         {
19327a984708SDavid Chisnall             if (frm_end-frm_nxt < 3)
19337a984708SDavid Chisnall                 return codecvt_base::partial;
19347a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
19357a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
19367a984708SDavid Chisnall             switch (c1)
19377a984708SDavid Chisnall             {
19387a984708SDavid Chisnall             case 0xE0:
19397a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0xA0)
19407a984708SDavid Chisnall                     return codecvt_base::error;
19417a984708SDavid Chisnall                  break;
19427a984708SDavid Chisnall             case 0xED:
19437a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0x80)
19447a984708SDavid Chisnall                     return codecvt_base::error;
19457a984708SDavid Chisnall                  break;
19467a984708SDavid Chisnall             default:
19477a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
19487a984708SDavid Chisnall                     return codecvt_base::error;
19497a984708SDavid Chisnall                  break;
19507a984708SDavid Chisnall             }
19517a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80)
19527a984708SDavid Chisnall                 return codecvt_base::error;
19537a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
19547a984708SDavid Chisnall                                              | ((c2 & 0x3F) << 6)
19557a984708SDavid Chisnall                                              |  (c3 & 0x3F));
19567a984708SDavid Chisnall             if (t > Maxcode)
19577a984708SDavid Chisnall                 return codecvt_base::error;
19587a984708SDavid Chisnall             *to_nxt = t;
19597a984708SDavid Chisnall             frm_nxt += 3;
19607a984708SDavid Chisnall         }
19617a984708SDavid Chisnall         else if (c1 < 0xF5)
19627a984708SDavid Chisnall         {
19637a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
19647a984708SDavid Chisnall                 return codecvt_base::partial;
19657a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
19667a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
19677a984708SDavid Chisnall             uint8_t c4 = frm_nxt[3];
19687a984708SDavid Chisnall             switch (c1)
19697a984708SDavid Chisnall             {
19707a984708SDavid Chisnall             case 0xF0:
19717a984708SDavid Chisnall                 if (!(0x90 <= c2 && c2 <= 0xBF))
19727a984708SDavid Chisnall                     return codecvt_base::error;
19737a984708SDavid Chisnall                  break;
19747a984708SDavid Chisnall             case 0xF4:
19757a984708SDavid Chisnall                 if ((c2 & 0xF0) != 0x80)
19767a984708SDavid Chisnall                     return codecvt_base::error;
19777a984708SDavid Chisnall                  break;
19787a984708SDavid Chisnall             default:
19797a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
19807a984708SDavid Chisnall                     return codecvt_base::error;
19817a984708SDavid Chisnall                  break;
19827a984708SDavid Chisnall             }
19837a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
19847a984708SDavid Chisnall                 return codecvt_base::error;
19857a984708SDavid Chisnall             if (to_end-to_nxt < 2)
19867a984708SDavid Chisnall                 return codecvt_base::partial;
1987d72607e9SDimitry Andric             if ((((c1 & 7UL) << 18) +
1988d72607e9SDimitry Andric                 ((c2 & 0x3FUL) << 12) +
1989d72607e9SDimitry Andric                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
19907a984708SDavid Chisnall                 return codecvt_base::error;
19917a984708SDavid Chisnall             *to_nxt = static_cast<uint16_t>(
19927a984708SDavid Chisnall                     0xD800
19937a984708SDavid Chisnall                   | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
19947a984708SDavid Chisnall                   | ((c2 & 0x0F) << 2)
19957a984708SDavid Chisnall                   | ((c3 & 0x30) >> 4));
19967a984708SDavid Chisnall             *++to_nxt = static_cast<uint16_t>(
19977a984708SDavid Chisnall                     0xDC00
19987a984708SDavid Chisnall                   | ((c3 & 0x0F) << 6)
19997a984708SDavid Chisnall                   |  (c4 & 0x3F));
20007a984708SDavid Chisnall             frm_nxt += 4;
20017a984708SDavid Chisnall         }
20027a984708SDavid Chisnall         else
20037a984708SDavid Chisnall         {
20047a984708SDavid Chisnall             return codecvt_base::error;
20057a984708SDavid Chisnall         }
20067a984708SDavid Chisnall     }
20077a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
20087a984708SDavid Chisnall }
20097a984708SDavid Chisnall 
20107a984708SDavid Chisnall static
20117a984708SDavid Chisnall codecvt_base::result
utf8_to_utf16(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))20127a984708SDavid Chisnall utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
20137a984708SDavid Chisnall               uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
20147a984708SDavid Chisnall               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
20157a984708SDavid Chisnall {
20167a984708SDavid Chisnall     frm_nxt = frm;
20177a984708SDavid Chisnall     to_nxt = to;
20187a984708SDavid Chisnall     if (mode & consume_header)
20197a984708SDavid Chisnall     {
20207a984708SDavid Chisnall         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
20217a984708SDavid Chisnall                                                           frm_nxt[2] == 0xBF)
20227a984708SDavid Chisnall             frm_nxt += 3;
20237a984708SDavid Chisnall     }
20247a984708SDavid Chisnall     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
20257a984708SDavid Chisnall     {
20267a984708SDavid Chisnall         uint8_t c1 = *frm_nxt;
20277a984708SDavid Chisnall         if (c1 > Maxcode)
20287a984708SDavid Chisnall             return codecvt_base::error;
20297a984708SDavid Chisnall         if (c1 < 0x80)
20307a984708SDavid Chisnall         {
20317a984708SDavid Chisnall             *to_nxt = static_cast<uint32_t>(c1);
20327a984708SDavid Chisnall             ++frm_nxt;
20337a984708SDavid Chisnall         }
20347a984708SDavid Chisnall         else if (c1 < 0xC2)
20357a984708SDavid Chisnall         {
20367a984708SDavid Chisnall             return codecvt_base::error;
20377a984708SDavid Chisnall         }
20387a984708SDavid Chisnall         else if (c1 < 0xE0)
20397a984708SDavid Chisnall         {
20407a984708SDavid Chisnall             if (frm_end-frm_nxt < 2)
20417a984708SDavid Chisnall                 return codecvt_base::partial;
20427a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
20437a984708SDavid Chisnall             if ((c2 & 0xC0) != 0x80)
20447a984708SDavid Chisnall                 return codecvt_base::error;
20457a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
20467a984708SDavid Chisnall             if (t > Maxcode)
20477a984708SDavid Chisnall                 return codecvt_base::error;
20487a984708SDavid Chisnall             *to_nxt = static_cast<uint32_t>(t);
20497a984708SDavid Chisnall             frm_nxt += 2;
20507a984708SDavid Chisnall         }
20517a984708SDavid Chisnall         else if (c1 < 0xF0)
20527a984708SDavid Chisnall         {
20537a984708SDavid Chisnall             if (frm_end-frm_nxt < 3)
20547a984708SDavid Chisnall                 return codecvt_base::partial;
20557a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
20567a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
20577a984708SDavid Chisnall             switch (c1)
20587a984708SDavid Chisnall             {
20597a984708SDavid Chisnall             case 0xE0:
20607a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0xA0)
20617a984708SDavid Chisnall                     return codecvt_base::error;
20627a984708SDavid Chisnall                  break;
20637a984708SDavid Chisnall             case 0xED:
20647a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0x80)
20657a984708SDavid Chisnall                     return codecvt_base::error;
20667a984708SDavid Chisnall                  break;
20677a984708SDavid Chisnall             default:
20687a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
20697a984708SDavid Chisnall                     return codecvt_base::error;
20707a984708SDavid Chisnall                  break;
20717a984708SDavid Chisnall             }
20727a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80)
20737a984708SDavid Chisnall                 return codecvt_base::error;
20747a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
20757a984708SDavid Chisnall                                              | ((c2 & 0x3F) << 6)
20767a984708SDavid Chisnall                                              |  (c3 & 0x3F));
20777a984708SDavid Chisnall             if (t > Maxcode)
20787a984708SDavid Chisnall                 return codecvt_base::error;
20797a984708SDavid Chisnall             *to_nxt = static_cast<uint32_t>(t);
20807a984708SDavid Chisnall             frm_nxt += 3;
20817a984708SDavid Chisnall         }
20827a984708SDavid Chisnall         else if (c1 < 0xF5)
20837a984708SDavid Chisnall         {
20847a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
20857a984708SDavid Chisnall                 return codecvt_base::partial;
20867a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
20877a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
20887a984708SDavid Chisnall             uint8_t c4 = frm_nxt[3];
20897a984708SDavid Chisnall             switch (c1)
20907a984708SDavid Chisnall             {
20917a984708SDavid Chisnall             case 0xF0:
20927a984708SDavid Chisnall                 if (!(0x90 <= c2 && c2 <= 0xBF))
20937a984708SDavid Chisnall                     return codecvt_base::error;
20947a984708SDavid Chisnall                  break;
20957a984708SDavid Chisnall             case 0xF4:
20967a984708SDavid Chisnall                 if ((c2 & 0xF0) != 0x80)
20977a984708SDavid Chisnall                     return codecvt_base::error;
20987a984708SDavid Chisnall                  break;
20997a984708SDavid Chisnall             default:
21007a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
21017a984708SDavid Chisnall                     return codecvt_base::error;
21027a984708SDavid Chisnall                  break;
21037a984708SDavid Chisnall             }
21047a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
21057a984708SDavid Chisnall                 return codecvt_base::error;
21067a984708SDavid Chisnall             if (to_end-to_nxt < 2)
21077a984708SDavid Chisnall                 return codecvt_base::partial;
2108d72607e9SDimitry Andric             if ((((c1 & 7UL) << 18) +
2109d72607e9SDimitry Andric                 ((c2 & 0x3FUL) << 12) +
2110d72607e9SDimitry Andric                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
21117a984708SDavid Chisnall                 return codecvt_base::error;
21127a984708SDavid Chisnall             *to_nxt = static_cast<uint32_t>(
21137a984708SDavid Chisnall                     0xD800
21147a984708SDavid Chisnall                   | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
21157a984708SDavid Chisnall                   | ((c2 & 0x0F) << 2)
21167a984708SDavid Chisnall                   | ((c3 & 0x30) >> 4));
21177a984708SDavid Chisnall             *++to_nxt = static_cast<uint32_t>(
21187a984708SDavid Chisnall                     0xDC00
21197a984708SDavid Chisnall                   | ((c3 & 0x0F) << 6)
21207a984708SDavid Chisnall                   |  (c4 & 0x3F));
21217a984708SDavid Chisnall             frm_nxt += 4;
21227a984708SDavid Chisnall         }
21237a984708SDavid Chisnall         else
21247a984708SDavid Chisnall         {
21257a984708SDavid Chisnall             return codecvt_base::error;
21267a984708SDavid Chisnall         }
21277a984708SDavid Chisnall     }
21287a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
21297a984708SDavid Chisnall }
21307a984708SDavid Chisnall 
21317a984708SDavid Chisnall static
21327a984708SDavid Chisnall int
utf8_to_utf16_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))21337a984708SDavid Chisnall utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
21347a984708SDavid Chisnall                      size_t mx, unsigned long Maxcode = 0x10FFFF,
21357a984708SDavid Chisnall                      codecvt_mode mode = codecvt_mode(0))
21367a984708SDavid Chisnall {
21377a984708SDavid Chisnall     const uint8_t* frm_nxt = frm;
21387a984708SDavid Chisnall     if (mode & consume_header)
21397a984708SDavid Chisnall     {
21407a984708SDavid Chisnall         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
21417a984708SDavid Chisnall                                                           frm_nxt[2] == 0xBF)
21427a984708SDavid Chisnall             frm_nxt += 3;
21437a984708SDavid Chisnall     }
21447a984708SDavid Chisnall     for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
21457a984708SDavid Chisnall     {
21467a984708SDavid Chisnall         uint8_t c1 = *frm_nxt;
21477a984708SDavid Chisnall         if (c1 > Maxcode)
21487a984708SDavid Chisnall             break;
21497a984708SDavid Chisnall         if (c1 < 0x80)
21507a984708SDavid Chisnall         {
21517a984708SDavid Chisnall             ++frm_nxt;
21527a984708SDavid Chisnall         }
21537a984708SDavid Chisnall         else if (c1 < 0xC2)
21547a984708SDavid Chisnall         {
21557a984708SDavid Chisnall             break;
21567a984708SDavid Chisnall         }
21577a984708SDavid Chisnall         else if (c1 < 0xE0)
21587a984708SDavid Chisnall         {
21597a984708SDavid Chisnall             if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
21607a984708SDavid Chisnall                 break;
21617a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
21627a984708SDavid Chisnall             if (t > Maxcode)
21637a984708SDavid Chisnall                 break;
21647a984708SDavid Chisnall             frm_nxt += 2;
21657a984708SDavid Chisnall         }
21667a984708SDavid Chisnall         else if (c1 < 0xF0)
21677a984708SDavid Chisnall         {
21687a984708SDavid Chisnall             if (frm_end-frm_nxt < 3)
21697a984708SDavid Chisnall                 break;
21707a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
21717a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
21727a984708SDavid Chisnall             switch (c1)
21737a984708SDavid Chisnall             {
21747a984708SDavid Chisnall             case 0xE0:
21757a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0xA0)
21767a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
21777a984708SDavid Chisnall                 break;
21787a984708SDavid Chisnall             case 0xED:
21797a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0x80)
21807a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
21817a984708SDavid Chisnall                  break;
21827a984708SDavid Chisnall             default:
21837a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
21847a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
21857a984708SDavid Chisnall                  break;
21867a984708SDavid Chisnall             }
21877a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80)
21887a984708SDavid Chisnall                 break;
218994e3ee44SDavid Chisnall             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
21907a984708SDavid Chisnall                 break;
21917a984708SDavid Chisnall             frm_nxt += 3;
21927a984708SDavid Chisnall         }
21937a984708SDavid Chisnall         else if (c1 < 0xF5)
21947a984708SDavid Chisnall         {
21957a984708SDavid Chisnall             if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
21967a984708SDavid Chisnall                 break;
21977a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
21987a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
21997a984708SDavid Chisnall             uint8_t c4 = frm_nxt[3];
22007a984708SDavid Chisnall             switch (c1)
22017a984708SDavid Chisnall             {
22027a984708SDavid Chisnall             case 0xF0:
22037a984708SDavid Chisnall                 if (!(0x90 <= c2 && c2 <= 0xBF))
22047a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
22057a984708SDavid Chisnall                  break;
22067a984708SDavid Chisnall             case 0xF4:
22077a984708SDavid Chisnall                 if ((c2 & 0xF0) != 0x80)
22087a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
22097a984708SDavid Chisnall                  break;
22107a984708SDavid Chisnall             default:
22117a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
22127a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
22137a984708SDavid Chisnall                  break;
22147a984708SDavid Chisnall             }
22157a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
22167a984708SDavid Chisnall                 break;
2217d72607e9SDimitry Andric             if ((((c1 & 7UL) << 18) +
2218d72607e9SDimitry Andric                 ((c2 & 0x3FUL) << 12) +
2219d72607e9SDimitry Andric                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
22207a984708SDavid Chisnall                 break;
22217a984708SDavid Chisnall             ++nchar16_t;
22227a984708SDavid Chisnall             frm_nxt += 4;
22237a984708SDavid Chisnall         }
22247a984708SDavid Chisnall         else
22257a984708SDavid Chisnall         {
22267a984708SDavid Chisnall             break;
22277a984708SDavid Chisnall         }
22287a984708SDavid Chisnall     }
22297a984708SDavid Chisnall     return static_cast<int>(frm_nxt - frm);
22307a984708SDavid Chisnall }
22317a984708SDavid Chisnall 
22327a984708SDavid Chisnall static
22337a984708SDavid Chisnall codecvt_base::result
ucs4_to_utf8(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))22347a984708SDavid Chisnall ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
22357a984708SDavid Chisnall              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
22367a984708SDavid Chisnall              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
22377a984708SDavid Chisnall {
22387a984708SDavid Chisnall     frm_nxt = frm;
22397a984708SDavid Chisnall     to_nxt = to;
22407a984708SDavid Chisnall     if (mode & generate_header)
22417a984708SDavid Chisnall     {
22427a984708SDavid Chisnall         if (to_end-to_nxt < 3)
22437a984708SDavid Chisnall             return codecvt_base::partial;
22447a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xEF);
22457a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBB);
22467a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBF);
22477a984708SDavid Chisnall     }
22487a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
22497a984708SDavid Chisnall     {
22507a984708SDavid Chisnall         uint32_t wc = *frm_nxt;
22517a984708SDavid Chisnall         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
22527a984708SDavid Chisnall             return codecvt_base::error;
22537a984708SDavid Chisnall         if (wc < 0x000080)
22547a984708SDavid Chisnall         {
22557a984708SDavid Chisnall             if (to_end-to_nxt < 1)
22567a984708SDavid Chisnall                 return codecvt_base::partial;
22577a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc);
22587a984708SDavid Chisnall         }
22597a984708SDavid Chisnall         else if (wc < 0x000800)
22607a984708SDavid Chisnall         {
22617a984708SDavid Chisnall             if (to_end-to_nxt < 2)
22627a984708SDavid Chisnall                 return codecvt_base::partial;
22637a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
22647a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
22657a984708SDavid Chisnall         }
22667a984708SDavid Chisnall         else if (wc < 0x010000)
22677a984708SDavid Chisnall         {
22687a984708SDavid Chisnall             if (to_end-to_nxt < 3)
22697a984708SDavid Chisnall                 return codecvt_base::partial;
22707a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
22717a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
22727a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
22737a984708SDavid Chisnall         }
22747a984708SDavid Chisnall         else // if (wc < 0x110000)
22757a984708SDavid Chisnall         {
22767a984708SDavid Chisnall             if (to_end-to_nxt < 4)
22777a984708SDavid Chisnall                 return codecvt_base::partial;
22787a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xF0 |  (wc >> 18));
22797a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
22807a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
22817a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x00003F));
22827a984708SDavid Chisnall         }
22837a984708SDavid Chisnall     }
22847a984708SDavid Chisnall     return codecvt_base::ok;
22857a984708SDavid Chisnall }
22867a984708SDavid Chisnall 
22877a984708SDavid Chisnall static
22887a984708SDavid Chisnall codecvt_base::result
utf8_to_ucs4(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))22897a984708SDavid Chisnall utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
22907a984708SDavid Chisnall              uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
22917a984708SDavid Chisnall              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
22927a984708SDavid Chisnall {
22937a984708SDavid Chisnall     frm_nxt = frm;
22947a984708SDavid Chisnall     to_nxt = to;
22957a984708SDavid Chisnall     if (mode & consume_header)
22967a984708SDavid Chisnall     {
22977a984708SDavid Chisnall         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
22987a984708SDavid Chisnall                                                           frm_nxt[2] == 0xBF)
22997a984708SDavid Chisnall             frm_nxt += 3;
23007a984708SDavid Chisnall     }
23017a984708SDavid Chisnall     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
23027a984708SDavid Chisnall     {
23037a984708SDavid Chisnall         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
23047a984708SDavid Chisnall         if (c1 < 0x80)
23057a984708SDavid Chisnall         {
23067a984708SDavid Chisnall             if (c1 > Maxcode)
23077a984708SDavid Chisnall                 return codecvt_base::error;
23087a984708SDavid Chisnall             *to_nxt = static_cast<uint32_t>(c1);
23097a984708SDavid Chisnall             ++frm_nxt;
23107a984708SDavid Chisnall         }
23117a984708SDavid Chisnall         else if (c1 < 0xC2)
23127a984708SDavid Chisnall         {
23137a984708SDavid Chisnall             return codecvt_base::error;
23147a984708SDavid Chisnall         }
23157a984708SDavid Chisnall         else if (c1 < 0xE0)
23167a984708SDavid Chisnall         {
23177a984708SDavid Chisnall             if (frm_end-frm_nxt < 2)
23187a984708SDavid Chisnall                 return codecvt_base::partial;
23197a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
23207a984708SDavid Chisnall             if ((c2 & 0xC0) != 0x80)
23217a984708SDavid Chisnall                 return codecvt_base::error;
23227a984708SDavid Chisnall             uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
23237a984708SDavid Chisnall                                               | (c2 & 0x3F));
23247a984708SDavid Chisnall             if (t > Maxcode)
23257a984708SDavid Chisnall                 return codecvt_base::error;
23267a984708SDavid Chisnall             *to_nxt = t;
23277a984708SDavid Chisnall             frm_nxt += 2;
23287a984708SDavid Chisnall         }
23297a984708SDavid Chisnall         else if (c1 < 0xF0)
23307a984708SDavid Chisnall         {
23317a984708SDavid Chisnall             if (frm_end-frm_nxt < 3)
23327a984708SDavid Chisnall                 return codecvt_base::partial;
23337a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
23347a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
23357a984708SDavid Chisnall             switch (c1)
23367a984708SDavid Chisnall             {
23377a984708SDavid Chisnall             case 0xE0:
23387a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0xA0)
23397a984708SDavid Chisnall                     return codecvt_base::error;
23407a984708SDavid Chisnall                  break;
23417a984708SDavid Chisnall             case 0xED:
23427a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0x80)
23437a984708SDavid Chisnall                     return codecvt_base::error;
23447a984708SDavid Chisnall                  break;
23457a984708SDavid Chisnall             default:
23467a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
23477a984708SDavid Chisnall                     return codecvt_base::error;
23487a984708SDavid Chisnall                  break;
23497a984708SDavid Chisnall             }
23507a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80)
23517a984708SDavid Chisnall                 return codecvt_base::error;
23527a984708SDavid Chisnall             uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
23537a984708SDavid Chisnall                                              | ((c2 & 0x3F) << 6)
23547a984708SDavid Chisnall                                              |  (c3 & 0x3F));
23557a984708SDavid Chisnall             if (t > Maxcode)
23567a984708SDavid Chisnall                 return codecvt_base::error;
23577a984708SDavid Chisnall             *to_nxt = t;
23587a984708SDavid Chisnall             frm_nxt += 3;
23597a984708SDavid Chisnall         }
23607a984708SDavid Chisnall         else if (c1 < 0xF5)
23617a984708SDavid Chisnall         {
23627a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
23637a984708SDavid Chisnall                 return codecvt_base::partial;
23647a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
23657a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
23667a984708SDavid Chisnall             uint8_t c4 = frm_nxt[3];
23677a984708SDavid Chisnall             switch (c1)
23687a984708SDavid Chisnall             {
23697a984708SDavid Chisnall             case 0xF0:
23707a984708SDavid Chisnall                 if (!(0x90 <= c2 && c2 <= 0xBF))
23717a984708SDavid Chisnall                     return codecvt_base::error;
23727a984708SDavid Chisnall                  break;
23737a984708SDavid Chisnall             case 0xF4:
23747a984708SDavid Chisnall                 if ((c2 & 0xF0) != 0x80)
23757a984708SDavid Chisnall                     return codecvt_base::error;
23767a984708SDavid Chisnall                  break;
23777a984708SDavid Chisnall             default:
23787a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
23797a984708SDavid Chisnall                     return codecvt_base::error;
23807a984708SDavid Chisnall                  break;
23817a984708SDavid Chisnall             }
23827a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
23837a984708SDavid Chisnall                 return codecvt_base::error;
23847a984708SDavid Chisnall             uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
23857a984708SDavid Chisnall                                              | ((c2 & 0x3F) << 12)
23867a984708SDavid Chisnall                                              | ((c3 & 0x3F) << 6)
23877a984708SDavid Chisnall                                              |  (c4 & 0x3F));
23887a984708SDavid Chisnall             if (t > Maxcode)
23897a984708SDavid Chisnall                 return codecvt_base::error;
23907a984708SDavid Chisnall             *to_nxt = t;
23917a984708SDavid Chisnall             frm_nxt += 4;
23927a984708SDavid Chisnall         }
23937a984708SDavid Chisnall         else
23947a984708SDavid Chisnall         {
23957a984708SDavid Chisnall             return codecvt_base::error;
23967a984708SDavid Chisnall         }
23977a984708SDavid Chisnall     }
23987a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
23997a984708SDavid Chisnall }
24007a984708SDavid Chisnall 
24017a984708SDavid Chisnall static
24027a984708SDavid Chisnall int
utf8_to_ucs4_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))24037a984708SDavid Chisnall utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
24047a984708SDavid Chisnall                     size_t mx, unsigned long Maxcode = 0x10FFFF,
24057a984708SDavid Chisnall                     codecvt_mode mode = codecvt_mode(0))
24067a984708SDavid Chisnall {
24077a984708SDavid Chisnall     const uint8_t* frm_nxt = frm;
24087a984708SDavid Chisnall     if (mode & consume_header)
24097a984708SDavid Chisnall     {
24107a984708SDavid Chisnall         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
24117a984708SDavid Chisnall                                                           frm_nxt[2] == 0xBF)
24127a984708SDavid Chisnall             frm_nxt += 3;
24137a984708SDavid Chisnall     }
24147a984708SDavid Chisnall     for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
24157a984708SDavid Chisnall     {
24167a984708SDavid Chisnall         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
24177a984708SDavid Chisnall         if (c1 < 0x80)
24187a984708SDavid Chisnall         {
24197a984708SDavid Chisnall             if (c1 > Maxcode)
24207a984708SDavid Chisnall                 break;
24217a984708SDavid Chisnall             ++frm_nxt;
24227a984708SDavid Chisnall         }
24237a984708SDavid Chisnall         else if (c1 < 0xC2)
24247a984708SDavid Chisnall         {
24257a984708SDavid Chisnall             break;
24267a984708SDavid Chisnall         }
24277a984708SDavid Chisnall         else if (c1 < 0xE0)
24287a984708SDavid Chisnall         {
24297a984708SDavid Chisnall             if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
24307a984708SDavid Chisnall                 break;
243194e3ee44SDavid Chisnall             if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
24327a984708SDavid Chisnall                 break;
24337a984708SDavid Chisnall             frm_nxt += 2;
24347a984708SDavid Chisnall         }
24357a984708SDavid Chisnall         else if (c1 < 0xF0)
24367a984708SDavid Chisnall         {
24377a984708SDavid Chisnall             if (frm_end-frm_nxt < 3)
24387a984708SDavid Chisnall                 break;
24397a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
24407a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
24417a984708SDavid Chisnall             switch (c1)
24427a984708SDavid Chisnall             {
24437a984708SDavid Chisnall             case 0xE0:
24447a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0xA0)
24457a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
24467a984708SDavid Chisnall                 break;
24477a984708SDavid Chisnall             case 0xED:
24487a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0x80)
24497a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
24507a984708SDavid Chisnall                  break;
24517a984708SDavid Chisnall             default:
24527a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
24537a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
24547a984708SDavid Chisnall                  break;
24557a984708SDavid Chisnall             }
24567a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80)
24577a984708SDavid Chisnall                 break;
245894e3ee44SDavid Chisnall             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
24597a984708SDavid Chisnall                 break;
24607a984708SDavid Chisnall             frm_nxt += 3;
24617a984708SDavid Chisnall         }
24627a984708SDavid Chisnall         else if (c1 < 0xF5)
24637a984708SDavid Chisnall         {
24647a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
24657a984708SDavid Chisnall                 break;
24667a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
24677a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
24687a984708SDavid Chisnall             uint8_t c4 = frm_nxt[3];
24697a984708SDavid Chisnall             switch (c1)
24707a984708SDavid Chisnall             {
24717a984708SDavid Chisnall             case 0xF0:
24727a984708SDavid Chisnall                 if (!(0x90 <= c2 && c2 <= 0xBF))
24737a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
24747a984708SDavid Chisnall                  break;
24757a984708SDavid Chisnall             case 0xF4:
24767a984708SDavid Chisnall                 if ((c2 & 0xF0) != 0x80)
24777a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
24787a984708SDavid Chisnall                  break;
24797a984708SDavid Chisnall             default:
24807a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
24817a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
24827a984708SDavid Chisnall                  break;
24837a984708SDavid Chisnall             }
24847a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
24857a984708SDavid Chisnall                 break;
248694e3ee44SDavid Chisnall             if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
248794e3ee44SDavid Chisnall                  ((c3 & 0x3Fu) << 6)  |  (c4 & 0x3Fu)) > Maxcode)
24887a984708SDavid Chisnall                 break;
24897a984708SDavid Chisnall             frm_nxt += 4;
24907a984708SDavid Chisnall         }
24917a984708SDavid Chisnall         else
24927a984708SDavid Chisnall         {
24937a984708SDavid Chisnall             break;
24947a984708SDavid Chisnall         }
24957a984708SDavid Chisnall     }
24967a984708SDavid Chisnall     return static_cast<int>(frm_nxt - frm);
24977a984708SDavid Chisnall }
24987a984708SDavid Chisnall 
24997a984708SDavid Chisnall static
25007a984708SDavid Chisnall codecvt_base::result
ucs2_to_utf8(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))25017a984708SDavid Chisnall ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
25027a984708SDavid Chisnall              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
25037a984708SDavid Chisnall              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
25047a984708SDavid Chisnall {
25057a984708SDavid Chisnall     frm_nxt = frm;
25067a984708SDavid Chisnall     to_nxt = to;
25077a984708SDavid Chisnall     if (mode & generate_header)
25087a984708SDavid Chisnall     {
25097a984708SDavid Chisnall         if (to_end-to_nxt < 3)
25107a984708SDavid Chisnall             return codecvt_base::partial;
25117a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xEF);
25127a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBB);
25137a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xBF);
25147a984708SDavid Chisnall     }
25157a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
25167a984708SDavid Chisnall     {
25177a984708SDavid Chisnall         uint16_t wc = *frm_nxt;
25187a984708SDavid Chisnall         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
25197a984708SDavid Chisnall             return codecvt_base::error;
25207a984708SDavid Chisnall         if (wc < 0x0080)
25217a984708SDavid Chisnall         {
25227a984708SDavid Chisnall             if (to_end-to_nxt < 1)
25237a984708SDavid Chisnall                 return codecvt_base::partial;
25247a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc);
25257a984708SDavid Chisnall         }
25267a984708SDavid Chisnall         else if (wc < 0x0800)
25277a984708SDavid Chisnall         {
25287a984708SDavid Chisnall             if (to_end-to_nxt < 2)
25297a984708SDavid Chisnall                 return codecvt_base::partial;
25307a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
25317a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
25327a984708SDavid Chisnall         }
25337a984708SDavid Chisnall         else // if (wc <= 0xFFFF)
25347a984708SDavid Chisnall         {
25357a984708SDavid Chisnall             if (to_end-to_nxt < 3)
25367a984708SDavid Chisnall                 return codecvt_base::partial;
25377a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
25387a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
25397a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
25407a984708SDavid Chisnall         }
25417a984708SDavid Chisnall     }
25427a984708SDavid Chisnall     return codecvt_base::ok;
25437a984708SDavid Chisnall }
25447a984708SDavid Chisnall 
25457a984708SDavid Chisnall static
25467a984708SDavid Chisnall codecvt_base::result
utf8_to_ucs2(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))25477a984708SDavid Chisnall utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
25487a984708SDavid Chisnall              uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
25497a984708SDavid Chisnall              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
25507a984708SDavid Chisnall {
25517a984708SDavid Chisnall     frm_nxt = frm;
25527a984708SDavid Chisnall     to_nxt = to;
25537a984708SDavid Chisnall     if (mode & consume_header)
25547a984708SDavid Chisnall     {
25557a984708SDavid Chisnall         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
25567a984708SDavid Chisnall                                                           frm_nxt[2] == 0xBF)
25577a984708SDavid Chisnall             frm_nxt += 3;
25587a984708SDavid Chisnall     }
25597a984708SDavid Chisnall     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
25607a984708SDavid Chisnall     {
25617a984708SDavid Chisnall         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
25627a984708SDavid Chisnall         if (c1 < 0x80)
25637a984708SDavid Chisnall         {
25647a984708SDavid Chisnall             if (c1 > Maxcode)
25657a984708SDavid Chisnall                 return codecvt_base::error;
25667a984708SDavid Chisnall             *to_nxt = static_cast<uint16_t>(c1);
25677a984708SDavid Chisnall             ++frm_nxt;
25687a984708SDavid Chisnall         }
25697a984708SDavid Chisnall         else if (c1 < 0xC2)
25707a984708SDavid Chisnall         {
25717a984708SDavid Chisnall             return codecvt_base::error;
25727a984708SDavid Chisnall         }
25737a984708SDavid Chisnall         else if (c1 < 0xE0)
25747a984708SDavid Chisnall         {
25757a984708SDavid Chisnall             if (frm_end-frm_nxt < 2)
25767a984708SDavid Chisnall                 return codecvt_base::partial;
25777a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
25787a984708SDavid Chisnall             if ((c2 & 0xC0) != 0x80)
25797a984708SDavid Chisnall                 return codecvt_base::error;
25807a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
25817a984708SDavid Chisnall                                               | (c2 & 0x3F));
25827a984708SDavid Chisnall             if (t > Maxcode)
25837a984708SDavid Chisnall                 return codecvt_base::error;
25847a984708SDavid Chisnall             *to_nxt = t;
25857a984708SDavid Chisnall             frm_nxt += 2;
25867a984708SDavid Chisnall         }
25877a984708SDavid Chisnall         else if (c1 < 0xF0)
25887a984708SDavid Chisnall         {
25897a984708SDavid Chisnall             if (frm_end-frm_nxt < 3)
25907a984708SDavid Chisnall                 return codecvt_base::partial;
25917a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
25927a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
25937a984708SDavid Chisnall             switch (c1)
25947a984708SDavid Chisnall             {
25957a984708SDavid Chisnall             case 0xE0:
25967a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0xA0)
25977a984708SDavid Chisnall                     return codecvt_base::error;
25987a984708SDavid Chisnall                  break;
25997a984708SDavid Chisnall             case 0xED:
26007a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0x80)
26017a984708SDavid Chisnall                     return codecvt_base::error;
26027a984708SDavid Chisnall                  break;
26037a984708SDavid Chisnall             default:
26047a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
26057a984708SDavid Chisnall                     return codecvt_base::error;
26067a984708SDavid Chisnall                  break;
26077a984708SDavid Chisnall             }
26087a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80)
26097a984708SDavid Chisnall                 return codecvt_base::error;
26107a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
26117a984708SDavid Chisnall                                              | ((c2 & 0x3F) << 6)
26127a984708SDavid Chisnall                                              |  (c3 & 0x3F));
26137a984708SDavid Chisnall             if (t > Maxcode)
26147a984708SDavid Chisnall                 return codecvt_base::error;
26157a984708SDavid Chisnall             *to_nxt = t;
26167a984708SDavid Chisnall             frm_nxt += 3;
26177a984708SDavid Chisnall         }
26187a984708SDavid Chisnall         else
26197a984708SDavid Chisnall         {
26207a984708SDavid Chisnall             return codecvt_base::error;
26217a984708SDavid Chisnall         }
26227a984708SDavid Chisnall     }
26237a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
26247a984708SDavid Chisnall }
26257a984708SDavid Chisnall 
26267a984708SDavid Chisnall static
26277a984708SDavid Chisnall int
utf8_to_ucs2_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))26287a984708SDavid Chisnall utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
26297a984708SDavid Chisnall                     size_t mx, unsigned long Maxcode = 0x10FFFF,
26307a984708SDavid Chisnall                     codecvt_mode mode = codecvt_mode(0))
26317a984708SDavid Chisnall {
26327a984708SDavid Chisnall     const uint8_t* frm_nxt = frm;
26337a984708SDavid Chisnall     if (mode & consume_header)
26347a984708SDavid Chisnall     {
26357a984708SDavid Chisnall         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
26367a984708SDavid Chisnall                                                           frm_nxt[2] == 0xBF)
26377a984708SDavid Chisnall             frm_nxt += 3;
26387a984708SDavid Chisnall     }
26397a984708SDavid Chisnall     for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
26407a984708SDavid Chisnall     {
26417a984708SDavid Chisnall         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
26427a984708SDavid Chisnall         if (c1 < 0x80)
26437a984708SDavid Chisnall         {
26447a984708SDavid Chisnall             if (c1 > Maxcode)
26457a984708SDavid Chisnall                 break;
26467a984708SDavid Chisnall             ++frm_nxt;
26477a984708SDavid Chisnall         }
26487a984708SDavid Chisnall         else if (c1 < 0xC2)
26497a984708SDavid Chisnall         {
26507a984708SDavid Chisnall             break;
26517a984708SDavid Chisnall         }
26527a984708SDavid Chisnall         else if (c1 < 0xE0)
26537a984708SDavid Chisnall         {
26547a984708SDavid Chisnall             if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
26557a984708SDavid Chisnall                 break;
265694e3ee44SDavid Chisnall             if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
26577a984708SDavid Chisnall                 break;
26587a984708SDavid Chisnall             frm_nxt += 2;
26597a984708SDavid Chisnall         }
26607a984708SDavid Chisnall         else if (c1 < 0xF0)
26617a984708SDavid Chisnall         {
26627a984708SDavid Chisnall             if (frm_end-frm_nxt < 3)
26637a984708SDavid Chisnall                 break;
26647a984708SDavid Chisnall             uint8_t c2 = frm_nxt[1];
26657a984708SDavid Chisnall             uint8_t c3 = frm_nxt[2];
26667a984708SDavid Chisnall             switch (c1)
26677a984708SDavid Chisnall             {
26687a984708SDavid Chisnall             case 0xE0:
26697a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0xA0)
26707a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
26717a984708SDavid Chisnall                 break;
26727a984708SDavid Chisnall             case 0xED:
26737a984708SDavid Chisnall                 if ((c2 & 0xE0) != 0x80)
26747a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
26757a984708SDavid Chisnall                  break;
26767a984708SDavid Chisnall             default:
26777a984708SDavid Chisnall                 if ((c2 & 0xC0) != 0x80)
26787a984708SDavid Chisnall                     return static_cast<int>(frm_nxt - frm);
26797a984708SDavid Chisnall                  break;
26807a984708SDavid Chisnall             }
26817a984708SDavid Chisnall             if ((c3 & 0xC0) != 0x80)
26827a984708SDavid Chisnall                 break;
268394e3ee44SDavid Chisnall             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
26847a984708SDavid Chisnall                 break;
26857a984708SDavid Chisnall             frm_nxt += 3;
26867a984708SDavid Chisnall         }
26877a984708SDavid Chisnall         else
26887a984708SDavid Chisnall         {
26897a984708SDavid Chisnall             break;
26907a984708SDavid Chisnall         }
26917a984708SDavid Chisnall     }
26927a984708SDavid Chisnall     return static_cast<int>(frm_nxt - frm);
26937a984708SDavid Chisnall }
26947a984708SDavid Chisnall 
26957a984708SDavid Chisnall static
26967a984708SDavid Chisnall codecvt_base::result
ucs4_to_utf16be(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))26977a984708SDavid Chisnall ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
26987a984708SDavid Chisnall                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
26997a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
27007a984708SDavid Chisnall {
27017a984708SDavid Chisnall     frm_nxt = frm;
27027a984708SDavid Chisnall     to_nxt = to;
27037a984708SDavid Chisnall     if (mode & generate_header)
27047a984708SDavid Chisnall     {
27057a984708SDavid Chisnall         if (to_end-to_nxt < 2)
27067a984708SDavid Chisnall             return codecvt_base::partial;
27077a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFE);
27087a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFF);
27097a984708SDavid Chisnall     }
27107a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
27117a984708SDavid Chisnall     {
27127a984708SDavid Chisnall         uint32_t wc = *frm_nxt;
27137a984708SDavid Chisnall         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
27147a984708SDavid Chisnall             return codecvt_base::error;
27157a984708SDavid Chisnall         if (wc < 0x010000)
27167a984708SDavid Chisnall         {
27177a984708SDavid Chisnall             if (to_end-to_nxt < 2)
27187a984708SDavid Chisnall                 return codecvt_base::partial;
27197a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc >> 8);
27207a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc);
27217a984708SDavid Chisnall         }
27227a984708SDavid Chisnall         else
27237a984708SDavid Chisnall         {
27247a984708SDavid Chisnall             if (to_end-to_nxt < 4)
27257a984708SDavid Chisnall                 return codecvt_base::partial;
27267a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(
27277a984708SDavid Chisnall                     0xD800
27287a984708SDavid Chisnall                   | ((((wc & 0x1F0000) >> 16) - 1) << 6)
27297a984708SDavid Chisnall                   |   ((wc & 0x00FC00) >> 10));
27307a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t >> 8);
27317a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t);
27327a984708SDavid Chisnall             t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
27337a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t >> 8);
27347a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t);
27357a984708SDavid Chisnall         }
27367a984708SDavid Chisnall     }
27377a984708SDavid Chisnall     return codecvt_base::ok;
27387a984708SDavid Chisnall }
27397a984708SDavid Chisnall 
27407a984708SDavid Chisnall static
27417a984708SDavid Chisnall codecvt_base::result
utf16be_to_ucs4(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))27427a984708SDavid Chisnall utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
27437a984708SDavid Chisnall                 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
27447a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
27457a984708SDavid Chisnall {
27467a984708SDavid Chisnall     frm_nxt = frm;
27477a984708SDavid Chisnall     to_nxt = to;
27487a984708SDavid Chisnall     if (mode & consume_header)
27497a984708SDavid Chisnall     {
27507a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
27517a984708SDavid Chisnall             frm_nxt += 2;
27527a984708SDavid Chisnall     }
27537a984708SDavid Chisnall     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
27547a984708SDavid Chisnall     {
275594e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
27567a984708SDavid Chisnall         if ((c1 & 0xFC00) == 0xDC00)
27577a984708SDavid Chisnall             return codecvt_base::error;
27587a984708SDavid Chisnall         if ((c1 & 0xFC00) != 0xD800)
27597a984708SDavid Chisnall         {
27607a984708SDavid Chisnall             if (c1 > Maxcode)
27617a984708SDavid Chisnall                 return codecvt_base::error;
27627a984708SDavid Chisnall             *to_nxt = static_cast<uint32_t>(c1);
27637a984708SDavid Chisnall             frm_nxt += 2;
27647a984708SDavid Chisnall         }
27657a984708SDavid Chisnall         else
27667a984708SDavid Chisnall         {
27677a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
27687a984708SDavid Chisnall                 return codecvt_base::partial;
276994e3ee44SDavid Chisnall             uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
27707a984708SDavid Chisnall             if ((c2 & 0xFC00) != 0xDC00)
27717a984708SDavid Chisnall                 return codecvt_base::error;
27727a984708SDavid Chisnall             uint32_t t = static_cast<uint32_t>(
27737a984708SDavid Chisnall                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
27747a984708SDavid Chisnall                   |   ((c1 & 0x003F) << 10)
27757a984708SDavid Chisnall                   |    (c2 & 0x03FF));
27767a984708SDavid Chisnall             if (t > Maxcode)
27777a984708SDavid Chisnall                 return codecvt_base::error;
27787a984708SDavid Chisnall             *to_nxt = t;
27797a984708SDavid Chisnall             frm_nxt += 4;
27807a984708SDavid Chisnall         }
27817a984708SDavid Chisnall     }
27827a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
27837a984708SDavid Chisnall }
27847a984708SDavid Chisnall 
27857a984708SDavid Chisnall static
27867a984708SDavid Chisnall int
utf16be_to_ucs4_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))27877a984708SDavid Chisnall utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
27887a984708SDavid Chisnall                        size_t mx, unsigned long Maxcode = 0x10FFFF,
27897a984708SDavid Chisnall                        codecvt_mode mode = codecvt_mode(0))
27907a984708SDavid Chisnall {
27917a984708SDavid Chisnall     const uint8_t* frm_nxt = frm;
27927a984708SDavid Chisnall     if (mode & consume_header)
27937a984708SDavid Chisnall     {
27947a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
27957a984708SDavid Chisnall             frm_nxt += 2;
27967a984708SDavid Chisnall     }
27977a984708SDavid Chisnall     for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
27987a984708SDavid Chisnall     {
279994e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
28007a984708SDavid Chisnall         if ((c1 & 0xFC00) == 0xDC00)
28017a984708SDavid Chisnall             break;
28027a984708SDavid Chisnall         if ((c1 & 0xFC00) != 0xD800)
28037a984708SDavid Chisnall         {
28047a984708SDavid Chisnall             if (c1 > Maxcode)
28057a984708SDavid Chisnall                 break;
28067a984708SDavid Chisnall             frm_nxt += 2;
28077a984708SDavid Chisnall         }
28087a984708SDavid Chisnall         else
28097a984708SDavid Chisnall         {
28107a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
28117a984708SDavid Chisnall                 break;
281294e3ee44SDavid Chisnall             uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
28137a984708SDavid Chisnall             if ((c2 & 0xFC00) != 0xDC00)
28147a984708SDavid Chisnall                 break;
28157a984708SDavid Chisnall             uint32_t t = static_cast<uint32_t>(
28167a984708SDavid Chisnall                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
28177a984708SDavid Chisnall                   |   ((c1 & 0x003F) << 10)
28187a984708SDavid Chisnall                   |    (c2 & 0x03FF));
28197a984708SDavid Chisnall             if (t > Maxcode)
28207a984708SDavid Chisnall                 break;
28217a984708SDavid Chisnall             frm_nxt += 4;
28227a984708SDavid Chisnall         }
28237a984708SDavid Chisnall     }
28247a984708SDavid Chisnall     return static_cast<int>(frm_nxt - frm);
28257a984708SDavid Chisnall }
28267a984708SDavid Chisnall 
28277a984708SDavid Chisnall static
28287a984708SDavid Chisnall codecvt_base::result
ucs4_to_utf16le(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))28297a984708SDavid Chisnall ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
28307a984708SDavid Chisnall                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
28317a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
28327a984708SDavid Chisnall {
28337a984708SDavid Chisnall     frm_nxt = frm;
28347a984708SDavid Chisnall     to_nxt = to;
28357a984708SDavid Chisnall     if (mode & generate_header)
28367a984708SDavid Chisnall     {
28377a984708SDavid Chisnall         if (to_end - to_nxt < 2)
28387a984708SDavid Chisnall             return codecvt_base::partial;
28397a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFF);
28407a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFE);
28417a984708SDavid Chisnall     }
28427a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
28437a984708SDavid Chisnall     {
28447a984708SDavid Chisnall         uint32_t wc = *frm_nxt;
28457a984708SDavid Chisnall         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
28467a984708SDavid Chisnall             return codecvt_base::error;
28477a984708SDavid Chisnall         if (wc < 0x010000)
28487a984708SDavid Chisnall         {
28497a984708SDavid Chisnall             if (to_end-to_nxt < 2)
28507a984708SDavid Chisnall                 return codecvt_base::partial;
28517a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc);
28527a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(wc >> 8);
28537a984708SDavid Chisnall         }
28547a984708SDavid Chisnall         else
28557a984708SDavid Chisnall         {
28567a984708SDavid Chisnall             if (to_end-to_nxt < 4)
28577a984708SDavid Chisnall                 return codecvt_base::partial;
28587a984708SDavid Chisnall             uint16_t t = static_cast<uint16_t>(
28597a984708SDavid Chisnall                     0xD800
28607a984708SDavid Chisnall                   | ((((wc & 0x1F0000) >> 16) - 1) << 6)
28617a984708SDavid Chisnall                   |   ((wc & 0x00FC00) >> 10));
28627a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t);
28637a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t >> 8);
28647a984708SDavid Chisnall             t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
28657a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t);
28667a984708SDavid Chisnall             *to_nxt++ = static_cast<uint8_t>(t >> 8);
28677a984708SDavid Chisnall         }
28687a984708SDavid Chisnall     }
28697a984708SDavid Chisnall     return codecvt_base::ok;
28707a984708SDavid Chisnall }
28717a984708SDavid Chisnall 
28727a984708SDavid Chisnall static
28737a984708SDavid Chisnall codecvt_base::result
utf16le_to_ucs4(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))28747a984708SDavid Chisnall utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
28757a984708SDavid Chisnall                 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
28767a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
28777a984708SDavid Chisnall {
28787a984708SDavid Chisnall     frm_nxt = frm;
28797a984708SDavid Chisnall     to_nxt = to;
28807a984708SDavid Chisnall     if (mode & consume_header)
28817a984708SDavid Chisnall     {
28827a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
28837a984708SDavid Chisnall             frm_nxt += 2;
28847a984708SDavid Chisnall     }
28857a984708SDavid Chisnall     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
28867a984708SDavid Chisnall     {
288794e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
28887a984708SDavid Chisnall         if ((c1 & 0xFC00) == 0xDC00)
28897a984708SDavid Chisnall             return codecvt_base::error;
28907a984708SDavid Chisnall         if ((c1 & 0xFC00) != 0xD800)
28917a984708SDavid Chisnall         {
28927a984708SDavid Chisnall             if (c1 > Maxcode)
28937a984708SDavid Chisnall                 return codecvt_base::error;
28947a984708SDavid Chisnall             *to_nxt = static_cast<uint32_t>(c1);
28957a984708SDavid Chisnall             frm_nxt += 2;
28967a984708SDavid Chisnall         }
28977a984708SDavid Chisnall         else
28987a984708SDavid Chisnall         {
28997a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
29007a984708SDavid Chisnall                 return codecvt_base::partial;
290194e3ee44SDavid Chisnall             uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
29027a984708SDavid Chisnall             if ((c2 & 0xFC00) != 0xDC00)
29037a984708SDavid Chisnall                 return codecvt_base::error;
29047a984708SDavid Chisnall             uint32_t t = static_cast<uint32_t>(
29057a984708SDavid Chisnall                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
29067a984708SDavid Chisnall                   |   ((c1 & 0x003F) << 10)
29077a984708SDavid Chisnall                   |    (c2 & 0x03FF));
29087a984708SDavid Chisnall             if (t > Maxcode)
29097a984708SDavid Chisnall                 return codecvt_base::error;
29107a984708SDavid Chisnall             *to_nxt = t;
29117a984708SDavid Chisnall             frm_nxt += 4;
29127a984708SDavid Chisnall         }
29137a984708SDavid Chisnall     }
29147a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
29157a984708SDavid Chisnall }
29167a984708SDavid Chisnall 
29177a984708SDavid Chisnall static
29187a984708SDavid Chisnall int
utf16le_to_ucs4_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))29197a984708SDavid Chisnall utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
29207a984708SDavid Chisnall                        size_t mx, unsigned long Maxcode = 0x10FFFF,
29217a984708SDavid Chisnall                        codecvt_mode mode = codecvt_mode(0))
29227a984708SDavid Chisnall {
29237a984708SDavid Chisnall     const uint8_t* frm_nxt = frm;
29247a984708SDavid Chisnall     if (mode & consume_header)
29257a984708SDavid Chisnall     {
29267a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
29277a984708SDavid Chisnall             frm_nxt += 2;
29287a984708SDavid Chisnall     }
29297a984708SDavid Chisnall     for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
29307a984708SDavid Chisnall     {
293194e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
29327a984708SDavid Chisnall         if ((c1 & 0xFC00) == 0xDC00)
29337a984708SDavid Chisnall             break;
29347a984708SDavid Chisnall         if ((c1 & 0xFC00) != 0xD800)
29357a984708SDavid Chisnall         {
29367a984708SDavid Chisnall             if (c1 > Maxcode)
29377a984708SDavid Chisnall                 break;
29387a984708SDavid Chisnall             frm_nxt += 2;
29397a984708SDavid Chisnall         }
29407a984708SDavid Chisnall         else
29417a984708SDavid Chisnall         {
29427a984708SDavid Chisnall             if (frm_end-frm_nxt < 4)
29437a984708SDavid Chisnall                 break;
294494e3ee44SDavid Chisnall             uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
29457a984708SDavid Chisnall             if ((c2 & 0xFC00) != 0xDC00)
29467a984708SDavid Chisnall                 break;
29477a984708SDavid Chisnall             uint32_t t = static_cast<uint32_t>(
29487a984708SDavid Chisnall                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
29497a984708SDavid Chisnall                   |   ((c1 & 0x003F) << 10)
29507a984708SDavid Chisnall                   |    (c2 & 0x03FF));
29517a984708SDavid Chisnall             if (t > Maxcode)
29527a984708SDavid Chisnall                 break;
29537a984708SDavid Chisnall             frm_nxt += 4;
29547a984708SDavid Chisnall         }
29557a984708SDavid Chisnall     }
29567a984708SDavid Chisnall     return static_cast<int>(frm_nxt - frm);
29577a984708SDavid Chisnall }
29587a984708SDavid Chisnall 
29597a984708SDavid Chisnall static
29607a984708SDavid Chisnall codecvt_base::result
ucs2_to_utf16be(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))29617a984708SDavid Chisnall ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
29627a984708SDavid Chisnall                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
29637a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
29647a984708SDavid Chisnall {
29657a984708SDavid Chisnall     frm_nxt = frm;
29667a984708SDavid Chisnall     to_nxt = to;
29677a984708SDavid Chisnall     if (mode & generate_header)
29687a984708SDavid Chisnall     {
29697a984708SDavid Chisnall         if (to_end-to_nxt < 2)
29707a984708SDavid Chisnall             return codecvt_base::partial;
29717a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFE);
29727a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFF);
29737a984708SDavid Chisnall     }
29747a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
29757a984708SDavid Chisnall     {
29767a984708SDavid Chisnall         uint16_t wc = *frm_nxt;
29777a984708SDavid Chisnall         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
29787a984708SDavid Chisnall             return codecvt_base::error;
29797a984708SDavid Chisnall         if (to_end-to_nxt < 2)
29807a984708SDavid Chisnall             return codecvt_base::partial;
29817a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(wc >> 8);
29827a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(wc);
29837a984708SDavid Chisnall     }
29847a984708SDavid Chisnall     return codecvt_base::ok;
29857a984708SDavid Chisnall }
29867a984708SDavid Chisnall 
29877a984708SDavid Chisnall static
29887a984708SDavid Chisnall codecvt_base::result
utf16be_to_ucs2(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))29897a984708SDavid Chisnall utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
29907a984708SDavid Chisnall                 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
29917a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
29927a984708SDavid Chisnall {
29937a984708SDavid Chisnall     frm_nxt = frm;
29947a984708SDavid Chisnall     to_nxt = to;
29957a984708SDavid Chisnall     if (mode & consume_header)
29967a984708SDavid Chisnall     {
29977a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
29987a984708SDavid Chisnall             frm_nxt += 2;
29997a984708SDavid Chisnall     }
30007a984708SDavid Chisnall     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
30017a984708SDavid Chisnall     {
300294e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
30037a984708SDavid Chisnall         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
30047a984708SDavid Chisnall             return codecvt_base::error;
30057a984708SDavid Chisnall         *to_nxt = c1;
30067a984708SDavid Chisnall         frm_nxt += 2;
30077a984708SDavid Chisnall     }
30087a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
30097a984708SDavid Chisnall }
30107a984708SDavid Chisnall 
30117a984708SDavid Chisnall static
30127a984708SDavid Chisnall int
utf16be_to_ucs2_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))30137a984708SDavid Chisnall utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
30147a984708SDavid Chisnall                        size_t mx, unsigned long Maxcode = 0x10FFFF,
30157a984708SDavid Chisnall                        codecvt_mode mode = codecvt_mode(0))
30167a984708SDavid Chisnall {
30177a984708SDavid Chisnall     const uint8_t* frm_nxt = frm;
30187a984708SDavid Chisnall     if (mode & consume_header)
30197a984708SDavid Chisnall     {
30207a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
30217a984708SDavid Chisnall             frm_nxt += 2;
30227a984708SDavid Chisnall     }
30237a984708SDavid Chisnall     for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
30247a984708SDavid Chisnall     {
302594e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
30267a984708SDavid Chisnall         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
30277a984708SDavid Chisnall             break;
30287a984708SDavid Chisnall         frm_nxt += 2;
30297a984708SDavid Chisnall     }
30307a984708SDavid Chisnall     return static_cast<int>(frm_nxt - frm);
30317a984708SDavid Chisnall }
30327a984708SDavid Chisnall 
30337a984708SDavid Chisnall static
30347a984708SDavid Chisnall codecvt_base::result
ucs2_to_utf16le(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))30357a984708SDavid Chisnall ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
30367a984708SDavid Chisnall                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
30377a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
30387a984708SDavid Chisnall {
30397a984708SDavid Chisnall     frm_nxt = frm;
30407a984708SDavid Chisnall     to_nxt = to;
30417a984708SDavid Chisnall     if (mode & generate_header)
30427a984708SDavid Chisnall     {
30437a984708SDavid Chisnall         if (to_end-to_nxt < 2)
30447a984708SDavid Chisnall             return codecvt_base::partial;
30457a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFF);
30467a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(0xFE);
30477a984708SDavid Chisnall     }
30487a984708SDavid Chisnall     for (; frm_nxt < frm_end; ++frm_nxt)
30497a984708SDavid Chisnall     {
30507a984708SDavid Chisnall         uint16_t wc = *frm_nxt;
30517a984708SDavid Chisnall         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
30527a984708SDavid Chisnall             return codecvt_base::error;
30537a984708SDavid Chisnall         if (to_end-to_nxt < 2)
30547a984708SDavid Chisnall             return codecvt_base::partial;
30557a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(wc);
30567a984708SDavid Chisnall         *to_nxt++ = static_cast<uint8_t>(wc >> 8);
30577a984708SDavid Chisnall     }
30587a984708SDavid Chisnall     return codecvt_base::ok;
30597a984708SDavid Chisnall }
30607a984708SDavid Chisnall 
30617a984708SDavid Chisnall static
30627a984708SDavid Chisnall codecvt_base::result
utf16le_to_ucs2(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))30637a984708SDavid Chisnall utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
30647a984708SDavid Chisnall                 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
30657a984708SDavid Chisnall                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
30667a984708SDavid Chisnall {
30677a984708SDavid Chisnall     frm_nxt = frm;
30687a984708SDavid Chisnall     to_nxt = to;
30697a984708SDavid Chisnall     if (mode & consume_header)
30707a984708SDavid Chisnall     {
30717a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
30727a984708SDavid Chisnall             frm_nxt += 2;
30737a984708SDavid Chisnall     }
30747a984708SDavid Chisnall     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
30757a984708SDavid Chisnall     {
307694e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
30777a984708SDavid Chisnall         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
30787a984708SDavid Chisnall             return codecvt_base::error;
30797a984708SDavid Chisnall         *to_nxt = c1;
30807a984708SDavid Chisnall         frm_nxt += 2;
30817a984708SDavid Chisnall     }
30827a984708SDavid Chisnall     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
30837a984708SDavid Chisnall }
30847a984708SDavid Chisnall 
30857a984708SDavid Chisnall static
30867a984708SDavid Chisnall int
utf16le_to_ucs2_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))30877a984708SDavid Chisnall utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
30887a984708SDavid Chisnall                        size_t mx, unsigned long Maxcode = 0x10FFFF,
30897a984708SDavid Chisnall                        codecvt_mode mode = codecvt_mode(0))
30907a984708SDavid Chisnall {
30917a984708SDavid Chisnall     const uint8_t* frm_nxt = frm;
30927a984708SDavid Chisnall     frm_nxt = frm;
30937a984708SDavid Chisnall     if (mode & consume_header)
30947a984708SDavid Chisnall     {
30957a984708SDavid Chisnall         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
30967a984708SDavid Chisnall             frm_nxt += 2;
30977a984708SDavid Chisnall     }
30987a984708SDavid Chisnall     for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
30997a984708SDavid Chisnall     {
310094e3ee44SDavid Chisnall         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
31017a984708SDavid Chisnall         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
31027a984708SDavid Chisnall             break;
31037a984708SDavid Chisnall         frm_nxt += 2;
31047a984708SDavid Chisnall     }
31057a984708SDavid Chisnall     return static_cast<int>(frm_nxt - frm);
31067a984708SDavid Chisnall }
31077a984708SDavid Chisnall 
31087a984708SDavid Chisnall // template <> class codecvt<char16_t, char, mbstate_t>
31097a984708SDavid Chisnall 
31107a984708SDavid Chisnall locale::id codecvt<char16_t, char, mbstate_t>::id;
31117a984708SDavid Chisnall 
~codecvt()31127a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::~codecvt()
31137a984708SDavid Chisnall {
31147a984708SDavid Chisnall }
31157a984708SDavid Chisnall 
31167a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const31177a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
31187a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
31197a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
31207a984708SDavid Chisnall {
31217a984708SDavid Chisnall     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
31227a984708SDavid Chisnall     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
31237a984708SDavid Chisnall     const uint16_t* _frm_nxt = _frm;
31247a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
31257a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
31267a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
31277a984708SDavid Chisnall     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
31287a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
31297a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
31307a984708SDavid Chisnall     return r;
31317a984708SDavid Chisnall }
31327a984708SDavid Chisnall 
31337a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const31347a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
31357a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
31367a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
31377a984708SDavid Chisnall {
31387a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
31397a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
31407a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
31417a984708SDavid Chisnall     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
31427a984708SDavid Chisnall     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
31437a984708SDavid Chisnall     uint16_t* _to_nxt = _to;
31447a984708SDavid Chisnall     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
31457a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
31467a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
31477a984708SDavid Chisnall     return r;
31487a984708SDavid Chisnall }
31497a984708SDavid Chisnall 
31507a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const31517a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
31527a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
31537a984708SDavid Chisnall {
31547a984708SDavid Chisnall     to_nxt = to;
31557a984708SDavid Chisnall     return noconv;
31567a984708SDavid Chisnall }
31577a984708SDavid Chisnall 
31587a984708SDavid Chisnall int
do_encoding() const31597a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
31607a984708SDavid Chisnall {
31617a984708SDavid Chisnall     return 0;
31627a984708SDavid Chisnall }
31637a984708SDavid Chisnall 
31647a984708SDavid Chisnall bool
do_always_noconv() const31657a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
31667a984708SDavid Chisnall {
31677a984708SDavid Chisnall     return false;
31687a984708SDavid Chisnall }
31697a984708SDavid Chisnall 
31707a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const31717a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
31727a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
31737a984708SDavid Chisnall {
31747a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
31757a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
31767a984708SDavid Chisnall     return utf8_to_utf16_length(_frm, _frm_end, mx);
31777a984708SDavid Chisnall }
31787a984708SDavid Chisnall 
31797a984708SDavid Chisnall int
do_max_length() const31807a984708SDavid Chisnall codecvt<char16_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
31817a984708SDavid Chisnall {
31827a984708SDavid Chisnall     return 4;
31837a984708SDavid Chisnall }
31847a984708SDavid Chisnall 
31857a984708SDavid Chisnall // template <> class codecvt<char32_t, char, mbstate_t>
31867a984708SDavid Chisnall 
31877a984708SDavid Chisnall locale::id codecvt<char32_t, char, mbstate_t>::id;
31887a984708SDavid Chisnall 
~codecvt()31897a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::~codecvt()
31907a984708SDavid Chisnall {
31917a984708SDavid Chisnall }
31927a984708SDavid Chisnall 
31937a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const31947a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
31957a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
31967a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
31977a984708SDavid Chisnall {
31987a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
31997a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
32007a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
32017a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
32027a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
32037a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
32047a984708SDavid Chisnall     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
32057a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
32067a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
32077a984708SDavid Chisnall     return r;
32087a984708SDavid Chisnall }
32097a984708SDavid Chisnall 
32107a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const32117a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
32127a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
32137a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
32147a984708SDavid Chisnall {
32157a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
32167a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
32177a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
32187a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
32197a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
32207a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
32217a984708SDavid Chisnall     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
32227a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
32237a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
32247a984708SDavid Chisnall     return r;
32257a984708SDavid Chisnall }
32267a984708SDavid Chisnall 
32277a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const32287a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
32297a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
32307a984708SDavid Chisnall {
32317a984708SDavid Chisnall     to_nxt = to;
32327a984708SDavid Chisnall     return noconv;
32337a984708SDavid Chisnall }
32347a984708SDavid Chisnall 
32357a984708SDavid Chisnall int
do_encoding() const32367a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
32377a984708SDavid Chisnall {
32387a984708SDavid Chisnall     return 0;
32397a984708SDavid Chisnall }
32407a984708SDavid Chisnall 
32417a984708SDavid Chisnall bool
do_always_noconv() const32427a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
32437a984708SDavid Chisnall {
32447a984708SDavid Chisnall     return false;
32457a984708SDavid Chisnall }
32467a984708SDavid Chisnall 
32477a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const32487a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
32497a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
32507a984708SDavid Chisnall {
32517a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
32527a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
32537a984708SDavid Chisnall     return utf8_to_ucs4_length(_frm, _frm_end, mx);
32547a984708SDavid Chisnall }
32557a984708SDavid Chisnall 
32567a984708SDavid Chisnall int
do_max_length() const32577a984708SDavid Chisnall codecvt<char32_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
32587a984708SDavid Chisnall {
32597a984708SDavid Chisnall     return 4;
32607a984708SDavid Chisnall }
32617a984708SDavid Chisnall 
32627a984708SDavid Chisnall // __codecvt_utf8<wchar_t>
32637a984708SDavid Chisnall 
32647a984708SDavid Chisnall __codecvt_utf8<wchar_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const32657a984708SDavid Chisnall __codecvt_utf8<wchar_t>::do_out(state_type&,
32667a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
32677a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
32687a984708SDavid Chisnall {
3269aed8d94eSDimitry Andric #if defined(_LIBCPP_SHORT_WCHAR)
32704f7ab58eSDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
32714f7ab58eSDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
32724f7ab58eSDimitry Andric     const uint16_t* _frm_nxt = _frm;
32734f7ab58eSDimitry Andric #else
32747a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
32757a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
32767a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
32774f7ab58eSDimitry Andric #endif
32787a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
32797a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
32807a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
3281aed8d94eSDimitry Andric #if defined(_LIBCPP_SHORT_WCHAR)
32824f7ab58eSDimitry Andric     result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
32834f7ab58eSDimitry Andric                             _Maxcode_, _Mode_);
32844f7ab58eSDimitry Andric #else
32857a984708SDavid Chisnall     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
32867a984708SDavid Chisnall                             _Maxcode_, _Mode_);
32874f7ab58eSDimitry Andric #endif
32887a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
32897a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
32907a984708SDavid Chisnall     return r;
32917a984708SDavid Chisnall }
32927a984708SDavid Chisnall 
32937a984708SDavid Chisnall __codecvt_utf8<wchar_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const32947a984708SDavid Chisnall __codecvt_utf8<wchar_t>::do_in(state_type&,
32957a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
32967a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
32977a984708SDavid Chisnall {
32987a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
32997a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
33007a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
3301aed8d94eSDimitry Andric #if defined(_LIBCPP_SHORT_WCHAR)
33024f7ab58eSDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
33034f7ab58eSDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
33044f7ab58eSDimitry Andric     uint16_t* _to_nxt = _to;
33054f7ab58eSDimitry Andric     result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
33064f7ab58eSDimitry Andric                             _Maxcode_, _Mode_);
33074f7ab58eSDimitry Andric #else
33087a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
33097a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
33107a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
33117a984708SDavid Chisnall     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
33127a984708SDavid Chisnall                             _Maxcode_, _Mode_);
33134f7ab58eSDimitry Andric #endif
33147a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
33157a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
33167a984708SDavid Chisnall     return r;
33177a984708SDavid Chisnall }
33187a984708SDavid Chisnall 
33197a984708SDavid Chisnall __codecvt_utf8<wchar_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const33207a984708SDavid Chisnall __codecvt_utf8<wchar_t>::do_unshift(state_type&,
33217a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
33227a984708SDavid Chisnall {
33237a984708SDavid Chisnall     to_nxt = to;
33247a984708SDavid Chisnall     return noconv;
33257a984708SDavid Chisnall }
33267a984708SDavid Chisnall 
33277a984708SDavid Chisnall int
do_encoding() const33287a984708SDavid Chisnall __codecvt_utf8<wchar_t>::do_encoding() const  _NOEXCEPT
33297a984708SDavid Chisnall {
33307a984708SDavid Chisnall     return 0;
33317a984708SDavid Chisnall }
33327a984708SDavid Chisnall 
33337a984708SDavid Chisnall bool
do_always_noconv() const33347a984708SDavid Chisnall __codecvt_utf8<wchar_t>::do_always_noconv() const  _NOEXCEPT
33357a984708SDavid Chisnall {
33367a984708SDavid Chisnall     return false;
33377a984708SDavid Chisnall }
33387a984708SDavid Chisnall 
33397a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const33407a984708SDavid Chisnall __codecvt_utf8<wchar_t>::do_length(state_type&,
33417a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
33427a984708SDavid Chisnall {
33437a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
33447a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
33457a984708SDavid Chisnall     return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
33467a984708SDavid Chisnall }
33477a984708SDavid Chisnall 
33487a984708SDavid Chisnall int
do_max_length() const33497a984708SDavid Chisnall __codecvt_utf8<wchar_t>::do_max_length() const  _NOEXCEPT
33507a984708SDavid Chisnall {
33517a984708SDavid Chisnall     if (_Mode_ & consume_header)
33527a984708SDavid Chisnall         return 7;
33537a984708SDavid Chisnall     return 4;
33547a984708SDavid Chisnall }
33557a984708SDavid Chisnall 
33567a984708SDavid Chisnall // __codecvt_utf8<char16_t>
33577a984708SDavid Chisnall 
33587a984708SDavid Chisnall __codecvt_utf8<char16_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const33597a984708SDavid Chisnall __codecvt_utf8<char16_t>::do_out(state_type&,
33607a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
33617a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
33627a984708SDavid Chisnall {
33637a984708SDavid Chisnall     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
33647a984708SDavid Chisnall     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
33657a984708SDavid Chisnall     const uint16_t* _frm_nxt = _frm;
33667a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
33677a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
33687a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
33697a984708SDavid Chisnall     result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
33707a984708SDavid Chisnall                             _Maxcode_, _Mode_);
33717a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
33727a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
33737a984708SDavid Chisnall     return r;
33747a984708SDavid Chisnall }
33757a984708SDavid Chisnall 
33767a984708SDavid Chisnall __codecvt_utf8<char16_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const33777a984708SDavid Chisnall __codecvt_utf8<char16_t>::do_in(state_type&,
33787a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
33797a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
33807a984708SDavid Chisnall {
33817a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
33827a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
33837a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
33847a984708SDavid Chisnall     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
33857a984708SDavid Chisnall     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
33867a984708SDavid Chisnall     uint16_t* _to_nxt = _to;
33877a984708SDavid Chisnall     result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
33887a984708SDavid Chisnall                             _Maxcode_, _Mode_);
33897a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
33907a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
33917a984708SDavid Chisnall     return r;
33927a984708SDavid Chisnall }
33937a984708SDavid Chisnall 
33947a984708SDavid Chisnall __codecvt_utf8<char16_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const33957a984708SDavid Chisnall __codecvt_utf8<char16_t>::do_unshift(state_type&,
33967a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
33977a984708SDavid Chisnall {
33987a984708SDavid Chisnall     to_nxt = to;
33997a984708SDavid Chisnall     return noconv;
34007a984708SDavid Chisnall }
34017a984708SDavid Chisnall 
34027a984708SDavid Chisnall int
do_encoding() const34037a984708SDavid Chisnall __codecvt_utf8<char16_t>::do_encoding() const  _NOEXCEPT
34047a984708SDavid Chisnall {
34057a984708SDavid Chisnall     return 0;
34067a984708SDavid Chisnall }
34077a984708SDavid Chisnall 
34087a984708SDavid Chisnall bool
do_always_noconv() const34097a984708SDavid Chisnall __codecvt_utf8<char16_t>::do_always_noconv() const  _NOEXCEPT
34107a984708SDavid Chisnall {
34117a984708SDavid Chisnall     return false;
34127a984708SDavid Chisnall }
34137a984708SDavid Chisnall 
34147a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const34157a984708SDavid Chisnall __codecvt_utf8<char16_t>::do_length(state_type&,
34167a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
34177a984708SDavid Chisnall {
34187a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
34197a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
34207a984708SDavid Chisnall     return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
34217a984708SDavid Chisnall }
34227a984708SDavid Chisnall 
34237a984708SDavid Chisnall int
do_max_length() const34247a984708SDavid Chisnall __codecvt_utf8<char16_t>::do_max_length() const  _NOEXCEPT
34257a984708SDavid Chisnall {
34267a984708SDavid Chisnall     if (_Mode_ & consume_header)
34277a984708SDavid Chisnall         return 6;
34287a984708SDavid Chisnall     return 3;
34297a984708SDavid Chisnall }
34307a984708SDavid Chisnall 
34317a984708SDavid Chisnall // __codecvt_utf8<char32_t>
34327a984708SDavid Chisnall 
34337a984708SDavid Chisnall __codecvt_utf8<char32_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const34347a984708SDavid Chisnall __codecvt_utf8<char32_t>::do_out(state_type&,
34357a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
34367a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
34377a984708SDavid Chisnall {
34387a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
34397a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
34407a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
34417a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
34427a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
34437a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
34447a984708SDavid Chisnall     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
34457a984708SDavid Chisnall                             _Maxcode_, _Mode_);
34467a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
34477a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
34487a984708SDavid Chisnall     return r;
34497a984708SDavid Chisnall }
34507a984708SDavid Chisnall 
34517a984708SDavid Chisnall __codecvt_utf8<char32_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const34527a984708SDavid Chisnall __codecvt_utf8<char32_t>::do_in(state_type&,
34537a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
34547a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
34557a984708SDavid Chisnall {
34567a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
34577a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
34587a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
34597a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
34607a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
34617a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
34627a984708SDavid Chisnall     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
34637a984708SDavid Chisnall                             _Maxcode_, _Mode_);
34647a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
34657a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
34667a984708SDavid Chisnall     return r;
34677a984708SDavid Chisnall }
34687a984708SDavid Chisnall 
34697a984708SDavid Chisnall __codecvt_utf8<char32_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const34707a984708SDavid Chisnall __codecvt_utf8<char32_t>::do_unshift(state_type&,
34717a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
34727a984708SDavid Chisnall {
34737a984708SDavid Chisnall     to_nxt = to;
34747a984708SDavid Chisnall     return noconv;
34757a984708SDavid Chisnall }
34767a984708SDavid Chisnall 
34777a984708SDavid Chisnall int
do_encoding() const34787a984708SDavid Chisnall __codecvt_utf8<char32_t>::do_encoding() const  _NOEXCEPT
34797a984708SDavid Chisnall {
34807a984708SDavid Chisnall     return 0;
34817a984708SDavid Chisnall }
34827a984708SDavid Chisnall 
34837a984708SDavid Chisnall bool
do_always_noconv() const34847a984708SDavid Chisnall __codecvt_utf8<char32_t>::do_always_noconv() const  _NOEXCEPT
34857a984708SDavid Chisnall {
34867a984708SDavid Chisnall     return false;
34877a984708SDavid Chisnall }
34887a984708SDavid Chisnall 
34897a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const34907a984708SDavid Chisnall __codecvt_utf8<char32_t>::do_length(state_type&,
34917a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
34927a984708SDavid Chisnall {
34937a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
34947a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
34957a984708SDavid Chisnall     return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
34967a984708SDavid Chisnall }
34977a984708SDavid Chisnall 
34987a984708SDavid Chisnall int
do_max_length() const34997a984708SDavid Chisnall __codecvt_utf8<char32_t>::do_max_length() const  _NOEXCEPT
35007a984708SDavid Chisnall {
35017a984708SDavid Chisnall     if (_Mode_ & consume_header)
35027a984708SDavid Chisnall         return 7;
35037a984708SDavid Chisnall     return 4;
35047a984708SDavid Chisnall }
35057a984708SDavid Chisnall 
35067a984708SDavid Chisnall // __codecvt_utf16<wchar_t, false>
35077a984708SDavid Chisnall 
35087a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const35097a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::do_out(state_type&,
35107a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
35117a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
35127a984708SDavid Chisnall {
35137a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
35147a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
35157a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
35167a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
35177a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
35187a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
35197a984708SDavid Chisnall     result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
35207a984708SDavid Chisnall                                _Maxcode_, _Mode_);
35217a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
35227a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
35237a984708SDavid Chisnall     return r;
35247a984708SDavid Chisnall }
35257a984708SDavid Chisnall 
35267a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const35277a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::do_in(state_type&,
35287a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
35297a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
35307a984708SDavid Chisnall {
35317a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
35327a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
35337a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
35347a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
35357a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
35367a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
35377a984708SDavid Chisnall     result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
35387a984708SDavid Chisnall                                _Maxcode_, _Mode_);
35397a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
35407a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
35417a984708SDavid Chisnall     return r;
35427a984708SDavid Chisnall }
35437a984708SDavid Chisnall 
35447a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const35457a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
35467a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
35477a984708SDavid Chisnall {
35487a984708SDavid Chisnall     to_nxt = to;
35497a984708SDavid Chisnall     return noconv;
35507a984708SDavid Chisnall }
35517a984708SDavid Chisnall 
35527a984708SDavid Chisnall int
do_encoding() const35537a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::do_encoding() const  _NOEXCEPT
35547a984708SDavid Chisnall {
35557a984708SDavid Chisnall     return 0;
35567a984708SDavid Chisnall }
35577a984708SDavid Chisnall 
35587a984708SDavid Chisnall bool
do_always_noconv() const35597a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::do_always_noconv() const  _NOEXCEPT
35607a984708SDavid Chisnall {
35617a984708SDavid Chisnall     return false;
35627a984708SDavid Chisnall }
35637a984708SDavid Chisnall 
35647a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const35657a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::do_length(state_type&,
35667a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
35677a984708SDavid Chisnall {
35687a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
35697a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
35707a984708SDavid Chisnall     return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
35717a984708SDavid Chisnall }
35727a984708SDavid Chisnall 
35737a984708SDavid Chisnall int
do_max_length() const35747a984708SDavid Chisnall __codecvt_utf16<wchar_t, false>::do_max_length() const  _NOEXCEPT
35757a984708SDavid Chisnall {
35767a984708SDavid Chisnall     if (_Mode_ & consume_header)
35777a984708SDavid Chisnall         return 6;
35787a984708SDavid Chisnall     return 4;
35797a984708SDavid Chisnall }
35807a984708SDavid Chisnall 
35817a984708SDavid Chisnall // __codecvt_utf16<wchar_t, true>
35827a984708SDavid Chisnall 
35837a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const35847a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::do_out(state_type&,
35857a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
35867a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
35877a984708SDavid Chisnall {
35887a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
35897a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
35907a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
35917a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
35927a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
35937a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
35947a984708SDavid Chisnall     result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
35957a984708SDavid Chisnall                                _Maxcode_, _Mode_);
35967a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
35977a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
35987a984708SDavid Chisnall     return r;
35997a984708SDavid Chisnall }
36007a984708SDavid Chisnall 
36017a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const36027a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::do_in(state_type&,
36037a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
36047a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
36057a984708SDavid Chisnall {
36067a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
36077a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
36087a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
36097a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
36107a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
36117a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
36127a984708SDavid Chisnall     result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
36137a984708SDavid Chisnall                                _Maxcode_, _Mode_);
36147a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
36157a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
36167a984708SDavid Chisnall     return r;
36177a984708SDavid Chisnall }
36187a984708SDavid Chisnall 
36197a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const36207a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
36217a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
36227a984708SDavid Chisnall {
36237a984708SDavid Chisnall     to_nxt = to;
36247a984708SDavid Chisnall     return noconv;
36257a984708SDavid Chisnall }
36267a984708SDavid Chisnall 
36277a984708SDavid Chisnall int
do_encoding() const36287a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::do_encoding() const  _NOEXCEPT
36297a984708SDavid Chisnall {
36307a984708SDavid Chisnall     return 0;
36317a984708SDavid Chisnall }
36327a984708SDavid Chisnall 
36337a984708SDavid Chisnall bool
do_always_noconv() const36347a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::do_always_noconv() const  _NOEXCEPT
36357a984708SDavid Chisnall {
36367a984708SDavid Chisnall     return false;
36377a984708SDavid Chisnall }
36387a984708SDavid Chisnall 
36397a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const36407a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::do_length(state_type&,
36417a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
36427a984708SDavid Chisnall {
36437a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
36447a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
36457a984708SDavid Chisnall     return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
36467a984708SDavid Chisnall }
36477a984708SDavid Chisnall 
36487a984708SDavid Chisnall int
do_max_length() const36497a984708SDavid Chisnall __codecvt_utf16<wchar_t, true>::do_max_length() const  _NOEXCEPT
36507a984708SDavid Chisnall {
36517a984708SDavid Chisnall     if (_Mode_ & consume_header)
36527a984708SDavid Chisnall         return 6;
36537a984708SDavid Chisnall     return 4;
36547a984708SDavid Chisnall }
36557a984708SDavid Chisnall 
36567a984708SDavid Chisnall // __codecvt_utf16<char16_t, false>
36577a984708SDavid Chisnall 
36587a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const36597a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::do_out(state_type&,
36607a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
36617a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
36627a984708SDavid Chisnall {
36637a984708SDavid Chisnall     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
36647a984708SDavid Chisnall     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
36657a984708SDavid Chisnall     const uint16_t* _frm_nxt = _frm;
36667a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
36677a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
36687a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
36697a984708SDavid Chisnall     result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
36707a984708SDavid Chisnall                                _Maxcode_, _Mode_);
36717a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
36727a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
36737a984708SDavid Chisnall     return r;
36747a984708SDavid Chisnall }
36757a984708SDavid Chisnall 
36767a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const36777a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::do_in(state_type&,
36787a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
36797a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
36807a984708SDavid Chisnall {
36817a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
36827a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
36837a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
36847a984708SDavid Chisnall     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
36857a984708SDavid Chisnall     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
36867a984708SDavid Chisnall     uint16_t* _to_nxt = _to;
36877a984708SDavid Chisnall     result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
36887a984708SDavid Chisnall                                _Maxcode_, _Mode_);
36897a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
36907a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
36917a984708SDavid Chisnall     return r;
36927a984708SDavid Chisnall }
36937a984708SDavid Chisnall 
36947a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const36957a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::do_unshift(state_type&,
36967a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
36977a984708SDavid Chisnall {
36987a984708SDavid Chisnall     to_nxt = to;
36997a984708SDavid Chisnall     return noconv;
37007a984708SDavid Chisnall }
37017a984708SDavid Chisnall 
37027a984708SDavid Chisnall int
do_encoding() const37037a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::do_encoding() const  _NOEXCEPT
37047a984708SDavid Chisnall {
37057a984708SDavid Chisnall     return 0;
37067a984708SDavid Chisnall }
37077a984708SDavid Chisnall 
37087a984708SDavid Chisnall bool
do_always_noconv() const37097a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::do_always_noconv() const  _NOEXCEPT
37107a984708SDavid Chisnall {
37117a984708SDavid Chisnall     return false;
37127a984708SDavid Chisnall }
37137a984708SDavid Chisnall 
37147a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const37157a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::do_length(state_type&,
37167a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
37177a984708SDavid Chisnall {
37187a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
37197a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
37207a984708SDavid Chisnall     return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
37217a984708SDavid Chisnall }
37227a984708SDavid Chisnall 
37237a984708SDavid Chisnall int
do_max_length() const37247a984708SDavid Chisnall __codecvt_utf16<char16_t, false>::do_max_length() const  _NOEXCEPT
37257a984708SDavid Chisnall {
37267a984708SDavid Chisnall     if (_Mode_ & consume_header)
37277a984708SDavid Chisnall         return 4;
37287a984708SDavid Chisnall     return 2;
37297a984708SDavid Chisnall }
37307a984708SDavid Chisnall 
37317a984708SDavid Chisnall // __codecvt_utf16<char16_t, true>
37327a984708SDavid Chisnall 
37337a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const37347a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::do_out(state_type&,
37357a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
37367a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
37377a984708SDavid Chisnall {
37387a984708SDavid Chisnall     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
37397a984708SDavid Chisnall     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
37407a984708SDavid Chisnall     const uint16_t* _frm_nxt = _frm;
37417a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
37427a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
37437a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
37447a984708SDavid Chisnall     result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
37457a984708SDavid Chisnall                                _Maxcode_, _Mode_);
37467a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
37477a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
37487a984708SDavid Chisnall     return r;
37497a984708SDavid Chisnall }
37507a984708SDavid Chisnall 
37517a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const37527a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::do_in(state_type&,
37537a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
37547a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
37557a984708SDavid Chisnall {
37567a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
37577a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
37587a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
37597a984708SDavid Chisnall     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
37607a984708SDavid Chisnall     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
37617a984708SDavid Chisnall     uint16_t* _to_nxt = _to;
37627a984708SDavid Chisnall     result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
37637a984708SDavid Chisnall                                _Maxcode_, _Mode_);
37647a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
37657a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
37667a984708SDavid Chisnall     return r;
37677a984708SDavid Chisnall }
37687a984708SDavid Chisnall 
37697a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const37707a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::do_unshift(state_type&,
37717a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
37727a984708SDavid Chisnall {
37737a984708SDavid Chisnall     to_nxt = to;
37747a984708SDavid Chisnall     return noconv;
37757a984708SDavid Chisnall }
37767a984708SDavid Chisnall 
37777a984708SDavid Chisnall int
do_encoding() const37787a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::do_encoding() const  _NOEXCEPT
37797a984708SDavid Chisnall {
37807a984708SDavid Chisnall     return 0;
37817a984708SDavid Chisnall }
37827a984708SDavid Chisnall 
37837a984708SDavid Chisnall bool
do_always_noconv() const37847a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::do_always_noconv() const  _NOEXCEPT
37857a984708SDavid Chisnall {
37867a984708SDavid Chisnall     return false;
37877a984708SDavid Chisnall }
37887a984708SDavid Chisnall 
37897a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const37907a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::do_length(state_type&,
37917a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
37927a984708SDavid Chisnall {
37937a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
37947a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
37957a984708SDavid Chisnall     return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
37967a984708SDavid Chisnall }
37977a984708SDavid Chisnall 
37987a984708SDavid Chisnall int
do_max_length() const37997a984708SDavid Chisnall __codecvt_utf16<char16_t, true>::do_max_length() const  _NOEXCEPT
38007a984708SDavid Chisnall {
38017a984708SDavid Chisnall     if (_Mode_ & consume_header)
38027a984708SDavid Chisnall         return 4;
38037a984708SDavid Chisnall     return 2;
38047a984708SDavid Chisnall }
38057a984708SDavid Chisnall 
38067a984708SDavid Chisnall // __codecvt_utf16<char32_t, false>
38077a984708SDavid Chisnall 
38087a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const38097a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::do_out(state_type&,
38107a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
38117a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
38127a984708SDavid Chisnall {
38137a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
38147a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
38157a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
38167a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
38177a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
38187a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
38197a984708SDavid Chisnall     result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
38207a984708SDavid Chisnall                                _Maxcode_, _Mode_);
38217a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
38227a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
38237a984708SDavid Chisnall     return r;
38247a984708SDavid Chisnall }
38257a984708SDavid Chisnall 
38267a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const38277a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::do_in(state_type&,
38287a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
38297a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
38307a984708SDavid Chisnall {
38317a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
38327a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
38337a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
38347a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
38357a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
38367a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
38377a984708SDavid Chisnall     result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
38387a984708SDavid Chisnall                                _Maxcode_, _Mode_);
38397a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
38407a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
38417a984708SDavid Chisnall     return r;
38427a984708SDavid Chisnall }
38437a984708SDavid Chisnall 
38447a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const38457a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::do_unshift(state_type&,
38467a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
38477a984708SDavid Chisnall {
38487a984708SDavid Chisnall     to_nxt = to;
38497a984708SDavid Chisnall     return noconv;
38507a984708SDavid Chisnall }
38517a984708SDavid Chisnall 
38527a984708SDavid Chisnall int
do_encoding() const38537a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::do_encoding() const  _NOEXCEPT
38547a984708SDavid Chisnall {
38557a984708SDavid Chisnall     return 0;
38567a984708SDavid Chisnall }
38577a984708SDavid Chisnall 
38587a984708SDavid Chisnall bool
do_always_noconv() const38597a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::do_always_noconv() const  _NOEXCEPT
38607a984708SDavid Chisnall {
38617a984708SDavid Chisnall     return false;
38627a984708SDavid Chisnall }
38637a984708SDavid Chisnall 
38647a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const38657a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::do_length(state_type&,
38667a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
38677a984708SDavid Chisnall {
38687a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
38697a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
38707a984708SDavid Chisnall     return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
38717a984708SDavid Chisnall }
38727a984708SDavid Chisnall 
38737a984708SDavid Chisnall int
do_max_length() const38747a984708SDavid Chisnall __codecvt_utf16<char32_t, false>::do_max_length() const  _NOEXCEPT
38757a984708SDavid Chisnall {
38767a984708SDavid Chisnall     if (_Mode_ & consume_header)
38777a984708SDavid Chisnall         return 6;
38787a984708SDavid Chisnall     return 4;
38797a984708SDavid Chisnall }
38807a984708SDavid Chisnall 
38817a984708SDavid Chisnall // __codecvt_utf16<char32_t, true>
38827a984708SDavid Chisnall 
38837a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const38847a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::do_out(state_type&,
38857a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
38867a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
38877a984708SDavid Chisnall {
38887a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
38897a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
38907a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
38917a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
38927a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
38937a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
38947a984708SDavid Chisnall     result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
38957a984708SDavid Chisnall                                _Maxcode_, _Mode_);
38967a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
38977a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
38987a984708SDavid Chisnall     return r;
38997a984708SDavid Chisnall }
39007a984708SDavid Chisnall 
39017a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const39027a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::do_in(state_type&,
39037a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
39047a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
39057a984708SDavid Chisnall {
39067a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
39077a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
39087a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
39097a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
39107a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
39117a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
39127a984708SDavid Chisnall     result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
39137a984708SDavid Chisnall                                _Maxcode_, _Mode_);
39147a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
39157a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
39167a984708SDavid Chisnall     return r;
39177a984708SDavid Chisnall }
39187a984708SDavid Chisnall 
39197a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const39207a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::do_unshift(state_type&,
39217a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
39227a984708SDavid Chisnall {
39237a984708SDavid Chisnall     to_nxt = to;
39247a984708SDavid Chisnall     return noconv;
39257a984708SDavid Chisnall }
39267a984708SDavid Chisnall 
39277a984708SDavid Chisnall int
do_encoding() const39287a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::do_encoding() const  _NOEXCEPT
39297a984708SDavid Chisnall {
39307a984708SDavid Chisnall     return 0;
39317a984708SDavid Chisnall }
39327a984708SDavid Chisnall 
39337a984708SDavid Chisnall bool
do_always_noconv() const39347a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::do_always_noconv() const  _NOEXCEPT
39357a984708SDavid Chisnall {
39367a984708SDavid Chisnall     return false;
39377a984708SDavid Chisnall }
39387a984708SDavid Chisnall 
39397a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const39407a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::do_length(state_type&,
39417a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
39427a984708SDavid Chisnall {
39437a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
39447a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
39457a984708SDavid Chisnall     return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
39467a984708SDavid Chisnall }
39477a984708SDavid Chisnall 
39487a984708SDavid Chisnall int
do_max_length() const39497a984708SDavid Chisnall __codecvt_utf16<char32_t, true>::do_max_length() const  _NOEXCEPT
39507a984708SDavid Chisnall {
39517a984708SDavid Chisnall     if (_Mode_ & consume_header)
39527a984708SDavid Chisnall         return 6;
39537a984708SDavid Chisnall     return 4;
39547a984708SDavid Chisnall }
39557a984708SDavid Chisnall 
39567a984708SDavid Chisnall // __codecvt_utf8_utf16<wchar_t>
39577a984708SDavid Chisnall 
39587a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const39597a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
39607a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
39617a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
39627a984708SDavid Chisnall {
39637a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
39647a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
39657a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
39667a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
39677a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
39687a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
39697a984708SDavid Chisnall     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
39707a984708SDavid Chisnall                              _Maxcode_, _Mode_);
39717a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
39727a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
39737a984708SDavid Chisnall     return r;
39747a984708SDavid Chisnall }
39757a984708SDavid Chisnall 
39767a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const39777a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
39787a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
39797a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
39807a984708SDavid Chisnall {
39817a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
39827a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
39837a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
39847a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
39857a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
39867a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
39877a984708SDavid Chisnall     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
39887a984708SDavid Chisnall                              _Maxcode_, _Mode_);
39897a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
39907a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
39917a984708SDavid Chisnall     return r;
39927a984708SDavid Chisnall }
39937a984708SDavid Chisnall 
39947a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const39957a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
39967a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
39977a984708SDavid Chisnall {
39987a984708SDavid Chisnall     to_nxt = to;
39997a984708SDavid Chisnall     return noconv;
40007a984708SDavid Chisnall }
40017a984708SDavid Chisnall 
40027a984708SDavid Chisnall int
do_encoding() const40037a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::do_encoding() const  _NOEXCEPT
40047a984708SDavid Chisnall {
40057a984708SDavid Chisnall     return 0;
40067a984708SDavid Chisnall }
40077a984708SDavid Chisnall 
40087a984708SDavid Chisnall bool
do_always_noconv() const40097a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const  _NOEXCEPT
40107a984708SDavid Chisnall {
40117a984708SDavid Chisnall     return false;
40127a984708SDavid Chisnall }
40137a984708SDavid Chisnall 
40147a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const40157a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
40167a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
40177a984708SDavid Chisnall {
40187a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
40197a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
40207a984708SDavid Chisnall     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
40217a984708SDavid Chisnall }
40227a984708SDavid Chisnall 
40237a984708SDavid Chisnall int
do_max_length() const40247a984708SDavid Chisnall __codecvt_utf8_utf16<wchar_t>::do_max_length() const  _NOEXCEPT
40257a984708SDavid Chisnall {
40267a984708SDavid Chisnall     if (_Mode_ & consume_header)
40277a984708SDavid Chisnall         return 7;
40287a984708SDavid Chisnall     return 4;
40297a984708SDavid Chisnall }
40307a984708SDavid Chisnall 
40317a984708SDavid Chisnall // __codecvt_utf8_utf16<char16_t>
40327a984708SDavid Chisnall 
40337a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const40347a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::do_out(state_type&,
40357a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
40367a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
40377a984708SDavid Chisnall {
40387a984708SDavid Chisnall     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
40397a984708SDavid Chisnall     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
40407a984708SDavid Chisnall     const uint16_t* _frm_nxt = _frm;
40417a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
40427a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
40437a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
40447a984708SDavid Chisnall     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
40457a984708SDavid Chisnall                              _Maxcode_, _Mode_);
40467a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
40477a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
40487a984708SDavid Chisnall     return r;
40497a984708SDavid Chisnall }
40507a984708SDavid Chisnall 
40517a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const40527a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::do_in(state_type&,
40537a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
40547a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
40557a984708SDavid Chisnall {
40567a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
40577a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
40587a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
40597a984708SDavid Chisnall     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
40607a984708SDavid Chisnall     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
40617a984708SDavid Chisnall     uint16_t* _to_nxt = _to;
40627a984708SDavid Chisnall     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
40637a984708SDavid Chisnall                              _Maxcode_, _Mode_);
40647a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
40657a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
40667a984708SDavid Chisnall     return r;
40677a984708SDavid Chisnall }
40687a984708SDavid Chisnall 
40697a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const40707a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
40717a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
40727a984708SDavid Chisnall {
40737a984708SDavid Chisnall     to_nxt = to;
40747a984708SDavid Chisnall     return noconv;
40757a984708SDavid Chisnall }
40767a984708SDavid Chisnall 
40777a984708SDavid Chisnall int
do_encoding() const40787a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::do_encoding() const  _NOEXCEPT
40797a984708SDavid Chisnall {
40807a984708SDavid Chisnall     return 0;
40817a984708SDavid Chisnall }
40827a984708SDavid Chisnall 
40837a984708SDavid Chisnall bool
do_always_noconv() const40847a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::do_always_noconv() const  _NOEXCEPT
40857a984708SDavid Chisnall {
40867a984708SDavid Chisnall     return false;
40877a984708SDavid Chisnall }
40887a984708SDavid Chisnall 
40897a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const40907a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::do_length(state_type&,
40917a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
40927a984708SDavid Chisnall {
40937a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
40947a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
40957a984708SDavid Chisnall     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
40967a984708SDavid Chisnall }
40977a984708SDavid Chisnall 
40987a984708SDavid Chisnall int
do_max_length() const40997a984708SDavid Chisnall __codecvt_utf8_utf16<char16_t>::do_max_length() const  _NOEXCEPT
41007a984708SDavid Chisnall {
41017a984708SDavid Chisnall     if (_Mode_ & consume_header)
41027a984708SDavid Chisnall         return 7;
41037a984708SDavid Chisnall     return 4;
41047a984708SDavid Chisnall }
41057a984708SDavid Chisnall 
41067a984708SDavid Chisnall // __codecvt_utf8_utf16<char32_t>
41077a984708SDavid Chisnall 
41087a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::result
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const41097a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::do_out(state_type&,
41107a984708SDavid Chisnall     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
41117a984708SDavid Chisnall     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
41127a984708SDavid Chisnall {
41137a984708SDavid Chisnall     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
41147a984708SDavid Chisnall     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
41157a984708SDavid Chisnall     const uint32_t* _frm_nxt = _frm;
41167a984708SDavid Chisnall     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
41177a984708SDavid Chisnall     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
41187a984708SDavid Chisnall     uint8_t* _to_nxt = _to;
41197a984708SDavid Chisnall     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
41207a984708SDavid Chisnall                              _Maxcode_, _Mode_);
41217a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
41227a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
41237a984708SDavid Chisnall     return r;
41247a984708SDavid Chisnall }
41257a984708SDavid Chisnall 
41267a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::result
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const41277a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::do_in(state_type&,
41287a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
41297a984708SDavid Chisnall     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
41307a984708SDavid Chisnall {
41317a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
41327a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
41337a984708SDavid Chisnall     const uint8_t* _frm_nxt = _frm;
41347a984708SDavid Chisnall     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
41357a984708SDavid Chisnall     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
41367a984708SDavid Chisnall     uint32_t* _to_nxt = _to;
41377a984708SDavid Chisnall     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
41387a984708SDavid Chisnall                              _Maxcode_, _Mode_);
41397a984708SDavid Chisnall     frm_nxt = frm + (_frm_nxt - _frm);
41407a984708SDavid Chisnall     to_nxt = to + (_to_nxt - _to);
41417a984708SDavid Chisnall     return r;
41427a984708SDavid Chisnall }
41437a984708SDavid Chisnall 
41447a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const41457a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
41467a984708SDavid Chisnall     extern_type* to, extern_type*, extern_type*& to_nxt) const
41477a984708SDavid Chisnall {
41487a984708SDavid Chisnall     to_nxt = to;
41497a984708SDavid Chisnall     return noconv;
41507a984708SDavid Chisnall }
41517a984708SDavid Chisnall 
41527a984708SDavid Chisnall int
do_encoding() const41537a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::do_encoding() const  _NOEXCEPT
41547a984708SDavid Chisnall {
41557a984708SDavid Chisnall     return 0;
41567a984708SDavid Chisnall }
41577a984708SDavid Chisnall 
41587a984708SDavid Chisnall bool
do_always_noconv() const41597a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::do_always_noconv() const  _NOEXCEPT
41607a984708SDavid Chisnall {
41617a984708SDavid Chisnall     return false;
41627a984708SDavid Chisnall }
41637a984708SDavid Chisnall 
41647a984708SDavid Chisnall int
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const41657a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::do_length(state_type&,
41667a984708SDavid Chisnall     const extern_type* frm, const extern_type* frm_end, size_t mx) const
41677a984708SDavid Chisnall {
41687a984708SDavid Chisnall     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
41697a984708SDavid Chisnall     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
41707a984708SDavid Chisnall     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
41717a984708SDavid Chisnall }
41727a984708SDavid Chisnall 
41737a984708SDavid Chisnall int
do_max_length() const41747a984708SDavid Chisnall __codecvt_utf8_utf16<char32_t>::do_max_length() const  _NOEXCEPT
41757a984708SDavid Chisnall {
41767a984708SDavid Chisnall     if (_Mode_ & consume_header)
41777a984708SDavid Chisnall         return 7;
41787a984708SDavid Chisnall     return 4;
41797a984708SDavid Chisnall }
41807a984708SDavid Chisnall 
41817a984708SDavid Chisnall // __narrow_to_utf8<16>
41827a984708SDavid Chisnall 
~__narrow_to_utf8()41837a984708SDavid Chisnall __narrow_to_utf8<16>::~__narrow_to_utf8()
41847a984708SDavid Chisnall {
41857a984708SDavid Chisnall }
41867a984708SDavid Chisnall 
41877a984708SDavid Chisnall // __narrow_to_utf8<32>
41887a984708SDavid Chisnall 
~__narrow_to_utf8()41897a984708SDavid Chisnall __narrow_to_utf8<32>::~__narrow_to_utf8()
41907a984708SDavid Chisnall {
41917a984708SDavid Chisnall }
41927a984708SDavid Chisnall 
41937a984708SDavid Chisnall // __widen_from_utf8<16>
41947a984708SDavid Chisnall 
~__widen_from_utf8()41957a984708SDavid Chisnall __widen_from_utf8<16>::~__widen_from_utf8()
41967a984708SDavid Chisnall {
41977a984708SDavid Chisnall }
41987a984708SDavid Chisnall 
41997a984708SDavid Chisnall // __widen_from_utf8<32>
42007a984708SDavid Chisnall 
~__widen_from_utf8()42017a984708SDavid Chisnall __widen_from_utf8<32>::~__widen_from_utf8()
42027a984708SDavid Chisnall {
42037a984708SDavid Chisnall }
42047a984708SDavid Chisnall 
4205aed8d94eSDimitry Andric 
checked_string_to_wchar_convert(wchar_t & dest,const char * ptr,locale_t loc)4206aed8d94eSDimitry Andric static bool checked_string_to_wchar_convert(wchar_t& dest,
4207aed8d94eSDimitry Andric                                             const char* ptr,
42085517e702SDimitry Andric                                             locale_t loc) {
4209aed8d94eSDimitry Andric   if (*ptr == '\0')
4210aed8d94eSDimitry Andric     return false;
4211aed8d94eSDimitry Andric   mbstate_t mb = {};
4212aed8d94eSDimitry Andric   wchar_t out;
4213aed8d94eSDimitry Andric   size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4214aed8d94eSDimitry Andric   if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4215aed8d94eSDimitry Andric     return false;
4216aed8d94eSDimitry Andric   }
4217aed8d94eSDimitry Andric   dest = out;
4218aed8d94eSDimitry Andric   return true;
4219aed8d94eSDimitry Andric }
4220aed8d94eSDimitry Andric 
checked_string_to_char_convert(char & dest,const char * ptr,locale_t __loc)4221aed8d94eSDimitry Andric static bool checked_string_to_char_convert(char& dest,
4222aed8d94eSDimitry Andric                                            const char* ptr,
42235517e702SDimitry Andric                                            locale_t __loc) {
4224aed8d94eSDimitry Andric   if (*ptr == '\0')
4225aed8d94eSDimitry Andric     return false;
4226aed8d94eSDimitry Andric   if (!ptr[1]) {
4227aed8d94eSDimitry Andric     dest = *ptr;
4228aed8d94eSDimitry Andric     return true;
4229aed8d94eSDimitry Andric   }
4230aed8d94eSDimitry Andric   // First convert the MBS into a wide char then attempt to narrow it using
4231aed8d94eSDimitry Andric   // wctob_l.
4232aed8d94eSDimitry Andric   wchar_t wout;
4233aed8d94eSDimitry Andric   if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4234aed8d94eSDimitry Andric     return false;
4235aed8d94eSDimitry Andric   int res;
4236aed8d94eSDimitry Andric   if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4237aed8d94eSDimitry Andric     dest = res;
4238aed8d94eSDimitry Andric     return true;
4239aed8d94eSDimitry Andric   }
4240aed8d94eSDimitry Andric   // FIXME: Work around specific multibyte sequences that we can reasonable
4241aed8d94eSDimitry Andric   // translate into a different single byte.
4242aed8d94eSDimitry Andric   switch (wout) {
4243*4ba319b5SDimitry Andric   case L'\u202F': // narrow non-breaking space
4244aed8d94eSDimitry Andric   case L'\u00A0': // non-breaking space
4245aed8d94eSDimitry Andric     dest = ' ';
4246aed8d94eSDimitry Andric     return true;
4247aed8d94eSDimitry Andric   default:
4248aed8d94eSDimitry Andric     return false;
4249aed8d94eSDimitry Andric   }
4250aed8d94eSDimitry Andric   _LIBCPP_UNREACHABLE();
4251aed8d94eSDimitry Andric }
4252aed8d94eSDimitry Andric 
4253aed8d94eSDimitry Andric 
42547a984708SDavid Chisnall // numpunct<char> && numpunct<wchar_t>
42557a984708SDavid Chisnall 
42567a984708SDavid Chisnall locale::id numpunct< char  >::id;
42577a984708SDavid Chisnall locale::id numpunct<wchar_t>::id;
42587a984708SDavid Chisnall 
numpunct(size_t refs)42597a984708SDavid Chisnall numpunct<char>::numpunct(size_t refs)
42607a984708SDavid Chisnall     : locale::facet(refs),
42617a984708SDavid Chisnall       __decimal_point_('.'),
42627a984708SDavid Chisnall       __thousands_sep_(',')
42637a984708SDavid Chisnall {
42647a984708SDavid Chisnall }
42657a984708SDavid Chisnall 
numpunct(size_t refs)42667a984708SDavid Chisnall numpunct<wchar_t>::numpunct(size_t refs)
42677a984708SDavid Chisnall     : locale::facet(refs),
42687a984708SDavid Chisnall       __decimal_point_(L'.'),
42697a984708SDavid Chisnall       __thousands_sep_(L',')
42707a984708SDavid Chisnall {
42717a984708SDavid Chisnall }
42727a984708SDavid Chisnall 
~numpunct()42737a984708SDavid Chisnall numpunct<char>::~numpunct()
42747a984708SDavid Chisnall {
42757a984708SDavid Chisnall }
42767a984708SDavid Chisnall 
~numpunct()42777a984708SDavid Chisnall numpunct<wchar_t>::~numpunct()
42787a984708SDavid Chisnall {
42797a984708SDavid Chisnall }
42807a984708SDavid Chisnall 
do_decimal_point() const42817a984708SDavid Chisnall  char   numpunct< char  >::do_decimal_point() const {return __decimal_point_;}
do_decimal_point() const42827a984708SDavid Chisnall wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
42837a984708SDavid Chisnall 
do_thousands_sep() const42847a984708SDavid Chisnall  char   numpunct< char  >::do_thousands_sep() const {return __thousands_sep_;}
do_thousands_sep() const42857a984708SDavid Chisnall wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
42867a984708SDavid Chisnall 
do_grouping() const42877a984708SDavid Chisnall string numpunct< char  >::do_grouping() const {return __grouping_;}
do_grouping() const42887a984708SDavid Chisnall string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
42897a984708SDavid Chisnall 
do_truename() const42907a984708SDavid Chisnall  string numpunct< char  >::do_truename() const {return "true";}
do_truename() const42917a984708SDavid Chisnall wstring numpunct<wchar_t>::do_truename() const {return L"true";}
42927a984708SDavid Chisnall 
do_falsename() const42937a984708SDavid Chisnall  string numpunct< char  >::do_falsename() const {return "false";}
do_falsename() const42947a984708SDavid Chisnall wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
42957a984708SDavid Chisnall 
42967a984708SDavid Chisnall // numpunct_byname<char>
42977a984708SDavid Chisnall 
numpunct_byname(const char * nm,size_t refs)42987a984708SDavid Chisnall numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
42997a984708SDavid Chisnall     : numpunct<char>(refs)
43007a984708SDavid Chisnall {
43017a984708SDavid Chisnall     __init(nm);
43027a984708SDavid Chisnall }
43037a984708SDavid Chisnall 
numpunct_byname(const string & nm,size_t refs)43047a984708SDavid Chisnall numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
43057a984708SDavid Chisnall     : numpunct<char>(refs)
43067a984708SDavid Chisnall {
43077a984708SDavid Chisnall     __init(nm.c_str());
43087a984708SDavid Chisnall }
43097a984708SDavid Chisnall 
~numpunct_byname()43107a984708SDavid Chisnall numpunct_byname<char>::~numpunct_byname()
43117a984708SDavid Chisnall {
43127a984708SDavid Chisnall }
43137a984708SDavid Chisnall 
43147a984708SDavid Chisnall void
__init(const char * nm)43157a984708SDavid Chisnall numpunct_byname<char>::__init(const char* nm)
43167a984708SDavid Chisnall {
43177a984708SDavid Chisnall     if (strcmp(nm, "C") != 0)
43187a984708SDavid Chisnall     {
43195517e702SDimitry Andric         __libcpp_unique_locale loc(nm);
43205517e702SDimitry Andric         if (!loc)
4321aed8d94eSDimitry Andric             __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
43227a984708SDavid Chisnall                                 " failed to construct for " + string(nm));
4323aed8d94eSDimitry Andric 
43247c82a1ecSDimitry Andric         lconv* lc = __libcpp_localeconv_l(loc.get());
4325aed8d94eSDimitry Andric         checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4326aed8d94eSDimitry Andric                                        loc.get());
4327aed8d94eSDimitry Andric         checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4328aed8d94eSDimitry Andric                                        loc.get());
43297a984708SDavid Chisnall         __grouping_ = lc->grouping;
43307a984708SDavid Chisnall         // localization for truename and falsename is not available
43317a984708SDavid Chisnall     }
43327a984708SDavid Chisnall }
43337a984708SDavid Chisnall 
43347a984708SDavid Chisnall // numpunct_byname<wchar_t>
43357a984708SDavid Chisnall 
numpunct_byname(const char * nm,size_t refs)43367a984708SDavid Chisnall numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
43377a984708SDavid Chisnall     : numpunct<wchar_t>(refs)
43387a984708SDavid Chisnall {
43397a984708SDavid Chisnall     __init(nm);
43407a984708SDavid Chisnall }
43417a984708SDavid Chisnall 
numpunct_byname(const string & nm,size_t refs)43427a984708SDavid Chisnall numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
43437a984708SDavid Chisnall     : numpunct<wchar_t>(refs)
43447a984708SDavid Chisnall {
43457a984708SDavid Chisnall     __init(nm.c_str());
43467a984708SDavid Chisnall }
43477a984708SDavid Chisnall 
~numpunct_byname()43487a984708SDavid Chisnall numpunct_byname<wchar_t>::~numpunct_byname()
43497a984708SDavid Chisnall {
43507a984708SDavid Chisnall }
43517a984708SDavid Chisnall 
43527a984708SDavid Chisnall void
__init(const char * nm)43537a984708SDavid Chisnall numpunct_byname<wchar_t>::__init(const char* nm)
43547a984708SDavid Chisnall {
43557a984708SDavid Chisnall     if (strcmp(nm, "C") != 0)
43567a984708SDavid Chisnall     {
43575517e702SDimitry Andric         __libcpp_unique_locale loc(nm);
43585517e702SDimitry Andric         if (!loc)
4359aed8d94eSDimitry Andric             __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
43607a984708SDavid Chisnall                                 " failed to construct for " + string(nm));
4361aed8d94eSDimitry Andric 
43627c82a1ecSDimitry Andric         lconv* lc = __libcpp_localeconv_l(loc.get());
4363aed8d94eSDimitry Andric         checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4364aed8d94eSDimitry Andric                                         loc.get());
4365aed8d94eSDimitry Andric         checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4366aed8d94eSDimitry Andric                                         loc.get());
43677a984708SDavid Chisnall         __grouping_ = lc->grouping;
4368aed8d94eSDimitry Andric         // localization for truename and falsename is not available
43697a984708SDavid Chisnall     }
43707a984708SDavid Chisnall }
43717a984708SDavid Chisnall 
43727a984708SDavid Chisnall // num_get helpers
43737a984708SDavid Chisnall 
43747a984708SDavid Chisnall int
__get_base(ios_base & iob)43757a984708SDavid Chisnall __num_get_base::__get_base(ios_base& iob)
43767a984708SDavid Chisnall {
43777a984708SDavid Chisnall     ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
43787a984708SDavid Chisnall     if (__basefield == ios_base::oct)
43797a984708SDavid Chisnall         return 8;
43807a984708SDavid Chisnall     else if (__basefield == ios_base::hex)
43817a984708SDavid Chisnall         return 16;
43827a984708SDavid Chisnall     else if (__basefield == 0)
43837a984708SDavid Chisnall         return 0;
43847a984708SDavid Chisnall     return 10;
43857a984708SDavid Chisnall }
43867a984708SDavid Chisnall 
43877a984708SDavid Chisnall const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
43887a984708SDavid Chisnall 
43897a984708SDavid Chisnall void
__check_grouping(const string & __grouping,unsigned * __g,unsigned * __g_end,ios_base::iostate & __err)43907a984708SDavid Chisnall __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
43917a984708SDavid Chisnall                  ios_base::iostate& __err)
43927a984708SDavid Chisnall {
43937a984708SDavid Chisnall     if (__grouping.size() != 0)
43947a984708SDavid Chisnall     {
43957a984708SDavid Chisnall         reverse(__g, __g_end);
43967a984708SDavid Chisnall         const char* __ig = __grouping.data();
43977a984708SDavid Chisnall         const char* __eg = __ig + __grouping.size();
43987a984708SDavid Chisnall         for (unsigned* __r = __g; __r < __g_end-1; ++__r)
43997a984708SDavid Chisnall         {
44007a984708SDavid Chisnall             if (0 < *__ig && *__ig < numeric_limits<char>::max())
44017a984708SDavid Chisnall             {
440294e3ee44SDavid Chisnall                 if (static_cast<unsigned>(*__ig) != *__r)
44037a984708SDavid Chisnall                 {
44047a984708SDavid Chisnall                     __err = ios_base::failbit;
44057a984708SDavid Chisnall                     return;
44067a984708SDavid Chisnall                 }
44077a984708SDavid Chisnall             }
44087a984708SDavid Chisnall             if (__eg - __ig > 1)
44097a984708SDavid Chisnall                 ++__ig;
44107a984708SDavid Chisnall         }
44117a984708SDavid Chisnall         if (0 < *__ig && *__ig < numeric_limits<char>::max())
44127a984708SDavid Chisnall         {
441394e3ee44SDavid Chisnall             if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
44147a984708SDavid Chisnall                 __err = ios_base::failbit;
44157a984708SDavid Chisnall         }
44167a984708SDavid Chisnall     }
44177a984708SDavid Chisnall }
44187a984708SDavid Chisnall 
44197a984708SDavid Chisnall void
__format_int(char * __fmtp,const char * __len,bool __signd,ios_base::fmtflags __flags)44207a984708SDavid Chisnall __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
44217a984708SDavid Chisnall                              ios_base::fmtflags __flags)
44227a984708SDavid Chisnall {
44237a984708SDavid Chisnall     if (__flags & ios_base::showpos)
44247a984708SDavid Chisnall         *__fmtp++ = '+';
44257a984708SDavid Chisnall     if (__flags & ios_base::showbase)
44267a984708SDavid Chisnall         *__fmtp++ = '#';
44277a984708SDavid Chisnall     while(*__len)
44287a984708SDavid Chisnall         *__fmtp++ = *__len++;
44297a984708SDavid Chisnall     if ((__flags & ios_base::basefield) == ios_base::oct)
44307a984708SDavid Chisnall         *__fmtp = 'o';
44317a984708SDavid Chisnall     else if ((__flags & ios_base::basefield) == ios_base::hex)
44327a984708SDavid Chisnall     {
44337a984708SDavid Chisnall         if (__flags & ios_base::uppercase)
44347a984708SDavid Chisnall             *__fmtp = 'X';
44357a984708SDavid Chisnall         else
44367a984708SDavid Chisnall             *__fmtp = 'x';
44377a984708SDavid Chisnall     }
44387a984708SDavid Chisnall     else if (__signd)
44397a984708SDavid Chisnall         *__fmtp = 'd';
44407a984708SDavid Chisnall     else
44417a984708SDavid Chisnall         *__fmtp = 'u';
44427a984708SDavid Chisnall }
44437a984708SDavid Chisnall 
44447a984708SDavid Chisnall bool
__format_float(char * __fmtp,const char * __len,ios_base::fmtflags __flags)44457a984708SDavid Chisnall __num_put_base::__format_float(char* __fmtp, const char* __len,
44467a984708SDavid Chisnall                                ios_base::fmtflags __flags)
44477a984708SDavid Chisnall {
44487a984708SDavid Chisnall     bool specify_precision = true;
44497a984708SDavid Chisnall     if (__flags & ios_base::showpos)
44507a984708SDavid Chisnall         *__fmtp++ = '+';
44517a984708SDavid Chisnall     if (__flags & ios_base::showpoint)
44527a984708SDavid Chisnall         *__fmtp++ = '#';
44537a984708SDavid Chisnall     ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
44544f7ab58eSDimitry Andric     bool uppercase = (__flags & ios_base::uppercase) != 0;
44557a984708SDavid Chisnall     if (floatfield == (ios_base::fixed | ios_base::scientific))
44567a984708SDavid Chisnall         specify_precision = false;
44577a984708SDavid Chisnall     else
44587a984708SDavid Chisnall     {
44597a984708SDavid Chisnall         *__fmtp++ = '.';
44607a984708SDavid Chisnall         *__fmtp++ = '*';
44617a984708SDavid Chisnall     }
44627a984708SDavid Chisnall     while(*__len)
44637a984708SDavid Chisnall         *__fmtp++ = *__len++;
44647a984708SDavid Chisnall     if (floatfield == ios_base::fixed)
44657a984708SDavid Chisnall     {
44667a984708SDavid Chisnall         if (uppercase)
44677a984708SDavid Chisnall             *__fmtp = 'F';
44687a984708SDavid Chisnall         else
44697a984708SDavid Chisnall             *__fmtp = 'f';
44707a984708SDavid Chisnall     }
44717a984708SDavid Chisnall     else if (floatfield == ios_base::scientific)
44727a984708SDavid Chisnall     {
44737a984708SDavid Chisnall         if (uppercase)
44747a984708SDavid Chisnall             *__fmtp = 'E';
44757a984708SDavid Chisnall         else
44767a984708SDavid Chisnall             *__fmtp = 'e';
44777a984708SDavid Chisnall     }
44787a984708SDavid Chisnall     else if (floatfield == (ios_base::fixed | ios_base::scientific))
44797a984708SDavid Chisnall     {
44807a984708SDavid Chisnall         if (uppercase)
44817a984708SDavid Chisnall             *__fmtp = 'A';
44827a984708SDavid Chisnall         else
44837a984708SDavid Chisnall             *__fmtp = 'a';
44847a984708SDavid Chisnall     }
44857a984708SDavid Chisnall     else
44867a984708SDavid Chisnall     {
44877a984708SDavid Chisnall         if (uppercase)
44887a984708SDavid Chisnall             *__fmtp = 'G';
44897a984708SDavid Chisnall         else
44907a984708SDavid Chisnall             *__fmtp = 'g';
44917a984708SDavid Chisnall     }
44927a984708SDavid Chisnall     return specify_precision;
44937a984708SDavid Chisnall }
44947a984708SDavid Chisnall 
44957a984708SDavid Chisnall char*
__identify_padding(char * __nb,char * __ne,const ios_base & __iob)44967a984708SDavid Chisnall __num_put_base::__identify_padding(char* __nb, char* __ne,
44977a984708SDavid Chisnall                                    const ios_base& __iob)
44987a984708SDavid Chisnall {
44997a984708SDavid Chisnall     switch (__iob.flags() & ios_base::adjustfield)
45007a984708SDavid Chisnall     {
45017a984708SDavid Chisnall     case ios_base::internal:
45027a984708SDavid Chisnall         if (__nb[0] == '-' || __nb[0] == '+')
45037a984708SDavid Chisnall             return __nb+1;
45047a984708SDavid Chisnall         if (__ne - __nb >= 2 && __nb[0] == '0'
45057a984708SDavid Chisnall                             && (__nb[1] == 'x' || __nb[1] == 'X'))
45067a984708SDavid Chisnall             return __nb+2;
45077a984708SDavid Chisnall         break;
45087a984708SDavid Chisnall     case ios_base::left:
45097a984708SDavid Chisnall         return __ne;
45107a984708SDavid Chisnall     case ios_base::right:
45117a984708SDavid Chisnall     default:
45127a984708SDavid Chisnall         break;
45137a984708SDavid Chisnall     }
45147a984708SDavid Chisnall     return __nb;
45157a984708SDavid Chisnall }
45167a984708SDavid Chisnall 
45177a984708SDavid Chisnall // time_get
45187a984708SDavid Chisnall 
45197a984708SDavid Chisnall static
45207a984708SDavid Chisnall string*
init_weeks()45217a984708SDavid Chisnall init_weeks()
45227a984708SDavid Chisnall {
45237a984708SDavid Chisnall     static string weeks[14];
45247a984708SDavid Chisnall     weeks[0]  = "Sunday";
45257a984708SDavid Chisnall     weeks[1]  = "Monday";
45267a984708SDavid Chisnall     weeks[2]  = "Tuesday";
45277a984708SDavid Chisnall     weeks[3]  = "Wednesday";
45287a984708SDavid Chisnall     weeks[4]  = "Thursday";
45297a984708SDavid Chisnall     weeks[5]  = "Friday";
45307a984708SDavid Chisnall     weeks[6]  = "Saturday";
45317a984708SDavid Chisnall     weeks[7]  = "Sun";
45327a984708SDavid Chisnall     weeks[8]  = "Mon";
45337a984708SDavid Chisnall     weeks[9]  = "Tue";
45347a984708SDavid Chisnall     weeks[10] = "Wed";
45357a984708SDavid Chisnall     weeks[11] = "Thu";
45367a984708SDavid Chisnall     weeks[12] = "Fri";
45377a984708SDavid Chisnall     weeks[13] = "Sat";
45387a984708SDavid Chisnall     return weeks;
45397a984708SDavid Chisnall }
45407a984708SDavid Chisnall 
45417a984708SDavid Chisnall static
45427a984708SDavid Chisnall wstring*
init_wweeks()45437a984708SDavid Chisnall init_wweeks()
45447a984708SDavid Chisnall {
45457a984708SDavid Chisnall     static wstring weeks[14];
45467a984708SDavid Chisnall     weeks[0]  = L"Sunday";
45477a984708SDavid Chisnall     weeks[1]  = L"Monday";
45487a984708SDavid Chisnall     weeks[2]  = L"Tuesday";
45497a984708SDavid Chisnall     weeks[3]  = L"Wednesday";
45507a984708SDavid Chisnall     weeks[4]  = L"Thursday";
45517a984708SDavid Chisnall     weeks[5]  = L"Friday";
45527a984708SDavid Chisnall     weeks[6]  = L"Saturday";
45537a984708SDavid Chisnall     weeks[7]  = L"Sun";
45547a984708SDavid Chisnall     weeks[8]  = L"Mon";
45557a984708SDavid Chisnall     weeks[9]  = L"Tue";
45567a984708SDavid Chisnall     weeks[10] = L"Wed";
45577a984708SDavid Chisnall     weeks[11] = L"Thu";
45587a984708SDavid Chisnall     weeks[12] = L"Fri";
45597a984708SDavid Chisnall     weeks[13] = L"Sat";
45607a984708SDavid Chisnall     return weeks;
45617a984708SDavid Chisnall }
45627a984708SDavid Chisnall 
45637a984708SDavid Chisnall template <>
45647a984708SDavid Chisnall const string*
__weeks() const45657a984708SDavid Chisnall __time_get_c_storage<char>::__weeks() const
45667a984708SDavid Chisnall {
45677a984708SDavid Chisnall     static const string* weeks = init_weeks();
45687a984708SDavid Chisnall     return weeks;
45697a984708SDavid Chisnall }
45707a984708SDavid Chisnall 
45717a984708SDavid Chisnall template <>
45727a984708SDavid Chisnall const wstring*
__weeks() const45737a984708SDavid Chisnall __time_get_c_storage<wchar_t>::__weeks() const
45747a984708SDavid Chisnall {
45757a984708SDavid Chisnall     static const wstring* weeks = init_wweeks();
45767a984708SDavid Chisnall     return weeks;
45777a984708SDavid Chisnall }
45787a984708SDavid Chisnall 
45797a984708SDavid Chisnall static
45807a984708SDavid Chisnall string*
init_months()45817a984708SDavid Chisnall init_months()
45827a984708SDavid Chisnall {
45837a984708SDavid Chisnall     static string months[24];
45847a984708SDavid Chisnall     months[0]  = "January";
45857a984708SDavid Chisnall     months[1]  = "February";
45867a984708SDavid Chisnall     months[2]  = "March";
45877a984708SDavid Chisnall     months[3]  = "April";
45887a984708SDavid Chisnall     months[4]  = "May";
45897a984708SDavid Chisnall     months[5]  = "June";
45907a984708SDavid Chisnall     months[6]  = "July";
45917a984708SDavid Chisnall     months[7]  = "August";
45927a984708SDavid Chisnall     months[8]  = "September";
45937a984708SDavid Chisnall     months[9]  = "October";
45947a984708SDavid Chisnall     months[10] = "November";
45957a984708SDavid Chisnall     months[11] = "December";
45967a984708SDavid Chisnall     months[12] = "Jan";
45977a984708SDavid Chisnall     months[13] = "Feb";
45987a984708SDavid Chisnall     months[14] = "Mar";
45997a984708SDavid Chisnall     months[15] = "Apr";
46007a984708SDavid Chisnall     months[16] = "May";
46017a984708SDavid Chisnall     months[17] = "Jun";
46027a984708SDavid Chisnall     months[18] = "Jul";
46037a984708SDavid Chisnall     months[19] = "Aug";
46047a984708SDavid Chisnall     months[20] = "Sep";
46057a984708SDavid Chisnall     months[21] = "Oct";
46067a984708SDavid Chisnall     months[22] = "Nov";
46077a984708SDavid Chisnall     months[23] = "Dec";
46087a984708SDavid Chisnall     return months;
46097a984708SDavid Chisnall }
46107a984708SDavid Chisnall 
46117a984708SDavid Chisnall static
46127a984708SDavid Chisnall wstring*
init_wmonths()46137a984708SDavid Chisnall init_wmonths()
46147a984708SDavid Chisnall {
46157a984708SDavid Chisnall     static wstring months[24];
46167a984708SDavid Chisnall     months[0]  = L"January";
46177a984708SDavid Chisnall     months[1]  = L"February";
46187a984708SDavid Chisnall     months[2]  = L"March";
46197a984708SDavid Chisnall     months[3]  = L"April";
46207a984708SDavid Chisnall     months[4]  = L"May";
46217a984708SDavid Chisnall     months[5]  = L"June";
46227a984708SDavid Chisnall     months[6]  = L"July";
46237a984708SDavid Chisnall     months[7]  = L"August";
46247a984708SDavid Chisnall     months[8]  = L"September";
46257a984708SDavid Chisnall     months[9]  = L"October";
46267a984708SDavid Chisnall     months[10] = L"November";
46277a984708SDavid Chisnall     months[11] = L"December";
46287a984708SDavid Chisnall     months[12] = L"Jan";
46297a984708SDavid Chisnall     months[13] = L"Feb";
46307a984708SDavid Chisnall     months[14] = L"Mar";
46317a984708SDavid Chisnall     months[15] = L"Apr";
46327a984708SDavid Chisnall     months[16] = L"May";
46337a984708SDavid Chisnall     months[17] = L"Jun";
46347a984708SDavid Chisnall     months[18] = L"Jul";
46357a984708SDavid Chisnall     months[19] = L"Aug";
46367a984708SDavid Chisnall     months[20] = L"Sep";
46377a984708SDavid Chisnall     months[21] = L"Oct";
46387a984708SDavid Chisnall     months[22] = L"Nov";
46397a984708SDavid Chisnall     months[23] = L"Dec";
46407a984708SDavid Chisnall     return months;
46417a984708SDavid Chisnall }
46427a984708SDavid Chisnall 
46437a984708SDavid Chisnall template <>
46447a984708SDavid Chisnall const string*
__months() const46457a984708SDavid Chisnall __time_get_c_storage<char>::__months() const
46467a984708SDavid Chisnall {
46477a984708SDavid Chisnall     static const string* months = init_months();
46487a984708SDavid Chisnall     return months;
46497a984708SDavid Chisnall }
46507a984708SDavid Chisnall 
46517a984708SDavid Chisnall template <>
46527a984708SDavid Chisnall const wstring*
__months() const46537a984708SDavid Chisnall __time_get_c_storage<wchar_t>::__months() const
46547a984708SDavid Chisnall {
46557a984708SDavid Chisnall     static const wstring* months = init_wmonths();
46567a984708SDavid Chisnall     return months;
46577a984708SDavid Chisnall }
46587a984708SDavid Chisnall 
46597a984708SDavid Chisnall static
46607a984708SDavid Chisnall string*
init_am_pm()46617a984708SDavid Chisnall init_am_pm()
46627a984708SDavid Chisnall {
4663*4ba319b5SDimitry Andric     static string am_pm[2];
46647a984708SDavid Chisnall     am_pm[0]  = "AM";
46657a984708SDavid Chisnall     am_pm[1]  = "PM";
46667a984708SDavid Chisnall     return am_pm;
46677a984708SDavid Chisnall }
46687a984708SDavid Chisnall 
46697a984708SDavid Chisnall static
46707a984708SDavid Chisnall wstring*
init_wam_pm()46717a984708SDavid Chisnall init_wam_pm()
46727a984708SDavid Chisnall {
4673*4ba319b5SDimitry Andric     static wstring am_pm[2];
46747a984708SDavid Chisnall     am_pm[0]  = L"AM";
46757a984708SDavid Chisnall     am_pm[1]  = L"PM";
46767a984708SDavid Chisnall     return am_pm;
46777a984708SDavid Chisnall }
46787a984708SDavid Chisnall 
46797a984708SDavid Chisnall template <>
46807a984708SDavid Chisnall const string*
__am_pm() const46817a984708SDavid Chisnall __time_get_c_storage<char>::__am_pm() const
46827a984708SDavid Chisnall {
46837a984708SDavid Chisnall     static const string* am_pm = init_am_pm();
46847a984708SDavid Chisnall     return am_pm;
46857a984708SDavid Chisnall }
46867a984708SDavid Chisnall 
46877a984708SDavid Chisnall template <>
46887a984708SDavid Chisnall const wstring*
__am_pm() const46897a984708SDavid Chisnall __time_get_c_storage<wchar_t>::__am_pm() const
46907a984708SDavid Chisnall {
46917a984708SDavid Chisnall     static const wstring* am_pm = init_wam_pm();
46927a984708SDavid Chisnall     return am_pm;
46937a984708SDavid Chisnall }
46947a984708SDavid Chisnall 
46957a984708SDavid Chisnall template <>
46967a984708SDavid Chisnall const string&
__x() const46977a984708SDavid Chisnall __time_get_c_storage<char>::__x() const
46987a984708SDavid Chisnall {
46997a984708SDavid Chisnall     static string s("%m/%d/%y");
47007a984708SDavid Chisnall     return s;
47017a984708SDavid Chisnall }
47027a984708SDavid Chisnall 
47037a984708SDavid Chisnall template <>
47047a984708SDavid Chisnall const wstring&
__x() const47057a984708SDavid Chisnall __time_get_c_storage<wchar_t>::__x() const
47067a984708SDavid Chisnall {
47077a984708SDavid Chisnall     static wstring s(L"%m/%d/%y");
47087a984708SDavid Chisnall     return s;
47097a984708SDavid Chisnall }
47107a984708SDavid Chisnall 
47117a984708SDavid Chisnall template <>
47127a984708SDavid Chisnall const string&
__X() const47137a984708SDavid Chisnall __time_get_c_storage<char>::__X() const
47147a984708SDavid Chisnall {
47157a984708SDavid Chisnall     static string s("%H:%M:%S");
47167a984708SDavid Chisnall     return s;
47177a984708SDavid Chisnall }
47187a984708SDavid Chisnall 
47197a984708SDavid Chisnall template <>
47207a984708SDavid Chisnall const wstring&
__X() const47217a984708SDavid Chisnall __time_get_c_storage<wchar_t>::__X() const
47227a984708SDavid Chisnall {
47237a984708SDavid Chisnall     static wstring s(L"%H:%M:%S");
47247a984708SDavid Chisnall     return s;
47257a984708SDavid Chisnall }
47267a984708SDavid Chisnall 
47277a984708SDavid Chisnall template <>
47287a984708SDavid Chisnall const string&
__c() const47297a984708SDavid Chisnall __time_get_c_storage<char>::__c() const
47307a984708SDavid Chisnall {
47317a984708SDavid Chisnall     static string s("%a %b %d %H:%M:%S %Y");
47327a984708SDavid Chisnall     return s;
47337a984708SDavid Chisnall }
47347a984708SDavid Chisnall 
47357a984708SDavid Chisnall template <>
47367a984708SDavid Chisnall const wstring&
__c() const47377a984708SDavid Chisnall __time_get_c_storage<wchar_t>::__c() const
47387a984708SDavid Chisnall {
47397a984708SDavid Chisnall     static wstring s(L"%a %b %d %H:%M:%S %Y");
47407a984708SDavid Chisnall     return s;
47417a984708SDavid Chisnall }
47427a984708SDavid Chisnall 
47437a984708SDavid Chisnall template <>
47447a984708SDavid Chisnall const string&
__r() const47457a984708SDavid Chisnall __time_get_c_storage<char>::__r() const
47467a984708SDavid Chisnall {
47477a984708SDavid Chisnall     static string s("%I:%M:%S %p");
47487a984708SDavid Chisnall     return s;
47497a984708SDavid Chisnall }
47507a984708SDavid Chisnall 
47517a984708SDavid Chisnall template <>
47527a984708SDavid Chisnall const wstring&
__r() const47537a984708SDavid Chisnall __time_get_c_storage<wchar_t>::__r() const
47547a984708SDavid Chisnall {
47557a984708SDavid Chisnall     static wstring s(L"%I:%M:%S %p");
47567a984708SDavid Chisnall     return s;
47577a984708SDavid Chisnall }
47587a984708SDavid Chisnall 
47597a984708SDavid Chisnall // time_get_byname
47607a984708SDavid Chisnall 
__time_get(const char * nm)47617a984708SDavid Chisnall __time_get::__time_get(const char* nm)
47627a984708SDavid Chisnall     : __loc_(newlocale(LC_ALL_MASK, nm, 0))
47637a984708SDavid Chisnall {
47647a984708SDavid Chisnall     if (__loc_ == 0)
4765aed8d94eSDimitry Andric         __throw_runtime_error("time_get_byname"
47667a984708SDavid Chisnall                             " failed to construct for " + string(nm));
47677a984708SDavid Chisnall }
47687a984708SDavid Chisnall 
__time_get(const string & nm)47697a984708SDavid Chisnall __time_get::__time_get(const string& nm)
47707a984708SDavid Chisnall     : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
47717a984708SDavid Chisnall {
47727a984708SDavid Chisnall     if (__loc_ == 0)
4773aed8d94eSDimitry Andric         __throw_runtime_error("time_get_byname"
47747a984708SDavid Chisnall                             " failed to construct for " + nm);
47757a984708SDavid Chisnall }
47767a984708SDavid Chisnall 
~__time_get()47777a984708SDavid Chisnall __time_get::~__time_get()
47787a984708SDavid Chisnall {
47797a984708SDavid Chisnall     freelocale(__loc_);
47807a984708SDavid Chisnall }
47814f7ab58eSDimitry Andric #if defined(__clang__)
478294e3ee44SDavid Chisnall #pragma clang diagnostic ignored "-Wmissing-field-initializers"
47834f7ab58eSDimitry Andric #endif
47844f7ab58eSDimitry Andric #if defined(__GNUG__)
4785cfdf2879SDavid Chisnall #pragma GCC   diagnostic ignored "-Wmissing-field-initializers"
47864f7ab58eSDimitry Andric #endif
478794e3ee44SDavid Chisnall 
47887a984708SDavid Chisnall template <>
47897a984708SDavid Chisnall string
__analyze(char fmt,const ctype<char> & ct)47907a984708SDavid Chisnall __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
47917a984708SDavid Chisnall {
479294e3ee44SDavid Chisnall     tm t = {0};
47937a984708SDavid Chisnall     t.tm_sec = 59;
47947a984708SDavid Chisnall     t.tm_min = 55;
47957a984708SDavid Chisnall     t.tm_hour = 23;
47967a984708SDavid Chisnall     t.tm_mday = 31;
47977a984708SDavid Chisnall     t.tm_mon = 11;
47987a984708SDavid Chisnall     t.tm_year = 161;
47997a984708SDavid Chisnall     t.tm_wday = 6;
48007a984708SDavid Chisnall     t.tm_yday = 364;
48017a984708SDavid Chisnall     t.tm_isdst = -1;
48027a984708SDavid Chisnall     char buf[100];
48037a984708SDavid Chisnall     char f[3] = {0};
48047a984708SDavid Chisnall     f[0] = '%';
48057a984708SDavid Chisnall     f[1] = fmt;
4806cfdf2879SDavid Chisnall     size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
48077a984708SDavid Chisnall     char* bb = buf;
48087a984708SDavid Chisnall     char* be = buf + n;
48097a984708SDavid Chisnall     string result;
48107a984708SDavid Chisnall     while (bb != be)
48117a984708SDavid Chisnall     {
48127a984708SDavid Chisnall         if (ct.is(ctype_base::space, *bb))
48137a984708SDavid Chisnall         {
48147a984708SDavid Chisnall             result.push_back(' ');
48157a984708SDavid Chisnall             for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
48167a984708SDavid Chisnall                 ;
48177a984708SDavid Chisnall             continue;
48187a984708SDavid Chisnall         }
48197a984708SDavid Chisnall         char* w = bb;
48207a984708SDavid Chisnall         ios_base::iostate err = ios_base::goodbit;
482194e3ee44SDavid Chisnall         ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
48227a984708SDavid Chisnall                                ct, err, false)
48237a984708SDavid Chisnall                                - this->__weeks_;
48247a984708SDavid Chisnall         if (i < 14)
48257a984708SDavid Chisnall         {
48267a984708SDavid Chisnall             result.push_back('%');
48277a984708SDavid Chisnall             if (i < 7)
48287a984708SDavid Chisnall                 result.push_back('A');
48297a984708SDavid Chisnall             else
48307a984708SDavid Chisnall                 result.push_back('a');
48317a984708SDavid Chisnall             bb = w;
48327a984708SDavid Chisnall             continue;
48337a984708SDavid Chisnall         }
48347a984708SDavid Chisnall         w = bb;
48357a984708SDavid Chisnall         i = __scan_keyword(w, be, this->__months_, this->__months_+24,
48367a984708SDavid Chisnall                            ct, err, false)
48377a984708SDavid Chisnall                            - this->__months_;
48387a984708SDavid Chisnall         if (i < 24)
48397a984708SDavid Chisnall         {
48407a984708SDavid Chisnall             result.push_back('%');
48417a984708SDavid Chisnall             if (i < 12)
48427a984708SDavid Chisnall                 result.push_back('B');
48437a984708SDavid Chisnall             else
48447a984708SDavid Chisnall                 result.push_back('b');
48457a984708SDavid Chisnall             if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
48467a984708SDavid Chisnall                 result.back() = 'm';
48477a984708SDavid Chisnall             bb = w;
48487a984708SDavid Chisnall             continue;
48497a984708SDavid Chisnall         }
48507a984708SDavid Chisnall         if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
48517a984708SDavid Chisnall         {
48527a984708SDavid Chisnall             w = bb;
48537a984708SDavid Chisnall             i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
48547a984708SDavid Chisnall                                ct, err, false) - this->__am_pm_;
48557a984708SDavid Chisnall             if (i < 2)
48567a984708SDavid Chisnall             {
48577a984708SDavid Chisnall                 result.push_back('%');
48587a984708SDavid Chisnall                 result.push_back('p');
48597a984708SDavid Chisnall                 bb = w;
48607a984708SDavid Chisnall                 continue;
48617a984708SDavid Chisnall             }
48627a984708SDavid Chisnall         }
48637a984708SDavid Chisnall         w = bb;
48647a984708SDavid Chisnall         if (ct.is(ctype_base::digit, *bb))
48657a984708SDavid Chisnall         {
48667a984708SDavid Chisnall             switch(__get_up_to_n_digits(bb, be, err, ct, 4))
48677a984708SDavid Chisnall             {
48687a984708SDavid Chisnall             case 6:
48697a984708SDavid Chisnall                 result.push_back('%');
48707a984708SDavid Chisnall                 result.push_back('w');
48717a984708SDavid Chisnall                 break;
48727a984708SDavid Chisnall             case 7:
48737a984708SDavid Chisnall                 result.push_back('%');
48747a984708SDavid Chisnall                 result.push_back('u');
48757a984708SDavid Chisnall                 break;
48767a984708SDavid Chisnall             case 11:
48777a984708SDavid Chisnall                 result.push_back('%');
48787a984708SDavid Chisnall                 result.push_back('I');
48797a984708SDavid Chisnall                 break;
48807a984708SDavid Chisnall             case 12:
48817a984708SDavid Chisnall                 result.push_back('%');
48827a984708SDavid Chisnall                 result.push_back('m');
48837a984708SDavid Chisnall                 break;
48847a984708SDavid Chisnall             case 23:
48857a984708SDavid Chisnall                 result.push_back('%');
48867a984708SDavid Chisnall                 result.push_back('H');
48877a984708SDavid Chisnall                 break;
48887a984708SDavid Chisnall             case 31:
48897a984708SDavid Chisnall                 result.push_back('%');
48907a984708SDavid Chisnall                 result.push_back('d');
48917a984708SDavid Chisnall                 break;
48927a984708SDavid Chisnall             case 55:
48937a984708SDavid Chisnall                 result.push_back('%');
48947a984708SDavid Chisnall                 result.push_back('M');
48957a984708SDavid Chisnall                 break;
48967a984708SDavid Chisnall             case 59:
48977a984708SDavid Chisnall                 result.push_back('%');
48987a984708SDavid Chisnall                 result.push_back('S');
48997a984708SDavid Chisnall                 break;
49007a984708SDavid Chisnall             case 61:
49017a984708SDavid Chisnall                 result.push_back('%');
49027a984708SDavid Chisnall                 result.push_back('y');
49037a984708SDavid Chisnall                 break;
49047a984708SDavid Chisnall             case 364:
49057a984708SDavid Chisnall                 result.push_back('%');
49067a984708SDavid Chisnall                 result.push_back('j');
49077a984708SDavid Chisnall                 break;
49087a984708SDavid Chisnall             case 2061:
49097a984708SDavid Chisnall                 result.push_back('%');
49107a984708SDavid Chisnall                 result.push_back('Y');
49117a984708SDavid Chisnall                 break;
49127a984708SDavid Chisnall             default:
49137a984708SDavid Chisnall                 for (; w != bb; ++w)
49147a984708SDavid Chisnall                     result.push_back(*w);
49157a984708SDavid Chisnall                 break;
49167a984708SDavid Chisnall             }
49177a984708SDavid Chisnall             continue;
49187a984708SDavid Chisnall         }
49197a984708SDavid Chisnall         if (*bb == '%')
49207a984708SDavid Chisnall         {
49217a984708SDavid Chisnall             result.push_back('%');
49227a984708SDavid Chisnall             result.push_back('%');
49237a984708SDavid Chisnall             ++bb;
49247a984708SDavid Chisnall             continue;
49257a984708SDavid Chisnall         }
49267a984708SDavid Chisnall         result.push_back(*bb);
49277a984708SDavid Chisnall         ++bb;
49287a984708SDavid Chisnall     }
49297a984708SDavid Chisnall     return result;
49307a984708SDavid Chisnall }
49317a984708SDavid Chisnall 
49324f7ab58eSDimitry Andric #if defined(__clang__)
493394e3ee44SDavid Chisnall #pragma clang diagnostic ignored "-Wmissing-braces"
49344f7ab58eSDimitry Andric #endif
493594e3ee44SDavid Chisnall 
49367a984708SDavid Chisnall template <>
49377a984708SDavid Chisnall wstring
__analyze(char fmt,const ctype<wchar_t> & ct)49387a984708SDavid Chisnall __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
49397a984708SDavid Chisnall {
494094e3ee44SDavid Chisnall     tm t = {0};
49417a984708SDavid Chisnall     t.tm_sec = 59;
49427a984708SDavid Chisnall     t.tm_min = 55;
49437a984708SDavid Chisnall     t.tm_hour = 23;
49447a984708SDavid Chisnall     t.tm_mday = 31;
49457a984708SDavid Chisnall     t.tm_mon = 11;
49467a984708SDavid Chisnall     t.tm_year = 161;
49477a984708SDavid Chisnall     t.tm_wday = 6;
49487a984708SDavid Chisnall     t.tm_yday = 364;
49497a984708SDavid Chisnall     t.tm_isdst = -1;
49507a984708SDavid Chisnall     char buf[100];
49517a984708SDavid Chisnall     char f[3] = {0};
49527a984708SDavid Chisnall     f[0] = '%';
49537a984708SDavid Chisnall     f[1] = fmt;
4954cfdf2879SDavid Chisnall     strftime_l(buf, countof(buf), f, &t, __loc_);
49557a984708SDavid Chisnall     wchar_t wbuf[100];
49567a984708SDavid Chisnall     wchar_t* wbb = wbuf;
49577a984708SDavid Chisnall     mbstate_t mb = {0};
49587a984708SDavid Chisnall     const char* bb = buf;
49597c82a1ecSDimitry Andric     size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
496094e3ee44SDavid Chisnall     if (j == size_t(-1))
49617a984708SDavid Chisnall         __throw_runtime_error("locale not supported");
496294e3ee44SDavid Chisnall     wchar_t* wbe = wbb + j;
49637a984708SDavid Chisnall     wstring result;
49647a984708SDavid Chisnall     while (wbb != wbe)
49657a984708SDavid Chisnall     {
49667a984708SDavid Chisnall         if (ct.is(ctype_base::space, *wbb))
49677a984708SDavid Chisnall         {
49687a984708SDavid Chisnall             result.push_back(L' ');
49697a984708SDavid Chisnall             for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
49707a984708SDavid Chisnall                 ;
49717a984708SDavid Chisnall             continue;
49727a984708SDavid Chisnall         }
49737a984708SDavid Chisnall         wchar_t* w = wbb;
49747a984708SDavid Chisnall         ios_base::iostate err = ios_base::goodbit;
497594e3ee44SDavid Chisnall         ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
49767a984708SDavid Chisnall                                ct, err, false)
49777a984708SDavid Chisnall                                - this->__weeks_;
49787a984708SDavid Chisnall         if (i < 14)
49797a984708SDavid Chisnall         {
49807a984708SDavid Chisnall             result.push_back(L'%');
49817a984708SDavid Chisnall             if (i < 7)
49827a984708SDavid Chisnall                 result.push_back(L'A');
49837a984708SDavid Chisnall             else
49847a984708SDavid Chisnall                 result.push_back(L'a');
49857a984708SDavid Chisnall             wbb = w;
49867a984708SDavid Chisnall             continue;
49877a984708SDavid Chisnall         }
49887a984708SDavid Chisnall         w = wbb;
49897a984708SDavid Chisnall         i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
49907a984708SDavid Chisnall                            ct, err, false)
49917a984708SDavid Chisnall                            - this->__months_;
49927a984708SDavid Chisnall         if (i < 24)
49937a984708SDavid Chisnall         {
49947a984708SDavid Chisnall             result.push_back(L'%');
49957a984708SDavid Chisnall             if (i < 12)
49967a984708SDavid Chisnall                 result.push_back(L'B');
49977a984708SDavid Chisnall             else
49987a984708SDavid Chisnall                 result.push_back(L'b');
49997a984708SDavid Chisnall             if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
50007a984708SDavid Chisnall                 result.back() = L'm';
50017a984708SDavid Chisnall             wbb = w;
50027a984708SDavid Chisnall             continue;
50037a984708SDavid Chisnall         }
50047a984708SDavid Chisnall         if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
50057a984708SDavid Chisnall         {
50067a984708SDavid Chisnall             w = wbb;
50077a984708SDavid Chisnall             i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
50087a984708SDavid Chisnall                                ct, err, false) - this->__am_pm_;
50097a984708SDavid Chisnall             if (i < 2)
50107a984708SDavid Chisnall             {
50117a984708SDavid Chisnall                 result.push_back(L'%');
50127a984708SDavid Chisnall                 result.push_back(L'p');
50137a984708SDavid Chisnall                 wbb = w;
50147a984708SDavid Chisnall                 continue;
50157a984708SDavid Chisnall             }
50167a984708SDavid Chisnall         }
50177a984708SDavid Chisnall         w = wbb;
50187a984708SDavid Chisnall         if (ct.is(ctype_base::digit, *wbb))
50197a984708SDavid Chisnall         {
50207a984708SDavid Chisnall             switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
50217a984708SDavid Chisnall             {
50227a984708SDavid Chisnall             case 6:
50237a984708SDavid Chisnall                 result.push_back(L'%');
50247a984708SDavid Chisnall                 result.push_back(L'w');
50257a984708SDavid Chisnall                 break;
50267a984708SDavid Chisnall             case 7:
50277a984708SDavid Chisnall                 result.push_back(L'%');
50287a984708SDavid Chisnall                 result.push_back(L'u');
50297a984708SDavid Chisnall                 break;
50307a984708SDavid Chisnall             case 11:
50317a984708SDavid Chisnall                 result.push_back(L'%');
50327a984708SDavid Chisnall                 result.push_back(L'I');
50337a984708SDavid Chisnall                 break;
50347a984708SDavid Chisnall             case 12:
50357a984708SDavid Chisnall                 result.push_back(L'%');
50367a984708SDavid Chisnall                 result.push_back(L'm');
50377a984708SDavid Chisnall                 break;
50387a984708SDavid Chisnall             case 23:
50397a984708SDavid Chisnall                 result.push_back(L'%');
50407a984708SDavid Chisnall                 result.push_back(L'H');
50417a984708SDavid Chisnall                 break;
50427a984708SDavid Chisnall             case 31:
50437a984708SDavid Chisnall                 result.push_back(L'%');
50447a984708SDavid Chisnall                 result.push_back(L'd');
50457a984708SDavid Chisnall                 break;
50467a984708SDavid Chisnall             case 55:
50477a984708SDavid Chisnall                 result.push_back(L'%');
50487a984708SDavid Chisnall                 result.push_back(L'M');
50497a984708SDavid Chisnall                 break;
50507a984708SDavid Chisnall             case 59:
50517a984708SDavid Chisnall                 result.push_back(L'%');
50527a984708SDavid Chisnall                 result.push_back(L'S');
50537a984708SDavid Chisnall                 break;
50547a984708SDavid Chisnall             case 61:
50557a984708SDavid Chisnall                 result.push_back(L'%');
50567a984708SDavid Chisnall                 result.push_back(L'y');
50577a984708SDavid Chisnall                 break;
50587a984708SDavid Chisnall             case 364:
50597a984708SDavid Chisnall                 result.push_back(L'%');
50607a984708SDavid Chisnall                 result.push_back(L'j');
50617a984708SDavid Chisnall                 break;
50627a984708SDavid Chisnall             case 2061:
50637a984708SDavid Chisnall                 result.push_back(L'%');
50647a984708SDavid Chisnall                 result.push_back(L'Y');
50657a984708SDavid Chisnall                 break;
50667a984708SDavid Chisnall             default:
50677a984708SDavid Chisnall                 for (; w != wbb; ++w)
50687a984708SDavid Chisnall                     result.push_back(*w);
50697a984708SDavid Chisnall                 break;
50707a984708SDavid Chisnall             }
50717a984708SDavid Chisnall             continue;
50727a984708SDavid Chisnall         }
50737a984708SDavid Chisnall         if (ct.narrow(*wbb, 0) == '%')
50747a984708SDavid Chisnall         {
50757a984708SDavid Chisnall             result.push_back(L'%');
50767a984708SDavid Chisnall             result.push_back(L'%');
50777a984708SDavid Chisnall             ++wbb;
50787a984708SDavid Chisnall             continue;
50797a984708SDavid Chisnall         }
50807a984708SDavid Chisnall         result.push_back(*wbb);
50817a984708SDavid Chisnall         ++wbb;
50827a984708SDavid Chisnall     }
50837a984708SDavid Chisnall     return result;
50847a984708SDavid Chisnall }
50857a984708SDavid Chisnall 
50867a984708SDavid Chisnall template <>
50877a984708SDavid Chisnall void
init(const ctype<char> & ct)50887a984708SDavid Chisnall __time_get_storage<char>::init(const ctype<char>& ct)
50897a984708SDavid Chisnall {
5090936e9439SDimitry Andric     tm t = {0};
50917a984708SDavid Chisnall     char buf[100];
50927a984708SDavid Chisnall     // __weeks_
50937a984708SDavid Chisnall     for (int i = 0; i < 7; ++i)
50947a984708SDavid Chisnall     {
50957a984708SDavid Chisnall         t.tm_wday = i;
5096cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%A", &t, __loc_);
50977a984708SDavid Chisnall         __weeks_[i] = buf;
5098cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%a", &t, __loc_);
50997a984708SDavid Chisnall         __weeks_[i+7] = buf;
51007a984708SDavid Chisnall     }
51017a984708SDavid Chisnall     // __months_
51027a984708SDavid Chisnall     for (int i = 0; i < 12; ++i)
51037a984708SDavid Chisnall     {
51047a984708SDavid Chisnall         t.tm_mon = i;
5105cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%B", &t, __loc_);
51067a984708SDavid Chisnall         __months_[i] = buf;
5107cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%b", &t, __loc_);
51087a984708SDavid Chisnall         __months_[i+12] = buf;
51097a984708SDavid Chisnall     }
51107a984708SDavid Chisnall     // __am_pm_
51117a984708SDavid Chisnall     t.tm_hour = 1;
5112cfdf2879SDavid Chisnall     strftime_l(buf, countof(buf), "%p", &t, __loc_);
51137a984708SDavid Chisnall     __am_pm_[0] = buf;
51147a984708SDavid Chisnall     t.tm_hour = 13;
5115cfdf2879SDavid Chisnall     strftime_l(buf, countof(buf), "%p", &t, __loc_);
51167a984708SDavid Chisnall     __am_pm_[1] = buf;
51177a984708SDavid Chisnall     __c_ = __analyze('c', ct);
51187a984708SDavid Chisnall     __r_ = __analyze('r', ct);
51197a984708SDavid Chisnall     __x_ = __analyze('x', ct);
51207a984708SDavid Chisnall     __X_ = __analyze('X', ct);
51217a984708SDavid Chisnall }
51227a984708SDavid Chisnall 
51237a984708SDavid Chisnall template <>
51247a984708SDavid Chisnall void
init(const ctype<wchar_t> & ct)51257a984708SDavid Chisnall __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
51267a984708SDavid Chisnall {
51277a984708SDavid Chisnall     tm t = {0};
51287a984708SDavid Chisnall     char buf[100];
51297a984708SDavid Chisnall     wchar_t wbuf[100];
51307a984708SDavid Chisnall     wchar_t* wbe;
51317a984708SDavid Chisnall     mbstate_t mb = {0};
51327a984708SDavid Chisnall     // __weeks_
51337a984708SDavid Chisnall     for (int i = 0; i < 7; ++i)
51347a984708SDavid Chisnall     {
51357a984708SDavid Chisnall         t.tm_wday = i;
5136cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%A", &t, __loc_);
51377a984708SDavid Chisnall         mb = mbstate_t();
51387a984708SDavid Chisnall         const char* bb = buf;
51397c82a1ecSDimitry Andric         size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
514094e3ee44SDavid Chisnall         if (j == size_t(-1))
51417a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
51427a984708SDavid Chisnall         wbe = wbuf + j;
51437a984708SDavid Chisnall         __weeks_[i].assign(wbuf, wbe);
5144cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%a", &t, __loc_);
51457a984708SDavid Chisnall         mb = mbstate_t();
51467a984708SDavid Chisnall         bb = buf;
51477c82a1ecSDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
514894e3ee44SDavid Chisnall         if (j == size_t(-1))
51497a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
51507a984708SDavid Chisnall         wbe = wbuf + j;
51517a984708SDavid Chisnall         __weeks_[i+7].assign(wbuf, wbe);
51527a984708SDavid Chisnall     }
51537a984708SDavid Chisnall     // __months_
51547a984708SDavid Chisnall     for (int i = 0; i < 12; ++i)
51557a984708SDavid Chisnall     {
51567a984708SDavid Chisnall         t.tm_mon = i;
5157cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%B", &t, __loc_);
51587a984708SDavid Chisnall         mb = mbstate_t();
51597a984708SDavid Chisnall         const char* bb = buf;
51607c82a1ecSDimitry Andric         size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
516194e3ee44SDavid Chisnall         if (j == size_t(-1))
51627a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
51637a984708SDavid Chisnall         wbe = wbuf + j;
51647a984708SDavid Chisnall         __months_[i].assign(wbuf, wbe);
5165cfdf2879SDavid Chisnall         strftime_l(buf, countof(buf), "%b", &t, __loc_);
51667a984708SDavid Chisnall         mb = mbstate_t();
51677a984708SDavid Chisnall         bb = buf;
51687c82a1ecSDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
516994e3ee44SDavid Chisnall         if (j == size_t(-1))
51707a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
51717a984708SDavid Chisnall         wbe = wbuf + j;
51727a984708SDavid Chisnall         __months_[i+12].assign(wbuf, wbe);
51737a984708SDavid Chisnall     }
51747a984708SDavid Chisnall     // __am_pm_
51757a984708SDavid Chisnall     t.tm_hour = 1;
5176cfdf2879SDavid Chisnall     strftime_l(buf, countof(buf), "%p", &t, __loc_);
51777a984708SDavid Chisnall     mb = mbstate_t();
51787a984708SDavid Chisnall     const char* bb = buf;
51797c82a1ecSDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
518094e3ee44SDavid Chisnall     if (j == size_t(-1))
51817a984708SDavid Chisnall         __throw_runtime_error("locale not supported");
51827a984708SDavid Chisnall     wbe = wbuf + j;
51837a984708SDavid Chisnall     __am_pm_[0].assign(wbuf, wbe);
51847a984708SDavid Chisnall     t.tm_hour = 13;
5185cfdf2879SDavid Chisnall     strftime_l(buf, countof(buf), "%p", &t, __loc_);
51867a984708SDavid Chisnall     mb = mbstate_t();
51877a984708SDavid Chisnall     bb = buf;
51887c82a1ecSDimitry Andric     j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
518994e3ee44SDavid Chisnall     if (j == size_t(-1))
51907a984708SDavid Chisnall         __throw_runtime_error("locale not supported");
51917a984708SDavid Chisnall     wbe = wbuf + j;
51927a984708SDavid Chisnall     __am_pm_[1].assign(wbuf, wbe);
51937a984708SDavid Chisnall     __c_ = __analyze('c', ct);
51947a984708SDavid Chisnall     __r_ = __analyze('r', ct);
51957a984708SDavid Chisnall     __x_ = __analyze('x', ct);
51967a984708SDavid Chisnall     __X_ = __analyze('X', ct);
51977a984708SDavid Chisnall }
51987a984708SDavid Chisnall 
51997a984708SDavid Chisnall template <class CharT>
52007a984708SDavid Chisnall struct _LIBCPP_HIDDEN __time_get_temp
52017a984708SDavid Chisnall     : public ctype_byname<CharT>
52027a984708SDavid Chisnall {
__time_get_temp__time_get_temp52037a984708SDavid Chisnall     explicit __time_get_temp(const char* nm)
52047a984708SDavid Chisnall         : ctype_byname<CharT>(nm, 1) {}
__time_get_temp__time_get_temp52057a984708SDavid Chisnall     explicit __time_get_temp(const string& nm)
52067a984708SDavid Chisnall         : ctype_byname<CharT>(nm, 1) {}
52077a984708SDavid Chisnall };
52087a984708SDavid Chisnall 
52097a984708SDavid Chisnall template <>
__time_get_storage(const char * __nm)52107a984708SDavid Chisnall __time_get_storage<char>::__time_get_storage(const char* __nm)
52117a984708SDavid Chisnall     : __time_get(__nm)
52127a984708SDavid Chisnall {
52137a984708SDavid Chisnall     const __time_get_temp<char> ct(__nm);
52147a984708SDavid Chisnall     init(ct);
52157a984708SDavid Chisnall }
52167a984708SDavid Chisnall 
52177a984708SDavid Chisnall template <>
__time_get_storage(const string & __nm)52187a984708SDavid Chisnall __time_get_storage<char>::__time_get_storage(const string& __nm)
52197a984708SDavid Chisnall     : __time_get(__nm)
52207a984708SDavid Chisnall {
52217a984708SDavid Chisnall     const __time_get_temp<char> ct(__nm);
52227a984708SDavid Chisnall     init(ct);
52237a984708SDavid Chisnall }
52247a984708SDavid Chisnall 
52257a984708SDavid Chisnall template <>
__time_get_storage(const char * __nm)52267a984708SDavid Chisnall __time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
52277a984708SDavid Chisnall     : __time_get(__nm)
52287a984708SDavid Chisnall {
52297a984708SDavid Chisnall     const __time_get_temp<wchar_t> ct(__nm);
52307a984708SDavid Chisnall     init(ct);
52317a984708SDavid Chisnall }
52327a984708SDavid Chisnall 
52337a984708SDavid Chisnall template <>
__time_get_storage(const string & __nm)52347a984708SDavid Chisnall __time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
52357a984708SDavid Chisnall     : __time_get(__nm)
52367a984708SDavid Chisnall {
52377a984708SDavid Chisnall     const __time_get_temp<wchar_t> ct(__nm);
52387a984708SDavid Chisnall     init(ct);
52397a984708SDavid Chisnall }
52407a984708SDavid Chisnall 
52417a984708SDavid Chisnall template <>
52427a984708SDavid Chisnall time_base::dateorder
__do_date_order() const52437a984708SDavid Chisnall __time_get_storage<char>::__do_date_order() const
52447a984708SDavid Chisnall {
52457a984708SDavid Chisnall     unsigned i;
52467a984708SDavid Chisnall     for (i = 0; i < __x_.size(); ++i)
52477a984708SDavid Chisnall         if (__x_[i] == '%')
52487a984708SDavid Chisnall             break;
52497a984708SDavid Chisnall     ++i;
52507a984708SDavid Chisnall     switch (__x_[i])
52517a984708SDavid Chisnall     {
52527a984708SDavid Chisnall     case 'y':
52537a984708SDavid Chisnall     case 'Y':
52547a984708SDavid Chisnall         for (++i; i < __x_.size(); ++i)
52557a984708SDavid Chisnall             if (__x_[i] == '%')
52567a984708SDavid Chisnall                 break;
52577a984708SDavid Chisnall         if (i == __x_.size())
52587a984708SDavid Chisnall             break;
52597a984708SDavid Chisnall         ++i;
52607a984708SDavid Chisnall         switch (__x_[i])
52617a984708SDavid Chisnall         {
52627a984708SDavid Chisnall         case 'm':
52637a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
52647a984708SDavid Chisnall                 if (__x_[i] == '%')
52657a984708SDavid Chisnall                     break;
52667a984708SDavid Chisnall             if (i == __x_.size())
52677a984708SDavid Chisnall                 break;
52687a984708SDavid Chisnall             ++i;
52697a984708SDavid Chisnall             if (__x_[i] == 'd')
52707a984708SDavid Chisnall                 return time_base::ymd;
52717a984708SDavid Chisnall             break;
52727a984708SDavid Chisnall         case 'd':
52737a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
52747a984708SDavid Chisnall                 if (__x_[i] == '%')
52757a984708SDavid Chisnall                     break;
52767a984708SDavid Chisnall             if (i == __x_.size())
52777a984708SDavid Chisnall                 break;
52787a984708SDavid Chisnall             ++i;
52797a984708SDavid Chisnall             if (__x_[i] == 'm')
52807a984708SDavid Chisnall                 return time_base::ydm;
52817a984708SDavid Chisnall             break;
52827a984708SDavid Chisnall         }
52837a984708SDavid Chisnall         break;
52847a984708SDavid Chisnall     case 'm':
52857a984708SDavid Chisnall         for (++i; i < __x_.size(); ++i)
52867a984708SDavid Chisnall             if (__x_[i] == '%')
52877a984708SDavid Chisnall                 break;
52887a984708SDavid Chisnall         if (i == __x_.size())
52897a984708SDavid Chisnall             break;
52907a984708SDavid Chisnall         ++i;
52917a984708SDavid Chisnall         if (__x_[i] == 'd')
52927a984708SDavid Chisnall         {
52937a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
52947a984708SDavid Chisnall                 if (__x_[i] == '%')
52957a984708SDavid Chisnall                     break;
52967a984708SDavid Chisnall             if (i == __x_.size())
52977a984708SDavid Chisnall                 break;
52987a984708SDavid Chisnall             ++i;
52997a984708SDavid Chisnall             if (__x_[i] == 'y' || __x_[i] == 'Y')
53007a984708SDavid Chisnall                 return time_base::mdy;
53017a984708SDavid Chisnall             break;
53027a984708SDavid Chisnall         }
53037a984708SDavid Chisnall         break;
53047a984708SDavid Chisnall     case 'd':
53057a984708SDavid Chisnall         for (++i; i < __x_.size(); ++i)
53067a984708SDavid Chisnall             if (__x_[i] == '%')
53077a984708SDavid Chisnall                 break;
53087a984708SDavid Chisnall         if (i == __x_.size())
53097a984708SDavid Chisnall             break;
53107a984708SDavid Chisnall         ++i;
53117a984708SDavid Chisnall         if (__x_[i] == 'm')
53127a984708SDavid Chisnall         {
53137a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
53147a984708SDavid Chisnall                 if (__x_[i] == '%')
53157a984708SDavid Chisnall                     break;
53167a984708SDavid Chisnall             if (i == __x_.size())
53177a984708SDavid Chisnall                 break;
53187a984708SDavid Chisnall             ++i;
53197a984708SDavid Chisnall             if (__x_[i] == 'y' || __x_[i] == 'Y')
53207a984708SDavid Chisnall                 return time_base::dmy;
53217a984708SDavid Chisnall             break;
53227a984708SDavid Chisnall         }
53237a984708SDavid Chisnall         break;
53247a984708SDavid Chisnall     }
53257a984708SDavid Chisnall     return time_base::no_order;
53267a984708SDavid Chisnall }
53277a984708SDavid Chisnall 
53287a984708SDavid Chisnall template <>
53297a984708SDavid Chisnall time_base::dateorder
__do_date_order() const53307a984708SDavid Chisnall __time_get_storage<wchar_t>::__do_date_order() const
53317a984708SDavid Chisnall {
53327a984708SDavid Chisnall     unsigned i;
53337a984708SDavid Chisnall     for (i = 0; i < __x_.size(); ++i)
53347a984708SDavid Chisnall         if (__x_[i] == L'%')
53357a984708SDavid Chisnall             break;
53367a984708SDavid Chisnall     ++i;
53377a984708SDavid Chisnall     switch (__x_[i])
53387a984708SDavid Chisnall     {
53397a984708SDavid Chisnall     case L'y':
53407a984708SDavid Chisnall     case L'Y':
53417a984708SDavid Chisnall         for (++i; i < __x_.size(); ++i)
53427a984708SDavid Chisnall             if (__x_[i] == L'%')
53437a984708SDavid Chisnall                 break;
53447a984708SDavid Chisnall         if (i == __x_.size())
53457a984708SDavid Chisnall             break;
53467a984708SDavid Chisnall         ++i;
53477a984708SDavid Chisnall         switch (__x_[i])
53487a984708SDavid Chisnall         {
53497a984708SDavid Chisnall         case L'm':
53507a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
53517a984708SDavid Chisnall                 if (__x_[i] == L'%')
53527a984708SDavid Chisnall                     break;
53537a984708SDavid Chisnall             if (i == __x_.size())
53547a984708SDavid Chisnall                 break;
53557a984708SDavid Chisnall             ++i;
53567a984708SDavid Chisnall             if (__x_[i] == L'd')
53577a984708SDavid Chisnall                 return time_base::ymd;
53587a984708SDavid Chisnall             break;
53597a984708SDavid Chisnall         case L'd':
53607a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
53617a984708SDavid Chisnall                 if (__x_[i] == L'%')
53627a984708SDavid Chisnall                     break;
53637a984708SDavid Chisnall             if (i == __x_.size())
53647a984708SDavid Chisnall                 break;
53657a984708SDavid Chisnall             ++i;
53667a984708SDavid Chisnall             if (__x_[i] == L'm')
53677a984708SDavid Chisnall                 return time_base::ydm;
53687a984708SDavid Chisnall             break;
53697a984708SDavid Chisnall         }
53707a984708SDavid Chisnall         break;
53717a984708SDavid Chisnall     case L'm':
53727a984708SDavid Chisnall         for (++i; i < __x_.size(); ++i)
53737a984708SDavid Chisnall             if (__x_[i] == L'%')
53747a984708SDavid Chisnall                 break;
53757a984708SDavid Chisnall         if (i == __x_.size())
53767a984708SDavid Chisnall             break;
53777a984708SDavid Chisnall         ++i;
53787a984708SDavid Chisnall         if (__x_[i] == L'd')
53797a984708SDavid Chisnall         {
53807a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
53817a984708SDavid Chisnall                 if (__x_[i] == L'%')
53827a984708SDavid Chisnall                     break;
53837a984708SDavid Chisnall             if (i == __x_.size())
53847a984708SDavid Chisnall                 break;
53857a984708SDavid Chisnall             ++i;
53867a984708SDavid Chisnall             if (__x_[i] == L'y' || __x_[i] == L'Y')
53877a984708SDavid Chisnall                 return time_base::mdy;
53887a984708SDavid Chisnall             break;
53897a984708SDavid Chisnall         }
53907a984708SDavid Chisnall         break;
53917a984708SDavid Chisnall     case L'd':
53927a984708SDavid Chisnall         for (++i; i < __x_.size(); ++i)
53937a984708SDavid Chisnall             if (__x_[i] == L'%')
53947a984708SDavid Chisnall                 break;
53957a984708SDavid Chisnall         if (i == __x_.size())
53967a984708SDavid Chisnall             break;
53977a984708SDavid Chisnall         ++i;
53987a984708SDavid Chisnall         if (__x_[i] == L'm')
53997a984708SDavid Chisnall         {
54007a984708SDavid Chisnall             for (++i; i < __x_.size(); ++i)
54017a984708SDavid Chisnall                 if (__x_[i] == L'%')
54027a984708SDavid Chisnall                     break;
54037a984708SDavid Chisnall             if (i == __x_.size())
54047a984708SDavid Chisnall                 break;
54057a984708SDavid Chisnall             ++i;
54067a984708SDavid Chisnall             if (__x_[i] == L'y' || __x_[i] == L'Y')
54077a984708SDavid Chisnall                 return time_base::dmy;
54087a984708SDavid Chisnall             break;
54097a984708SDavid Chisnall         }
54107a984708SDavid Chisnall         break;
54117a984708SDavid Chisnall     }
54127a984708SDavid Chisnall     return time_base::no_order;
54137a984708SDavid Chisnall }
54147a984708SDavid Chisnall 
54157a984708SDavid Chisnall // time_put
54167a984708SDavid Chisnall 
__time_put(const char * nm)54177a984708SDavid Chisnall __time_put::__time_put(const char* nm)
54187a984708SDavid Chisnall     : __loc_(newlocale(LC_ALL_MASK, nm, 0))
54197a984708SDavid Chisnall {
54207a984708SDavid Chisnall     if (__loc_ == 0)
5421aed8d94eSDimitry Andric         __throw_runtime_error("time_put_byname"
54227a984708SDavid Chisnall                             " failed to construct for " + string(nm));
54237a984708SDavid Chisnall }
54247a984708SDavid Chisnall 
__time_put(const string & nm)54257a984708SDavid Chisnall __time_put::__time_put(const string& nm)
54267a984708SDavid Chisnall     : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
54277a984708SDavid Chisnall {
54287a984708SDavid Chisnall     if (__loc_ == 0)
5429aed8d94eSDimitry Andric         __throw_runtime_error("time_put_byname"
54307a984708SDavid Chisnall                             " failed to construct for " + nm);
54317a984708SDavid Chisnall }
54327a984708SDavid Chisnall 
~__time_put()54337a984708SDavid Chisnall __time_put::~__time_put()
54347a984708SDavid Chisnall {
54354bab9fd9SDavid Chisnall     if (__loc_ != _LIBCPP_GET_C_LOCALE)
54367a984708SDavid Chisnall         freelocale(__loc_);
54377a984708SDavid Chisnall }
54387a984708SDavid Chisnall 
54397a984708SDavid Chisnall void
__do_put(char * __nb,char * & __ne,const tm * __tm,char __fmt,char __mod) const54407a984708SDavid Chisnall __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
54417a984708SDavid Chisnall                      char __fmt, char __mod) const
54427a984708SDavid Chisnall {
54437a984708SDavid Chisnall     char fmt[] = {'%', __fmt, __mod, 0};
54447a984708SDavid Chisnall     if (__mod != 0)
54457a984708SDavid Chisnall         swap(fmt[1], fmt[2]);
5446cfdf2879SDavid Chisnall     size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
54477a984708SDavid Chisnall     __ne = __nb + n;
54487a984708SDavid Chisnall }
54497a984708SDavid Chisnall 
54507a984708SDavid Chisnall void
__do_put(wchar_t * __wb,wchar_t * & __we,const tm * __tm,char __fmt,char __mod) const54517a984708SDavid Chisnall __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
54527a984708SDavid Chisnall                      char __fmt, char __mod) const
54537a984708SDavid Chisnall {
54547a984708SDavid Chisnall     char __nar[100];
54557a984708SDavid Chisnall     char* __ne = __nar + 100;
54567a984708SDavid Chisnall     __do_put(__nar, __ne, __tm, __fmt, __mod);
54577a984708SDavid Chisnall     mbstate_t mb = {0};
54587a984708SDavid Chisnall     const char* __nb = __nar;
54597c82a1ecSDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
546094e3ee44SDavid Chisnall     if (j == size_t(-1))
54617a984708SDavid Chisnall         __throw_runtime_error("locale not supported");
54627a984708SDavid Chisnall     __we = __wb + j;
54637a984708SDavid Chisnall }
54647a984708SDavid Chisnall 
54657a984708SDavid Chisnall // moneypunct_byname
54667a984708SDavid Chisnall 
546794e3ee44SDavid Chisnall template <class charT>
54687a984708SDavid Chisnall static
54697a984708SDavid Chisnall void
__init_pat(money_base::pattern & pat,basic_string<charT> & __curr_symbol_,bool intl,char cs_precedes,char sep_by_space,char sign_posn,charT space_char)547094e3ee44SDavid Chisnall __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
547194e3ee44SDavid Chisnall            bool intl, char cs_precedes, char sep_by_space, char sign_posn,
547294e3ee44SDavid Chisnall            charT space_char)
54737a984708SDavid Chisnall {
54747a984708SDavid Chisnall     const char sign = static_cast<char>(money_base::sign);
54757a984708SDavid Chisnall     const char space = static_cast<char>(money_base::space);
54767a984708SDavid Chisnall     const char none = static_cast<char>(money_base::none);
54777a984708SDavid Chisnall     const char symbol = static_cast<char>(money_base::symbol);
54787a984708SDavid Chisnall     const char value = static_cast<char>(money_base::value);
547994e3ee44SDavid Chisnall     const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
548094e3ee44SDavid Chisnall 
548194e3ee44SDavid Chisnall     // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
548294e3ee44SDavid Chisnall     // function'. "Space between sign and symbol or value" means that
548394e3ee44SDavid Chisnall     // if the sign is adjacent to the symbol, there's a space between
548494e3ee44SDavid Chisnall     // them, and otherwise there's a space between the sign and value.
548594e3ee44SDavid Chisnall     //
548694e3ee44SDavid Chisnall     // C11's localeconv specifies that the fourth character of an
548794e3ee44SDavid Chisnall     // international curr_symbol is used to separate the sign and
548894e3ee44SDavid Chisnall     // value when sep_by_space says to do so. C++ can't represent
548994e3ee44SDavid Chisnall     // that, so we just use a space.  When sep_by_space says to
549094e3ee44SDavid Chisnall     // separate the symbol and value-or-sign with a space, we rearrange the
549194e3ee44SDavid Chisnall     // curr_symbol to put its spacing character on the correct side of
549294e3ee44SDavid Chisnall     // the symbol.
549394e3ee44SDavid Chisnall     //
549494e3ee44SDavid Chisnall     // We also need to avoid adding an extra space between the sign
549594e3ee44SDavid Chisnall     // and value when the currency symbol is suppressed (by not
549694e3ee44SDavid Chisnall     // setting showbase).  We match glibc's strfmon by interpreting
549794e3ee44SDavid Chisnall     // sep_by_space==1 as "omit the space when the currency symbol is
549894e3ee44SDavid Chisnall     // absent".
549994e3ee44SDavid Chisnall     //
550094e3ee44SDavid Chisnall     // Users who want to get this right should use ICU instead.
550194e3ee44SDavid Chisnall 
55027a984708SDavid Chisnall     switch (cs_precedes)
55037a984708SDavid Chisnall     {
550494e3ee44SDavid Chisnall     case 0:  // value before curr_symbol
550594e3ee44SDavid Chisnall         if (symbol_contains_sep) {
550694e3ee44SDavid Chisnall             // Move the separator to before the symbol, to place it
550794e3ee44SDavid Chisnall             // between the value and symbol.
550894e3ee44SDavid Chisnall             rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
550994e3ee44SDavid Chisnall                    __curr_symbol_.end());
551094e3ee44SDavid Chisnall         }
55117a984708SDavid Chisnall         switch (sign_posn)
55127a984708SDavid Chisnall         {
551394e3ee44SDavid Chisnall         case 0:  // Parentheses surround the quantity and currency symbol.
55147a984708SDavid Chisnall             pat.field[0] = sign;
55157a984708SDavid Chisnall             pat.field[1] = value;
551694e3ee44SDavid Chisnall             pat.field[2] = none;  // Any space appears in the symbol.
55177a984708SDavid Chisnall             pat.field[3] = symbol;
55187a984708SDavid Chisnall             switch (sep_by_space)
55197a984708SDavid Chisnall             {
552094e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
552194e3ee44SDavid Chisnall                 // This case may have changed between C99 and C11;
552294e3ee44SDavid Chisnall                 // assume the currency symbol matches the intention.
552394e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
552494e3ee44SDavid Chisnall                 // The "sign" is two parentheses, so no space here either.
55257a984708SDavid Chisnall                 return;
552694e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
552794e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
552894e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
552994e3ee44SDavid Chisnall                     // setting pat.field[2]=space so that when
553094e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
553194e3ee44SDavid Chisnall                     __curr_symbol_.insert(0, 1, space_char);
553294e3ee44SDavid Chisnall                 }
55337a984708SDavid Chisnall                 return;
55347a984708SDavid Chisnall             default:
55357a984708SDavid Chisnall                 break;
55367a984708SDavid Chisnall             }
55377a984708SDavid Chisnall             break;
553894e3ee44SDavid Chisnall         case 1:  // The sign string precedes the quantity and currency symbol.
55397a984708SDavid Chisnall             pat.field[0] = sign;
55407a984708SDavid Chisnall             pat.field[3] = symbol;
55417a984708SDavid Chisnall             switch (sep_by_space)
55427a984708SDavid Chisnall             {
554394e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
55447a984708SDavid Chisnall                 pat.field[1] = value;
55457a984708SDavid Chisnall                 pat.field[2] = none;
55467a984708SDavid Chisnall                 return;
554794e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
55487a984708SDavid Chisnall                 pat.field[1] = value;
554994e3ee44SDavid Chisnall                 pat.field[2] = none;
555094e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
555194e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
555294e3ee44SDavid Chisnall                     // setting pat.field[2]=space so that when
555394e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
555494e3ee44SDavid Chisnall                     __curr_symbol_.insert(0, 1, space_char);
555594e3ee44SDavid Chisnall                 }
55567a984708SDavid Chisnall                 return;
555794e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
55587a984708SDavid Chisnall                 pat.field[1] = space;
55597a984708SDavid Chisnall                 pat.field[2] = value;
556094e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
556194e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
556294e3ee44SDavid Chisnall                     // has already appeared after the sign.
556394e3ee44SDavid Chisnall                     __curr_symbol_.erase(__curr_symbol_.begin());
556494e3ee44SDavid Chisnall                 }
55657a984708SDavid Chisnall                 return;
55667a984708SDavid Chisnall             default:
55677a984708SDavid Chisnall                 break;
55687a984708SDavid Chisnall             }
55697a984708SDavid Chisnall             break;
557094e3ee44SDavid Chisnall         case 2:  // The sign string succeeds the quantity and currency symbol.
55717a984708SDavid Chisnall             pat.field[0] = value;
55727a984708SDavid Chisnall             pat.field[3] = sign;
55737a984708SDavid Chisnall             switch (sep_by_space)
55747a984708SDavid Chisnall             {
557594e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
55767a984708SDavid Chisnall                 pat.field[1] = none;
55777a984708SDavid Chisnall                 pat.field[2] = symbol;
55787a984708SDavid Chisnall                 return;
557994e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
558094e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
558194e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
558294e3ee44SDavid Chisnall                     // setting pat.field[1]=space so that when
558394e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
558494e3ee44SDavid Chisnall                     __curr_symbol_.insert(0, 1, space_char);
558594e3ee44SDavid Chisnall                 }
558694e3ee44SDavid Chisnall                 pat.field[1] = none;
55877a984708SDavid Chisnall                 pat.field[2] = symbol;
55887a984708SDavid Chisnall                 return;
558994e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
55907a984708SDavid Chisnall                 pat.field[1] = symbol;
55917a984708SDavid Chisnall                 pat.field[2] = space;
559294e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
559394e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
559494e3ee44SDavid Chisnall                     // should not be removed if showbase is absent.
559594e3ee44SDavid Chisnall                     __curr_symbol_.erase(__curr_symbol_.begin());
559694e3ee44SDavid Chisnall                 }
55977a984708SDavid Chisnall                 return;
55987a984708SDavid Chisnall             default:
55997a984708SDavid Chisnall                 break;
56007a984708SDavid Chisnall             }
56017a984708SDavid Chisnall             break;
560294e3ee44SDavid Chisnall         case 3:  // The sign string immediately precedes the currency symbol.
56037a984708SDavid Chisnall             pat.field[0] = value;
56047a984708SDavid Chisnall             pat.field[3] = symbol;
56057a984708SDavid Chisnall             switch (sep_by_space)
56067a984708SDavid Chisnall             {
560794e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
56087a984708SDavid Chisnall                 pat.field[1] = none;
56097a984708SDavid Chisnall                 pat.field[2] = sign;
56107a984708SDavid Chisnall                 return;
561194e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
56127a984708SDavid Chisnall                 pat.field[1] = space;
56137a984708SDavid Chisnall                 pat.field[2] = sign;
561494e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
561594e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
561694e3ee44SDavid Chisnall                     // has already appeared before the sign.
561794e3ee44SDavid Chisnall                     __curr_symbol_.erase(__curr_symbol_.begin());
561894e3ee44SDavid Chisnall                 }
56197a984708SDavid Chisnall                 return;
562094e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
56217a984708SDavid Chisnall                 pat.field[1] = sign;
562294e3ee44SDavid Chisnall                 pat.field[2] = none;
562394e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
562494e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
562594e3ee44SDavid Chisnall                     // setting pat.field[2]=space so that when
562694e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
562794e3ee44SDavid Chisnall                     __curr_symbol_.insert(0, 1, space_char);
562894e3ee44SDavid Chisnall                 }
56297a984708SDavid Chisnall                 return;
56307a984708SDavid Chisnall             default:
56317a984708SDavid Chisnall                 break;
56327a984708SDavid Chisnall             }
56337a984708SDavid Chisnall             break;
563494e3ee44SDavid Chisnall         case 4:  // The sign string immediately succeeds the currency symbol.
56357a984708SDavid Chisnall             pat.field[0] = value;
56367a984708SDavid Chisnall             pat.field[3] = sign;
56377a984708SDavid Chisnall             switch (sep_by_space)
56387a984708SDavid Chisnall             {
563994e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
56407a984708SDavid Chisnall                 pat.field[1] = none;
56417a984708SDavid Chisnall                 pat.field[2] = symbol;
56427a984708SDavid Chisnall                 return;
564394e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
564494e3ee44SDavid Chisnall                 pat.field[1] = none;
56457a984708SDavid Chisnall                 pat.field[2] = symbol;
564694e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
564794e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
564894e3ee44SDavid Chisnall                     // setting pat.field[1]=space so that when
564994e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
565094e3ee44SDavid Chisnall                     __curr_symbol_.insert(0, 1, space_char);
565194e3ee44SDavid Chisnall                 }
56527a984708SDavid Chisnall                 return;
565394e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
56547a984708SDavid Chisnall                 pat.field[1] = symbol;
56557a984708SDavid Chisnall                 pat.field[2] = space;
565694e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
565794e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
565894e3ee44SDavid Chisnall                     // should not disappear when showbase is absent.
565994e3ee44SDavid Chisnall                     __curr_symbol_.erase(__curr_symbol_.begin());
566094e3ee44SDavid Chisnall                 }
56617a984708SDavid Chisnall                 return;
56627a984708SDavid Chisnall             default:
56637a984708SDavid Chisnall                 break;
56647a984708SDavid Chisnall             }
56657a984708SDavid Chisnall             break;
56667a984708SDavid Chisnall         default:
56677a984708SDavid Chisnall             break;
56687a984708SDavid Chisnall         }
56697a984708SDavid Chisnall         break;
567094e3ee44SDavid Chisnall     case 1:  // curr_symbol before value
56717a984708SDavid Chisnall         switch (sign_posn)
56727a984708SDavid Chisnall         {
567394e3ee44SDavid Chisnall         case 0:  // Parentheses surround the quantity and currency symbol.
56747a984708SDavid Chisnall             pat.field[0] = sign;
56757a984708SDavid Chisnall             pat.field[1] = symbol;
567694e3ee44SDavid Chisnall             pat.field[2] = none;  // Any space appears in the symbol.
56777a984708SDavid Chisnall             pat.field[3] = value;
56787a984708SDavid Chisnall             switch (sep_by_space)
56797a984708SDavid Chisnall             {
568094e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
568194e3ee44SDavid Chisnall                 // This case may have changed between C99 and C11;
568294e3ee44SDavid Chisnall                 // assume the currency symbol matches the intention.
568394e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
568494e3ee44SDavid Chisnall                 // The "sign" is two parentheses, so no space here either.
56857a984708SDavid Chisnall                 return;
568694e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
568794e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
568894e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
568994e3ee44SDavid Chisnall                     // setting pat.field[2]=space so that when
569094e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
569194e3ee44SDavid Chisnall                     __curr_symbol_.insert(0, 1, space_char);
569294e3ee44SDavid Chisnall                 }
56937a984708SDavid Chisnall                 return;
56947a984708SDavid Chisnall             default:
56957a984708SDavid Chisnall                 break;
56967a984708SDavid Chisnall             }
56977a984708SDavid Chisnall             break;
569894e3ee44SDavid Chisnall         case 1:  // The sign string precedes the quantity and currency symbol.
56997a984708SDavid Chisnall             pat.field[0] = sign;
57007a984708SDavid Chisnall             pat.field[3] = value;
57017a984708SDavid Chisnall             switch (sep_by_space)
57027a984708SDavid Chisnall             {
570394e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
57047a984708SDavid Chisnall                 pat.field[1] = symbol;
57057a984708SDavid Chisnall                 pat.field[2] = none;
57067a984708SDavid Chisnall                 return;
570794e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
57087a984708SDavid Chisnall                 pat.field[1] = symbol;
570994e3ee44SDavid Chisnall                 pat.field[2] = none;
571094e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
571194e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
571294e3ee44SDavid Chisnall                     // setting pat.field[2]=space so that when
571394e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
571494e3ee44SDavid Chisnall                     __curr_symbol_.push_back(space_char);
571594e3ee44SDavid Chisnall                 }
57167a984708SDavid Chisnall                 return;
571794e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
57187a984708SDavid Chisnall                 pat.field[1] = space;
57197a984708SDavid Chisnall                 pat.field[2] = symbol;
572094e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
572194e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
572294e3ee44SDavid Chisnall                     // has already appeared after the sign.
572394e3ee44SDavid Chisnall                     __curr_symbol_.pop_back();
572494e3ee44SDavid Chisnall                 }
57257a984708SDavid Chisnall                 return;
57267a984708SDavid Chisnall             default:
57277a984708SDavid Chisnall                 break;
57287a984708SDavid Chisnall             }
57297a984708SDavid Chisnall             break;
573094e3ee44SDavid Chisnall         case 2:  // The sign string succeeds the quantity and currency symbol.
57317a984708SDavid Chisnall             pat.field[0] = symbol;
57327a984708SDavid Chisnall             pat.field[3] = sign;
57337a984708SDavid Chisnall             switch (sep_by_space)
57347a984708SDavid Chisnall             {
573594e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
57367a984708SDavid Chisnall                 pat.field[1] = none;
57377a984708SDavid Chisnall                 pat.field[2] = value;
57387a984708SDavid Chisnall                 return;
573994e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
574094e3ee44SDavid Chisnall                 pat.field[1] = none;
57417a984708SDavid Chisnall                 pat.field[2] = value;
574294e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
574394e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
574494e3ee44SDavid Chisnall                     // setting pat.field[1]=space so that when
574594e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
574694e3ee44SDavid Chisnall                     __curr_symbol_.push_back(space_char);
574794e3ee44SDavid Chisnall                 }
57487a984708SDavid Chisnall                 return;
574994e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
57507a984708SDavid Chisnall                 pat.field[1] = value;
57517a984708SDavid Chisnall                 pat.field[2] = space;
575294e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
575394e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
575494e3ee44SDavid Chisnall                     // will appear before the sign.
575594e3ee44SDavid Chisnall                     __curr_symbol_.pop_back();
575694e3ee44SDavid Chisnall                 }
57577a984708SDavid Chisnall                 return;
57587a984708SDavid Chisnall             default:
57597a984708SDavid Chisnall                 break;
57607a984708SDavid Chisnall             }
57617a984708SDavid Chisnall             break;
576294e3ee44SDavid Chisnall         case 3:  // The sign string immediately precedes the currency symbol.
57637a984708SDavid Chisnall             pat.field[0] = sign;
57647a984708SDavid Chisnall             pat.field[3] = value;
57657a984708SDavid Chisnall             switch (sep_by_space)
57667a984708SDavid Chisnall             {
576794e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
57687a984708SDavid Chisnall                 pat.field[1] = symbol;
57697a984708SDavid Chisnall                 pat.field[2] = none;
57707a984708SDavid Chisnall                 return;
577194e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
57727a984708SDavid Chisnall                 pat.field[1] = symbol;
577394e3ee44SDavid Chisnall                 pat.field[2] = none;
577494e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
577594e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
577694e3ee44SDavid Chisnall                     // setting pat.field[2]=space so that when
577794e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
577894e3ee44SDavid Chisnall                     __curr_symbol_.push_back(space_char);
577994e3ee44SDavid Chisnall                 }
57807a984708SDavid Chisnall                 return;
578194e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
57827a984708SDavid Chisnall                 pat.field[1] = space;
57837a984708SDavid Chisnall                 pat.field[2] = symbol;
578494e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
578594e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
578694e3ee44SDavid Chisnall                     // has already appeared after the sign.
578794e3ee44SDavid Chisnall                     __curr_symbol_.pop_back();
578894e3ee44SDavid Chisnall                 }
57897a984708SDavid Chisnall                 return;
57907a984708SDavid Chisnall             default:
57917a984708SDavid Chisnall                 break;
57927a984708SDavid Chisnall             }
57937a984708SDavid Chisnall             break;
579494e3ee44SDavid Chisnall         case 4:  // The sign string immediately succeeds the currency symbol.
57957a984708SDavid Chisnall             pat.field[0] = symbol;
57967a984708SDavid Chisnall             pat.field[3] = value;
57977a984708SDavid Chisnall             switch (sep_by_space)
57987a984708SDavid Chisnall             {
579994e3ee44SDavid Chisnall             case 0:  // No space separates the currency symbol and value.
58007a984708SDavid Chisnall                 pat.field[1] = sign;
58017a984708SDavid Chisnall                 pat.field[2] = none;
58027a984708SDavid Chisnall                 return;
580394e3ee44SDavid Chisnall             case 1:  // Space between currency-and-sign or currency and value.
58047a984708SDavid Chisnall                 pat.field[1] = sign;
58057a984708SDavid Chisnall                 pat.field[2] = space;
580694e3ee44SDavid Chisnall                 if (symbol_contains_sep) {
580794e3ee44SDavid Chisnall                     // Remove the separator from the symbol, since it
580894e3ee44SDavid Chisnall                     // should not disappear when showbase is absent.
580994e3ee44SDavid Chisnall                     __curr_symbol_.pop_back();
581094e3ee44SDavid Chisnall                 }
58117a984708SDavid Chisnall                 return;
581294e3ee44SDavid Chisnall             case 2:  // Space between sign and currency or value.
581394e3ee44SDavid Chisnall                 pat.field[1] = none;
58147a984708SDavid Chisnall                 pat.field[2] = sign;
581594e3ee44SDavid Chisnall                 if (!symbol_contains_sep) {
581694e3ee44SDavid Chisnall                     // We insert the space into the symbol instead of
581794e3ee44SDavid Chisnall                     // setting pat.field[1]=space so that when
581894e3ee44SDavid Chisnall                     // showbase is not set, the space goes away too.
581994e3ee44SDavid Chisnall                     __curr_symbol_.push_back(space_char);
582094e3ee44SDavid Chisnall                 }
58217a984708SDavid Chisnall                 return;
58227a984708SDavid Chisnall            default:
58237a984708SDavid Chisnall                 break;
58247a984708SDavid Chisnall             }
58257a984708SDavid Chisnall             break;
58267a984708SDavid Chisnall         default:
58277a984708SDavid Chisnall             break;
58287a984708SDavid Chisnall         }
58297a984708SDavid Chisnall         break;
58307a984708SDavid Chisnall     default:
58317a984708SDavid Chisnall         break;
58327a984708SDavid Chisnall     }
58337a984708SDavid Chisnall     pat.field[0] = symbol;
58347a984708SDavid Chisnall     pat.field[1] = sign;
58357a984708SDavid Chisnall     pat.field[2] = none;
58367a984708SDavid Chisnall     pat.field[3] = value;
58377a984708SDavid Chisnall }
58387a984708SDavid Chisnall 
58397a984708SDavid Chisnall template<>
58407a984708SDavid Chisnall void
init(const char * nm)58417a984708SDavid Chisnall moneypunct_byname<char, false>::init(const char* nm)
58427a984708SDavid Chisnall {
58437a984708SDavid Chisnall     typedef moneypunct<char, false> base;
58445517e702SDimitry Andric     __libcpp_unique_locale loc(nm);
58455517e702SDimitry Andric     if (!loc)
5846aed8d94eSDimitry Andric         __throw_runtime_error("moneypunct_byname"
58477a984708SDavid Chisnall                             " failed to construct for " + string(nm));
5848aed8d94eSDimitry Andric 
58497c82a1ecSDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
5850aed8d94eSDimitry Andric     if (!checked_string_to_char_convert(__decimal_point_,
5851aed8d94eSDimitry Andric                                         lc->mon_decimal_point,
5852aed8d94eSDimitry Andric                                         loc.get()))
58537a984708SDavid Chisnall       __decimal_point_ = base::do_decimal_point();
5854aed8d94eSDimitry Andric     if (!checked_string_to_char_convert(__thousands_sep_,
5855aed8d94eSDimitry Andric                                         lc->mon_thousands_sep,
5856aed8d94eSDimitry Andric                                         loc.get()))
58577a984708SDavid Chisnall       __thousands_sep_ = base::do_thousands_sep();
5858aed8d94eSDimitry Andric 
58597a984708SDavid Chisnall     __grouping_ = lc->mon_grouping;
58607a984708SDavid Chisnall     __curr_symbol_ = lc->currency_symbol;
58617a984708SDavid Chisnall     if (lc->frac_digits != CHAR_MAX)
58627a984708SDavid Chisnall         __frac_digits_ = lc->frac_digits;
58637a984708SDavid Chisnall     else
58647a984708SDavid Chisnall         __frac_digits_ = base::do_frac_digits();
58657a984708SDavid Chisnall     if (lc->p_sign_posn == 0)
58667a984708SDavid Chisnall         __positive_sign_ = "()";
58677a984708SDavid Chisnall     else
58687a984708SDavid Chisnall         __positive_sign_ = lc->positive_sign;
58697a984708SDavid Chisnall     if (lc->n_sign_posn == 0)
58707a984708SDavid Chisnall         __negative_sign_ = "()";
58717a984708SDavid Chisnall     else
58727a984708SDavid Chisnall         __negative_sign_ = lc->negative_sign;
587394e3ee44SDavid Chisnall     // Assume the positive and negative formats will want spaces in
587494e3ee44SDavid Chisnall     // the same places in curr_symbol since there's no way to
587594e3ee44SDavid Chisnall     // represent anything else.
587694e3ee44SDavid Chisnall     string_type __dummy_curr_symbol = __curr_symbol_;
587794e3ee44SDavid Chisnall     __init_pat(__pos_format_, __dummy_curr_symbol, false,
587894e3ee44SDavid Chisnall                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
587994e3ee44SDavid Chisnall     __init_pat(__neg_format_, __curr_symbol_, false,
588094e3ee44SDavid Chisnall                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
58817a984708SDavid Chisnall }
58827a984708SDavid Chisnall 
58837a984708SDavid Chisnall template<>
58847a984708SDavid Chisnall void
init(const char * nm)58857a984708SDavid Chisnall moneypunct_byname<char, true>::init(const char* nm)
58867a984708SDavid Chisnall {
58877a984708SDavid Chisnall     typedef moneypunct<char, true> base;
58885517e702SDimitry Andric     __libcpp_unique_locale loc(nm);
58895517e702SDimitry Andric     if (!loc)
5890aed8d94eSDimitry Andric         __throw_runtime_error("moneypunct_byname"
58917a984708SDavid Chisnall                             " failed to construct for " + string(nm));
5892aed8d94eSDimitry Andric 
58937c82a1ecSDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
5894aed8d94eSDimitry Andric     if (!checked_string_to_char_convert(__decimal_point_,
5895aed8d94eSDimitry Andric                                         lc->mon_decimal_point,
5896aed8d94eSDimitry Andric                                         loc.get()))
58977a984708SDavid Chisnall       __decimal_point_ = base::do_decimal_point();
5898aed8d94eSDimitry Andric     if (!checked_string_to_char_convert(__thousands_sep_,
5899aed8d94eSDimitry Andric                                         lc->mon_thousands_sep,
5900aed8d94eSDimitry Andric                                         loc.get()))
59017a984708SDavid Chisnall       __thousands_sep_ = base::do_thousands_sep();
59027a984708SDavid Chisnall     __grouping_ = lc->mon_grouping;
59037a984708SDavid Chisnall     __curr_symbol_ = lc->int_curr_symbol;
59047a984708SDavid Chisnall     if (lc->int_frac_digits != CHAR_MAX)
59057a984708SDavid Chisnall         __frac_digits_ = lc->int_frac_digits;
59067a984708SDavid Chisnall     else
59077a984708SDavid Chisnall         __frac_digits_ = base::do_frac_digits();
59084f7ab58eSDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
59097a984708SDavid Chisnall     if (lc->p_sign_posn == 0)
59104f7ab58eSDimitry Andric #else // _LIBCPP_MSVCRT
59117a984708SDavid Chisnall     if (lc->int_p_sign_posn == 0)
59124f7ab58eSDimitry Andric #endif // !_LIBCPP_MSVCRT
59137a984708SDavid Chisnall         __positive_sign_ = "()";
59147a984708SDavid Chisnall     else
59157a984708SDavid Chisnall         __positive_sign_ = lc->positive_sign;
59164f7ab58eSDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
59177a984708SDavid Chisnall     if(lc->n_sign_posn == 0)
59184f7ab58eSDimitry Andric #else // _LIBCPP_MSVCRT
59197a984708SDavid Chisnall     if (lc->int_n_sign_posn == 0)
59204f7ab58eSDimitry Andric #endif // !_LIBCPP_MSVCRT
59217a984708SDavid Chisnall         __negative_sign_ = "()";
59227a984708SDavid Chisnall     else
59237a984708SDavid Chisnall         __negative_sign_ = lc->negative_sign;
592494e3ee44SDavid Chisnall     // Assume the positive and negative formats will want spaces in
592594e3ee44SDavid Chisnall     // the same places in curr_symbol since there's no way to
592694e3ee44SDavid Chisnall     // represent anything else.
592794e3ee44SDavid Chisnall     string_type __dummy_curr_symbol = __curr_symbol_;
59284f7ab58eSDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
592994e3ee44SDavid Chisnall     __init_pat(__pos_format_, __dummy_curr_symbol, true,
593094e3ee44SDavid Chisnall                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
593194e3ee44SDavid Chisnall     __init_pat(__neg_format_, __curr_symbol_, true,
593294e3ee44SDavid Chisnall                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
59334f7ab58eSDimitry Andric #else // _LIBCPP_MSVCRT
593494e3ee44SDavid Chisnall     __init_pat(__pos_format_, __dummy_curr_symbol, true,
593594e3ee44SDavid Chisnall                lc->int_p_cs_precedes, lc->int_p_sep_by_space,
593694e3ee44SDavid Chisnall                lc->int_p_sign_posn, ' ');
593794e3ee44SDavid Chisnall     __init_pat(__neg_format_, __curr_symbol_, true,
593894e3ee44SDavid Chisnall                lc->int_n_cs_precedes, lc->int_n_sep_by_space,
593994e3ee44SDavid Chisnall                lc->int_n_sign_posn, ' ');
59404f7ab58eSDimitry Andric #endif // !_LIBCPP_MSVCRT
59417a984708SDavid Chisnall }
59427a984708SDavid Chisnall 
59437a984708SDavid Chisnall template<>
59447a984708SDavid Chisnall void
init(const char * nm)59457a984708SDavid Chisnall moneypunct_byname<wchar_t, false>::init(const char* nm)
59467a984708SDavid Chisnall {
59477a984708SDavid Chisnall     typedef moneypunct<wchar_t, false> base;
59485517e702SDimitry Andric     __libcpp_unique_locale loc(nm);
59495517e702SDimitry Andric     if (!loc)
5950aed8d94eSDimitry Andric         __throw_runtime_error("moneypunct_byname"
59517a984708SDavid Chisnall                             " failed to construct for " + string(nm));
59527c82a1ecSDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
5953aed8d94eSDimitry Andric     if (!checked_string_to_wchar_convert(__decimal_point_,
5954aed8d94eSDimitry Andric                                          lc->mon_decimal_point,
5955aed8d94eSDimitry Andric                                          loc.get()))
59567a984708SDavid Chisnall       __decimal_point_ = base::do_decimal_point();
5957aed8d94eSDimitry Andric     if (!checked_string_to_wchar_convert(__thousands_sep_,
5958aed8d94eSDimitry Andric                                          lc->mon_thousands_sep,
5959aed8d94eSDimitry Andric                                          loc.get()))
59607a984708SDavid Chisnall       __thousands_sep_ = base::do_thousands_sep();
59617a984708SDavid Chisnall     __grouping_ = lc->mon_grouping;
59627a984708SDavid Chisnall     wchar_t wbuf[100];
59637a984708SDavid Chisnall     mbstate_t mb = {0};
59647a984708SDavid Chisnall     const char* bb = lc->currency_symbol;
59657c82a1ecSDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
596694e3ee44SDavid Chisnall     if (j == size_t(-1))
59677a984708SDavid Chisnall         __throw_runtime_error("locale not supported");
59687a984708SDavid Chisnall     wchar_t* wbe = wbuf + j;
59697a984708SDavid Chisnall     __curr_symbol_.assign(wbuf, wbe);
59707a984708SDavid Chisnall     if (lc->frac_digits != CHAR_MAX)
59717a984708SDavid Chisnall         __frac_digits_ = lc->frac_digits;
59727a984708SDavid Chisnall     else
59737a984708SDavid Chisnall         __frac_digits_ = base::do_frac_digits();
59747a984708SDavid Chisnall     if (lc->p_sign_posn == 0)
59757a984708SDavid Chisnall         __positive_sign_ = L"()";
59767a984708SDavid Chisnall     else
59777a984708SDavid Chisnall     {
59787a984708SDavid Chisnall         mb = mbstate_t();
59797a984708SDavid Chisnall         bb = lc->positive_sign;
59807c82a1ecSDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
598194e3ee44SDavid Chisnall         if (j == size_t(-1))
59827a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
59837a984708SDavid Chisnall         wbe = wbuf + j;
59847a984708SDavid Chisnall         __positive_sign_.assign(wbuf, wbe);
59857a984708SDavid Chisnall     }
59867a984708SDavid Chisnall     if (lc->n_sign_posn == 0)
59877a984708SDavid Chisnall         __negative_sign_ = L"()";
59887a984708SDavid Chisnall     else
59897a984708SDavid Chisnall     {
59907a984708SDavid Chisnall         mb = mbstate_t();
59917a984708SDavid Chisnall         bb = lc->negative_sign;
59927c82a1ecSDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
599394e3ee44SDavid Chisnall         if (j == size_t(-1))
59947a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
59957a984708SDavid Chisnall         wbe = wbuf + j;
59967a984708SDavid Chisnall         __negative_sign_.assign(wbuf, wbe);
59977a984708SDavid Chisnall     }
599894e3ee44SDavid Chisnall     // Assume the positive and negative formats will want spaces in
599994e3ee44SDavid Chisnall     // the same places in curr_symbol since there's no way to
600094e3ee44SDavid Chisnall     // represent anything else.
600194e3ee44SDavid Chisnall     string_type __dummy_curr_symbol = __curr_symbol_;
600294e3ee44SDavid Chisnall     __init_pat(__pos_format_, __dummy_curr_symbol, false,
600394e3ee44SDavid Chisnall                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
600494e3ee44SDavid Chisnall     __init_pat(__neg_format_, __curr_symbol_, false,
600594e3ee44SDavid Chisnall                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
60067a984708SDavid Chisnall }
60077a984708SDavid Chisnall 
60087a984708SDavid Chisnall template<>
60097a984708SDavid Chisnall void
init(const char * nm)60107a984708SDavid Chisnall moneypunct_byname<wchar_t, true>::init(const char* nm)
60117a984708SDavid Chisnall {
60127a984708SDavid Chisnall     typedef moneypunct<wchar_t, true> base;
60135517e702SDimitry Andric     __libcpp_unique_locale loc(nm);
60145517e702SDimitry Andric     if (!loc)
6015aed8d94eSDimitry Andric         __throw_runtime_error("moneypunct_byname"
60167a984708SDavid Chisnall                             " failed to construct for " + string(nm));
6017aed8d94eSDimitry Andric 
60187c82a1ecSDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
6019aed8d94eSDimitry Andric     if (!checked_string_to_wchar_convert(__decimal_point_,
6020aed8d94eSDimitry Andric                                          lc->mon_decimal_point,
6021aed8d94eSDimitry Andric                                          loc.get()))
60227a984708SDavid Chisnall       __decimal_point_ = base::do_decimal_point();
6023aed8d94eSDimitry Andric     if (!checked_string_to_wchar_convert(__thousands_sep_,
6024aed8d94eSDimitry Andric                                          lc->mon_thousands_sep,
6025aed8d94eSDimitry Andric                                          loc.get()))
60267a984708SDavid Chisnall       __thousands_sep_ = base::do_thousands_sep();
60277a984708SDavid Chisnall     __grouping_ = lc->mon_grouping;
60287a984708SDavid Chisnall     wchar_t wbuf[100];
60297a984708SDavid Chisnall     mbstate_t mb = {0};
60307a984708SDavid Chisnall     const char* bb = lc->int_curr_symbol;
60317c82a1ecSDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
603294e3ee44SDavid Chisnall     if (j == size_t(-1))
60337a984708SDavid Chisnall         __throw_runtime_error("locale not supported");
60347a984708SDavid Chisnall     wchar_t* wbe = wbuf + j;
60357a984708SDavid Chisnall     __curr_symbol_.assign(wbuf, wbe);
60367a984708SDavid Chisnall     if (lc->int_frac_digits != CHAR_MAX)
60377a984708SDavid Chisnall         __frac_digits_ = lc->int_frac_digits;
60387a984708SDavid Chisnall     else
60397a984708SDavid Chisnall         __frac_digits_ = base::do_frac_digits();
60404f7ab58eSDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
60417a984708SDavid Chisnall     if (lc->p_sign_posn == 0)
60424f7ab58eSDimitry Andric #else // _LIBCPP_MSVCRT
60437a984708SDavid Chisnall     if (lc->int_p_sign_posn == 0)
60444f7ab58eSDimitry Andric #endif // !_LIBCPP_MSVCRT
60457a984708SDavid Chisnall         __positive_sign_ = L"()";
60467a984708SDavid Chisnall     else
60477a984708SDavid Chisnall     {
60487a984708SDavid Chisnall         mb = mbstate_t();
60497a984708SDavid Chisnall         bb = lc->positive_sign;
60507c82a1ecSDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
605194e3ee44SDavid Chisnall         if (j == size_t(-1))
60527a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
60537a984708SDavid Chisnall         wbe = wbuf + j;
60547a984708SDavid Chisnall         __positive_sign_.assign(wbuf, wbe);
60557a984708SDavid Chisnall     }
60564f7ab58eSDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
60577a984708SDavid Chisnall     if (lc->n_sign_posn == 0)
60584f7ab58eSDimitry Andric #else // _LIBCPP_MSVCRT
60597a984708SDavid Chisnall     if (lc->int_n_sign_posn == 0)
60604f7ab58eSDimitry Andric #endif // !_LIBCPP_MSVCRT
60617a984708SDavid Chisnall         __negative_sign_ = L"()";
60627a984708SDavid Chisnall     else
60637a984708SDavid Chisnall     {
60647a984708SDavid Chisnall         mb = mbstate_t();
60657a984708SDavid Chisnall         bb = lc->negative_sign;
60667c82a1ecSDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
606794e3ee44SDavid Chisnall         if (j == size_t(-1))
60687a984708SDavid Chisnall             __throw_runtime_error("locale not supported");
60697a984708SDavid Chisnall         wbe = wbuf + j;
60707a984708SDavid Chisnall         __negative_sign_.assign(wbuf, wbe);
60717a984708SDavid Chisnall     }
607294e3ee44SDavid Chisnall     // Assume the positive and negative formats will want spaces in
607394e3ee44SDavid Chisnall     // the same places in curr_symbol since there's no way to
607494e3ee44SDavid Chisnall     // represent anything else.
607594e3ee44SDavid Chisnall     string_type __dummy_curr_symbol = __curr_symbol_;
60764f7ab58eSDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
607794e3ee44SDavid Chisnall     __init_pat(__pos_format_, __dummy_curr_symbol, true,
607894e3ee44SDavid Chisnall                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
607994e3ee44SDavid Chisnall     __init_pat(__neg_format_, __curr_symbol_, true,
608094e3ee44SDavid Chisnall                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
60814f7ab58eSDimitry Andric #else // _LIBCPP_MSVCRT
608294e3ee44SDavid Chisnall     __init_pat(__pos_format_, __dummy_curr_symbol, true,
608394e3ee44SDavid Chisnall                lc->int_p_cs_precedes, lc->int_p_sep_by_space,
608494e3ee44SDavid Chisnall                lc->int_p_sign_posn, L' ');
608594e3ee44SDavid Chisnall     __init_pat(__neg_format_, __curr_symbol_, true,
608694e3ee44SDavid Chisnall                lc->int_n_cs_precedes, lc->int_n_sep_by_space,
608794e3ee44SDavid Chisnall                lc->int_n_sign_posn, L' ');
60884f7ab58eSDimitry Andric #endif // !_LIBCPP_MSVCRT
60897a984708SDavid Chisnall }
60907a984708SDavid Chisnall 
__do_nothing(void *)60917a984708SDavid Chisnall void __do_nothing(void*) {}
60927a984708SDavid Chisnall 
__throw_runtime_error(const char * msg)60937a984708SDavid Chisnall void __throw_runtime_error(const char* msg)
60947a984708SDavid Chisnall {
60957a984708SDavid Chisnall #ifndef _LIBCPP_NO_EXCEPTIONS
60967a984708SDavid Chisnall     throw runtime_error(msg);
60971bf9f7c1SDimitry Andric #else
60981bf9f7c1SDimitry Andric     (void)msg;
6099aed8d94eSDimitry Andric     _VSTD::abort();
61007a984708SDavid Chisnall #endif
61017a984708SDavid Chisnall }
61027a984708SDavid Chisnall 
6103aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6104aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
61057a984708SDavid Chisnall 
6106aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6107aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
61087a984708SDavid Chisnall 
6109aed8d94eSDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6110aed8d94eSDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
61117a984708SDavid Chisnall 
6112aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6113aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
61147a984708SDavid Chisnall 
6115aed8d94eSDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6116aed8d94eSDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
61177a984708SDavid Chisnall 
6118aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6119aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
61207a984708SDavid Chisnall 
6121aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6122aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
61237a984708SDavid Chisnall 
6124aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6125aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
61267a984708SDavid Chisnall 
6127aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6128aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
61297a984708SDavid Chisnall 
6130aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6131aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6132aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6133aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
61347a984708SDavid Chisnall 
6135aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6136aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6137aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6138aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
61397a984708SDavid Chisnall 
6140aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6141aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
61427a984708SDavid Chisnall 
6143aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6144aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
61457a984708SDavid Chisnall 
6146aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6147aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
61487a984708SDavid Chisnall 
6149aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6150aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
61517a984708SDavid Chisnall 
6152aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6153aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
61547a984708SDavid Chisnall 
6155aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6156aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
61577a984708SDavid Chisnall 
6158aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6159aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6160aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6161aed8d94eSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
61627a984708SDavid Chisnall 
61637a984708SDavid Chisnall _LIBCPP_END_NAMESPACE_STD
6164