xref: /freebsd/contrib/llvm-project/libcxx/src/locale.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
10b57cec5SDimitry Andric //===------------------------- locale.cpp ---------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric // On Solaris, we need to define something to make the C99 parts of localeconv
100b57cec5SDimitry Andric // visible.
110b57cec5SDimitry Andric #ifdef __sun__
120b57cec5SDimitry Andric #define _LCONV_C99
130b57cec5SDimitry Andric #endif
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "string"
160b57cec5SDimitry Andric #include "locale"
170b57cec5SDimitry Andric #include "codecvt"
180b57cec5SDimitry Andric #include "vector"
190b57cec5SDimitry Andric #include "algorithm"
200b57cec5SDimitry Andric #include "typeinfo"
210b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
220b57cec5SDimitry Andric #  include "type_traits"
230b57cec5SDimitry Andric #endif
240b57cec5SDimitry Andric #include "clocale"
250b57cec5SDimitry Andric #include "cstring"
260b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT)
270b57cec5SDimitry Andric #define _CTYPE_DISABLE_MACROS
280b57cec5SDimitry Andric #endif
290b57cec5SDimitry Andric #include "cwctype"
300b57cec5SDimitry Andric #include "__sso_allocator"
310b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
320b57cec5SDimitry Andric #include "support/win32/locale_win32.h"
33*e8d8bef9SDimitry Andric #elif !defined(__BIONIC__) && !defined(__NuttX__)
340b57cec5SDimitry Andric #include <langinfo.h>
350b57cec5SDimitry Andric #endif
360b57cec5SDimitry Andric #include <stdlib.h>
370b57cec5SDimitry Andric #include <stdio.h>
380b57cec5SDimitry Andric #include "include/atomic_support.h"
390b57cec5SDimitry Andric #include "__undef_macros"
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric // On Linux, wint_t and wchar_t have different signed-ness, and this causes
420b57cec5SDimitry Andric // lots of noise in the build log, but no bugs that I know of.
430b57cec5SDimitry Andric #if defined(__clang__)
440b57cec5SDimitry Andric #pragma clang diagnostic ignored "-Wsign-conversion"
450b57cec5SDimitry Andric #endif
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric struct __libcpp_unique_locale {
500b57cec5SDimitry Andric   __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   ~__libcpp_unique_locale() {
530b57cec5SDimitry Andric     if (__loc_)
540b57cec5SDimitry Andric       freelocale(__loc_);
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   explicit operator bool() const { return __loc_; }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   locale_t& get() { return __loc_; }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   locale_t __loc_;
620b57cec5SDimitry Andric private:
630b57cec5SDimitry Andric   __libcpp_unique_locale(__libcpp_unique_locale const&);
640b57cec5SDimitry Andric   __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
650b57cec5SDimitry Andric };
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric #ifdef __cloc_defined
680b57cec5SDimitry Andric locale_t __cloc() {
690b57cec5SDimitry Andric   // In theory this could create a race condition. In practice
700b57cec5SDimitry Andric   // the race condition is non-fatal since it will just create
710b57cec5SDimitry Andric   // a little resource leak. Better approach would be appreciated.
720b57cec5SDimitry Andric   static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
730b57cec5SDimitry Andric   return result;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric #endif // __cloc_defined
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric namespace {
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric struct release
800b57cec5SDimitry Andric {
810b57cec5SDimitry Andric     void operator()(locale::facet* p) {p->__release_shared();}
820b57cec5SDimitry Andric };
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric template <class T, class A0>
850b57cec5SDimitry Andric inline
860b57cec5SDimitry Andric T&
870b57cec5SDimitry Andric make(A0 a0)
880b57cec5SDimitry Andric {
890b57cec5SDimitry Andric     static typename aligned_storage<sizeof(T)>::type buf;
900b57cec5SDimitry Andric     auto *obj = ::new (&buf) T(a0);
910b57cec5SDimitry Andric     return *obj;
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric template <class T, class A0, class A1>
950b57cec5SDimitry Andric inline
960b57cec5SDimitry Andric T&
970b57cec5SDimitry Andric make(A0 a0, A1 a1)
980b57cec5SDimitry Andric {
990b57cec5SDimitry Andric     static typename aligned_storage<sizeof(T)>::type buf;
1000b57cec5SDimitry Andric     ::new (&buf) T(a0, a1);
1010b57cec5SDimitry Andric     return *reinterpret_cast<T*>(&buf);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric template <class T, class A0, class A1, class A2>
1050b57cec5SDimitry Andric inline
1060b57cec5SDimitry Andric T&
1070b57cec5SDimitry Andric make(A0 a0, A1 a1, A2 a2)
1080b57cec5SDimitry Andric {
1090b57cec5SDimitry Andric     static typename aligned_storage<sizeof(T)>::type buf;
1100b57cec5SDimitry Andric     auto *obj = ::new (&buf) T(a0, a1, a2);
1110b57cec5SDimitry Andric     return *obj;
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric template <typename T, size_t N>
1150b57cec5SDimitry Andric inline
1160b57cec5SDimitry Andric _LIBCPP_CONSTEXPR
1170b57cec5SDimitry Andric size_t
1180b57cec5SDimitry Andric countof(const T (&)[N])
1190b57cec5SDimitry Andric {
1200b57cec5SDimitry Andric     return N;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric template <typename T>
1240b57cec5SDimitry Andric inline
1250b57cec5SDimitry Andric _LIBCPP_CONSTEXPR
1260b57cec5SDimitry Andric size_t
1270b57cec5SDimitry Andric countof(const T * const begin, const T * const end)
1280b57cec5SDimitry Andric {
1290b57cec5SDimitry Andric     return static_cast<size_t>(end - begin);
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric _LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
1330b57cec5SDimitry Andric {
1340b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
1350b57cec5SDimitry Andric     throw runtime_error(msg);
1360b57cec5SDimitry Andric #else
1370b57cec5SDimitry Andric     (void)msg;
1380b57cec5SDimitry Andric     _VSTD::abort();
1390b57cec5SDimitry Andric #endif
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric #if defined(_AIX)
1450b57cec5SDimitry Andric // Set priority to INT_MIN + 256 + 150
1460b57cec5SDimitry Andric # pragma priority ( -2147483242 )
1470b57cec5SDimitry Andric #endif
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric const locale::category locale::none;
1500b57cec5SDimitry Andric const locale::category locale::collate;
1510b57cec5SDimitry Andric const locale::category locale::ctype;
1520b57cec5SDimitry Andric const locale::category locale::monetary;
1530b57cec5SDimitry Andric const locale::category locale::numeric;
1540b57cec5SDimitry Andric const locale::category locale::time;
1550b57cec5SDimitry Andric const locale::category locale::messages;
1560b57cec5SDimitry Andric const locale::category locale::all;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric class _LIBCPP_HIDDEN locale::__imp
1590b57cec5SDimitry Andric     : public facet
1600b57cec5SDimitry Andric {
161*e8d8bef9SDimitry Andric     enum {N = 30};
1620b57cec5SDimitry Andric #if defined(_LIBCPP_COMPILER_MSVC)
1630b57cec5SDimitry Andric // FIXME: MSVC doesn't support aligned parameters by value.
1640b57cec5SDimitry Andric // I can't get the __sso_allocator to work here
1650b57cec5SDimitry Andric // for MSVC I think for this reason.
1660b57cec5SDimitry Andric     vector<facet*> facets_;
1670b57cec5SDimitry Andric #else
1680b57cec5SDimitry Andric     vector<facet*, __sso_allocator<facet*, N> > facets_;
1690b57cec5SDimitry Andric #endif
1700b57cec5SDimitry Andric     string         name_;
1710b57cec5SDimitry Andric public:
1720b57cec5SDimitry Andric     explicit __imp(size_t refs = 0);
1730b57cec5SDimitry Andric     explicit __imp(const string& name, size_t refs = 0);
1740b57cec5SDimitry Andric     __imp(const __imp&);
1750b57cec5SDimitry Andric     __imp(const __imp&, const string&, locale::category c);
1760b57cec5SDimitry Andric     __imp(const __imp& other, const __imp& one, locale::category c);
1770b57cec5SDimitry Andric     __imp(const __imp&, facet* f, long id);
1780b57cec5SDimitry Andric     ~__imp();
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     const string& name() const {return name_;}
1810b57cec5SDimitry Andric     bool has_facet(long id) const
1820b57cec5SDimitry Andric         {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
1830b57cec5SDimitry Andric     const locale::facet* use_facet(long id) const;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     static const locale& make_classic();
1860b57cec5SDimitry Andric     static       locale& make_global();
1870b57cec5SDimitry Andric private:
1880b57cec5SDimitry Andric     void install(facet* f, long id);
1890b57cec5SDimitry Andric     template <class F> void install(F* f) {install(f, f->id.__get());}
1900b57cec5SDimitry Andric     template <class F> void install_from(const __imp& other);
1910b57cec5SDimitry Andric };
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric locale::__imp::__imp(size_t refs)
1940b57cec5SDimitry Andric     : facet(refs),
1950b57cec5SDimitry Andric       facets_(N),
1960b57cec5SDimitry Andric       name_("C")
1970b57cec5SDimitry Andric {
1980b57cec5SDimitry Andric     facets_.clear();
1990b57cec5SDimitry Andric     install(&make<_VSTD::collate<char> >(1u));
2000b57cec5SDimitry Andric     install(&make<_VSTD::collate<wchar_t> >(1u));
2010b57cec5SDimitry Andric     install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
2020b57cec5SDimitry Andric     install(&make<_VSTD::ctype<wchar_t> >(1u));
2030b57cec5SDimitry Andric     install(&make<codecvt<char, char, mbstate_t> >(1u));
2040b57cec5SDimitry Andric     install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
205*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
2060b57cec5SDimitry Andric     install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
2070b57cec5SDimitry Andric     install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
208*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
209*e8d8bef9SDimitry Andric #ifndef _LIBCPP_NO_HAS_CHAR8_T
210*e8d8bef9SDimitry Andric     install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
211*e8d8bef9SDimitry Andric     install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
212*e8d8bef9SDimitry Andric #endif
2130b57cec5SDimitry Andric     install(&make<numpunct<char> >(1u));
2140b57cec5SDimitry Andric     install(&make<numpunct<wchar_t> >(1u));
2150b57cec5SDimitry Andric     install(&make<num_get<char> >(1u));
2160b57cec5SDimitry Andric     install(&make<num_get<wchar_t> >(1u));
2170b57cec5SDimitry Andric     install(&make<num_put<char> >(1u));
2180b57cec5SDimitry Andric     install(&make<num_put<wchar_t> >(1u));
2190b57cec5SDimitry Andric     install(&make<moneypunct<char, false> >(1u));
2200b57cec5SDimitry Andric     install(&make<moneypunct<char, true> >(1u));
2210b57cec5SDimitry Andric     install(&make<moneypunct<wchar_t, false> >(1u));
2220b57cec5SDimitry Andric     install(&make<moneypunct<wchar_t, true> >(1u));
2230b57cec5SDimitry Andric     install(&make<money_get<char> >(1u));
2240b57cec5SDimitry Andric     install(&make<money_get<wchar_t> >(1u));
2250b57cec5SDimitry Andric     install(&make<money_put<char> >(1u));
2260b57cec5SDimitry Andric     install(&make<money_put<wchar_t> >(1u));
2270b57cec5SDimitry Andric     install(&make<time_get<char> >(1u));
2280b57cec5SDimitry Andric     install(&make<time_get<wchar_t> >(1u));
2290b57cec5SDimitry Andric     install(&make<time_put<char> >(1u));
2300b57cec5SDimitry Andric     install(&make<time_put<wchar_t> >(1u));
2310b57cec5SDimitry Andric     install(&make<_VSTD::messages<char> >(1u));
2320b57cec5SDimitry Andric     install(&make<_VSTD::messages<wchar_t> >(1u));
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric locale::__imp::__imp(const string& name, size_t refs)
2360b57cec5SDimitry Andric     : facet(refs),
2370b57cec5SDimitry Andric       facets_(N),
2380b57cec5SDimitry Andric       name_(name)
2390b57cec5SDimitry Andric {
2400b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
2410b57cec5SDimitry Andric     try
2420b57cec5SDimitry Andric     {
2430b57cec5SDimitry Andric #endif  // _LIBCPP_NO_EXCEPTIONS
2440b57cec5SDimitry Andric         facets_ = locale::classic().__locale_->facets_;
2450b57cec5SDimitry Andric         for (unsigned i = 0; i < facets_.size(); ++i)
2460b57cec5SDimitry Andric             if (facets_[i])
2470b57cec5SDimitry Andric                 facets_[i]->__add_shared();
2480b57cec5SDimitry Andric         install(new collate_byname<char>(name_));
2490b57cec5SDimitry Andric         install(new collate_byname<wchar_t>(name_));
2500b57cec5SDimitry Andric         install(new ctype_byname<char>(name_));
2510b57cec5SDimitry Andric         install(new ctype_byname<wchar_t>(name_));
2520b57cec5SDimitry Andric         install(new codecvt_byname<char, char, mbstate_t>(name_));
2530b57cec5SDimitry Andric         install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
254*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
2550b57cec5SDimitry Andric         install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
2560b57cec5SDimitry Andric         install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
257*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
258*e8d8bef9SDimitry Andric #ifndef _LIBCPP_NO_HAS_CHAR8_T
259*e8d8bef9SDimitry Andric         install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
260*e8d8bef9SDimitry Andric         install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
261*e8d8bef9SDimitry Andric #endif
2620b57cec5SDimitry Andric         install(new numpunct_byname<char>(name_));
2630b57cec5SDimitry Andric         install(new numpunct_byname<wchar_t>(name_));
2640b57cec5SDimitry Andric         install(new moneypunct_byname<char, false>(name_));
2650b57cec5SDimitry Andric         install(new moneypunct_byname<char, true>(name_));
2660b57cec5SDimitry Andric         install(new moneypunct_byname<wchar_t, false>(name_));
2670b57cec5SDimitry Andric         install(new moneypunct_byname<wchar_t, true>(name_));
2680b57cec5SDimitry Andric         install(new time_get_byname<char>(name_));
2690b57cec5SDimitry Andric         install(new time_get_byname<wchar_t>(name_));
2700b57cec5SDimitry Andric         install(new time_put_byname<char>(name_));
2710b57cec5SDimitry Andric         install(new time_put_byname<wchar_t>(name_));
2720b57cec5SDimitry Andric         install(new messages_byname<char>(name_));
2730b57cec5SDimitry Andric         install(new messages_byname<wchar_t>(name_));
2740b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
2750b57cec5SDimitry Andric     }
2760b57cec5SDimitry Andric     catch (...)
2770b57cec5SDimitry Andric     {
2780b57cec5SDimitry Andric         for (unsigned i = 0; i < facets_.size(); ++i)
2790b57cec5SDimitry Andric             if (facets_[i])
2800b57cec5SDimitry Andric                 facets_[i]->__release_shared();
2810b57cec5SDimitry Andric         throw;
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric #endif  // _LIBCPP_NO_EXCEPTIONS
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric // NOTE avoid the `base class should be explicitly initialized in the
2870b57cec5SDimitry Andric // copy constructor` warning emitted by GCC
2880b57cec5SDimitry Andric #if defined(__clang__) || _GNUC_VER >= 406
2890b57cec5SDimitry Andric #pragma GCC diagnostic push
2900b57cec5SDimitry Andric #pragma GCC diagnostic ignored "-Wextra"
2910b57cec5SDimitry Andric #endif
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other)
2940b57cec5SDimitry Andric     : facets_(max<size_t>(N, other.facets_.size())),
2950b57cec5SDimitry Andric       name_(other.name_)
2960b57cec5SDimitry Andric {
2970b57cec5SDimitry Andric     facets_ = other.facets_;
2980b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
2990b57cec5SDimitry Andric         if (facets_[i])
3000b57cec5SDimitry Andric             facets_[i]->__add_shared();
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric #if defined(__clang__) || _GNUC_VER >= 406
3040b57cec5SDimitry Andric #pragma GCC diagnostic pop
3050b57cec5SDimitry Andric #endif
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
3080b57cec5SDimitry Andric     : facets_(N),
3090b57cec5SDimitry Andric       name_("*")
3100b57cec5SDimitry Andric {
3110b57cec5SDimitry Andric     facets_ = other.facets_;
3120b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
3130b57cec5SDimitry Andric         if (facets_[i])
3140b57cec5SDimitry Andric             facets_[i]->__add_shared();
3150b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
3160b57cec5SDimitry Andric     try
3170b57cec5SDimitry Andric     {
3180b57cec5SDimitry Andric #endif  // _LIBCPP_NO_EXCEPTIONS
3190b57cec5SDimitry Andric         if (c & locale::collate)
3200b57cec5SDimitry Andric         {
3210b57cec5SDimitry Andric             install(new collate_byname<char>(name));
3220b57cec5SDimitry Andric             install(new collate_byname<wchar_t>(name));
3230b57cec5SDimitry Andric         }
3240b57cec5SDimitry Andric         if (c & locale::ctype)
3250b57cec5SDimitry Andric         {
3260b57cec5SDimitry Andric             install(new ctype_byname<char>(name));
3270b57cec5SDimitry Andric             install(new ctype_byname<wchar_t>(name));
3280b57cec5SDimitry Andric             install(new codecvt_byname<char, char, mbstate_t>(name));
3290b57cec5SDimitry Andric             install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
330*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3310b57cec5SDimitry Andric             install(new codecvt_byname<char16_t, char, mbstate_t>(name));
3320b57cec5SDimitry Andric             install(new codecvt_byname<char32_t, char, mbstate_t>(name));
333*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
334*e8d8bef9SDimitry Andric #ifndef _LIBCPP_NO_HAS_CHAR8_T
335*e8d8bef9SDimitry Andric             install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
336*e8d8bef9SDimitry Andric             install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
337*e8d8bef9SDimitry Andric #endif
3380b57cec5SDimitry Andric         }
3390b57cec5SDimitry Andric         if (c & locale::monetary)
3400b57cec5SDimitry Andric         {
3410b57cec5SDimitry Andric             install(new moneypunct_byname<char, false>(name));
3420b57cec5SDimitry Andric             install(new moneypunct_byname<char, true>(name));
3430b57cec5SDimitry Andric             install(new moneypunct_byname<wchar_t, false>(name));
3440b57cec5SDimitry Andric             install(new moneypunct_byname<wchar_t, true>(name));
3450b57cec5SDimitry Andric         }
3460b57cec5SDimitry Andric         if (c & locale::numeric)
3470b57cec5SDimitry Andric         {
3480b57cec5SDimitry Andric             install(new numpunct_byname<char>(name));
3490b57cec5SDimitry Andric             install(new numpunct_byname<wchar_t>(name));
3500b57cec5SDimitry Andric         }
3510b57cec5SDimitry Andric         if (c & locale::time)
3520b57cec5SDimitry Andric         {
3530b57cec5SDimitry Andric             install(new time_get_byname<char>(name));
3540b57cec5SDimitry Andric             install(new time_get_byname<wchar_t>(name));
3550b57cec5SDimitry Andric             install(new time_put_byname<char>(name));
3560b57cec5SDimitry Andric             install(new time_put_byname<wchar_t>(name));
3570b57cec5SDimitry Andric         }
3580b57cec5SDimitry Andric         if (c & locale::messages)
3590b57cec5SDimitry Andric         {
3600b57cec5SDimitry Andric             install(new messages_byname<char>(name));
3610b57cec5SDimitry Andric             install(new messages_byname<wchar_t>(name));
3620b57cec5SDimitry Andric         }
3630b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
3640b57cec5SDimitry Andric     }
3650b57cec5SDimitry Andric     catch (...)
3660b57cec5SDimitry Andric     {
3670b57cec5SDimitry Andric         for (unsigned i = 0; i < facets_.size(); ++i)
3680b57cec5SDimitry Andric             if (facets_[i])
3690b57cec5SDimitry Andric                 facets_[i]->__release_shared();
3700b57cec5SDimitry Andric         throw;
3710b57cec5SDimitry Andric     }
3720b57cec5SDimitry Andric #endif  // _LIBCPP_NO_EXCEPTIONS
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric template<class F>
3760b57cec5SDimitry Andric inline
3770b57cec5SDimitry Andric void
3780b57cec5SDimitry Andric locale::__imp::install_from(const locale::__imp& one)
3790b57cec5SDimitry Andric {
3800b57cec5SDimitry Andric     long id = F::id.__get();
3810b57cec5SDimitry Andric     install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
3850b57cec5SDimitry Andric     : facets_(N),
3860b57cec5SDimitry Andric       name_("*")
3870b57cec5SDimitry Andric {
3880b57cec5SDimitry Andric     facets_ = other.facets_;
3890b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
3900b57cec5SDimitry Andric         if (facets_[i])
3910b57cec5SDimitry Andric             facets_[i]->__add_shared();
3920b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
3930b57cec5SDimitry Andric     try
3940b57cec5SDimitry Andric     {
3950b57cec5SDimitry Andric #endif  // _LIBCPP_NO_EXCEPTIONS
3960b57cec5SDimitry Andric         if (c & locale::collate)
3970b57cec5SDimitry Andric         {
3980b57cec5SDimitry Andric             install_from<_VSTD::collate<char> >(one);
3990b57cec5SDimitry Andric             install_from<_VSTD::collate<wchar_t> >(one);
4000b57cec5SDimitry Andric         }
4010b57cec5SDimitry Andric         if (c & locale::ctype)
4020b57cec5SDimitry Andric         {
4030b57cec5SDimitry Andric             install_from<_VSTD::ctype<char> >(one);
4040b57cec5SDimitry Andric             install_from<_VSTD::ctype<wchar_t> >(one);
4050b57cec5SDimitry Andric             install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
406*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4070b57cec5SDimitry Andric             install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
4080b57cec5SDimitry Andric             install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
409*e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
410*e8d8bef9SDimitry Andric #ifndef _LIBCPP_NO_HAS_CHAR8_T
411*e8d8bef9SDimitry Andric             install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
412*e8d8bef9SDimitry Andric             install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
413*e8d8bef9SDimitry Andric #endif
4140b57cec5SDimitry Andric             install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
4150b57cec5SDimitry Andric         }
4160b57cec5SDimitry Andric         if (c & locale::monetary)
4170b57cec5SDimitry Andric         {
4180b57cec5SDimitry Andric             install_from<moneypunct<char, false> >(one);
4190b57cec5SDimitry Andric             install_from<moneypunct<char, true> >(one);
4200b57cec5SDimitry Andric             install_from<moneypunct<wchar_t, false> >(one);
4210b57cec5SDimitry Andric             install_from<moneypunct<wchar_t, true> >(one);
4220b57cec5SDimitry Andric             install_from<money_get<char> >(one);
4230b57cec5SDimitry Andric             install_from<money_get<wchar_t> >(one);
4240b57cec5SDimitry Andric             install_from<money_put<char> >(one);
4250b57cec5SDimitry Andric             install_from<money_put<wchar_t> >(one);
4260b57cec5SDimitry Andric         }
4270b57cec5SDimitry Andric         if (c & locale::numeric)
4280b57cec5SDimitry Andric         {
4290b57cec5SDimitry Andric             install_from<numpunct<char> >(one);
4300b57cec5SDimitry Andric             install_from<numpunct<wchar_t> >(one);
4310b57cec5SDimitry Andric             install_from<num_get<char> >(one);
4320b57cec5SDimitry Andric             install_from<num_get<wchar_t> >(one);
4330b57cec5SDimitry Andric             install_from<num_put<char> >(one);
4340b57cec5SDimitry Andric             install_from<num_put<wchar_t> >(one);
4350b57cec5SDimitry Andric         }
4360b57cec5SDimitry Andric         if (c & locale::time)
4370b57cec5SDimitry Andric         {
4380b57cec5SDimitry Andric             install_from<time_get<char> >(one);
4390b57cec5SDimitry Andric             install_from<time_get<wchar_t> >(one);
4400b57cec5SDimitry Andric             install_from<time_put<char> >(one);
4410b57cec5SDimitry Andric             install_from<time_put<wchar_t> >(one);
4420b57cec5SDimitry Andric         }
4430b57cec5SDimitry Andric         if (c & locale::messages)
4440b57cec5SDimitry Andric         {
4450b57cec5SDimitry Andric             install_from<_VSTD::messages<char> >(one);
4460b57cec5SDimitry Andric             install_from<_VSTD::messages<wchar_t> >(one);
4470b57cec5SDimitry Andric         }
4480b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
4490b57cec5SDimitry Andric     }
4500b57cec5SDimitry Andric     catch (...)
4510b57cec5SDimitry Andric     {
4520b57cec5SDimitry Andric         for (unsigned i = 0; i < facets_.size(); ++i)
4530b57cec5SDimitry Andric             if (facets_[i])
4540b57cec5SDimitry Andric                 facets_[i]->__release_shared();
4550b57cec5SDimitry Andric         throw;
4560b57cec5SDimitry Andric     }
4570b57cec5SDimitry Andric #endif  // _LIBCPP_NO_EXCEPTIONS
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, facet* f, long id)
4610b57cec5SDimitry Andric     : facets_(max<size_t>(N, other.facets_.size()+1)),
4620b57cec5SDimitry Andric       name_("*")
4630b57cec5SDimitry Andric {
4640b57cec5SDimitry Andric     f->__add_shared();
4650b57cec5SDimitry Andric     unique_ptr<facet, release> hold(f);
4660b57cec5SDimitry Andric     facets_ = other.facets_;
4670b57cec5SDimitry Andric     for (unsigned i = 0; i < other.facets_.size(); ++i)
4680b57cec5SDimitry Andric         if (facets_[i])
4690b57cec5SDimitry Andric             facets_[i]->__add_shared();
4700b57cec5SDimitry Andric     install(hold.get(), id);
4710b57cec5SDimitry Andric }
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric locale::__imp::~__imp()
4740b57cec5SDimitry Andric {
4750b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
4760b57cec5SDimitry Andric         if (facets_[i])
4770b57cec5SDimitry Andric             facets_[i]->__release_shared();
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric void
4810b57cec5SDimitry Andric locale::__imp::install(facet* f, long id)
4820b57cec5SDimitry Andric {
4830b57cec5SDimitry Andric     f->__add_shared();
4840b57cec5SDimitry Andric     unique_ptr<facet, release> hold(f);
4850b57cec5SDimitry Andric     if (static_cast<size_t>(id) >= facets_.size())
4860b57cec5SDimitry Andric         facets_.resize(static_cast<size_t>(id+1));
4870b57cec5SDimitry Andric     if (facets_[static_cast<size_t>(id)])
4880b57cec5SDimitry Andric         facets_[static_cast<size_t>(id)]->__release_shared();
4890b57cec5SDimitry Andric     facets_[static_cast<size_t>(id)] = hold.release();
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric const locale::facet*
4930b57cec5SDimitry Andric locale::__imp::use_facet(long id) const
4940b57cec5SDimitry Andric {
4950b57cec5SDimitry Andric     if (!has_facet(id))
4960b57cec5SDimitry Andric         __throw_bad_cast();
4970b57cec5SDimitry Andric     return facets_[static_cast<size_t>(id)];
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric // locale
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric const locale&
5030b57cec5SDimitry Andric locale::__imp::make_classic()
5040b57cec5SDimitry Andric {
5050b57cec5SDimitry Andric     // only one thread can get in here and it only gets in once
5060b57cec5SDimitry Andric     static aligned_storage<sizeof(locale)>::type buf;
5070b57cec5SDimitry Andric     locale* c = reinterpret_cast<locale*>(&buf);
5080b57cec5SDimitry Andric     c->__locale_ = &make<__imp>(1u);
5090b57cec5SDimitry Andric     return *c;
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric const locale&
5130b57cec5SDimitry Andric locale::classic()
5140b57cec5SDimitry Andric {
5150b57cec5SDimitry Andric     static const locale& c = __imp::make_classic();
5160b57cec5SDimitry Andric     return c;
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric locale&
5200b57cec5SDimitry Andric locale::__imp::make_global()
5210b57cec5SDimitry Andric {
5220b57cec5SDimitry Andric     // only one thread can get in here and it only gets in once
5230b57cec5SDimitry Andric     static aligned_storage<sizeof(locale)>::type buf;
5240b57cec5SDimitry Andric     auto *obj = ::new (&buf) locale(locale::classic());
5250b57cec5SDimitry Andric     return *obj;
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric locale&
5290b57cec5SDimitry Andric locale::__global()
5300b57cec5SDimitry Andric {
5310b57cec5SDimitry Andric     static locale& g = __imp::make_global();
5320b57cec5SDimitry Andric     return g;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric locale::locale()  _NOEXCEPT
5360b57cec5SDimitry Andric     : __locale_(__global().__locale_)
5370b57cec5SDimitry Andric {
5380b57cec5SDimitry Andric     __locale_->__add_shared();
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric locale::locale(const locale& l)  _NOEXCEPT
5420b57cec5SDimitry Andric     : __locale_(l.__locale_)
5430b57cec5SDimitry Andric {
5440b57cec5SDimitry Andric     __locale_->__add_shared();
5450b57cec5SDimitry Andric }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric locale::~locale()
5480b57cec5SDimitry Andric {
5490b57cec5SDimitry Andric     __locale_->__release_shared();
5500b57cec5SDimitry Andric }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric const locale&
5530b57cec5SDimitry Andric locale::operator=(const locale& other)  _NOEXCEPT
5540b57cec5SDimitry Andric {
5550b57cec5SDimitry Andric     other.__locale_->__add_shared();
5560b57cec5SDimitry Andric     __locale_->__release_shared();
5570b57cec5SDimitry Andric     __locale_ = other.__locale_;
5580b57cec5SDimitry Andric     return *this;
5590b57cec5SDimitry Andric }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric locale::locale(const char* name)
5620b57cec5SDimitry Andric     : __locale_(name ? new __imp(name)
5635ffd83dbSDimitry Andric                      : (__throw_runtime_error("locale constructed with null"), nullptr))
5640b57cec5SDimitry Andric {
5650b57cec5SDimitry Andric     __locale_->__add_shared();
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric locale::locale(const string& name)
5690b57cec5SDimitry Andric     : __locale_(new __imp(name))
5700b57cec5SDimitry Andric {
5710b57cec5SDimitry Andric     __locale_->__add_shared();
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric locale::locale(const locale& other, const char* name, category c)
5750b57cec5SDimitry Andric     : __locale_(name ? new __imp(*other.__locale_, name, c)
5765ffd83dbSDimitry Andric                      : (__throw_runtime_error("locale constructed with null"), nullptr))
5770b57cec5SDimitry Andric {
5780b57cec5SDimitry Andric     __locale_->__add_shared();
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric locale::locale(const locale& other, const string& name, category c)
5820b57cec5SDimitry Andric     : __locale_(new __imp(*other.__locale_, name, c))
5830b57cec5SDimitry Andric {
5840b57cec5SDimitry Andric     __locale_->__add_shared();
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric locale::locale(const locale& other, const locale& one, category c)
5880b57cec5SDimitry Andric     : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
5890b57cec5SDimitry Andric {
5900b57cec5SDimitry Andric     __locale_->__add_shared();
5910b57cec5SDimitry Andric }
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric string
5940b57cec5SDimitry Andric locale::name() const
5950b57cec5SDimitry Andric {
5960b57cec5SDimitry Andric     return __locale_->name();
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric void
6000b57cec5SDimitry Andric locale::__install_ctor(const locale& other, facet* f, long id)
6010b57cec5SDimitry Andric {
6020b57cec5SDimitry Andric     if (f)
6030b57cec5SDimitry Andric         __locale_ = new __imp(*other.__locale_, f, id);
6040b57cec5SDimitry Andric     else
6050b57cec5SDimitry Andric         __locale_ = other.__locale_;
6060b57cec5SDimitry Andric     __locale_->__add_shared();
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric locale
6100b57cec5SDimitry Andric locale::global(const locale& loc)
6110b57cec5SDimitry Andric {
6120b57cec5SDimitry Andric     locale& g = __global();
6130b57cec5SDimitry Andric     locale r = g;
6140b57cec5SDimitry Andric     g = loc;
6150b57cec5SDimitry Andric     if (g.name() != "*")
6160b57cec5SDimitry Andric         setlocale(LC_ALL, g.name().c_str());
6170b57cec5SDimitry Andric     return r;
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric bool
6210b57cec5SDimitry Andric locale::has_facet(id& x) const
6220b57cec5SDimitry Andric {
6230b57cec5SDimitry Andric     return __locale_->has_facet(x.__get());
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric const locale::facet*
6270b57cec5SDimitry Andric locale::use_facet(id& x) const
6280b57cec5SDimitry Andric {
6290b57cec5SDimitry Andric     return __locale_->use_facet(x.__get());
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric bool
6330b57cec5SDimitry Andric locale::operator==(const locale& y) const
6340b57cec5SDimitry Andric {
6350b57cec5SDimitry Andric     return (__locale_ == y.__locale_)
6360b57cec5SDimitry Andric         || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
6370b57cec5SDimitry Andric }
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric // locale::facet
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric locale::facet::~facet()
6420b57cec5SDimitry Andric {
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric void
6460b57cec5SDimitry Andric locale::facet::__on_zero_shared() _NOEXCEPT
6470b57cec5SDimitry Andric {
6480b57cec5SDimitry Andric     delete this;
6490b57cec5SDimitry Andric }
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric // locale::id
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric int32_t locale::id::__next_id = 0;
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric namespace
6560b57cec5SDimitry Andric {
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric class __fake_bind
6590b57cec5SDimitry Andric {
6600b57cec5SDimitry Andric     locale::id* id_;
6610b57cec5SDimitry Andric     void (locale::id::* pmf_)();
6620b57cec5SDimitry Andric public:
6630b57cec5SDimitry Andric     __fake_bind(void (locale::id::* pmf)(), locale::id* id)
6640b57cec5SDimitry Andric         : id_(id), pmf_(pmf) {}
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric     void operator()() const
6670b57cec5SDimitry Andric     {
6680b57cec5SDimitry Andric         (id_->*pmf_)();
6690b57cec5SDimitry Andric     }
6700b57cec5SDimitry Andric };
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric long
6750b57cec5SDimitry Andric locale::id::__get()
6760b57cec5SDimitry Andric {
6770b57cec5SDimitry Andric     call_once(__flag_, __fake_bind(&locale::id::__init, this));
6780b57cec5SDimitry Andric     return __id_ - 1;
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric void
6820b57cec5SDimitry Andric locale::id::__init()
6830b57cec5SDimitry Andric {
6840b57cec5SDimitry Andric     __id_ = __libcpp_atomic_add(&__next_id, 1);
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric // template <> class collate_byname<char>
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric collate_byname<char>::collate_byname(const char* n, size_t refs)
6900b57cec5SDimitry Andric     : collate<char>(refs),
6910b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, n, 0))
6920b57cec5SDimitry Andric {
6930b57cec5SDimitry Andric     if (__l == 0)
6940b57cec5SDimitry Andric         __throw_runtime_error("collate_byname<char>::collate_byname"
6950b57cec5SDimitry Andric                             " failed to construct for " + string(n));
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric collate_byname<char>::collate_byname(const string& name, size_t refs)
6990b57cec5SDimitry Andric     : collate<char>(refs),
7000b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
7010b57cec5SDimitry Andric {
7020b57cec5SDimitry Andric     if (__l == 0)
7030b57cec5SDimitry Andric         __throw_runtime_error("collate_byname<char>::collate_byname"
7040b57cec5SDimitry Andric                             " failed to construct for " + name);
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric collate_byname<char>::~collate_byname()
7080b57cec5SDimitry Andric {
7090b57cec5SDimitry Andric     freelocale(__l);
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric int
7130b57cec5SDimitry Andric collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
7140b57cec5SDimitry Andric                                  const char_type* __lo2, const char_type* __hi2) const
7150b57cec5SDimitry Andric {
7160b57cec5SDimitry Andric     string_type lhs(__lo1, __hi1);
7170b57cec5SDimitry Andric     string_type rhs(__lo2, __hi2);
7180b57cec5SDimitry Andric     int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
7190b57cec5SDimitry Andric     if (r < 0)
7200b57cec5SDimitry Andric         return -1;
7210b57cec5SDimitry Andric     if (r > 0)
7220b57cec5SDimitry Andric         return 1;
7230b57cec5SDimitry Andric     return r;
7240b57cec5SDimitry Andric }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric collate_byname<char>::string_type
7270b57cec5SDimitry Andric collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
7280b57cec5SDimitry Andric {
7290b57cec5SDimitry Andric     const string_type in(lo, hi);
7300b57cec5SDimitry Andric     string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
7310b57cec5SDimitry Andric     strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
7320b57cec5SDimitry Andric     return out;
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric // template <> class collate_byname<wchar_t>
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
7380b57cec5SDimitry Andric     : collate<wchar_t>(refs),
7390b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, n, 0))
7400b57cec5SDimitry Andric {
7410b57cec5SDimitry Andric     if (__l == 0)
7420b57cec5SDimitry Andric         __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
7430b57cec5SDimitry Andric                             " failed to construct for " + string(n));
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
7470b57cec5SDimitry Andric     : collate<wchar_t>(refs),
7480b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
7490b57cec5SDimitry Andric {
7500b57cec5SDimitry Andric     if (__l == 0)
7510b57cec5SDimitry Andric         __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
7520b57cec5SDimitry Andric                             " failed to construct for " + name);
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric collate_byname<wchar_t>::~collate_byname()
7560b57cec5SDimitry Andric {
7570b57cec5SDimitry Andric     freelocale(__l);
7580b57cec5SDimitry Andric }
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric int
7610b57cec5SDimitry Andric collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
7620b57cec5SDimitry Andric                                  const char_type* __lo2, const char_type* __hi2) const
7630b57cec5SDimitry Andric {
7640b57cec5SDimitry Andric     string_type lhs(__lo1, __hi1);
7650b57cec5SDimitry Andric     string_type rhs(__lo2, __hi2);
7660b57cec5SDimitry Andric     int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
7670b57cec5SDimitry Andric     if (r < 0)
7680b57cec5SDimitry Andric         return -1;
7690b57cec5SDimitry Andric     if (r > 0)
7700b57cec5SDimitry Andric         return 1;
7710b57cec5SDimitry Andric     return r;
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric collate_byname<wchar_t>::string_type
7750b57cec5SDimitry Andric collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
7760b57cec5SDimitry Andric {
7770b57cec5SDimitry Andric     const string_type in(lo, hi);
7780b57cec5SDimitry Andric     string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
7790b57cec5SDimitry Andric     wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
7800b57cec5SDimitry Andric     return out;
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric // template <> class ctype<wchar_t>;
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric const ctype_base::mask ctype_base::space;
7860b57cec5SDimitry Andric const ctype_base::mask ctype_base::print;
7870b57cec5SDimitry Andric const ctype_base::mask ctype_base::cntrl;
7880b57cec5SDimitry Andric const ctype_base::mask ctype_base::upper;
7890b57cec5SDimitry Andric const ctype_base::mask ctype_base::lower;
7900b57cec5SDimitry Andric const ctype_base::mask ctype_base::alpha;
7910b57cec5SDimitry Andric const ctype_base::mask ctype_base::digit;
7920b57cec5SDimitry Andric const ctype_base::mask ctype_base::punct;
7930b57cec5SDimitry Andric const ctype_base::mask ctype_base::xdigit;
7940b57cec5SDimitry Andric const ctype_base::mask ctype_base::blank;
7950b57cec5SDimitry Andric const ctype_base::mask ctype_base::alnum;
7960b57cec5SDimitry Andric const ctype_base::mask ctype_base::graph;
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric locale::id ctype<wchar_t>::id;
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric ctype<wchar_t>::~ctype()
8010b57cec5SDimitry Andric {
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric bool
8050b57cec5SDimitry Andric ctype<wchar_t>::do_is(mask m, char_type c) const
8060b57cec5SDimitry Andric {
8070b57cec5SDimitry Andric     return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
8080b57cec5SDimitry Andric }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric const wchar_t*
8110b57cec5SDimitry Andric ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
8120b57cec5SDimitry Andric {
8130b57cec5SDimitry Andric     for (; low != high; ++low, ++vec)
8140b57cec5SDimitry Andric         *vec = static_cast<mask>(isascii(*low) ?
8150b57cec5SDimitry Andric                                    ctype<char>::classic_table()[*low] : 0);
8160b57cec5SDimitry Andric     return low;
8170b57cec5SDimitry Andric }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric const wchar_t*
8200b57cec5SDimitry Andric ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
8210b57cec5SDimitry Andric {
8220b57cec5SDimitry Andric     for (; low != high; ++low)
8230b57cec5SDimitry Andric         if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
8240b57cec5SDimitry Andric             break;
8250b57cec5SDimitry Andric     return low;
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric const wchar_t*
8290b57cec5SDimitry Andric ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
8300b57cec5SDimitry Andric {
8310b57cec5SDimitry Andric     for (; low != high; ++low)
8320b57cec5SDimitry Andric         if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
8330b57cec5SDimitry Andric             break;
8340b57cec5SDimitry Andric     return low;
8350b57cec5SDimitry Andric }
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric wchar_t
8380b57cec5SDimitry Andric ctype<wchar_t>::do_toupper(char_type c) const
8390b57cec5SDimitry Andric {
8400b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8410b57cec5SDimitry Andric     return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
8420b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8430b57cec5SDimitry Andric       defined(__NetBSD__)
8440b57cec5SDimitry Andric     return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
8450b57cec5SDimitry Andric #else
8460b57cec5SDimitry Andric     return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
8470b57cec5SDimitry Andric #endif
8480b57cec5SDimitry Andric }
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric const wchar_t*
8510b57cec5SDimitry Andric ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
8520b57cec5SDimitry Andric {
8530b57cec5SDimitry Andric     for (; low != high; ++low)
8540b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8550b57cec5SDimitry Andric         *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
8560b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8570b57cec5SDimitry Andric       defined(__NetBSD__)
8580b57cec5SDimitry Andric         *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
8590b57cec5SDimitry Andric                              : *low;
8600b57cec5SDimitry Andric #else
8610b57cec5SDimitry Andric         *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
8620b57cec5SDimitry Andric #endif
8630b57cec5SDimitry Andric     return low;
8640b57cec5SDimitry Andric }
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric wchar_t
8670b57cec5SDimitry Andric ctype<wchar_t>::do_tolower(char_type c) const
8680b57cec5SDimitry Andric {
8690b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8700b57cec5SDimitry Andric     return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
8710b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8720b57cec5SDimitry Andric       defined(__NetBSD__)
8730b57cec5SDimitry Andric     return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
8740b57cec5SDimitry Andric #else
8750b57cec5SDimitry Andric     return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
8760b57cec5SDimitry Andric #endif
8770b57cec5SDimitry Andric }
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric const wchar_t*
8800b57cec5SDimitry Andric ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
8810b57cec5SDimitry Andric {
8820b57cec5SDimitry Andric     for (; low != high; ++low)
8830b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8840b57cec5SDimitry Andric         *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
8850b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
8860b57cec5SDimitry Andric       defined(__NetBSD__)
8870b57cec5SDimitry Andric         *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
8880b57cec5SDimitry Andric                              : *low;
8890b57cec5SDimitry Andric #else
8900b57cec5SDimitry Andric         *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
8910b57cec5SDimitry Andric #endif
8920b57cec5SDimitry Andric     return low;
8930b57cec5SDimitry Andric }
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric wchar_t
8960b57cec5SDimitry Andric ctype<wchar_t>::do_widen(char c) const
8970b57cec5SDimitry Andric {
8980b57cec5SDimitry Andric     return c;
8990b57cec5SDimitry Andric }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric const char*
9020b57cec5SDimitry Andric ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
9030b57cec5SDimitry Andric {
9040b57cec5SDimitry Andric     for (; low != high; ++low, ++dest)
9050b57cec5SDimitry Andric         *dest = *low;
9060b57cec5SDimitry Andric     return low;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric char
9100b57cec5SDimitry Andric ctype<wchar_t>::do_narrow(char_type c, char dfault) const
9110b57cec5SDimitry Andric {
9120b57cec5SDimitry Andric     if (isascii(c))
9130b57cec5SDimitry Andric         return static_cast<char>(c);
9140b57cec5SDimitry Andric     return dfault;
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric const wchar_t*
9180b57cec5SDimitry Andric ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
9190b57cec5SDimitry Andric {
9200b57cec5SDimitry Andric     for (; low != high; ++low, ++dest)
9210b57cec5SDimitry Andric         if (isascii(*low))
9220b57cec5SDimitry Andric             *dest = static_cast<char>(*low);
9230b57cec5SDimitry Andric         else
9240b57cec5SDimitry Andric             *dest = dfault;
9250b57cec5SDimitry Andric     return low;
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric // template <> class ctype<char>;
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric locale::id ctype<char>::id;
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric ctype<char>::ctype(const mask* tab, bool del, size_t refs)
9330b57cec5SDimitry Andric     : locale::facet(refs),
9340b57cec5SDimitry Andric       __tab_(tab),
9350b57cec5SDimitry Andric       __del_(del)
9360b57cec5SDimitry Andric {
9370b57cec5SDimitry Andric   if (__tab_ == 0)
9380b57cec5SDimitry Andric       __tab_ = classic_table();
9390b57cec5SDimitry Andric }
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric ctype<char>::~ctype()
9420b57cec5SDimitry Andric {
9430b57cec5SDimitry Andric     if (__tab_ && __del_)
9440b57cec5SDimitry Andric         delete [] __tab_;
9450b57cec5SDimitry Andric }
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric char
9480b57cec5SDimitry Andric ctype<char>::do_toupper(char_type c) const
9490b57cec5SDimitry Andric {
9500b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
9510b57cec5SDimitry Andric     return isascii(c) ?
9520b57cec5SDimitry Andric       static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
9530b57cec5SDimitry Andric #elif defined(__NetBSD__)
9540b57cec5SDimitry Andric     return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
9550b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
9560b57cec5SDimitry Andric     return isascii(c) ?
9570b57cec5SDimitry Andric       static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
9580b57cec5SDimitry Andric #else
9590b57cec5SDimitry Andric     return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
9600b57cec5SDimitry Andric #endif
9610b57cec5SDimitry Andric }
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric const char*
9640b57cec5SDimitry Andric ctype<char>::do_toupper(char_type* low, const char_type* high) const
9650b57cec5SDimitry Andric {
9660b57cec5SDimitry Andric     for (; low != high; ++low)
9670b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
9680b57cec5SDimitry Andric         *low = isascii(*low) ?
9690b57cec5SDimitry Andric           static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
9700b57cec5SDimitry Andric #elif defined(__NetBSD__)
9710b57cec5SDimitry Andric         *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
9720b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
9730b57cec5SDimitry Andric         *low = isascii(*low) ?
9740b57cec5SDimitry Andric           static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
9750b57cec5SDimitry Andric #else
9760b57cec5SDimitry Andric         *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
9770b57cec5SDimitry Andric #endif
9780b57cec5SDimitry Andric     return low;
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric char
9820b57cec5SDimitry Andric ctype<char>::do_tolower(char_type c) const
9830b57cec5SDimitry Andric {
9840b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
9850b57cec5SDimitry Andric     return isascii(c) ?
9860b57cec5SDimitry Andric       static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
9870b57cec5SDimitry Andric #elif defined(__NetBSD__)
9880b57cec5SDimitry Andric     return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
9890b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
9900b57cec5SDimitry Andric     return isascii(c) ?
9910b57cec5SDimitry Andric       static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
9920b57cec5SDimitry Andric #else
9930b57cec5SDimitry Andric     return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
9940b57cec5SDimitry Andric #endif
9950b57cec5SDimitry Andric }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric const char*
9980b57cec5SDimitry Andric ctype<char>::do_tolower(char_type* low, const char_type* high) const
9990b57cec5SDimitry Andric {
10000b57cec5SDimitry Andric     for (; low != high; ++low)
10010b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
10020b57cec5SDimitry Andric         *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
10030b57cec5SDimitry Andric #elif defined(__NetBSD__)
10040b57cec5SDimitry Andric         *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
10050b57cec5SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
10060b57cec5SDimitry Andric         *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
10070b57cec5SDimitry Andric #else
10080b57cec5SDimitry Andric         *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
10090b57cec5SDimitry Andric #endif
10100b57cec5SDimitry Andric     return low;
10110b57cec5SDimitry Andric }
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric char
10140b57cec5SDimitry Andric ctype<char>::do_widen(char c) const
10150b57cec5SDimitry Andric {
10160b57cec5SDimitry Andric     return c;
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric const char*
10200b57cec5SDimitry Andric ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
10210b57cec5SDimitry Andric {
10220b57cec5SDimitry Andric     for (; low != high; ++low, ++dest)
10230b57cec5SDimitry Andric         *dest = *low;
10240b57cec5SDimitry Andric     return low;
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric char
10280b57cec5SDimitry Andric ctype<char>::do_narrow(char_type c, char dfault) const
10290b57cec5SDimitry Andric {
10300b57cec5SDimitry Andric     if (isascii(c))
10310b57cec5SDimitry Andric         return static_cast<char>(c);
10320b57cec5SDimitry Andric     return dfault;
10330b57cec5SDimitry Andric }
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric const char*
10360b57cec5SDimitry Andric ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
10370b57cec5SDimitry Andric {
10380b57cec5SDimitry Andric     for (; low != high; ++low, ++dest)
10390b57cec5SDimitry Andric         if (isascii(*low))
10400b57cec5SDimitry Andric             *dest = *low;
10410b57cec5SDimitry Andric         else
10420b57cec5SDimitry Andric             *dest = dfault;
10430b57cec5SDimitry Andric     return low;
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric #if defined(__EMSCRIPTEN__)
10470b57cec5SDimitry Andric extern "C" const unsigned short ** __ctype_b_loc();
10480b57cec5SDimitry Andric extern "C" const int ** __ctype_tolower_loc();
10490b57cec5SDimitry Andric extern "C" const int ** __ctype_toupper_loc();
10500b57cec5SDimitry Andric #endif
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
10530b57cec5SDimitry Andric const ctype<char>::mask*
10540b57cec5SDimitry Andric ctype<char>::classic_table()  _NOEXCEPT
10550b57cec5SDimitry Andric {
10560b57cec5SDimitry Andric     static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
10570b57cec5SDimitry Andric         cntrl,                          cntrl,
10580b57cec5SDimitry Andric         cntrl,                          cntrl,
10590b57cec5SDimitry Andric         cntrl,                          cntrl,
10600b57cec5SDimitry Andric         cntrl,                          cntrl,
10610b57cec5SDimitry Andric         cntrl,                          cntrl | space | blank,
10620b57cec5SDimitry Andric         cntrl | space,                  cntrl | space,
10630b57cec5SDimitry Andric         cntrl | space,                  cntrl | space,
10640b57cec5SDimitry Andric         cntrl,                          cntrl,
10650b57cec5SDimitry Andric         cntrl,                          cntrl,
10660b57cec5SDimitry Andric         cntrl,                          cntrl,
10670b57cec5SDimitry Andric         cntrl,                          cntrl,
10680b57cec5SDimitry Andric         cntrl,                          cntrl,
10690b57cec5SDimitry Andric         cntrl,                          cntrl,
10700b57cec5SDimitry Andric         cntrl,                          cntrl,
10710b57cec5SDimitry Andric         cntrl,                          cntrl,
10720b57cec5SDimitry Andric         cntrl,                          cntrl,
10730b57cec5SDimitry Andric         space | blank | print,          punct | print,
10740b57cec5SDimitry Andric         punct | print,                  punct | print,
10750b57cec5SDimitry Andric         punct | print,                  punct | print,
10760b57cec5SDimitry Andric         punct | print,                  punct | print,
10770b57cec5SDimitry Andric         punct | print,                  punct | print,
10780b57cec5SDimitry Andric         punct | print,                  punct | print,
10790b57cec5SDimitry Andric         punct | print,                  punct | print,
10800b57cec5SDimitry Andric         punct | print,                  punct | print,
10810b57cec5SDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
10820b57cec5SDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
10830b57cec5SDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
10840b57cec5SDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
10850b57cec5SDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
10860b57cec5SDimitry Andric         punct | print,                  punct | print,
10870b57cec5SDimitry Andric         punct | print,                  punct | print,
10880b57cec5SDimitry Andric         punct | print,                  punct | print,
10890b57cec5SDimitry Andric         punct | print,                  upper | xdigit | print | alpha,
10900b57cec5SDimitry Andric         upper | xdigit | print | alpha, upper | xdigit | print | alpha,
10910b57cec5SDimitry Andric         upper | xdigit | print | alpha, upper | xdigit | print | alpha,
10920b57cec5SDimitry Andric         upper | xdigit | print | alpha, upper | print | alpha,
10930b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
10940b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
10950b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
10960b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
10970b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
10980b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
10990b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
11000b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
11010b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
11020b57cec5SDimitry Andric         upper | print | alpha,          punct | print,
11030b57cec5SDimitry Andric         punct | print,                  punct | print,
11040b57cec5SDimitry Andric         punct | print,                  punct | print,
11050b57cec5SDimitry Andric         punct | print,                  lower | xdigit | print | alpha,
11060b57cec5SDimitry Andric         lower | xdigit | print | alpha, lower | xdigit | print | alpha,
11070b57cec5SDimitry Andric         lower | xdigit | print | alpha, lower | xdigit | print | alpha,
11080b57cec5SDimitry Andric         lower | xdigit | print | alpha, lower | print | alpha,
11090b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11100b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11110b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11120b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11130b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11140b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11150b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11160b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11170b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
11180b57cec5SDimitry Andric         lower | print | alpha,          punct | print,
11190b57cec5SDimitry Andric         punct | print,                  punct | print,
11200b57cec5SDimitry Andric         punct | print,                  cntrl,
11210b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11220b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11230b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11240b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11250b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11260b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11270b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11280b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
11290b57cec5SDimitry Andric     };
11300b57cec5SDimitry Andric     return builtin_table;
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric #else
11330b57cec5SDimitry Andric const ctype<char>::mask*
11340b57cec5SDimitry Andric ctype<char>::classic_table()  _NOEXCEPT
11350b57cec5SDimitry Andric {
11360b57cec5SDimitry Andric #if defined(__APPLE__) || defined(__FreeBSD__)
11370b57cec5SDimitry Andric     return _DefaultRuneLocale.__runetype;
11380b57cec5SDimitry Andric #elif defined(__NetBSD__)
11390b57cec5SDimitry Andric     return _C_ctype_tab_ + 1;
11400b57cec5SDimitry Andric #elif defined(__GLIBC__)
11410b57cec5SDimitry Andric     return _LIBCPP_GET_C_LOCALE->__ctype_b;
11420b57cec5SDimitry Andric #elif __sun__
11430b57cec5SDimitry Andric     return __ctype_mask;
11440b57cec5SDimitry Andric #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
11450b57cec5SDimitry Andric     return __pctype_func();
11460b57cec5SDimitry Andric #elif defined(__EMSCRIPTEN__)
11470b57cec5SDimitry Andric     return *__ctype_b_loc();
11480b57cec5SDimitry Andric #elif defined(_NEWLIB_VERSION)
11490b57cec5SDimitry Andric     // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
11500b57cec5SDimitry Andric     return _ctype_ + 1;
11510b57cec5SDimitry Andric #elif defined(_AIX)
11520b57cec5SDimitry Andric     return (const unsigned int *)__lc_ctype_ptr->obj->mask;
11530b57cec5SDimitry Andric #else
11540b57cec5SDimitry Andric     // Platform not supported: abort so the person doing the port knows what to
11550b57cec5SDimitry Andric     // fix
11560b57cec5SDimitry Andric # warning  ctype<char>::classic_table() is not implemented
11570b57cec5SDimitry Andric     printf("ctype<char>::classic_table() is not implemented\n");
11580b57cec5SDimitry Andric     abort();
11590b57cec5SDimitry Andric     return NULL;
11600b57cec5SDimitry Andric #endif
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric #endif
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric #if defined(__GLIBC__)
11650b57cec5SDimitry Andric const int*
11660b57cec5SDimitry Andric ctype<char>::__classic_lower_table() _NOEXCEPT
11670b57cec5SDimitry Andric {
11680b57cec5SDimitry Andric     return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric const int*
11720b57cec5SDimitry Andric ctype<char>::__classic_upper_table() _NOEXCEPT
11730b57cec5SDimitry Andric {
11740b57cec5SDimitry Andric     return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
11750b57cec5SDimitry Andric }
1176*e8d8bef9SDimitry Andric #elif defined(__NetBSD__)
11770b57cec5SDimitry Andric const short*
11780b57cec5SDimitry Andric ctype<char>::__classic_lower_table() _NOEXCEPT
11790b57cec5SDimitry Andric {
11800b57cec5SDimitry Andric     return _C_tolower_tab_ + 1;
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric const short*
11840b57cec5SDimitry Andric ctype<char>::__classic_upper_table() _NOEXCEPT
11850b57cec5SDimitry Andric {
11860b57cec5SDimitry Andric     return _C_toupper_tab_ + 1;
11870b57cec5SDimitry Andric }
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric #elif defined(__EMSCRIPTEN__)
11900b57cec5SDimitry Andric const int*
11910b57cec5SDimitry Andric ctype<char>::__classic_lower_table() _NOEXCEPT
11920b57cec5SDimitry Andric {
11930b57cec5SDimitry Andric     return *__ctype_tolower_loc();
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric const int*
11970b57cec5SDimitry Andric ctype<char>::__classic_upper_table() _NOEXCEPT
11980b57cec5SDimitry Andric {
11990b57cec5SDimitry Andric     return *__ctype_toupper_loc();
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric // template <> class ctype_byname<char>
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric ctype_byname<char>::ctype_byname(const char* name, size_t refs)
12060b57cec5SDimitry Andric     : ctype<char>(0, false, refs),
12070b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, name, 0))
12080b57cec5SDimitry Andric {
12090b57cec5SDimitry Andric     if (__l == 0)
12100b57cec5SDimitry Andric         __throw_runtime_error("ctype_byname<char>::ctype_byname"
12110b57cec5SDimitry Andric                             " failed to construct for " + string(name));
12120b57cec5SDimitry Andric }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric ctype_byname<char>::ctype_byname(const string& name, size_t refs)
12150b57cec5SDimitry Andric     : ctype<char>(0, false, refs),
12160b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
12170b57cec5SDimitry Andric {
12180b57cec5SDimitry Andric     if (__l == 0)
12190b57cec5SDimitry Andric         __throw_runtime_error("ctype_byname<char>::ctype_byname"
12200b57cec5SDimitry Andric                             " failed to construct for " + name);
12210b57cec5SDimitry Andric }
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric ctype_byname<char>::~ctype_byname()
12240b57cec5SDimitry Andric {
12250b57cec5SDimitry Andric     freelocale(__l);
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric char
12290b57cec5SDimitry Andric ctype_byname<char>::do_toupper(char_type c) const
12300b57cec5SDimitry Andric {
12310b57cec5SDimitry Andric     return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
12320b57cec5SDimitry Andric }
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric const char*
12350b57cec5SDimitry Andric ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
12360b57cec5SDimitry Andric {
12370b57cec5SDimitry Andric     for (; low != high; ++low)
12380b57cec5SDimitry Andric         *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
12390b57cec5SDimitry Andric     return low;
12400b57cec5SDimitry Andric }
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric char
12430b57cec5SDimitry Andric ctype_byname<char>::do_tolower(char_type c) const
12440b57cec5SDimitry Andric {
12450b57cec5SDimitry Andric     return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric 
12480b57cec5SDimitry Andric const char*
12490b57cec5SDimitry Andric ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
12500b57cec5SDimitry Andric {
12510b57cec5SDimitry Andric     for (; low != high; ++low)
12520b57cec5SDimitry Andric         *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
12530b57cec5SDimitry Andric     return low;
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric // template <> class ctype_byname<wchar_t>
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
12590b57cec5SDimitry Andric     : ctype<wchar_t>(refs),
12600b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, name, 0))
12610b57cec5SDimitry Andric {
12620b57cec5SDimitry Andric     if (__l == 0)
12630b57cec5SDimitry Andric         __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
12640b57cec5SDimitry Andric                             " failed to construct for " + string(name));
12650b57cec5SDimitry Andric }
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
12680b57cec5SDimitry Andric     : ctype<wchar_t>(refs),
12690b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
12700b57cec5SDimitry Andric {
12710b57cec5SDimitry Andric     if (__l == 0)
12720b57cec5SDimitry Andric         __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
12730b57cec5SDimitry Andric                             " failed to construct for " + name);
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric ctype_byname<wchar_t>::~ctype_byname()
12770b57cec5SDimitry Andric {
12780b57cec5SDimitry Andric     freelocale(__l);
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric bool
12820b57cec5SDimitry Andric ctype_byname<wchar_t>::do_is(mask m, char_type c) const
12830b57cec5SDimitry Andric {
12840b57cec5SDimitry Andric #ifdef _LIBCPP_WCTYPE_IS_MASK
12850b57cec5SDimitry Andric     return static_cast<bool>(iswctype_l(c, m, __l));
12860b57cec5SDimitry Andric #else
12870b57cec5SDimitry Andric     bool result = false;
12880b57cec5SDimitry Andric     wint_t ch = static_cast<wint_t>(c);
12890b57cec5SDimitry Andric     if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
12900b57cec5SDimitry Andric     if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
12910b57cec5SDimitry Andric     if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
12920b57cec5SDimitry Andric     if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
12930b57cec5SDimitry Andric     if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
12940b57cec5SDimitry Andric     if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
12950b57cec5SDimitry Andric     if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
12960b57cec5SDimitry Andric     if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
12970b57cec5SDimitry Andric     if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
12980b57cec5SDimitry Andric     if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
12990b57cec5SDimitry Andric     return result;
13000b57cec5SDimitry Andric #endif
13010b57cec5SDimitry Andric }
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric const wchar_t*
13040b57cec5SDimitry Andric ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
13050b57cec5SDimitry Andric {
13060b57cec5SDimitry Andric     for (; low != high; ++low, ++vec)
13070b57cec5SDimitry Andric     {
13080b57cec5SDimitry Andric         if (isascii(*low))
13090b57cec5SDimitry Andric             *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
13100b57cec5SDimitry Andric         else
13110b57cec5SDimitry Andric         {
13120b57cec5SDimitry Andric             *vec = 0;
13130b57cec5SDimitry Andric             wint_t ch = static_cast<wint_t>(*low);
13140b57cec5SDimitry Andric             if (iswspace_l(ch, __l))
13150b57cec5SDimitry Andric                 *vec |= space;
13160b57cec5SDimitry Andric #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
13170b57cec5SDimitry Andric             if (iswprint_l(ch, __l))
13180b57cec5SDimitry Andric                 *vec |= print;
13190b57cec5SDimitry Andric #endif
13200b57cec5SDimitry Andric             if (iswcntrl_l(ch, __l))
13210b57cec5SDimitry Andric                 *vec |= cntrl;
13220b57cec5SDimitry Andric             if (iswupper_l(ch, __l))
13230b57cec5SDimitry Andric                 *vec |= upper;
13240b57cec5SDimitry Andric             if (iswlower_l(ch, __l))
13250b57cec5SDimitry Andric                 *vec |= lower;
13260b57cec5SDimitry Andric #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
13270b57cec5SDimitry Andric             if (iswalpha_l(ch, __l))
13280b57cec5SDimitry Andric                 *vec |= alpha;
13290b57cec5SDimitry Andric #endif
13300b57cec5SDimitry Andric             if (iswdigit_l(ch, __l))
13310b57cec5SDimitry Andric                 *vec |= digit;
13320b57cec5SDimitry Andric             if (iswpunct_l(ch, __l))
13330b57cec5SDimitry Andric                 *vec |= punct;
13340b57cec5SDimitry Andric #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
13350b57cec5SDimitry Andric             if (iswxdigit_l(ch, __l))
13360b57cec5SDimitry Andric                 *vec |= xdigit;
13370b57cec5SDimitry Andric #endif
13380b57cec5SDimitry Andric #if !defined(__sun__)
13390b57cec5SDimitry Andric             if (iswblank_l(ch, __l))
13400b57cec5SDimitry Andric                 *vec |= blank;
13410b57cec5SDimitry Andric #endif
13420b57cec5SDimitry Andric         }
13430b57cec5SDimitry Andric     }
13440b57cec5SDimitry Andric     return low;
13450b57cec5SDimitry Andric }
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric const wchar_t*
13480b57cec5SDimitry Andric ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
13490b57cec5SDimitry Andric {
13500b57cec5SDimitry Andric     for (; low != high; ++low)
13510b57cec5SDimitry Andric     {
13520b57cec5SDimitry Andric #ifdef _LIBCPP_WCTYPE_IS_MASK
13530b57cec5SDimitry Andric         if (iswctype_l(*low, m, __l))
13540b57cec5SDimitry Andric             break;
13550b57cec5SDimitry Andric #else
13560b57cec5SDimitry Andric         wint_t ch = static_cast<wint_t>(*low);
13570b57cec5SDimitry Andric         if ((m & space) == space && iswspace_l(ch, __l)) break;
13580b57cec5SDimitry Andric         if ((m & print) == print && iswprint_l(ch, __l)) break;
13590b57cec5SDimitry Andric         if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
13600b57cec5SDimitry Andric         if ((m & upper) == upper && iswupper_l(ch, __l)) break;
13610b57cec5SDimitry Andric         if ((m & lower) == lower && iswlower_l(ch, __l)) break;
13620b57cec5SDimitry Andric         if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
13630b57cec5SDimitry Andric         if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
13640b57cec5SDimitry Andric         if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
13650b57cec5SDimitry Andric         if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
13660b57cec5SDimitry Andric         if ((m & blank) == blank && iswblank_l(ch, __l)) break;
13670b57cec5SDimitry Andric #endif
13680b57cec5SDimitry Andric     }
13690b57cec5SDimitry Andric     return low;
13700b57cec5SDimitry Andric }
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric const wchar_t*
13730b57cec5SDimitry Andric ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
13740b57cec5SDimitry Andric {
13750b57cec5SDimitry Andric     for (; low != high; ++low)
13760b57cec5SDimitry Andric     {
13770b57cec5SDimitry Andric #ifdef _LIBCPP_WCTYPE_IS_MASK
13780b57cec5SDimitry Andric         if (!iswctype_l(*low, m, __l))
13790b57cec5SDimitry Andric             break;
13800b57cec5SDimitry Andric #else
13810b57cec5SDimitry Andric         wint_t ch = static_cast<wint_t>(*low);
13820b57cec5SDimitry Andric         if ((m & space) == space && iswspace_l(ch, __l)) continue;
13830b57cec5SDimitry Andric         if ((m & print) == print && iswprint_l(ch, __l)) continue;
13840b57cec5SDimitry Andric         if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
13850b57cec5SDimitry Andric         if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
13860b57cec5SDimitry Andric         if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
13870b57cec5SDimitry Andric         if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
13880b57cec5SDimitry Andric         if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
13890b57cec5SDimitry Andric         if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
13900b57cec5SDimitry Andric         if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
13910b57cec5SDimitry Andric         if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
13920b57cec5SDimitry Andric         break;
13930b57cec5SDimitry Andric #endif
13940b57cec5SDimitry Andric     }
13950b57cec5SDimitry Andric     return low;
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric wchar_t
13990b57cec5SDimitry Andric ctype_byname<wchar_t>::do_toupper(char_type c) const
14000b57cec5SDimitry Andric {
14010b57cec5SDimitry Andric     return towupper_l(c, __l);
14020b57cec5SDimitry Andric }
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric const wchar_t*
14050b57cec5SDimitry Andric ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
14060b57cec5SDimitry Andric {
14070b57cec5SDimitry Andric     for (; low != high; ++low)
14080b57cec5SDimitry Andric         *low = towupper_l(*low, __l);
14090b57cec5SDimitry Andric     return low;
14100b57cec5SDimitry Andric }
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric wchar_t
14130b57cec5SDimitry Andric ctype_byname<wchar_t>::do_tolower(char_type c) const
14140b57cec5SDimitry Andric {
14150b57cec5SDimitry Andric     return towlower_l(c, __l);
14160b57cec5SDimitry Andric }
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric const wchar_t*
14190b57cec5SDimitry Andric ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
14200b57cec5SDimitry Andric {
14210b57cec5SDimitry Andric     for (; low != high; ++low)
14220b57cec5SDimitry Andric         *low = towlower_l(*low, __l);
14230b57cec5SDimitry Andric     return low;
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric wchar_t
14270b57cec5SDimitry Andric ctype_byname<wchar_t>::do_widen(char c) const
14280b57cec5SDimitry Andric {
14290b57cec5SDimitry Andric     return __libcpp_btowc_l(c, __l);
14300b57cec5SDimitry Andric }
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric const char*
14330b57cec5SDimitry Andric ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
14340b57cec5SDimitry Andric {
14350b57cec5SDimitry Andric     for (; low != high; ++low, ++dest)
14360b57cec5SDimitry Andric         *dest = __libcpp_btowc_l(*low, __l);
14370b57cec5SDimitry Andric     return low;
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric 
14400b57cec5SDimitry Andric char
14410b57cec5SDimitry Andric ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
14420b57cec5SDimitry Andric {
14430b57cec5SDimitry Andric     int r = __libcpp_wctob_l(c, __l);
14440b57cec5SDimitry Andric     return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
14450b57cec5SDimitry Andric }
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric const wchar_t*
14480b57cec5SDimitry Andric ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
14490b57cec5SDimitry Andric {
14500b57cec5SDimitry Andric     for (; low != high; ++low, ++dest)
14510b57cec5SDimitry Andric     {
14520b57cec5SDimitry Andric         int r = __libcpp_wctob_l(*low, __l);
14530b57cec5SDimitry Andric         *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
14540b57cec5SDimitry Andric     }
14550b57cec5SDimitry Andric     return low;
14560b57cec5SDimitry Andric }
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric // template <> class codecvt<char, char, mbstate_t>
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric locale::id codecvt<char, char, mbstate_t>::id;
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::~codecvt()
14630b57cec5SDimitry Andric {
14640b57cec5SDimitry Andric }
14650b57cec5SDimitry Andric 
14660b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::result
14670b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::do_out(state_type&,
14680b57cec5SDimitry Andric     const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
14690b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
14700b57cec5SDimitry Andric {
14710b57cec5SDimitry Andric     frm_nxt = frm;
14720b57cec5SDimitry Andric     to_nxt = to;
14730b57cec5SDimitry Andric     return noconv;
14740b57cec5SDimitry Andric }
14750b57cec5SDimitry Andric 
14760b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::result
14770b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::do_in(state_type&,
14780b57cec5SDimitry Andric     const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
14790b57cec5SDimitry Andric     intern_type* to, intern_type*, intern_type*& to_nxt) const
14800b57cec5SDimitry Andric {
14810b57cec5SDimitry Andric     frm_nxt = frm;
14820b57cec5SDimitry Andric     to_nxt = to;
14830b57cec5SDimitry Andric     return noconv;
14840b57cec5SDimitry Andric }
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::result
14870b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::do_unshift(state_type&,
14880b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
14890b57cec5SDimitry Andric {
14900b57cec5SDimitry Andric     to_nxt = to;
14910b57cec5SDimitry Andric     return noconv;
14920b57cec5SDimitry Andric }
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric int
14950b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::do_encoding() const  _NOEXCEPT
14960b57cec5SDimitry Andric {
14970b57cec5SDimitry Andric     return 1;
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric 
15000b57cec5SDimitry Andric bool
15010b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
15020b57cec5SDimitry Andric {
15030b57cec5SDimitry Andric     return true;
15040b57cec5SDimitry Andric }
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric int
15070b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::do_length(state_type&,
15080b57cec5SDimitry Andric     const extern_type* frm, const extern_type* end, size_t mx) const
15090b57cec5SDimitry Andric {
15100b57cec5SDimitry Andric     return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
15110b57cec5SDimitry Andric }
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric int
15140b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::do_max_length() const  _NOEXCEPT
15150b57cec5SDimitry Andric {
15160b57cec5SDimitry Andric     return 1;
15170b57cec5SDimitry Andric }
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric // template <> class codecvt<wchar_t, char, mbstate_t>
15200b57cec5SDimitry Andric 
15210b57cec5SDimitry Andric locale::id codecvt<wchar_t, char, mbstate_t>::id;
15220b57cec5SDimitry Andric 
15230b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
15240b57cec5SDimitry Andric     : locale::facet(refs),
15250b57cec5SDimitry Andric       __l(_LIBCPP_GET_C_LOCALE)
15260b57cec5SDimitry Andric {
15270b57cec5SDimitry Andric }
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
15300b57cec5SDimitry Andric     : locale::facet(refs),
15310b57cec5SDimitry Andric       __l(newlocale(LC_ALL_MASK, nm, 0))
15320b57cec5SDimitry Andric {
15330b57cec5SDimitry Andric     if (__l == 0)
15340b57cec5SDimitry Andric         __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
15350b57cec5SDimitry Andric                             " failed to construct for " + string(nm));
15360b57cec5SDimitry Andric }
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::~codecvt()
15390b57cec5SDimitry Andric {
15400b57cec5SDimitry Andric     if (__l != _LIBCPP_GET_C_LOCALE)
15410b57cec5SDimitry Andric         freelocale(__l);
15420b57cec5SDimitry Andric }
15430b57cec5SDimitry Andric 
15440b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::result
15450b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
15460b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
15470b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
15480b57cec5SDimitry Andric {
15490b57cec5SDimitry Andric     // look for first internal null in frm
15500b57cec5SDimitry Andric     const intern_type* fend = frm;
15510b57cec5SDimitry Andric     for (; fend != frm_end; ++fend)
15520b57cec5SDimitry Andric         if (*fend == 0)
15530b57cec5SDimitry Andric             break;
15540b57cec5SDimitry Andric     // loop over all null-terminated sequences in frm
15550b57cec5SDimitry Andric     to_nxt = to;
15560b57cec5SDimitry Andric     for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
15570b57cec5SDimitry Andric     {
15580b57cec5SDimitry Andric         // save state in case it is needed to recover to_nxt on error
15590b57cec5SDimitry Andric         mbstate_t save_state = st;
15600b57cec5SDimitry Andric         size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
15610b57cec5SDimitry Andric                                      static_cast<size_t>(to_end-to), &st, __l);
15620b57cec5SDimitry Andric         if (n == size_t(-1))
15630b57cec5SDimitry Andric         {
15640b57cec5SDimitry Andric             // need to recover to_nxt
15650b57cec5SDimitry Andric             for (to_nxt = to; frm != frm_nxt; ++frm)
15660b57cec5SDimitry Andric             {
15670b57cec5SDimitry Andric                 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
15680b57cec5SDimitry Andric                 if (n == size_t(-1))
15690b57cec5SDimitry Andric                     break;
15700b57cec5SDimitry Andric                 to_nxt += n;
15710b57cec5SDimitry Andric             }
15720b57cec5SDimitry Andric             frm_nxt = frm;
15730b57cec5SDimitry Andric             return error;
15740b57cec5SDimitry Andric         }
15750b57cec5SDimitry Andric         if (n == 0)
15760b57cec5SDimitry Andric             return partial;
15770b57cec5SDimitry Andric         to_nxt += n;
15780b57cec5SDimitry Andric         if (to_nxt == to_end)
15790b57cec5SDimitry Andric             break;
15800b57cec5SDimitry Andric         if (fend != frm_end)  // set up next null terminated sequence
15810b57cec5SDimitry Andric         {
15820b57cec5SDimitry Andric             // Try to write the terminating null
15830b57cec5SDimitry Andric             extern_type tmp[MB_LEN_MAX];
15840b57cec5SDimitry Andric             n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
15850b57cec5SDimitry Andric             if (n == size_t(-1))  // on error
15860b57cec5SDimitry Andric                 return error;
15870b57cec5SDimitry Andric             if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
15880b57cec5SDimitry Andric                 return partial;
15890b57cec5SDimitry Andric             for (extern_type* p = tmp; n; --n)  // write it
15900b57cec5SDimitry Andric                 *to_nxt++ = *p++;
15910b57cec5SDimitry Andric             ++frm_nxt;
15920b57cec5SDimitry Andric             // look for next null in frm
15930b57cec5SDimitry Andric             for (fend = frm_nxt; fend != frm_end; ++fend)
15940b57cec5SDimitry Andric                 if (*fend == 0)
15950b57cec5SDimitry Andric                     break;
15960b57cec5SDimitry Andric         }
15970b57cec5SDimitry Andric     }
15980b57cec5SDimitry Andric     return frm_nxt == frm_end ? ok : partial;
15990b57cec5SDimitry Andric }
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::result
16020b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
16030b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
16040b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
16050b57cec5SDimitry Andric {
16060b57cec5SDimitry Andric     // look for first internal null in frm
16070b57cec5SDimitry Andric     const extern_type* fend = frm;
16080b57cec5SDimitry Andric     for (; fend != frm_end; ++fend)
16090b57cec5SDimitry Andric         if (*fend == 0)
16100b57cec5SDimitry Andric             break;
16110b57cec5SDimitry Andric     // loop over all null-terminated sequences in frm
16120b57cec5SDimitry Andric     to_nxt = to;
16130b57cec5SDimitry Andric     for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
16140b57cec5SDimitry Andric     {
16150b57cec5SDimitry Andric         // save state in case it is needed to recover to_nxt on error
16160b57cec5SDimitry Andric         mbstate_t save_state = st;
16170b57cec5SDimitry Andric         size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
16180b57cec5SDimitry Andric                                      static_cast<size_t>(to_end-to), &st, __l);
16190b57cec5SDimitry Andric         if (n == size_t(-1))
16200b57cec5SDimitry Andric         {
16210b57cec5SDimitry Andric             // need to recover to_nxt
16220b57cec5SDimitry Andric             for (to_nxt = to; frm != frm_nxt; ++to_nxt)
16230b57cec5SDimitry Andric             {
16240b57cec5SDimitry Andric                 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
16250b57cec5SDimitry Andric                                    &save_state, __l);
16260b57cec5SDimitry Andric                 switch (n)
16270b57cec5SDimitry Andric                 {
16280b57cec5SDimitry Andric                 case 0:
16290b57cec5SDimitry Andric                     ++frm;
16300b57cec5SDimitry Andric                     break;
16310b57cec5SDimitry Andric                 case size_t(-1):
16320b57cec5SDimitry Andric                     frm_nxt = frm;
16330b57cec5SDimitry Andric                     return error;
16340b57cec5SDimitry Andric                 case size_t(-2):
16350b57cec5SDimitry Andric                     frm_nxt = frm;
16360b57cec5SDimitry Andric                     return partial;
16370b57cec5SDimitry Andric                 default:
16380b57cec5SDimitry Andric                     frm += n;
16390b57cec5SDimitry Andric                     break;
16400b57cec5SDimitry Andric                 }
16410b57cec5SDimitry Andric             }
16420b57cec5SDimitry Andric             frm_nxt = frm;
16430b57cec5SDimitry Andric             return frm_nxt == frm_end ? ok : partial;
16440b57cec5SDimitry Andric         }
16450b57cec5SDimitry Andric         if (n == size_t(-1))
16460b57cec5SDimitry Andric             return error;
16470b57cec5SDimitry Andric         to_nxt += n;
16480b57cec5SDimitry Andric         if (to_nxt == to_end)
16490b57cec5SDimitry Andric             break;
16500b57cec5SDimitry Andric         if (fend != frm_end)  // set up next null terminated sequence
16510b57cec5SDimitry Andric         {
16520b57cec5SDimitry Andric             // Try to write the terminating null
16530b57cec5SDimitry Andric             n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
16540b57cec5SDimitry Andric             if (n != 0)  // on error
16550b57cec5SDimitry Andric                 return error;
16560b57cec5SDimitry Andric             ++to_nxt;
16570b57cec5SDimitry Andric             ++frm_nxt;
16580b57cec5SDimitry Andric             // look for next null in frm
16590b57cec5SDimitry Andric             for (fend = frm_nxt; fend != frm_end; ++fend)
16600b57cec5SDimitry Andric                 if (*fend == 0)
16610b57cec5SDimitry Andric                     break;
16620b57cec5SDimitry Andric         }
16630b57cec5SDimitry Andric     }
16640b57cec5SDimitry Andric     return frm_nxt == frm_end ? ok : partial;
16650b57cec5SDimitry Andric }
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::result
16680b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
16690b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
16700b57cec5SDimitry Andric {
16710b57cec5SDimitry Andric     to_nxt = to;
16720b57cec5SDimitry Andric     extern_type tmp[MB_LEN_MAX];
16730b57cec5SDimitry Andric     size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
16740b57cec5SDimitry Andric     if (n == size_t(-1) || n == 0)  // on error
16750b57cec5SDimitry Andric         return error;
16760b57cec5SDimitry Andric     --n;
16770b57cec5SDimitry Andric     if (n > static_cast<size_t>(to_end-to_nxt))  // is there room?
16780b57cec5SDimitry Andric         return partial;
16790b57cec5SDimitry Andric     for (extern_type* p = tmp; n; --n)  // write it
16800b57cec5SDimitry Andric         *to_nxt++ = *p++;
16810b57cec5SDimitry Andric     return ok;
16820b57cec5SDimitry Andric }
16830b57cec5SDimitry Andric 
16840b57cec5SDimitry Andric int
16850b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
16860b57cec5SDimitry Andric {
16870b57cec5SDimitry Andric     if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
16880b57cec5SDimitry Andric         return -1;
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric     // stateless encoding
16910b57cec5SDimitry Andric     if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1)  // there are no known constant length encodings
16920b57cec5SDimitry Andric         return 1;                // which take more than 1 char to form a wchar_t
16930b57cec5SDimitry Andric     return 0;
16940b57cec5SDimitry Andric }
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric bool
16970b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
16980b57cec5SDimitry Andric {
16990b57cec5SDimitry Andric     return false;
17000b57cec5SDimitry Andric }
17010b57cec5SDimitry Andric 
17020b57cec5SDimitry Andric int
17030b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
17040b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
17050b57cec5SDimitry Andric {
17060b57cec5SDimitry Andric     int nbytes = 0;
17070b57cec5SDimitry Andric     for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
17080b57cec5SDimitry Andric     {
17090b57cec5SDimitry Andric         size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
17100b57cec5SDimitry Andric         switch (n)
17110b57cec5SDimitry Andric         {
17120b57cec5SDimitry Andric         case 0:
17130b57cec5SDimitry Andric             ++nbytes;
17140b57cec5SDimitry Andric             ++frm;
17150b57cec5SDimitry Andric             break;
17160b57cec5SDimitry Andric         case size_t(-1):
17170b57cec5SDimitry Andric         case size_t(-2):
17180b57cec5SDimitry Andric             return nbytes;
17190b57cec5SDimitry Andric         default:
17200b57cec5SDimitry Andric             nbytes += n;
17210b57cec5SDimitry Andric             frm += n;
17220b57cec5SDimitry Andric             break;
17230b57cec5SDimitry Andric         }
17240b57cec5SDimitry Andric     }
17250b57cec5SDimitry Andric     return nbytes;
17260b57cec5SDimitry Andric }
17270b57cec5SDimitry Andric 
17280b57cec5SDimitry Andric int
17290b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
17300b57cec5SDimitry Andric {
17310b57cec5SDimitry Andric     return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
17320b57cec5SDimitry Andric }
17330b57cec5SDimitry Andric 
17340b57cec5SDimitry Andric //                                     Valid UTF ranges
17350b57cec5SDimitry Andric //     UTF-32               UTF-16                          UTF-8               # of code points
17360b57cec5SDimitry Andric //                     first      second       first   second    third   fourth
17370b57cec5SDimitry Andric // 000000 - 00007F  0000 - 007F               00 - 7F                                 127
17380b57cec5SDimitry Andric // 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920
17390b57cec5SDimitry Andric // 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048
17400b57cec5SDimitry Andric // 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152
17410b57cec5SDimitry Andric // 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048
17420b57cec5SDimitry Andric // 00D800 - 00DFFF                invalid
17430b57cec5SDimitry Andric // 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192
17440b57cec5SDimitry Andric // 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608
17450b57cec5SDimitry Andric // 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432
17460b57cec5SDimitry Andric // 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric static
17490b57cec5SDimitry Andric codecvt_base::result
17500b57cec5SDimitry Andric utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
17510b57cec5SDimitry Andric               uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
17520b57cec5SDimitry Andric               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
17530b57cec5SDimitry Andric {
17540b57cec5SDimitry Andric     frm_nxt = frm;
17550b57cec5SDimitry Andric     to_nxt = to;
17560b57cec5SDimitry Andric     if (mode & generate_header)
17570b57cec5SDimitry Andric     {
17580b57cec5SDimitry Andric         if (to_end-to_nxt < 3)
17590b57cec5SDimitry Andric             return codecvt_base::partial;
17600b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xEF);
17610b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBB);
17620b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBF);
17630b57cec5SDimitry Andric     }
17640b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
17650b57cec5SDimitry Andric     {
17660b57cec5SDimitry Andric         uint16_t wc1 = *frm_nxt;
17670b57cec5SDimitry Andric         if (wc1 > Maxcode)
17680b57cec5SDimitry Andric             return codecvt_base::error;
17690b57cec5SDimitry Andric         if (wc1 < 0x0080)
17700b57cec5SDimitry Andric         {
17710b57cec5SDimitry Andric             if (to_end-to_nxt < 1)
17720b57cec5SDimitry Andric                 return codecvt_base::partial;
17730b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc1);
17740b57cec5SDimitry Andric         }
17750b57cec5SDimitry Andric         else if (wc1 < 0x0800)
17760b57cec5SDimitry Andric         {
17770b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
17780b57cec5SDimitry Andric                 return codecvt_base::partial;
17790b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
17800b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
17810b57cec5SDimitry Andric         }
17820b57cec5SDimitry Andric         else if (wc1 < 0xD800)
17830b57cec5SDimitry Andric         {
17840b57cec5SDimitry Andric             if (to_end-to_nxt < 3)
17850b57cec5SDimitry Andric                 return codecvt_base::partial;
17860b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
17870b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
17880b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
17890b57cec5SDimitry Andric         }
17900b57cec5SDimitry Andric         else if (wc1 < 0xDC00)
17910b57cec5SDimitry Andric         {
17920b57cec5SDimitry Andric             if (frm_end-frm_nxt < 2)
17930b57cec5SDimitry Andric                 return codecvt_base::partial;
17940b57cec5SDimitry Andric             uint16_t wc2 = frm_nxt[1];
17950b57cec5SDimitry Andric             if ((wc2 & 0xFC00) != 0xDC00)
17960b57cec5SDimitry Andric                 return codecvt_base::error;
17970b57cec5SDimitry Andric             if (to_end-to_nxt < 4)
17980b57cec5SDimitry Andric                 return codecvt_base::partial;
17990b57cec5SDimitry Andric             if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
18000b57cec5SDimitry Andric                 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
18010b57cec5SDimitry Andric                 return codecvt_base::error;
18020b57cec5SDimitry Andric             ++frm_nxt;
18030b57cec5SDimitry Andric             uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
18040b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
18050b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
18060b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
18070b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
18080b57cec5SDimitry Andric         }
18090b57cec5SDimitry Andric         else if (wc1 < 0xE000)
18100b57cec5SDimitry Andric         {
18110b57cec5SDimitry Andric             return codecvt_base::error;
18120b57cec5SDimitry Andric         }
18130b57cec5SDimitry Andric         else
18140b57cec5SDimitry Andric         {
18150b57cec5SDimitry Andric             if (to_end-to_nxt < 3)
18160b57cec5SDimitry Andric                 return codecvt_base::partial;
18170b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
18180b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
18190b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
18200b57cec5SDimitry Andric         }
18210b57cec5SDimitry Andric     }
18220b57cec5SDimitry Andric     return codecvt_base::ok;
18230b57cec5SDimitry Andric }
18240b57cec5SDimitry Andric 
18250b57cec5SDimitry Andric static
18260b57cec5SDimitry Andric codecvt_base::result
18270b57cec5SDimitry Andric utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
18280b57cec5SDimitry Andric               uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
18290b57cec5SDimitry Andric               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
18300b57cec5SDimitry Andric {
18310b57cec5SDimitry Andric     frm_nxt = frm;
18320b57cec5SDimitry Andric     to_nxt = to;
18330b57cec5SDimitry Andric     if (mode & generate_header)
18340b57cec5SDimitry Andric     {
18350b57cec5SDimitry Andric         if (to_end-to_nxt < 3)
18360b57cec5SDimitry Andric             return codecvt_base::partial;
18370b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xEF);
18380b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBB);
18390b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBF);
18400b57cec5SDimitry Andric     }
18410b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
18420b57cec5SDimitry Andric     {
18430b57cec5SDimitry Andric         uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
18440b57cec5SDimitry Andric         if (wc1 > Maxcode)
18450b57cec5SDimitry Andric             return codecvt_base::error;
18460b57cec5SDimitry Andric         if (wc1 < 0x0080)
18470b57cec5SDimitry Andric         {
18480b57cec5SDimitry Andric             if (to_end-to_nxt < 1)
18490b57cec5SDimitry Andric                 return codecvt_base::partial;
18500b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc1);
18510b57cec5SDimitry Andric         }
18520b57cec5SDimitry Andric         else if (wc1 < 0x0800)
18530b57cec5SDimitry Andric         {
18540b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
18550b57cec5SDimitry Andric                 return codecvt_base::partial;
18560b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
18570b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
18580b57cec5SDimitry Andric         }
18590b57cec5SDimitry Andric         else if (wc1 < 0xD800)
18600b57cec5SDimitry Andric         {
18610b57cec5SDimitry Andric             if (to_end-to_nxt < 3)
18620b57cec5SDimitry Andric                 return codecvt_base::partial;
18630b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
18640b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
18650b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
18660b57cec5SDimitry Andric         }
18670b57cec5SDimitry Andric         else if (wc1 < 0xDC00)
18680b57cec5SDimitry Andric         {
18690b57cec5SDimitry Andric             if (frm_end-frm_nxt < 2)
18700b57cec5SDimitry Andric                 return codecvt_base::partial;
18710b57cec5SDimitry Andric             uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
18720b57cec5SDimitry Andric             if ((wc2 & 0xFC00) != 0xDC00)
18730b57cec5SDimitry Andric                 return codecvt_base::error;
18740b57cec5SDimitry Andric             if (to_end-to_nxt < 4)
18750b57cec5SDimitry Andric                 return codecvt_base::partial;
18760b57cec5SDimitry Andric             if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
18770b57cec5SDimitry Andric                 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
18780b57cec5SDimitry Andric                 return codecvt_base::error;
18790b57cec5SDimitry Andric             ++frm_nxt;
18800b57cec5SDimitry Andric             uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
18810b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
18820b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2));
18830b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
18840b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F));
18850b57cec5SDimitry Andric         }
18860b57cec5SDimitry Andric         else if (wc1 < 0xE000)
18870b57cec5SDimitry Andric         {
18880b57cec5SDimitry Andric             return codecvt_base::error;
18890b57cec5SDimitry Andric         }
18900b57cec5SDimitry Andric         else
18910b57cec5SDimitry Andric         {
18920b57cec5SDimitry Andric             if (to_end-to_nxt < 3)
18930b57cec5SDimitry Andric                 return codecvt_base::partial;
18940b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12));
18950b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
18960b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F));
18970b57cec5SDimitry Andric         }
18980b57cec5SDimitry Andric     }
18990b57cec5SDimitry Andric     return codecvt_base::ok;
19000b57cec5SDimitry Andric }
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric static
19030b57cec5SDimitry Andric codecvt_base::result
19040b57cec5SDimitry Andric utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
19050b57cec5SDimitry Andric               uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
19060b57cec5SDimitry Andric               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
19070b57cec5SDimitry Andric {
19080b57cec5SDimitry Andric     frm_nxt = frm;
19090b57cec5SDimitry Andric     to_nxt = to;
19100b57cec5SDimitry Andric     if (mode & consume_header)
19110b57cec5SDimitry Andric     {
19120b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
19130b57cec5SDimitry Andric                                                           frm_nxt[2] == 0xBF)
19140b57cec5SDimitry Andric             frm_nxt += 3;
19150b57cec5SDimitry Andric     }
19160b57cec5SDimitry Andric     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
19170b57cec5SDimitry Andric     {
19180b57cec5SDimitry Andric         uint8_t c1 = *frm_nxt;
19190b57cec5SDimitry Andric         if (c1 > Maxcode)
19200b57cec5SDimitry Andric             return codecvt_base::error;
19210b57cec5SDimitry Andric         if (c1 < 0x80)
19220b57cec5SDimitry Andric         {
19230b57cec5SDimitry Andric             *to_nxt = static_cast<uint16_t>(c1);
19240b57cec5SDimitry Andric             ++frm_nxt;
19250b57cec5SDimitry Andric         }
19260b57cec5SDimitry Andric         else if (c1 < 0xC2)
19270b57cec5SDimitry Andric         {
19280b57cec5SDimitry Andric             return codecvt_base::error;
19290b57cec5SDimitry Andric         }
19300b57cec5SDimitry Andric         else if (c1 < 0xE0)
19310b57cec5SDimitry Andric         {
19320b57cec5SDimitry Andric             if (frm_end-frm_nxt < 2)
19330b57cec5SDimitry Andric                 return codecvt_base::partial;
19340b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
19350b57cec5SDimitry Andric             if ((c2 & 0xC0) != 0x80)
19360b57cec5SDimitry Andric                 return codecvt_base::error;
19370b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
19380b57cec5SDimitry Andric             if (t > Maxcode)
19390b57cec5SDimitry Andric                 return codecvt_base::error;
19400b57cec5SDimitry Andric             *to_nxt = t;
19410b57cec5SDimitry Andric             frm_nxt += 2;
19420b57cec5SDimitry Andric         }
19430b57cec5SDimitry Andric         else if (c1 < 0xF0)
19440b57cec5SDimitry Andric         {
19450b57cec5SDimitry Andric             if (frm_end-frm_nxt < 3)
19460b57cec5SDimitry Andric                 return codecvt_base::partial;
19470b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
19480b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
19490b57cec5SDimitry Andric             switch (c1)
19500b57cec5SDimitry Andric             {
19510b57cec5SDimitry Andric             case 0xE0:
19520b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0xA0)
19530b57cec5SDimitry Andric                     return codecvt_base::error;
19540b57cec5SDimitry Andric                  break;
19550b57cec5SDimitry Andric             case 0xED:
19560b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0x80)
19570b57cec5SDimitry Andric                     return codecvt_base::error;
19580b57cec5SDimitry Andric                  break;
19590b57cec5SDimitry Andric             default:
19600b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
19610b57cec5SDimitry Andric                     return codecvt_base::error;
19620b57cec5SDimitry Andric                  break;
19630b57cec5SDimitry Andric             }
19640b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80)
19650b57cec5SDimitry Andric                 return codecvt_base::error;
19660b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
19670b57cec5SDimitry Andric                                              | ((c2 & 0x3F) << 6)
19680b57cec5SDimitry Andric                                              |  (c3 & 0x3F));
19690b57cec5SDimitry Andric             if (t > Maxcode)
19700b57cec5SDimitry Andric                 return codecvt_base::error;
19710b57cec5SDimitry Andric             *to_nxt = t;
19720b57cec5SDimitry Andric             frm_nxt += 3;
19730b57cec5SDimitry Andric         }
19740b57cec5SDimitry Andric         else if (c1 < 0xF5)
19750b57cec5SDimitry Andric         {
19760b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
19770b57cec5SDimitry Andric                 return codecvt_base::partial;
19780b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
19790b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
19800b57cec5SDimitry Andric             uint8_t c4 = frm_nxt[3];
19810b57cec5SDimitry Andric             switch (c1)
19820b57cec5SDimitry Andric             {
19830b57cec5SDimitry Andric             case 0xF0:
19840b57cec5SDimitry Andric                 if (!(0x90 <= c2 && c2 <= 0xBF))
19850b57cec5SDimitry Andric                     return codecvt_base::error;
19860b57cec5SDimitry Andric                  break;
19870b57cec5SDimitry Andric             case 0xF4:
19880b57cec5SDimitry Andric                 if ((c2 & 0xF0) != 0x80)
19890b57cec5SDimitry Andric                     return codecvt_base::error;
19900b57cec5SDimitry Andric                  break;
19910b57cec5SDimitry Andric             default:
19920b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
19930b57cec5SDimitry Andric                     return codecvt_base::error;
19940b57cec5SDimitry Andric                  break;
19950b57cec5SDimitry Andric             }
19960b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
19970b57cec5SDimitry Andric                 return codecvt_base::error;
19980b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
19990b57cec5SDimitry Andric                 return codecvt_base::partial;
20000b57cec5SDimitry Andric             if ((((c1 & 7UL) << 18) +
20010b57cec5SDimitry Andric                 ((c2 & 0x3FUL) << 12) +
20020b57cec5SDimitry Andric                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
20030b57cec5SDimitry Andric                 return codecvt_base::error;
20040b57cec5SDimitry Andric             *to_nxt = static_cast<uint16_t>(
20050b57cec5SDimitry Andric                     0xD800
20060b57cec5SDimitry Andric                   | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
20070b57cec5SDimitry Andric                   | ((c2 & 0x0F) << 2)
20080b57cec5SDimitry Andric                   | ((c3 & 0x30) >> 4));
20090b57cec5SDimitry Andric             *++to_nxt = static_cast<uint16_t>(
20100b57cec5SDimitry Andric                     0xDC00
20110b57cec5SDimitry Andric                   | ((c3 & 0x0F) << 6)
20120b57cec5SDimitry Andric                   |  (c4 & 0x3F));
20130b57cec5SDimitry Andric             frm_nxt += 4;
20140b57cec5SDimitry Andric         }
20150b57cec5SDimitry Andric         else
20160b57cec5SDimitry Andric         {
20170b57cec5SDimitry Andric             return codecvt_base::error;
20180b57cec5SDimitry Andric         }
20190b57cec5SDimitry Andric     }
20200b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
20210b57cec5SDimitry Andric }
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric static
20240b57cec5SDimitry Andric codecvt_base::result
20250b57cec5SDimitry Andric utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
20260b57cec5SDimitry Andric               uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
20270b57cec5SDimitry Andric               unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
20280b57cec5SDimitry Andric {
20290b57cec5SDimitry Andric     frm_nxt = frm;
20300b57cec5SDimitry Andric     to_nxt = to;
20310b57cec5SDimitry Andric     if (mode & consume_header)
20320b57cec5SDimitry Andric     {
20330b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
20340b57cec5SDimitry Andric                                                           frm_nxt[2] == 0xBF)
20350b57cec5SDimitry Andric             frm_nxt += 3;
20360b57cec5SDimitry Andric     }
20370b57cec5SDimitry Andric     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
20380b57cec5SDimitry Andric     {
20390b57cec5SDimitry Andric         uint8_t c1 = *frm_nxt;
20400b57cec5SDimitry Andric         if (c1 > Maxcode)
20410b57cec5SDimitry Andric             return codecvt_base::error;
20420b57cec5SDimitry Andric         if (c1 < 0x80)
20430b57cec5SDimitry Andric         {
20440b57cec5SDimitry Andric             *to_nxt = static_cast<uint32_t>(c1);
20450b57cec5SDimitry Andric             ++frm_nxt;
20460b57cec5SDimitry Andric         }
20470b57cec5SDimitry Andric         else if (c1 < 0xC2)
20480b57cec5SDimitry Andric         {
20490b57cec5SDimitry Andric             return codecvt_base::error;
20500b57cec5SDimitry Andric         }
20510b57cec5SDimitry Andric         else if (c1 < 0xE0)
20520b57cec5SDimitry Andric         {
20530b57cec5SDimitry Andric             if (frm_end-frm_nxt < 2)
20540b57cec5SDimitry Andric                 return codecvt_base::partial;
20550b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
20560b57cec5SDimitry Andric             if ((c2 & 0xC0) != 0x80)
20570b57cec5SDimitry Andric                 return codecvt_base::error;
20580b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
20590b57cec5SDimitry Andric             if (t > Maxcode)
20600b57cec5SDimitry Andric                 return codecvt_base::error;
20610b57cec5SDimitry Andric             *to_nxt = static_cast<uint32_t>(t);
20620b57cec5SDimitry Andric             frm_nxt += 2;
20630b57cec5SDimitry Andric         }
20640b57cec5SDimitry Andric         else if (c1 < 0xF0)
20650b57cec5SDimitry Andric         {
20660b57cec5SDimitry Andric             if (frm_end-frm_nxt < 3)
20670b57cec5SDimitry Andric                 return codecvt_base::partial;
20680b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
20690b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
20700b57cec5SDimitry Andric             switch (c1)
20710b57cec5SDimitry Andric             {
20720b57cec5SDimitry Andric             case 0xE0:
20730b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0xA0)
20740b57cec5SDimitry Andric                     return codecvt_base::error;
20750b57cec5SDimitry Andric                  break;
20760b57cec5SDimitry Andric             case 0xED:
20770b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0x80)
20780b57cec5SDimitry Andric                     return codecvt_base::error;
20790b57cec5SDimitry Andric                  break;
20800b57cec5SDimitry Andric             default:
20810b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
20820b57cec5SDimitry Andric                     return codecvt_base::error;
20830b57cec5SDimitry Andric                  break;
20840b57cec5SDimitry Andric             }
20850b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80)
20860b57cec5SDimitry Andric                 return codecvt_base::error;
20870b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
20880b57cec5SDimitry Andric                                              | ((c2 & 0x3F) << 6)
20890b57cec5SDimitry Andric                                              |  (c3 & 0x3F));
20900b57cec5SDimitry Andric             if (t > Maxcode)
20910b57cec5SDimitry Andric                 return codecvt_base::error;
20920b57cec5SDimitry Andric             *to_nxt = static_cast<uint32_t>(t);
20930b57cec5SDimitry Andric             frm_nxt += 3;
20940b57cec5SDimitry Andric         }
20950b57cec5SDimitry Andric         else if (c1 < 0xF5)
20960b57cec5SDimitry Andric         {
20970b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
20980b57cec5SDimitry Andric                 return codecvt_base::partial;
20990b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
21000b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
21010b57cec5SDimitry Andric             uint8_t c4 = frm_nxt[3];
21020b57cec5SDimitry Andric             switch (c1)
21030b57cec5SDimitry Andric             {
21040b57cec5SDimitry Andric             case 0xF0:
21050b57cec5SDimitry Andric                 if (!(0x90 <= c2 && c2 <= 0xBF))
21060b57cec5SDimitry Andric                     return codecvt_base::error;
21070b57cec5SDimitry Andric                  break;
21080b57cec5SDimitry Andric             case 0xF4:
21090b57cec5SDimitry Andric                 if ((c2 & 0xF0) != 0x80)
21100b57cec5SDimitry Andric                     return codecvt_base::error;
21110b57cec5SDimitry Andric                  break;
21120b57cec5SDimitry Andric             default:
21130b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
21140b57cec5SDimitry Andric                     return codecvt_base::error;
21150b57cec5SDimitry Andric                  break;
21160b57cec5SDimitry Andric             }
21170b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
21180b57cec5SDimitry Andric                 return codecvt_base::error;
21190b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
21200b57cec5SDimitry Andric                 return codecvt_base::partial;
21210b57cec5SDimitry Andric             if ((((c1 & 7UL) << 18) +
21220b57cec5SDimitry Andric                 ((c2 & 0x3FUL) << 12) +
21230b57cec5SDimitry Andric                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
21240b57cec5SDimitry Andric                 return codecvt_base::error;
21250b57cec5SDimitry Andric             *to_nxt = static_cast<uint32_t>(
21260b57cec5SDimitry Andric                     0xD800
21270b57cec5SDimitry Andric                   | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
21280b57cec5SDimitry Andric                   | ((c2 & 0x0F) << 2)
21290b57cec5SDimitry Andric                   | ((c3 & 0x30) >> 4));
21300b57cec5SDimitry Andric             *++to_nxt = static_cast<uint32_t>(
21310b57cec5SDimitry Andric                     0xDC00
21320b57cec5SDimitry Andric                   | ((c3 & 0x0F) << 6)
21330b57cec5SDimitry Andric                   |  (c4 & 0x3F));
21340b57cec5SDimitry Andric             frm_nxt += 4;
21350b57cec5SDimitry Andric         }
21360b57cec5SDimitry Andric         else
21370b57cec5SDimitry Andric         {
21380b57cec5SDimitry Andric             return codecvt_base::error;
21390b57cec5SDimitry Andric         }
21400b57cec5SDimitry Andric     }
21410b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
21420b57cec5SDimitry Andric }
21430b57cec5SDimitry Andric 
21440b57cec5SDimitry Andric static
21450b57cec5SDimitry Andric int
21460b57cec5SDimitry Andric utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
21470b57cec5SDimitry Andric                      size_t mx, unsigned long Maxcode = 0x10FFFF,
21480b57cec5SDimitry Andric                      codecvt_mode mode = codecvt_mode(0))
21490b57cec5SDimitry Andric {
21500b57cec5SDimitry Andric     const uint8_t* frm_nxt = frm;
21510b57cec5SDimitry Andric     if (mode & consume_header)
21520b57cec5SDimitry Andric     {
21530b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
21540b57cec5SDimitry Andric                                                           frm_nxt[2] == 0xBF)
21550b57cec5SDimitry Andric             frm_nxt += 3;
21560b57cec5SDimitry Andric     }
21570b57cec5SDimitry Andric     for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
21580b57cec5SDimitry Andric     {
21590b57cec5SDimitry Andric         uint8_t c1 = *frm_nxt;
21600b57cec5SDimitry Andric         if (c1 > Maxcode)
21610b57cec5SDimitry Andric             break;
21620b57cec5SDimitry Andric         if (c1 < 0x80)
21630b57cec5SDimitry Andric         {
21640b57cec5SDimitry Andric             ++frm_nxt;
21650b57cec5SDimitry Andric         }
21660b57cec5SDimitry Andric         else if (c1 < 0xC2)
21670b57cec5SDimitry Andric         {
21680b57cec5SDimitry Andric             break;
21690b57cec5SDimitry Andric         }
21700b57cec5SDimitry Andric         else if (c1 < 0xE0)
21710b57cec5SDimitry Andric         {
21720b57cec5SDimitry Andric             if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
21730b57cec5SDimitry Andric                 break;
21740b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
21750b57cec5SDimitry Andric             if (t > Maxcode)
21760b57cec5SDimitry Andric                 break;
21770b57cec5SDimitry Andric             frm_nxt += 2;
21780b57cec5SDimitry Andric         }
21790b57cec5SDimitry Andric         else if (c1 < 0xF0)
21800b57cec5SDimitry Andric         {
21810b57cec5SDimitry Andric             if (frm_end-frm_nxt < 3)
21820b57cec5SDimitry Andric                 break;
21830b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
21840b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
21850b57cec5SDimitry Andric             switch (c1)
21860b57cec5SDimitry Andric             {
21870b57cec5SDimitry Andric             case 0xE0:
21880b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0xA0)
21890b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
21900b57cec5SDimitry Andric                 break;
21910b57cec5SDimitry Andric             case 0xED:
21920b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0x80)
21930b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
21940b57cec5SDimitry Andric                  break;
21950b57cec5SDimitry Andric             default:
21960b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
21970b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
21980b57cec5SDimitry Andric                  break;
21990b57cec5SDimitry Andric             }
22000b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80)
22010b57cec5SDimitry Andric                 break;
22020b57cec5SDimitry Andric             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
22030b57cec5SDimitry Andric                 break;
22040b57cec5SDimitry Andric             frm_nxt += 3;
22050b57cec5SDimitry Andric         }
22060b57cec5SDimitry Andric         else if (c1 < 0xF5)
22070b57cec5SDimitry Andric         {
22080b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
22090b57cec5SDimitry Andric                 break;
22100b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
22110b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
22120b57cec5SDimitry Andric             uint8_t c4 = frm_nxt[3];
22130b57cec5SDimitry Andric             switch (c1)
22140b57cec5SDimitry Andric             {
22150b57cec5SDimitry Andric             case 0xF0:
22160b57cec5SDimitry Andric                 if (!(0x90 <= c2 && c2 <= 0xBF))
22170b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
22180b57cec5SDimitry Andric                  break;
22190b57cec5SDimitry Andric             case 0xF4:
22200b57cec5SDimitry Andric                 if ((c2 & 0xF0) != 0x80)
22210b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
22220b57cec5SDimitry Andric                  break;
22230b57cec5SDimitry Andric             default:
22240b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
22250b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
22260b57cec5SDimitry Andric                  break;
22270b57cec5SDimitry Andric             }
22280b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
22290b57cec5SDimitry Andric                 break;
22300b57cec5SDimitry Andric             if ((((c1 & 7UL) << 18) +
22310b57cec5SDimitry Andric                 ((c2 & 0x3FUL) << 12) +
22320b57cec5SDimitry Andric                 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
22330b57cec5SDimitry Andric                 break;
22340b57cec5SDimitry Andric             ++nchar16_t;
22350b57cec5SDimitry Andric             frm_nxt += 4;
22360b57cec5SDimitry Andric         }
22370b57cec5SDimitry Andric         else
22380b57cec5SDimitry Andric         {
22390b57cec5SDimitry Andric             break;
22400b57cec5SDimitry Andric         }
22410b57cec5SDimitry Andric     }
22420b57cec5SDimitry Andric     return static_cast<int>(frm_nxt - frm);
22430b57cec5SDimitry Andric }
22440b57cec5SDimitry Andric 
22450b57cec5SDimitry Andric static
22460b57cec5SDimitry Andric codecvt_base::result
22470b57cec5SDimitry Andric ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
22480b57cec5SDimitry Andric              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
22490b57cec5SDimitry Andric              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
22500b57cec5SDimitry Andric {
22510b57cec5SDimitry Andric     frm_nxt = frm;
22520b57cec5SDimitry Andric     to_nxt = to;
22530b57cec5SDimitry Andric     if (mode & generate_header)
22540b57cec5SDimitry Andric     {
22550b57cec5SDimitry Andric         if (to_end-to_nxt < 3)
22560b57cec5SDimitry Andric             return codecvt_base::partial;
22570b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xEF);
22580b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBB);
22590b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBF);
22600b57cec5SDimitry Andric     }
22610b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
22620b57cec5SDimitry Andric     {
22630b57cec5SDimitry Andric         uint32_t wc = *frm_nxt;
22640b57cec5SDimitry Andric         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
22650b57cec5SDimitry Andric             return codecvt_base::error;
22660b57cec5SDimitry Andric         if (wc < 0x000080)
22670b57cec5SDimitry Andric         {
22680b57cec5SDimitry Andric             if (to_end-to_nxt < 1)
22690b57cec5SDimitry Andric                 return codecvt_base::partial;
22700b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc);
22710b57cec5SDimitry Andric         }
22720b57cec5SDimitry Andric         else if (wc < 0x000800)
22730b57cec5SDimitry Andric         {
22740b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
22750b57cec5SDimitry Andric                 return codecvt_base::partial;
22760b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
22770b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
22780b57cec5SDimitry Andric         }
22790b57cec5SDimitry Andric         else if (wc < 0x010000)
22800b57cec5SDimitry Andric         {
22810b57cec5SDimitry Andric             if (to_end-to_nxt < 3)
22820b57cec5SDimitry Andric                 return codecvt_base::partial;
22830b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
22840b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
22850b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
22860b57cec5SDimitry Andric         }
22870b57cec5SDimitry Andric         else // if (wc < 0x110000)
22880b57cec5SDimitry Andric         {
22890b57cec5SDimitry Andric             if (to_end-to_nxt < 4)
22900b57cec5SDimitry Andric                 return codecvt_base::partial;
22910b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xF0 |  (wc >> 18));
22920b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
22930b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
22940b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x00003F));
22950b57cec5SDimitry Andric         }
22960b57cec5SDimitry Andric     }
22970b57cec5SDimitry Andric     return codecvt_base::ok;
22980b57cec5SDimitry Andric }
22990b57cec5SDimitry Andric 
23000b57cec5SDimitry Andric static
23010b57cec5SDimitry Andric codecvt_base::result
23020b57cec5SDimitry Andric utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
23030b57cec5SDimitry Andric              uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
23040b57cec5SDimitry Andric              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
23050b57cec5SDimitry Andric {
23060b57cec5SDimitry Andric     frm_nxt = frm;
23070b57cec5SDimitry Andric     to_nxt = to;
23080b57cec5SDimitry Andric     if (mode & consume_header)
23090b57cec5SDimitry Andric     {
23100b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
23110b57cec5SDimitry Andric                                                           frm_nxt[2] == 0xBF)
23120b57cec5SDimitry Andric             frm_nxt += 3;
23130b57cec5SDimitry Andric     }
23140b57cec5SDimitry Andric     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
23150b57cec5SDimitry Andric     {
23160b57cec5SDimitry Andric         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
23170b57cec5SDimitry Andric         if (c1 < 0x80)
23180b57cec5SDimitry Andric         {
23190b57cec5SDimitry Andric             if (c1 > Maxcode)
23200b57cec5SDimitry Andric                 return codecvt_base::error;
23210b57cec5SDimitry Andric             *to_nxt = static_cast<uint32_t>(c1);
23220b57cec5SDimitry Andric             ++frm_nxt;
23230b57cec5SDimitry Andric         }
23240b57cec5SDimitry Andric         else if (c1 < 0xC2)
23250b57cec5SDimitry Andric         {
23260b57cec5SDimitry Andric             return codecvt_base::error;
23270b57cec5SDimitry Andric         }
23280b57cec5SDimitry Andric         else if (c1 < 0xE0)
23290b57cec5SDimitry Andric         {
23300b57cec5SDimitry Andric             if (frm_end-frm_nxt < 2)
23310b57cec5SDimitry Andric                 return codecvt_base::partial;
23320b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
23330b57cec5SDimitry Andric             if ((c2 & 0xC0) != 0x80)
23340b57cec5SDimitry Andric                 return codecvt_base::error;
23350b57cec5SDimitry Andric             uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
23360b57cec5SDimitry Andric                                               | (c2 & 0x3F));
23370b57cec5SDimitry Andric             if (t > Maxcode)
23380b57cec5SDimitry Andric                 return codecvt_base::error;
23390b57cec5SDimitry Andric             *to_nxt = t;
23400b57cec5SDimitry Andric             frm_nxt += 2;
23410b57cec5SDimitry Andric         }
23420b57cec5SDimitry Andric         else if (c1 < 0xF0)
23430b57cec5SDimitry Andric         {
23440b57cec5SDimitry Andric             if (frm_end-frm_nxt < 3)
23450b57cec5SDimitry Andric                 return codecvt_base::partial;
23460b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
23470b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
23480b57cec5SDimitry Andric             switch (c1)
23490b57cec5SDimitry Andric             {
23500b57cec5SDimitry Andric             case 0xE0:
23510b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0xA0)
23520b57cec5SDimitry Andric                     return codecvt_base::error;
23530b57cec5SDimitry Andric                  break;
23540b57cec5SDimitry Andric             case 0xED:
23550b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0x80)
23560b57cec5SDimitry Andric                     return codecvt_base::error;
23570b57cec5SDimitry Andric                  break;
23580b57cec5SDimitry Andric             default:
23590b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
23600b57cec5SDimitry Andric                     return codecvt_base::error;
23610b57cec5SDimitry Andric                  break;
23620b57cec5SDimitry Andric             }
23630b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80)
23640b57cec5SDimitry Andric                 return codecvt_base::error;
23650b57cec5SDimitry Andric             uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
23660b57cec5SDimitry Andric                                              | ((c2 & 0x3F) << 6)
23670b57cec5SDimitry Andric                                              |  (c3 & 0x3F));
23680b57cec5SDimitry Andric             if (t > Maxcode)
23690b57cec5SDimitry Andric                 return codecvt_base::error;
23700b57cec5SDimitry Andric             *to_nxt = t;
23710b57cec5SDimitry Andric             frm_nxt += 3;
23720b57cec5SDimitry Andric         }
23730b57cec5SDimitry Andric         else if (c1 < 0xF5)
23740b57cec5SDimitry Andric         {
23750b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
23760b57cec5SDimitry Andric                 return codecvt_base::partial;
23770b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
23780b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
23790b57cec5SDimitry Andric             uint8_t c4 = frm_nxt[3];
23800b57cec5SDimitry Andric             switch (c1)
23810b57cec5SDimitry Andric             {
23820b57cec5SDimitry Andric             case 0xF0:
23830b57cec5SDimitry Andric                 if (!(0x90 <= c2 && c2 <= 0xBF))
23840b57cec5SDimitry Andric                     return codecvt_base::error;
23850b57cec5SDimitry Andric                  break;
23860b57cec5SDimitry Andric             case 0xF4:
23870b57cec5SDimitry Andric                 if ((c2 & 0xF0) != 0x80)
23880b57cec5SDimitry Andric                     return codecvt_base::error;
23890b57cec5SDimitry Andric                  break;
23900b57cec5SDimitry Andric             default:
23910b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
23920b57cec5SDimitry Andric                     return codecvt_base::error;
23930b57cec5SDimitry Andric                  break;
23940b57cec5SDimitry Andric             }
23950b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
23960b57cec5SDimitry Andric                 return codecvt_base::error;
23970b57cec5SDimitry Andric             uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
23980b57cec5SDimitry Andric                                              | ((c2 & 0x3F) << 12)
23990b57cec5SDimitry Andric                                              | ((c3 & 0x3F) << 6)
24000b57cec5SDimitry Andric                                              |  (c4 & 0x3F));
24010b57cec5SDimitry Andric             if (t > Maxcode)
24020b57cec5SDimitry Andric                 return codecvt_base::error;
24030b57cec5SDimitry Andric             *to_nxt = t;
24040b57cec5SDimitry Andric             frm_nxt += 4;
24050b57cec5SDimitry Andric         }
24060b57cec5SDimitry Andric         else
24070b57cec5SDimitry Andric         {
24080b57cec5SDimitry Andric             return codecvt_base::error;
24090b57cec5SDimitry Andric         }
24100b57cec5SDimitry Andric     }
24110b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
24120b57cec5SDimitry Andric }
24130b57cec5SDimitry Andric 
24140b57cec5SDimitry Andric static
24150b57cec5SDimitry Andric int
24160b57cec5SDimitry Andric utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
24170b57cec5SDimitry Andric                     size_t mx, unsigned long Maxcode = 0x10FFFF,
24180b57cec5SDimitry Andric                     codecvt_mode mode = codecvt_mode(0))
24190b57cec5SDimitry Andric {
24200b57cec5SDimitry Andric     const uint8_t* frm_nxt = frm;
24210b57cec5SDimitry Andric     if (mode & consume_header)
24220b57cec5SDimitry Andric     {
24230b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
24240b57cec5SDimitry Andric                                                           frm_nxt[2] == 0xBF)
24250b57cec5SDimitry Andric             frm_nxt += 3;
24260b57cec5SDimitry Andric     }
24270b57cec5SDimitry Andric     for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
24280b57cec5SDimitry Andric     {
24290b57cec5SDimitry Andric         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
24300b57cec5SDimitry Andric         if (c1 < 0x80)
24310b57cec5SDimitry Andric         {
24320b57cec5SDimitry Andric             if (c1 > Maxcode)
24330b57cec5SDimitry Andric                 break;
24340b57cec5SDimitry Andric             ++frm_nxt;
24350b57cec5SDimitry Andric         }
24360b57cec5SDimitry Andric         else if (c1 < 0xC2)
24370b57cec5SDimitry Andric         {
24380b57cec5SDimitry Andric             break;
24390b57cec5SDimitry Andric         }
24400b57cec5SDimitry Andric         else if (c1 < 0xE0)
24410b57cec5SDimitry Andric         {
24420b57cec5SDimitry Andric             if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
24430b57cec5SDimitry Andric                 break;
24440b57cec5SDimitry Andric             if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
24450b57cec5SDimitry Andric                 break;
24460b57cec5SDimitry Andric             frm_nxt += 2;
24470b57cec5SDimitry Andric         }
24480b57cec5SDimitry Andric         else if (c1 < 0xF0)
24490b57cec5SDimitry Andric         {
24500b57cec5SDimitry Andric             if (frm_end-frm_nxt < 3)
24510b57cec5SDimitry Andric                 break;
24520b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
24530b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
24540b57cec5SDimitry Andric             switch (c1)
24550b57cec5SDimitry Andric             {
24560b57cec5SDimitry Andric             case 0xE0:
24570b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0xA0)
24580b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
24590b57cec5SDimitry Andric                 break;
24600b57cec5SDimitry Andric             case 0xED:
24610b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0x80)
24620b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
24630b57cec5SDimitry Andric                  break;
24640b57cec5SDimitry Andric             default:
24650b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
24660b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
24670b57cec5SDimitry Andric                  break;
24680b57cec5SDimitry Andric             }
24690b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80)
24700b57cec5SDimitry Andric                 break;
24710b57cec5SDimitry Andric             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
24720b57cec5SDimitry Andric                 break;
24730b57cec5SDimitry Andric             frm_nxt += 3;
24740b57cec5SDimitry Andric         }
24750b57cec5SDimitry Andric         else if (c1 < 0xF5)
24760b57cec5SDimitry Andric         {
24770b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
24780b57cec5SDimitry Andric                 break;
24790b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
24800b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
24810b57cec5SDimitry Andric             uint8_t c4 = frm_nxt[3];
24820b57cec5SDimitry Andric             switch (c1)
24830b57cec5SDimitry Andric             {
24840b57cec5SDimitry Andric             case 0xF0:
24850b57cec5SDimitry Andric                 if (!(0x90 <= c2 && c2 <= 0xBF))
24860b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
24870b57cec5SDimitry Andric                  break;
24880b57cec5SDimitry Andric             case 0xF4:
24890b57cec5SDimitry Andric                 if ((c2 & 0xF0) != 0x80)
24900b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
24910b57cec5SDimitry Andric                  break;
24920b57cec5SDimitry Andric             default:
24930b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
24940b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
24950b57cec5SDimitry Andric                  break;
24960b57cec5SDimitry Andric             }
24970b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
24980b57cec5SDimitry Andric                 break;
24990b57cec5SDimitry Andric             if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
25000b57cec5SDimitry Andric                  ((c3 & 0x3Fu) << 6)  |  (c4 & 0x3Fu)) > Maxcode)
25010b57cec5SDimitry Andric                 break;
25020b57cec5SDimitry Andric             frm_nxt += 4;
25030b57cec5SDimitry Andric         }
25040b57cec5SDimitry Andric         else
25050b57cec5SDimitry Andric         {
25060b57cec5SDimitry Andric             break;
25070b57cec5SDimitry Andric         }
25080b57cec5SDimitry Andric     }
25090b57cec5SDimitry Andric     return static_cast<int>(frm_nxt - frm);
25100b57cec5SDimitry Andric }
25110b57cec5SDimitry Andric 
25120b57cec5SDimitry Andric static
25130b57cec5SDimitry Andric codecvt_base::result
25140b57cec5SDimitry Andric ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
25150b57cec5SDimitry Andric              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
25160b57cec5SDimitry Andric              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
25170b57cec5SDimitry Andric {
25180b57cec5SDimitry Andric     frm_nxt = frm;
25190b57cec5SDimitry Andric     to_nxt = to;
25200b57cec5SDimitry Andric     if (mode & generate_header)
25210b57cec5SDimitry Andric     {
25220b57cec5SDimitry Andric         if (to_end-to_nxt < 3)
25230b57cec5SDimitry Andric             return codecvt_base::partial;
25240b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xEF);
25250b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBB);
25260b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xBF);
25270b57cec5SDimitry Andric     }
25280b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
25290b57cec5SDimitry Andric     {
25300b57cec5SDimitry Andric         uint16_t wc = *frm_nxt;
25310b57cec5SDimitry Andric         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
25320b57cec5SDimitry Andric             return codecvt_base::error;
25330b57cec5SDimitry Andric         if (wc < 0x0080)
25340b57cec5SDimitry Andric         {
25350b57cec5SDimitry Andric             if (to_end-to_nxt < 1)
25360b57cec5SDimitry Andric                 return codecvt_base::partial;
25370b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc);
25380b57cec5SDimitry Andric         }
25390b57cec5SDimitry Andric         else if (wc < 0x0800)
25400b57cec5SDimitry Andric         {
25410b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
25420b57cec5SDimitry Andric                 return codecvt_base::partial;
25430b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
25440b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
25450b57cec5SDimitry Andric         }
25460b57cec5SDimitry Andric         else // if (wc <= 0xFFFF)
25470b57cec5SDimitry Andric         {
25480b57cec5SDimitry Andric             if (to_end-to_nxt < 3)
25490b57cec5SDimitry Andric                 return codecvt_base::partial;
25500b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12));
25510b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
25520b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F));
25530b57cec5SDimitry Andric         }
25540b57cec5SDimitry Andric     }
25550b57cec5SDimitry Andric     return codecvt_base::ok;
25560b57cec5SDimitry Andric }
25570b57cec5SDimitry Andric 
25580b57cec5SDimitry Andric static
25590b57cec5SDimitry Andric codecvt_base::result
25600b57cec5SDimitry Andric utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
25610b57cec5SDimitry Andric              uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
25620b57cec5SDimitry Andric              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
25630b57cec5SDimitry Andric {
25640b57cec5SDimitry Andric     frm_nxt = frm;
25650b57cec5SDimitry Andric     to_nxt = to;
25660b57cec5SDimitry Andric     if (mode & consume_header)
25670b57cec5SDimitry Andric     {
25680b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
25690b57cec5SDimitry Andric                                                           frm_nxt[2] == 0xBF)
25700b57cec5SDimitry Andric             frm_nxt += 3;
25710b57cec5SDimitry Andric     }
25720b57cec5SDimitry Andric     for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
25730b57cec5SDimitry Andric     {
25740b57cec5SDimitry Andric         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
25750b57cec5SDimitry Andric         if (c1 < 0x80)
25760b57cec5SDimitry Andric         {
25770b57cec5SDimitry Andric             if (c1 > Maxcode)
25780b57cec5SDimitry Andric                 return codecvt_base::error;
25790b57cec5SDimitry Andric             *to_nxt = static_cast<uint16_t>(c1);
25800b57cec5SDimitry Andric             ++frm_nxt;
25810b57cec5SDimitry Andric         }
25820b57cec5SDimitry Andric         else if (c1 < 0xC2)
25830b57cec5SDimitry Andric         {
25840b57cec5SDimitry Andric             return codecvt_base::error;
25850b57cec5SDimitry Andric         }
25860b57cec5SDimitry Andric         else if (c1 < 0xE0)
25870b57cec5SDimitry Andric         {
25880b57cec5SDimitry Andric             if (frm_end-frm_nxt < 2)
25890b57cec5SDimitry Andric                 return codecvt_base::partial;
25900b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
25910b57cec5SDimitry Andric             if ((c2 & 0xC0) != 0x80)
25920b57cec5SDimitry Andric                 return codecvt_base::error;
25930b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
25940b57cec5SDimitry Andric                                               | (c2 & 0x3F));
25950b57cec5SDimitry Andric             if (t > Maxcode)
25960b57cec5SDimitry Andric                 return codecvt_base::error;
25970b57cec5SDimitry Andric             *to_nxt = t;
25980b57cec5SDimitry Andric             frm_nxt += 2;
25990b57cec5SDimitry Andric         }
26000b57cec5SDimitry Andric         else if (c1 < 0xF0)
26010b57cec5SDimitry Andric         {
26020b57cec5SDimitry Andric             if (frm_end-frm_nxt < 3)
26030b57cec5SDimitry Andric                 return codecvt_base::partial;
26040b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
26050b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
26060b57cec5SDimitry Andric             switch (c1)
26070b57cec5SDimitry Andric             {
26080b57cec5SDimitry Andric             case 0xE0:
26090b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0xA0)
26100b57cec5SDimitry Andric                     return codecvt_base::error;
26110b57cec5SDimitry Andric                  break;
26120b57cec5SDimitry Andric             case 0xED:
26130b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0x80)
26140b57cec5SDimitry Andric                     return codecvt_base::error;
26150b57cec5SDimitry Andric                  break;
26160b57cec5SDimitry Andric             default:
26170b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
26180b57cec5SDimitry Andric                     return codecvt_base::error;
26190b57cec5SDimitry Andric                  break;
26200b57cec5SDimitry Andric             }
26210b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80)
26220b57cec5SDimitry Andric                 return codecvt_base::error;
26230b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
26240b57cec5SDimitry Andric                                              | ((c2 & 0x3F) << 6)
26250b57cec5SDimitry Andric                                              |  (c3 & 0x3F));
26260b57cec5SDimitry Andric             if (t > Maxcode)
26270b57cec5SDimitry Andric                 return codecvt_base::error;
26280b57cec5SDimitry Andric             *to_nxt = t;
26290b57cec5SDimitry Andric             frm_nxt += 3;
26300b57cec5SDimitry Andric         }
26310b57cec5SDimitry Andric         else
26320b57cec5SDimitry Andric         {
26330b57cec5SDimitry Andric             return codecvt_base::error;
26340b57cec5SDimitry Andric         }
26350b57cec5SDimitry Andric     }
26360b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
26370b57cec5SDimitry Andric }
26380b57cec5SDimitry Andric 
26390b57cec5SDimitry Andric static
26400b57cec5SDimitry Andric int
26410b57cec5SDimitry Andric utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
26420b57cec5SDimitry Andric                     size_t mx, unsigned long Maxcode = 0x10FFFF,
26430b57cec5SDimitry Andric                     codecvt_mode mode = codecvt_mode(0))
26440b57cec5SDimitry Andric {
26450b57cec5SDimitry Andric     const uint8_t* frm_nxt = frm;
26460b57cec5SDimitry Andric     if (mode & consume_header)
26470b57cec5SDimitry Andric     {
26480b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
26490b57cec5SDimitry Andric                                                           frm_nxt[2] == 0xBF)
26500b57cec5SDimitry Andric             frm_nxt += 3;
26510b57cec5SDimitry Andric     }
26520b57cec5SDimitry Andric     for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
26530b57cec5SDimitry Andric     {
26540b57cec5SDimitry Andric         uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
26550b57cec5SDimitry Andric         if (c1 < 0x80)
26560b57cec5SDimitry Andric         {
26570b57cec5SDimitry Andric             if (c1 > Maxcode)
26580b57cec5SDimitry Andric                 break;
26590b57cec5SDimitry Andric             ++frm_nxt;
26600b57cec5SDimitry Andric         }
26610b57cec5SDimitry Andric         else if (c1 < 0xC2)
26620b57cec5SDimitry Andric         {
26630b57cec5SDimitry Andric             break;
26640b57cec5SDimitry Andric         }
26650b57cec5SDimitry Andric         else if (c1 < 0xE0)
26660b57cec5SDimitry Andric         {
26670b57cec5SDimitry Andric             if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
26680b57cec5SDimitry Andric                 break;
26690b57cec5SDimitry Andric             if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
26700b57cec5SDimitry Andric                 break;
26710b57cec5SDimitry Andric             frm_nxt += 2;
26720b57cec5SDimitry Andric         }
26730b57cec5SDimitry Andric         else if (c1 < 0xF0)
26740b57cec5SDimitry Andric         {
26750b57cec5SDimitry Andric             if (frm_end-frm_nxt < 3)
26760b57cec5SDimitry Andric                 break;
26770b57cec5SDimitry Andric             uint8_t c2 = frm_nxt[1];
26780b57cec5SDimitry Andric             uint8_t c3 = frm_nxt[2];
26790b57cec5SDimitry Andric             switch (c1)
26800b57cec5SDimitry Andric             {
26810b57cec5SDimitry Andric             case 0xE0:
26820b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0xA0)
26830b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
26840b57cec5SDimitry Andric                 break;
26850b57cec5SDimitry Andric             case 0xED:
26860b57cec5SDimitry Andric                 if ((c2 & 0xE0) != 0x80)
26870b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
26880b57cec5SDimitry Andric                  break;
26890b57cec5SDimitry Andric             default:
26900b57cec5SDimitry Andric                 if ((c2 & 0xC0) != 0x80)
26910b57cec5SDimitry Andric                     return static_cast<int>(frm_nxt - frm);
26920b57cec5SDimitry Andric                  break;
26930b57cec5SDimitry Andric             }
26940b57cec5SDimitry Andric             if ((c3 & 0xC0) != 0x80)
26950b57cec5SDimitry Andric                 break;
26960b57cec5SDimitry Andric             if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
26970b57cec5SDimitry Andric                 break;
26980b57cec5SDimitry Andric             frm_nxt += 3;
26990b57cec5SDimitry Andric         }
27000b57cec5SDimitry Andric         else
27010b57cec5SDimitry Andric         {
27020b57cec5SDimitry Andric             break;
27030b57cec5SDimitry Andric         }
27040b57cec5SDimitry Andric     }
27050b57cec5SDimitry Andric     return static_cast<int>(frm_nxt - frm);
27060b57cec5SDimitry Andric }
27070b57cec5SDimitry Andric 
27080b57cec5SDimitry Andric static
27090b57cec5SDimitry Andric codecvt_base::result
27100b57cec5SDimitry Andric ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
27110b57cec5SDimitry Andric                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
27120b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
27130b57cec5SDimitry Andric {
27140b57cec5SDimitry Andric     frm_nxt = frm;
27150b57cec5SDimitry Andric     to_nxt = to;
27160b57cec5SDimitry Andric     if (mode & generate_header)
27170b57cec5SDimitry Andric     {
27180b57cec5SDimitry Andric         if (to_end-to_nxt < 2)
27190b57cec5SDimitry Andric             return codecvt_base::partial;
27200b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFE);
27210b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFF);
27220b57cec5SDimitry Andric     }
27230b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
27240b57cec5SDimitry Andric     {
27250b57cec5SDimitry Andric         uint32_t wc = *frm_nxt;
27260b57cec5SDimitry Andric         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
27270b57cec5SDimitry Andric             return codecvt_base::error;
27280b57cec5SDimitry Andric         if (wc < 0x010000)
27290b57cec5SDimitry Andric         {
27300b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
27310b57cec5SDimitry Andric                 return codecvt_base::partial;
27320b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc >> 8);
27330b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc);
27340b57cec5SDimitry Andric         }
27350b57cec5SDimitry Andric         else
27360b57cec5SDimitry Andric         {
27370b57cec5SDimitry Andric             if (to_end-to_nxt < 4)
27380b57cec5SDimitry Andric                 return codecvt_base::partial;
27390b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(
27400b57cec5SDimitry Andric                     0xD800
27410b57cec5SDimitry Andric                   | ((((wc & 0x1F0000) >> 16) - 1) << 6)
27420b57cec5SDimitry Andric                   |   ((wc & 0x00FC00) >> 10));
27430b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t >> 8);
27440b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t);
27450b57cec5SDimitry Andric             t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
27460b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t >> 8);
27470b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t);
27480b57cec5SDimitry Andric         }
27490b57cec5SDimitry Andric     }
27500b57cec5SDimitry Andric     return codecvt_base::ok;
27510b57cec5SDimitry Andric }
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric static
27540b57cec5SDimitry Andric codecvt_base::result
27550b57cec5SDimitry Andric utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
27560b57cec5SDimitry Andric                 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
27570b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
27580b57cec5SDimitry Andric {
27590b57cec5SDimitry Andric     frm_nxt = frm;
27600b57cec5SDimitry Andric     to_nxt = to;
27610b57cec5SDimitry Andric     if (mode & consume_header)
27620b57cec5SDimitry Andric     {
27630b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
27640b57cec5SDimitry Andric             frm_nxt += 2;
27650b57cec5SDimitry Andric     }
27660b57cec5SDimitry Andric     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
27670b57cec5SDimitry Andric     {
27680b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
27690b57cec5SDimitry Andric         if ((c1 & 0xFC00) == 0xDC00)
27700b57cec5SDimitry Andric             return codecvt_base::error;
27710b57cec5SDimitry Andric         if ((c1 & 0xFC00) != 0xD800)
27720b57cec5SDimitry Andric         {
27730b57cec5SDimitry Andric             if (c1 > Maxcode)
27740b57cec5SDimitry Andric                 return codecvt_base::error;
27750b57cec5SDimitry Andric             *to_nxt = static_cast<uint32_t>(c1);
27760b57cec5SDimitry Andric             frm_nxt += 2;
27770b57cec5SDimitry Andric         }
27780b57cec5SDimitry Andric         else
27790b57cec5SDimitry Andric         {
27800b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
27810b57cec5SDimitry Andric                 return codecvt_base::partial;
27820b57cec5SDimitry Andric             uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
27830b57cec5SDimitry Andric             if ((c2 & 0xFC00) != 0xDC00)
27840b57cec5SDimitry Andric                 return codecvt_base::error;
27850b57cec5SDimitry Andric             uint32_t t = static_cast<uint32_t>(
27860b57cec5SDimitry Andric                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
27870b57cec5SDimitry Andric                   |   ((c1 & 0x003F) << 10)
27880b57cec5SDimitry Andric                   |    (c2 & 0x03FF));
27890b57cec5SDimitry Andric             if (t > Maxcode)
27900b57cec5SDimitry Andric                 return codecvt_base::error;
27910b57cec5SDimitry Andric             *to_nxt = t;
27920b57cec5SDimitry Andric             frm_nxt += 4;
27930b57cec5SDimitry Andric         }
27940b57cec5SDimitry Andric     }
27950b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
27960b57cec5SDimitry Andric }
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric static
27990b57cec5SDimitry Andric int
28000b57cec5SDimitry Andric utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
28010b57cec5SDimitry Andric                        size_t mx, unsigned long Maxcode = 0x10FFFF,
28020b57cec5SDimitry Andric                        codecvt_mode mode = codecvt_mode(0))
28030b57cec5SDimitry Andric {
28040b57cec5SDimitry Andric     const uint8_t* frm_nxt = frm;
28050b57cec5SDimitry Andric     if (mode & consume_header)
28060b57cec5SDimitry Andric     {
28070b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
28080b57cec5SDimitry Andric             frm_nxt += 2;
28090b57cec5SDimitry Andric     }
28100b57cec5SDimitry Andric     for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
28110b57cec5SDimitry Andric     {
28120b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
28130b57cec5SDimitry Andric         if ((c1 & 0xFC00) == 0xDC00)
28140b57cec5SDimitry Andric             break;
28150b57cec5SDimitry Andric         if ((c1 & 0xFC00) != 0xD800)
28160b57cec5SDimitry Andric         {
28170b57cec5SDimitry Andric             if (c1 > Maxcode)
28180b57cec5SDimitry Andric                 break;
28190b57cec5SDimitry Andric             frm_nxt += 2;
28200b57cec5SDimitry Andric         }
28210b57cec5SDimitry Andric         else
28220b57cec5SDimitry Andric         {
28230b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
28240b57cec5SDimitry Andric                 break;
28250b57cec5SDimitry Andric             uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
28260b57cec5SDimitry Andric             if ((c2 & 0xFC00) != 0xDC00)
28270b57cec5SDimitry Andric                 break;
28280b57cec5SDimitry Andric             uint32_t t = static_cast<uint32_t>(
28290b57cec5SDimitry Andric                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
28300b57cec5SDimitry Andric                   |   ((c1 & 0x003F) << 10)
28310b57cec5SDimitry Andric                   |    (c2 & 0x03FF));
28320b57cec5SDimitry Andric             if (t > Maxcode)
28330b57cec5SDimitry Andric                 break;
28340b57cec5SDimitry Andric             frm_nxt += 4;
28350b57cec5SDimitry Andric         }
28360b57cec5SDimitry Andric     }
28370b57cec5SDimitry Andric     return static_cast<int>(frm_nxt - frm);
28380b57cec5SDimitry Andric }
28390b57cec5SDimitry Andric 
28400b57cec5SDimitry Andric static
28410b57cec5SDimitry Andric codecvt_base::result
28420b57cec5SDimitry Andric ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
28430b57cec5SDimitry Andric                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
28440b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
28450b57cec5SDimitry Andric {
28460b57cec5SDimitry Andric     frm_nxt = frm;
28470b57cec5SDimitry Andric     to_nxt = to;
28480b57cec5SDimitry Andric     if (mode & generate_header)
28490b57cec5SDimitry Andric     {
28500b57cec5SDimitry Andric         if (to_end - to_nxt < 2)
28510b57cec5SDimitry Andric             return codecvt_base::partial;
28520b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFF);
28530b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFE);
28540b57cec5SDimitry Andric     }
28550b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
28560b57cec5SDimitry Andric     {
28570b57cec5SDimitry Andric         uint32_t wc = *frm_nxt;
28580b57cec5SDimitry Andric         if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
28590b57cec5SDimitry Andric             return codecvt_base::error;
28600b57cec5SDimitry Andric         if (wc < 0x010000)
28610b57cec5SDimitry Andric         {
28620b57cec5SDimitry Andric             if (to_end-to_nxt < 2)
28630b57cec5SDimitry Andric                 return codecvt_base::partial;
28640b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc);
28650b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(wc >> 8);
28660b57cec5SDimitry Andric         }
28670b57cec5SDimitry Andric         else
28680b57cec5SDimitry Andric         {
28690b57cec5SDimitry Andric             if (to_end-to_nxt < 4)
28700b57cec5SDimitry Andric                 return codecvt_base::partial;
28710b57cec5SDimitry Andric             uint16_t t = static_cast<uint16_t>(
28720b57cec5SDimitry Andric                     0xD800
28730b57cec5SDimitry Andric                   | ((((wc & 0x1F0000) >> 16) - 1) << 6)
28740b57cec5SDimitry Andric                   |   ((wc & 0x00FC00) >> 10));
28750b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t);
28760b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t >> 8);
28770b57cec5SDimitry Andric             t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
28780b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t);
28790b57cec5SDimitry Andric             *to_nxt++ = static_cast<uint8_t>(t >> 8);
28800b57cec5SDimitry Andric         }
28810b57cec5SDimitry Andric     }
28820b57cec5SDimitry Andric     return codecvt_base::ok;
28830b57cec5SDimitry Andric }
28840b57cec5SDimitry Andric 
28850b57cec5SDimitry Andric static
28860b57cec5SDimitry Andric codecvt_base::result
28870b57cec5SDimitry Andric utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
28880b57cec5SDimitry Andric                 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
28890b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
28900b57cec5SDimitry Andric {
28910b57cec5SDimitry Andric     frm_nxt = frm;
28920b57cec5SDimitry Andric     to_nxt = to;
28930b57cec5SDimitry Andric     if (mode & consume_header)
28940b57cec5SDimitry Andric     {
28950b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
28960b57cec5SDimitry Andric             frm_nxt += 2;
28970b57cec5SDimitry Andric     }
28980b57cec5SDimitry Andric     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
28990b57cec5SDimitry Andric     {
29000b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
29010b57cec5SDimitry Andric         if ((c1 & 0xFC00) == 0xDC00)
29020b57cec5SDimitry Andric             return codecvt_base::error;
29030b57cec5SDimitry Andric         if ((c1 & 0xFC00) != 0xD800)
29040b57cec5SDimitry Andric         {
29050b57cec5SDimitry Andric             if (c1 > Maxcode)
29060b57cec5SDimitry Andric                 return codecvt_base::error;
29070b57cec5SDimitry Andric             *to_nxt = static_cast<uint32_t>(c1);
29080b57cec5SDimitry Andric             frm_nxt += 2;
29090b57cec5SDimitry Andric         }
29100b57cec5SDimitry Andric         else
29110b57cec5SDimitry Andric         {
29120b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
29130b57cec5SDimitry Andric                 return codecvt_base::partial;
29140b57cec5SDimitry Andric             uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
29150b57cec5SDimitry Andric             if ((c2 & 0xFC00) != 0xDC00)
29160b57cec5SDimitry Andric                 return codecvt_base::error;
29170b57cec5SDimitry Andric             uint32_t t = static_cast<uint32_t>(
29180b57cec5SDimitry Andric                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
29190b57cec5SDimitry Andric                   |   ((c1 & 0x003F) << 10)
29200b57cec5SDimitry Andric                   |    (c2 & 0x03FF));
29210b57cec5SDimitry Andric             if (t > Maxcode)
29220b57cec5SDimitry Andric                 return codecvt_base::error;
29230b57cec5SDimitry Andric             *to_nxt = t;
29240b57cec5SDimitry Andric             frm_nxt += 4;
29250b57cec5SDimitry Andric         }
29260b57cec5SDimitry Andric     }
29270b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
29280b57cec5SDimitry Andric }
29290b57cec5SDimitry Andric 
29300b57cec5SDimitry Andric static
29310b57cec5SDimitry Andric int
29320b57cec5SDimitry Andric utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
29330b57cec5SDimitry Andric                        size_t mx, unsigned long Maxcode = 0x10FFFF,
29340b57cec5SDimitry Andric                        codecvt_mode mode = codecvt_mode(0))
29350b57cec5SDimitry Andric {
29360b57cec5SDimitry Andric     const uint8_t* frm_nxt = frm;
29370b57cec5SDimitry Andric     if (mode & consume_header)
29380b57cec5SDimitry Andric     {
29390b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
29400b57cec5SDimitry Andric             frm_nxt += 2;
29410b57cec5SDimitry Andric     }
29420b57cec5SDimitry Andric     for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
29430b57cec5SDimitry Andric     {
29440b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
29450b57cec5SDimitry Andric         if ((c1 & 0xFC00) == 0xDC00)
29460b57cec5SDimitry Andric             break;
29470b57cec5SDimitry Andric         if ((c1 & 0xFC00) != 0xD800)
29480b57cec5SDimitry Andric         {
29490b57cec5SDimitry Andric             if (c1 > Maxcode)
29500b57cec5SDimitry Andric                 break;
29510b57cec5SDimitry Andric             frm_nxt += 2;
29520b57cec5SDimitry Andric         }
29530b57cec5SDimitry Andric         else
29540b57cec5SDimitry Andric         {
29550b57cec5SDimitry Andric             if (frm_end-frm_nxt < 4)
29560b57cec5SDimitry Andric                 break;
29570b57cec5SDimitry Andric             uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
29580b57cec5SDimitry Andric             if ((c2 & 0xFC00) != 0xDC00)
29590b57cec5SDimitry Andric                 break;
29600b57cec5SDimitry Andric             uint32_t t = static_cast<uint32_t>(
29610b57cec5SDimitry Andric                     ((((c1 & 0x03C0) >> 6) + 1) << 16)
29620b57cec5SDimitry Andric                   |   ((c1 & 0x003F) << 10)
29630b57cec5SDimitry Andric                   |    (c2 & 0x03FF));
29640b57cec5SDimitry Andric             if (t > Maxcode)
29650b57cec5SDimitry Andric                 break;
29660b57cec5SDimitry Andric             frm_nxt += 4;
29670b57cec5SDimitry Andric         }
29680b57cec5SDimitry Andric     }
29690b57cec5SDimitry Andric     return static_cast<int>(frm_nxt - frm);
29700b57cec5SDimitry Andric }
29710b57cec5SDimitry Andric 
29720b57cec5SDimitry Andric static
29730b57cec5SDimitry Andric codecvt_base::result
29740b57cec5SDimitry Andric ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
29750b57cec5SDimitry Andric                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
29760b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
29770b57cec5SDimitry Andric {
29780b57cec5SDimitry Andric     frm_nxt = frm;
29790b57cec5SDimitry Andric     to_nxt = to;
29800b57cec5SDimitry Andric     if (mode & generate_header)
29810b57cec5SDimitry Andric     {
29820b57cec5SDimitry Andric         if (to_end-to_nxt < 2)
29830b57cec5SDimitry Andric             return codecvt_base::partial;
29840b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFE);
29850b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFF);
29860b57cec5SDimitry Andric     }
29870b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
29880b57cec5SDimitry Andric     {
29890b57cec5SDimitry Andric         uint16_t wc = *frm_nxt;
29900b57cec5SDimitry Andric         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
29910b57cec5SDimitry Andric             return codecvt_base::error;
29920b57cec5SDimitry Andric         if (to_end-to_nxt < 2)
29930b57cec5SDimitry Andric             return codecvt_base::partial;
29940b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(wc >> 8);
29950b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(wc);
29960b57cec5SDimitry Andric     }
29970b57cec5SDimitry Andric     return codecvt_base::ok;
29980b57cec5SDimitry Andric }
29990b57cec5SDimitry Andric 
30000b57cec5SDimitry Andric static
30010b57cec5SDimitry Andric codecvt_base::result
30020b57cec5SDimitry Andric utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
30030b57cec5SDimitry Andric                 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
30040b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
30050b57cec5SDimitry Andric {
30060b57cec5SDimitry Andric     frm_nxt = frm;
30070b57cec5SDimitry Andric     to_nxt = to;
30080b57cec5SDimitry Andric     if (mode & consume_header)
30090b57cec5SDimitry Andric     {
30100b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
30110b57cec5SDimitry Andric             frm_nxt += 2;
30120b57cec5SDimitry Andric     }
30130b57cec5SDimitry Andric     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
30140b57cec5SDimitry Andric     {
30150b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
30160b57cec5SDimitry Andric         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
30170b57cec5SDimitry Andric             return codecvt_base::error;
30180b57cec5SDimitry Andric         *to_nxt = c1;
30190b57cec5SDimitry Andric         frm_nxt += 2;
30200b57cec5SDimitry Andric     }
30210b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
30220b57cec5SDimitry Andric }
30230b57cec5SDimitry Andric 
30240b57cec5SDimitry Andric static
30250b57cec5SDimitry Andric int
30260b57cec5SDimitry Andric utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
30270b57cec5SDimitry Andric                        size_t mx, unsigned long Maxcode = 0x10FFFF,
30280b57cec5SDimitry Andric                        codecvt_mode mode = codecvt_mode(0))
30290b57cec5SDimitry Andric {
30300b57cec5SDimitry Andric     const uint8_t* frm_nxt = frm;
30310b57cec5SDimitry Andric     if (mode & consume_header)
30320b57cec5SDimitry Andric     {
30330b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
30340b57cec5SDimitry Andric             frm_nxt += 2;
30350b57cec5SDimitry Andric     }
30360b57cec5SDimitry Andric     for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
30370b57cec5SDimitry Andric     {
30380b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
30390b57cec5SDimitry Andric         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
30400b57cec5SDimitry Andric             break;
30410b57cec5SDimitry Andric         frm_nxt += 2;
30420b57cec5SDimitry Andric     }
30430b57cec5SDimitry Andric     return static_cast<int>(frm_nxt - frm);
30440b57cec5SDimitry Andric }
30450b57cec5SDimitry Andric 
30460b57cec5SDimitry Andric static
30470b57cec5SDimitry Andric codecvt_base::result
30480b57cec5SDimitry Andric ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
30490b57cec5SDimitry Andric                 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
30500b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
30510b57cec5SDimitry Andric {
30520b57cec5SDimitry Andric     frm_nxt = frm;
30530b57cec5SDimitry Andric     to_nxt = to;
30540b57cec5SDimitry Andric     if (mode & generate_header)
30550b57cec5SDimitry Andric     {
30560b57cec5SDimitry Andric         if (to_end-to_nxt < 2)
30570b57cec5SDimitry Andric             return codecvt_base::partial;
30580b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFF);
30590b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(0xFE);
30600b57cec5SDimitry Andric     }
30610b57cec5SDimitry Andric     for (; frm_nxt < frm_end; ++frm_nxt)
30620b57cec5SDimitry Andric     {
30630b57cec5SDimitry Andric         uint16_t wc = *frm_nxt;
30640b57cec5SDimitry Andric         if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
30650b57cec5SDimitry Andric             return codecvt_base::error;
30660b57cec5SDimitry Andric         if (to_end-to_nxt < 2)
30670b57cec5SDimitry Andric             return codecvt_base::partial;
30680b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(wc);
30690b57cec5SDimitry Andric         *to_nxt++ = static_cast<uint8_t>(wc >> 8);
30700b57cec5SDimitry Andric     }
30710b57cec5SDimitry Andric     return codecvt_base::ok;
30720b57cec5SDimitry Andric }
30730b57cec5SDimitry Andric 
30740b57cec5SDimitry Andric static
30750b57cec5SDimitry Andric codecvt_base::result
30760b57cec5SDimitry Andric utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
30770b57cec5SDimitry Andric                 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
30780b57cec5SDimitry Andric                 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
30790b57cec5SDimitry Andric {
30800b57cec5SDimitry Andric     frm_nxt = frm;
30810b57cec5SDimitry Andric     to_nxt = to;
30820b57cec5SDimitry Andric     if (mode & consume_header)
30830b57cec5SDimitry Andric     {
30840b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
30850b57cec5SDimitry Andric             frm_nxt += 2;
30860b57cec5SDimitry Andric     }
30870b57cec5SDimitry Andric     for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
30880b57cec5SDimitry Andric     {
30890b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
30900b57cec5SDimitry Andric         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
30910b57cec5SDimitry Andric             return codecvt_base::error;
30920b57cec5SDimitry Andric         *to_nxt = c1;
30930b57cec5SDimitry Andric         frm_nxt += 2;
30940b57cec5SDimitry Andric     }
30950b57cec5SDimitry Andric     return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
30960b57cec5SDimitry Andric }
30970b57cec5SDimitry Andric 
30980b57cec5SDimitry Andric static
30990b57cec5SDimitry Andric int
31000b57cec5SDimitry Andric utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
31010b57cec5SDimitry Andric                        size_t mx, unsigned long Maxcode = 0x10FFFF,
31020b57cec5SDimitry Andric                        codecvt_mode mode = codecvt_mode(0))
31030b57cec5SDimitry Andric {
31040b57cec5SDimitry Andric     const uint8_t* frm_nxt = frm;
31050b57cec5SDimitry Andric     frm_nxt = frm;
31060b57cec5SDimitry Andric     if (mode & consume_header)
31070b57cec5SDimitry Andric     {
31080b57cec5SDimitry Andric         if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
31090b57cec5SDimitry Andric             frm_nxt += 2;
31100b57cec5SDimitry Andric     }
31110b57cec5SDimitry Andric     for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
31120b57cec5SDimitry Andric     {
31130b57cec5SDimitry Andric         uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
31140b57cec5SDimitry Andric         if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
31150b57cec5SDimitry Andric             break;
31160b57cec5SDimitry Andric         frm_nxt += 2;
31170b57cec5SDimitry Andric     }
31180b57cec5SDimitry Andric     return static_cast<int>(frm_nxt - frm);
31190b57cec5SDimitry Andric }
31200b57cec5SDimitry Andric 
31210b57cec5SDimitry Andric // template <> class codecvt<char16_t, char, mbstate_t>
31220b57cec5SDimitry Andric 
31230b57cec5SDimitry Andric locale::id codecvt<char16_t, char, mbstate_t>::id;
31240b57cec5SDimitry Andric 
31250b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::~codecvt()
31260b57cec5SDimitry Andric {
31270b57cec5SDimitry Andric }
31280b57cec5SDimitry Andric 
31290b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::result
31300b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
31310b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
31320b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
31330b57cec5SDimitry Andric {
31340b57cec5SDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
31350b57cec5SDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
31360b57cec5SDimitry Andric     const uint16_t* _frm_nxt = _frm;
31370b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
31380b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
31390b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
31400b57cec5SDimitry Andric     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
31410b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
31420b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
31430b57cec5SDimitry Andric     return r;
31440b57cec5SDimitry Andric }
31450b57cec5SDimitry Andric 
31460b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::result
31470b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
31480b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
31490b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
31500b57cec5SDimitry Andric {
31510b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
31520b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
31530b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
31540b57cec5SDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
31550b57cec5SDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
31560b57cec5SDimitry Andric     uint16_t* _to_nxt = _to;
31570b57cec5SDimitry Andric     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
31580b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
31590b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
31600b57cec5SDimitry Andric     return r;
31610b57cec5SDimitry Andric }
31620b57cec5SDimitry Andric 
31630b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::result
31640b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
31650b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
31660b57cec5SDimitry Andric {
31670b57cec5SDimitry Andric     to_nxt = to;
31680b57cec5SDimitry Andric     return noconv;
31690b57cec5SDimitry Andric }
31700b57cec5SDimitry Andric 
31710b57cec5SDimitry Andric int
31720b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
31730b57cec5SDimitry Andric {
31740b57cec5SDimitry Andric     return 0;
31750b57cec5SDimitry Andric }
31760b57cec5SDimitry Andric 
31770b57cec5SDimitry Andric bool
31780b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
31790b57cec5SDimitry Andric {
31800b57cec5SDimitry Andric     return false;
31810b57cec5SDimitry Andric }
31820b57cec5SDimitry Andric 
31830b57cec5SDimitry Andric int
31840b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
31850b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
31860b57cec5SDimitry Andric {
31870b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
31880b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
31890b57cec5SDimitry Andric     return utf8_to_utf16_length(_frm, _frm_end, mx);
31900b57cec5SDimitry Andric }
31910b57cec5SDimitry Andric 
31920b57cec5SDimitry Andric int
31930b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
31940b57cec5SDimitry Andric {
31950b57cec5SDimitry Andric     return 4;
31960b57cec5SDimitry Andric }
31970b57cec5SDimitry Andric 
3198*e8d8bef9SDimitry Andric #ifndef _LIBCPP_NO_HAS_CHAR8_T
3199*e8d8bef9SDimitry Andric 
3200*e8d8bef9SDimitry Andric // template <> class codecvt<char16_t, char8_t, mbstate_t>
3201*e8d8bef9SDimitry Andric 
3202*e8d8bef9SDimitry Andric locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3203*e8d8bef9SDimitry Andric 
3204*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3205*e8d8bef9SDimitry Andric {
3206*e8d8bef9SDimitry Andric }
3207*e8d8bef9SDimitry Andric 
3208*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result
3209*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3210*e8d8bef9SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3211*e8d8bef9SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3212*e8d8bef9SDimitry Andric {
3213*e8d8bef9SDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3214*e8d8bef9SDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3215*e8d8bef9SDimitry Andric     const uint16_t* _frm_nxt = _frm;
3216*e8d8bef9SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3217*e8d8bef9SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3218*e8d8bef9SDimitry Andric     uint8_t* _to_nxt = _to;
3219*e8d8bef9SDimitry Andric     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3220*e8d8bef9SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
3221*e8d8bef9SDimitry Andric     to_nxt = to + (_to_nxt - _to);
3222*e8d8bef9SDimitry Andric     return r;
3223*e8d8bef9SDimitry Andric }
3224*e8d8bef9SDimitry Andric 
3225*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result
3226*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3227*e8d8bef9SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3228*e8d8bef9SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3229*e8d8bef9SDimitry Andric {
3230*e8d8bef9SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3231*e8d8bef9SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3232*e8d8bef9SDimitry Andric     const uint8_t* _frm_nxt = _frm;
3233*e8d8bef9SDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3234*e8d8bef9SDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3235*e8d8bef9SDimitry Andric     uint16_t* _to_nxt = _to;
3236*e8d8bef9SDimitry Andric     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3237*e8d8bef9SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
3238*e8d8bef9SDimitry Andric     to_nxt = to + (_to_nxt - _to);
3239*e8d8bef9SDimitry Andric     return r;
3240*e8d8bef9SDimitry Andric }
3241*e8d8bef9SDimitry Andric 
3242*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result
3243*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3244*e8d8bef9SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
3245*e8d8bef9SDimitry Andric {
3246*e8d8bef9SDimitry Andric     to_nxt = to;
3247*e8d8bef9SDimitry Andric     return noconv;
3248*e8d8bef9SDimitry Andric }
3249*e8d8bef9SDimitry Andric 
3250*e8d8bef9SDimitry Andric int
3251*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const  _NOEXCEPT
3252*e8d8bef9SDimitry Andric {
3253*e8d8bef9SDimitry Andric     return 0;
3254*e8d8bef9SDimitry Andric }
3255*e8d8bef9SDimitry Andric 
3256*e8d8bef9SDimitry Andric bool
3257*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3258*e8d8bef9SDimitry Andric {
3259*e8d8bef9SDimitry Andric     return false;
3260*e8d8bef9SDimitry Andric }
3261*e8d8bef9SDimitry Andric 
3262*e8d8bef9SDimitry Andric int
3263*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3264*e8d8bef9SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3265*e8d8bef9SDimitry Andric {
3266*e8d8bef9SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3267*e8d8bef9SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3268*e8d8bef9SDimitry Andric     return utf8_to_utf16_length(_frm, _frm_end, mx);
3269*e8d8bef9SDimitry Andric }
3270*e8d8bef9SDimitry Andric 
3271*e8d8bef9SDimitry Andric int
3272*e8d8bef9SDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const  _NOEXCEPT
3273*e8d8bef9SDimitry Andric {
3274*e8d8bef9SDimitry Andric     return 4;
3275*e8d8bef9SDimitry Andric }
3276*e8d8bef9SDimitry Andric 
3277*e8d8bef9SDimitry Andric #endif
3278*e8d8bef9SDimitry Andric 
32790b57cec5SDimitry Andric // template <> class codecvt<char32_t, char, mbstate_t>
32800b57cec5SDimitry Andric 
32810b57cec5SDimitry Andric locale::id codecvt<char32_t, char, mbstate_t>::id;
32820b57cec5SDimitry Andric 
32830b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::~codecvt()
32840b57cec5SDimitry Andric {
32850b57cec5SDimitry Andric }
32860b57cec5SDimitry Andric 
32870b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::result
32880b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
32890b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
32900b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
32910b57cec5SDimitry Andric {
32920b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
32930b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
32940b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
32950b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
32960b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
32970b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
32980b57cec5SDimitry Andric     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
32990b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
33000b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
33010b57cec5SDimitry Andric     return r;
33020b57cec5SDimitry Andric }
33030b57cec5SDimitry Andric 
33040b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::result
33050b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
33060b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
33070b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
33080b57cec5SDimitry Andric {
33090b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
33100b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
33110b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
33120b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
33130b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
33140b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
33150b57cec5SDimitry Andric     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
33160b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
33170b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
33180b57cec5SDimitry Andric     return r;
33190b57cec5SDimitry Andric }
33200b57cec5SDimitry Andric 
33210b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::result
33220b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
33230b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
33240b57cec5SDimitry Andric {
33250b57cec5SDimitry Andric     to_nxt = to;
33260b57cec5SDimitry Andric     return noconv;
33270b57cec5SDimitry Andric }
33280b57cec5SDimitry Andric 
33290b57cec5SDimitry Andric int
33300b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT
33310b57cec5SDimitry Andric {
33320b57cec5SDimitry Andric     return 0;
33330b57cec5SDimitry Andric }
33340b57cec5SDimitry Andric 
33350b57cec5SDimitry Andric bool
33360b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT
33370b57cec5SDimitry Andric {
33380b57cec5SDimitry Andric     return false;
33390b57cec5SDimitry Andric }
33400b57cec5SDimitry Andric 
33410b57cec5SDimitry Andric int
33420b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
33430b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
33440b57cec5SDimitry Andric {
33450b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
33460b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
33470b57cec5SDimitry Andric     return utf8_to_ucs4_length(_frm, _frm_end, mx);
33480b57cec5SDimitry Andric }
33490b57cec5SDimitry Andric 
33500b57cec5SDimitry Andric int
33510b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT
33520b57cec5SDimitry Andric {
33530b57cec5SDimitry Andric     return 4;
33540b57cec5SDimitry Andric }
33550b57cec5SDimitry Andric 
3356*e8d8bef9SDimitry Andric #ifndef _LIBCPP_NO_HAS_CHAR8_T
3357*e8d8bef9SDimitry Andric 
3358*e8d8bef9SDimitry Andric // template <> class codecvt<char32_t, char8_t, mbstate_t>
3359*e8d8bef9SDimitry Andric 
3360*e8d8bef9SDimitry Andric locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3361*e8d8bef9SDimitry Andric 
3362*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3363*e8d8bef9SDimitry Andric {
3364*e8d8bef9SDimitry Andric }
3365*e8d8bef9SDimitry Andric 
3366*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result
3367*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3368*e8d8bef9SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3369*e8d8bef9SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3370*e8d8bef9SDimitry Andric {
3371*e8d8bef9SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3372*e8d8bef9SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3373*e8d8bef9SDimitry Andric     const uint32_t* _frm_nxt = _frm;
3374*e8d8bef9SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3375*e8d8bef9SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3376*e8d8bef9SDimitry Andric     uint8_t* _to_nxt = _to;
3377*e8d8bef9SDimitry Andric     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3378*e8d8bef9SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
3379*e8d8bef9SDimitry Andric     to_nxt = to + (_to_nxt - _to);
3380*e8d8bef9SDimitry Andric     return r;
3381*e8d8bef9SDimitry Andric }
3382*e8d8bef9SDimitry Andric 
3383*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result
3384*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3385*e8d8bef9SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3386*e8d8bef9SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3387*e8d8bef9SDimitry Andric {
3388*e8d8bef9SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3389*e8d8bef9SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3390*e8d8bef9SDimitry Andric     const uint8_t* _frm_nxt = _frm;
3391*e8d8bef9SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3392*e8d8bef9SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3393*e8d8bef9SDimitry Andric     uint32_t* _to_nxt = _to;
3394*e8d8bef9SDimitry Andric     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3395*e8d8bef9SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
3396*e8d8bef9SDimitry Andric     to_nxt = to + (_to_nxt - _to);
3397*e8d8bef9SDimitry Andric     return r;
3398*e8d8bef9SDimitry Andric }
3399*e8d8bef9SDimitry Andric 
3400*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result
3401*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3402*e8d8bef9SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
3403*e8d8bef9SDimitry Andric {
3404*e8d8bef9SDimitry Andric     to_nxt = to;
3405*e8d8bef9SDimitry Andric     return noconv;
3406*e8d8bef9SDimitry Andric }
3407*e8d8bef9SDimitry Andric 
3408*e8d8bef9SDimitry Andric int
3409*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const  _NOEXCEPT
3410*e8d8bef9SDimitry Andric {
3411*e8d8bef9SDimitry Andric     return 0;
3412*e8d8bef9SDimitry Andric }
3413*e8d8bef9SDimitry Andric 
3414*e8d8bef9SDimitry Andric bool
3415*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const  _NOEXCEPT
3416*e8d8bef9SDimitry Andric {
3417*e8d8bef9SDimitry Andric     return false;
3418*e8d8bef9SDimitry Andric }
3419*e8d8bef9SDimitry Andric 
3420*e8d8bef9SDimitry Andric int
3421*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3422*e8d8bef9SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
3423*e8d8bef9SDimitry Andric {
3424*e8d8bef9SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3425*e8d8bef9SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3426*e8d8bef9SDimitry Andric     return utf8_to_ucs4_length(_frm, _frm_end, mx);
3427*e8d8bef9SDimitry Andric }
3428*e8d8bef9SDimitry Andric 
3429*e8d8bef9SDimitry Andric int
3430*e8d8bef9SDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const  _NOEXCEPT
3431*e8d8bef9SDimitry Andric {
3432*e8d8bef9SDimitry Andric     return 4;
3433*e8d8bef9SDimitry Andric }
3434*e8d8bef9SDimitry Andric 
3435*e8d8bef9SDimitry Andric #endif
3436*e8d8bef9SDimitry Andric 
34370b57cec5SDimitry Andric // __codecvt_utf8<wchar_t>
34380b57cec5SDimitry Andric 
34390b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::result
34400b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::do_out(state_type&,
34410b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
34420b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
34430b57cec5SDimitry Andric {
34440b57cec5SDimitry Andric #if defined(_LIBCPP_SHORT_WCHAR)
34450b57cec5SDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
34460b57cec5SDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
34470b57cec5SDimitry Andric     const uint16_t* _frm_nxt = _frm;
34480b57cec5SDimitry Andric #else
34490b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
34500b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
34510b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
34520b57cec5SDimitry Andric #endif
34530b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
34540b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
34550b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
34560b57cec5SDimitry Andric #if defined(_LIBCPP_SHORT_WCHAR)
34570b57cec5SDimitry Andric     result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
34580b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
34590b57cec5SDimitry Andric #else
34600b57cec5SDimitry Andric     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
34610b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
34620b57cec5SDimitry Andric #endif
34630b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
34640b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
34650b57cec5SDimitry Andric     return r;
34660b57cec5SDimitry Andric }
34670b57cec5SDimitry Andric 
34680b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::result
34690b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::do_in(state_type&,
34700b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
34710b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
34720b57cec5SDimitry Andric {
34730b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
34740b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
34750b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
34760b57cec5SDimitry Andric #if defined(_LIBCPP_SHORT_WCHAR)
34770b57cec5SDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
34780b57cec5SDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
34790b57cec5SDimitry Andric     uint16_t* _to_nxt = _to;
34800b57cec5SDimitry Andric     result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
34810b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
34820b57cec5SDimitry Andric #else
34830b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
34840b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
34850b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
34860b57cec5SDimitry Andric     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
34870b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
34880b57cec5SDimitry Andric #endif
34890b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
34900b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
34910b57cec5SDimitry Andric     return r;
34920b57cec5SDimitry Andric }
34930b57cec5SDimitry Andric 
34940b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::result
34950b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::do_unshift(state_type&,
34960b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
34970b57cec5SDimitry Andric {
34980b57cec5SDimitry Andric     to_nxt = to;
34990b57cec5SDimitry Andric     return noconv;
35000b57cec5SDimitry Andric }
35010b57cec5SDimitry Andric 
35020b57cec5SDimitry Andric int
35030b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::do_encoding() const  _NOEXCEPT
35040b57cec5SDimitry Andric {
35050b57cec5SDimitry Andric     return 0;
35060b57cec5SDimitry Andric }
35070b57cec5SDimitry Andric 
35080b57cec5SDimitry Andric bool
35090b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::do_always_noconv() const  _NOEXCEPT
35100b57cec5SDimitry Andric {
35110b57cec5SDimitry Andric     return false;
35120b57cec5SDimitry Andric }
35130b57cec5SDimitry Andric 
35140b57cec5SDimitry Andric int
35150b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::do_length(state_type&,
35160b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
35170b57cec5SDimitry Andric {
35180b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
35190b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
35200b57cec5SDimitry Andric     return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
35210b57cec5SDimitry Andric }
35220b57cec5SDimitry Andric 
35230b57cec5SDimitry Andric int
35240b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::do_max_length() const  _NOEXCEPT
35250b57cec5SDimitry Andric {
35260b57cec5SDimitry Andric     if (_Mode_ & consume_header)
35270b57cec5SDimitry Andric         return 7;
35280b57cec5SDimitry Andric     return 4;
35290b57cec5SDimitry Andric }
35300b57cec5SDimitry Andric 
35310b57cec5SDimitry Andric // __codecvt_utf8<char16_t>
35320b57cec5SDimitry Andric 
35330b57cec5SDimitry Andric __codecvt_utf8<char16_t>::result
35340b57cec5SDimitry Andric __codecvt_utf8<char16_t>::do_out(state_type&,
35350b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
35360b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
35370b57cec5SDimitry Andric {
35380b57cec5SDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
35390b57cec5SDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
35400b57cec5SDimitry Andric     const uint16_t* _frm_nxt = _frm;
35410b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
35420b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
35430b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
35440b57cec5SDimitry Andric     result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
35450b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
35460b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
35470b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
35480b57cec5SDimitry Andric     return r;
35490b57cec5SDimitry Andric }
35500b57cec5SDimitry Andric 
35510b57cec5SDimitry Andric __codecvt_utf8<char16_t>::result
35520b57cec5SDimitry Andric __codecvt_utf8<char16_t>::do_in(state_type&,
35530b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
35540b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
35550b57cec5SDimitry Andric {
35560b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
35570b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
35580b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
35590b57cec5SDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
35600b57cec5SDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
35610b57cec5SDimitry Andric     uint16_t* _to_nxt = _to;
35620b57cec5SDimitry Andric     result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
35630b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
35640b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
35650b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
35660b57cec5SDimitry Andric     return r;
35670b57cec5SDimitry Andric }
35680b57cec5SDimitry Andric 
35690b57cec5SDimitry Andric __codecvt_utf8<char16_t>::result
35700b57cec5SDimitry Andric __codecvt_utf8<char16_t>::do_unshift(state_type&,
35710b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
35720b57cec5SDimitry Andric {
35730b57cec5SDimitry Andric     to_nxt = to;
35740b57cec5SDimitry Andric     return noconv;
35750b57cec5SDimitry Andric }
35760b57cec5SDimitry Andric 
35770b57cec5SDimitry Andric int
35780b57cec5SDimitry Andric __codecvt_utf8<char16_t>::do_encoding() const  _NOEXCEPT
35790b57cec5SDimitry Andric {
35800b57cec5SDimitry Andric     return 0;
35810b57cec5SDimitry Andric }
35820b57cec5SDimitry Andric 
35830b57cec5SDimitry Andric bool
35840b57cec5SDimitry Andric __codecvt_utf8<char16_t>::do_always_noconv() const  _NOEXCEPT
35850b57cec5SDimitry Andric {
35860b57cec5SDimitry Andric     return false;
35870b57cec5SDimitry Andric }
35880b57cec5SDimitry Andric 
35890b57cec5SDimitry Andric int
35900b57cec5SDimitry Andric __codecvt_utf8<char16_t>::do_length(state_type&,
35910b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
35920b57cec5SDimitry Andric {
35930b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
35940b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
35950b57cec5SDimitry Andric     return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
35960b57cec5SDimitry Andric }
35970b57cec5SDimitry Andric 
35980b57cec5SDimitry Andric int
35990b57cec5SDimitry Andric __codecvt_utf8<char16_t>::do_max_length() const  _NOEXCEPT
36000b57cec5SDimitry Andric {
36010b57cec5SDimitry Andric     if (_Mode_ & consume_header)
36020b57cec5SDimitry Andric         return 6;
36030b57cec5SDimitry Andric     return 3;
36040b57cec5SDimitry Andric }
36050b57cec5SDimitry Andric 
36060b57cec5SDimitry Andric // __codecvt_utf8<char32_t>
36070b57cec5SDimitry Andric 
36080b57cec5SDimitry Andric __codecvt_utf8<char32_t>::result
36090b57cec5SDimitry Andric __codecvt_utf8<char32_t>::do_out(state_type&,
36100b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
36110b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
36120b57cec5SDimitry Andric {
36130b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
36140b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
36150b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
36160b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
36170b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
36180b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
36190b57cec5SDimitry Andric     result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
36200b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
36210b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
36220b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
36230b57cec5SDimitry Andric     return r;
36240b57cec5SDimitry Andric }
36250b57cec5SDimitry Andric 
36260b57cec5SDimitry Andric __codecvt_utf8<char32_t>::result
36270b57cec5SDimitry Andric __codecvt_utf8<char32_t>::do_in(state_type&,
36280b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
36290b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
36300b57cec5SDimitry Andric {
36310b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
36320b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
36330b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
36340b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
36350b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
36360b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
36370b57cec5SDimitry Andric     result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
36380b57cec5SDimitry Andric                             _Maxcode_, _Mode_);
36390b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
36400b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
36410b57cec5SDimitry Andric     return r;
36420b57cec5SDimitry Andric }
36430b57cec5SDimitry Andric 
36440b57cec5SDimitry Andric __codecvt_utf8<char32_t>::result
36450b57cec5SDimitry Andric __codecvt_utf8<char32_t>::do_unshift(state_type&,
36460b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
36470b57cec5SDimitry Andric {
36480b57cec5SDimitry Andric     to_nxt = to;
36490b57cec5SDimitry Andric     return noconv;
36500b57cec5SDimitry Andric }
36510b57cec5SDimitry Andric 
36520b57cec5SDimitry Andric int
36530b57cec5SDimitry Andric __codecvt_utf8<char32_t>::do_encoding() const  _NOEXCEPT
36540b57cec5SDimitry Andric {
36550b57cec5SDimitry Andric     return 0;
36560b57cec5SDimitry Andric }
36570b57cec5SDimitry Andric 
36580b57cec5SDimitry Andric bool
36590b57cec5SDimitry Andric __codecvt_utf8<char32_t>::do_always_noconv() const  _NOEXCEPT
36600b57cec5SDimitry Andric {
36610b57cec5SDimitry Andric     return false;
36620b57cec5SDimitry Andric }
36630b57cec5SDimitry Andric 
36640b57cec5SDimitry Andric int
36650b57cec5SDimitry Andric __codecvt_utf8<char32_t>::do_length(state_type&,
36660b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
36670b57cec5SDimitry Andric {
36680b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
36690b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
36700b57cec5SDimitry Andric     return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
36710b57cec5SDimitry Andric }
36720b57cec5SDimitry Andric 
36730b57cec5SDimitry Andric int
36740b57cec5SDimitry Andric __codecvt_utf8<char32_t>::do_max_length() const  _NOEXCEPT
36750b57cec5SDimitry Andric {
36760b57cec5SDimitry Andric     if (_Mode_ & consume_header)
36770b57cec5SDimitry Andric         return 7;
36780b57cec5SDimitry Andric     return 4;
36790b57cec5SDimitry Andric }
36800b57cec5SDimitry Andric 
36810b57cec5SDimitry Andric // __codecvt_utf16<wchar_t, false>
36820b57cec5SDimitry Andric 
36830b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::result
36840b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::do_out(state_type&,
36850b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
36860b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
36870b57cec5SDimitry Andric {
36880b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
36890b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
36900b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
36910b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
36920b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
36930b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
36940b57cec5SDimitry Andric     result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
36950b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
36960b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
36970b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
36980b57cec5SDimitry Andric     return r;
36990b57cec5SDimitry Andric }
37000b57cec5SDimitry Andric 
37010b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::result
37020b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::do_in(state_type&,
37030b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
37040b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
37050b57cec5SDimitry Andric {
37060b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
37070b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
37080b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
37090b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
37100b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
37110b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
37120b57cec5SDimitry Andric     result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
37130b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
37140b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
37150b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
37160b57cec5SDimitry Andric     return r;
37170b57cec5SDimitry Andric }
37180b57cec5SDimitry Andric 
37190b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::result
37200b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
37210b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
37220b57cec5SDimitry Andric {
37230b57cec5SDimitry Andric     to_nxt = to;
37240b57cec5SDimitry Andric     return noconv;
37250b57cec5SDimitry Andric }
37260b57cec5SDimitry Andric 
37270b57cec5SDimitry Andric int
37280b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::do_encoding() const  _NOEXCEPT
37290b57cec5SDimitry Andric {
37300b57cec5SDimitry Andric     return 0;
37310b57cec5SDimitry Andric }
37320b57cec5SDimitry Andric 
37330b57cec5SDimitry Andric bool
37340b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::do_always_noconv() const  _NOEXCEPT
37350b57cec5SDimitry Andric {
37360b57cec5SDimitry Andric     return false;
37370b57cec5SDimitry Andric }
37380b57cec5SDimitry Andric 
37390b57cec5SDimitry Andric int
37400b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::do_length(state_type&,
37410b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
37420b57cec5SDimitry Andric {
37430b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
37440b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
37450b57cec5SDimitry Andric     return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
37460b57cec5SDimitry Andric }
37470b57cec5SDimitry Andric 
37480b57cec5SDimitry Andric int
37490b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::do_max_length() const  _NOEXCEPT
37500b57cec5SDimitry Andric {
37510b57cec5SDimitry Andric     if (_Mode_ & consume_header)
37520b57cec5SDimitry Andric         return 6;
37530b57cec5SDimitry Andric     return 4;
37540b57cec5SDimitry Andric }
37550b57cec5SDimitry Andric 
37560b57cec5SDimitry Andric // __codecvt_utf16<wchar_t, true>
37570b57cec5SDimitry Andric 
37580b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::result
37590b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::do_out(state_type&,
37600b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
37610b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
37620b57cec5SDimitry Andric {
37630b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
37640b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
37650b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
37660b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
37670b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
37680b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
37690b57cec5SDimitry Andric     result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
37700b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
37710b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
37720b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
37730b57cec5SDimitry Andric     return r;
37740b57cec5SDimitry Andric }
37750b57cec5SDimitry Andric 
37760b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::result
37770b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::do_in(state_type&,
37780b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
37790b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
37800b57cec5SDimitry Andric {
37810b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
37820b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
37830b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
37840b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
37850b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
37860b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
37870b57cec5SDimitry Andric     result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
37880b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
37890b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
37900b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
37910b57cec5SDimitry Andric     return r;
37920b57cec5SDimitry Andric }
37930b57cec5SDimitry Andric 
37940b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::result
37950b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
37960b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
37970b57cec5SDimitry Andric {
37980b57cec5SDimitry Andric     to_nxt = to;
37990b57cec5SDimitry Andric     return noconv;
38000b57cec5SDimitry Andric }
38010b57cec5SDimitry Andric 
38020b57cec5SDimitry Andric int
38030b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::do_encoding() const  _NOEXCEPT
38040b57cec5SDimitry Andric {
38050b57cec5SDimitry Andric     return 0;
38060b57cec5SDimitry Andric }
38070b57cec5SDimitry Andric 
38080b57cec5SDimitry Andric bool
38090b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::do_always_noconv() const  _NOEXCEPT
38100b57cec5SDimitry Andric {
38110b57cec5SDimitry Andric     return false;
38120b57cec5SDimitry Andric }
38130b57cec5SDimitry Andric 
38140b57cec5SDimitry Andric int
38150b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::do_length(state_type&,
38160b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
38170b57cec5SDimitry Andric {
38180b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
38190b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
38200b57cec5SDimitry Andric     return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
38210b57cec5SDimitry Andric }
38220b57cec5SDimitry Andric 
38230b57cec5SDimitry Andric int
38240b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::do_max_length() const  _NOEXCEPT
38250b57cec5SDimitry Andric {
38260b57cec5SDimitry Andric     if (_Mode_ & consume_header)
38270b57cec5SDimitry Andric         return 6;
38280b57cec5SDimitry Andric     return 4;
38290b57cec5SDimitry Andric }
38300b57cec5SDimitry Andric 
38310b57cec5SDimitry Andric // __codecvt_utf16<char16_t, false>
38320b57cec5SDimitry Andric 
38330b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::result
38340b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::do_out(state_type&,
38350b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
38360b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
38370b57cec5SDimitry Andric {
38380b57cec5SDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
38390b57cec5SDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
38400b57cec5SDimitry Andric     const uint16_t* _frm_nxt = _frm;
38410b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
38420b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
38430b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
38440b57cec5SDimitry Andric     result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
38450b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
38460b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
38470b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
38480b57cec5SDimitry Andric     return r;
38490b57cec5SDimitry Andric }
38500b57cec5SDimitry Andric 
38510b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::result
38520b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::do_in(state_type&,
38530b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
38540b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
38550b57cec5SDimitry Andric {
38560b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
38570b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
38580b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
38590b57cec5SDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
38600b57cec5SDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
38610b57cec5SDimitry Andric     uint16_t* _to_nxt = _to;
38620b57cec5SDimitry Andric     result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
38630b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
38640b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
38650b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
38660b57cec5SDimitry Andric     return r;
38670b57cec5SDimitry Andric }
38680b57cec5SDimitry Andric 
38690b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::result
38700b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::do_unshift(state_type&,
38710b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
38720b57cec5SDimitry Andric {
38730b57cec5SDimitry Andric     to_nxt = to;
38740b57cec5SDimitry Andric     return noconv;
38750b57cec5SDimitry Andric }
38760b57cec5SDimitry Andric 
38770b57cec5SDimitry Andric int
38780b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::do_encoding() const  _NOEXCEPT
38790b57cec5SDimitry Andric {
38800b57cec5SDimitry Andric     return 0;
38810b57cec5SDimitry Andric }
38820b57cec5SDimitry Andric 
38830b57cec5SDimitry Andric bool
38840b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::do_always_noconv() const  _NOEXCEPT
38850b57cec5SDimitry Andric {
38860b57cec5SDimitry Andric     return false;
38870b57cec5SDimitry Andric }
38880b57cec5SDimitry Andric 
38890b57cec5SDimitry Andric int
38900b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::do_length(state_type&,
38910b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
38920b57cec5SDimitry Andric {
38930b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
38940b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
38950b57cec5SDimitry Andric     return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
38960b57cec5SDimitry Andric }
38970b57cec5SDimitry Andric 
38980b57cec5SDimitry Andric int
38990b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::do_max_length() const  _NOEXCEPT
39000b57cec5SDimitry Andric {
39010b57cec5SDimitry Andric     if (_Mode_ & consume_header)
39020b57cec5SDimitry Andric         return 4;
39030b57cec5SDimitry Andric     return 2;
39040b57cec5SDimitry Andric }
39050b57cec5SDimitry Andric 
39060b57cec5SDimitry Andric // __codecvt_utf16<char16_t, true>
39070b57cec5SDimitry Andric 
39080b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::result
39090b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::do_out(state_type&,
39100b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
39110b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
39120b57cec5SDimitry Andric {
39130b57cec5SDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
39140b57cec5SDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
39150b57cec5SDimitry Andric     const uint16_t* _frm_nxt = _frm;
39160b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
39170b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
39180b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
39190b57cec5SDimitry Andric     result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
39200b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
39210b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
39220b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
39230b57cec5SDimitry Andric     return r;
39240b57cec5SDimitry Andric }
39250b57cec5SDimitry Andric 
39260b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::result
39270b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::do_in(state_type&,
39280b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
39290b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
39300b57cec5SDimitry Andric {
39310b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
39320b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
39330b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
39340b57cec5SDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
39350b57cec5SDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
39360b57cec5SDimitry Andric     uint16_t* _to_nxt = _to;
39370b57cec5SDimitry Andric     result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
39380b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
39390b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
39400b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
39410b57cec5SDimitry Andric     return r;
39420b57cec5SDimitry Andric }
39430b57cec5SDimitry Andric 
39440b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::result
39450b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::do_unshift(state_type&,
39460b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
39470b57cec5SDimitry Andric {
39480b57cec5SDimitry Andric     to_nxt = to;
39490b57cec5SDimitry Andric     return noconv;
39500b57cec5SDimitry Andric }
39510b57cec5SDimitry Andric 
39520b57cec5SDimitry Andric int
39530b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::do_encoding() const  _NOEXCEPT
39540b57cec5SDimitry Andric {
39550b57cec5SDimitry Andric     return 0;
39560b57cec5SDimitry Andric }
39570b57cec5SDimitry Andric 
39580b57cec5SDimitry Andric bool
39590b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::do_always_noconv() const  _NOEXCEPT
39600b57cec5SDimitry Andric {
39610b57cec5SDimitry Andric     return false;
39620b57cec5SDimitry Andric }
39630b57cec5SDimitry Andric 
39640b57cec5SDimitry Andric int
39650b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::do_length(state_type&,
39660b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
39670b57cec5SDimitry Andric {
39680b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
39690b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
39700b57cec5SDimitry Andric     return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
39710b57cec5SDimitry Andric }
39720b57cec5SDimitry Andric 
39730b57cec5SDimitry Andric int
39740b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::do_max_length() const  _NOEXCEPT
39750b57cec5SDimitry Andric {
39760b57cec5SDimitry Andric     if (_Mode_ & consume_header)
39770b57cec5SDimitry Andric         return 4;
39780b57cec5SDimitry Andric     return 2;
39790b57cec5SDimitry Andric }
39800b57cec5SDimitry Andric 
39810b57cec5SDimitry Andric // __codecvt_utf16<char32_t, false>
39820b57cec5SDimitry Andric 
39830b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::result
39840b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::do_out(state_type&,
39850b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
39860b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
39870b57cec5SDimitry Andric {
39880b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
39890b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
39900b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
39910b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
39920b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
39930b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
39940b57cec5SDimitry Andric     result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
39950b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
39960b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
39970b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
39980b57cec5SDimitry Andric     return r;
39990b57cec5SDimitry Andric }
40000b57cec5SDimitry Andric 
40010b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::result
40020b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::do_in(state_type&,
40030b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
40040b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
40050b57cec5SDimitry Andric {
40060b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
40070b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
40080b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
40090b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
40100b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
40110b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
40120b57cec5SDimitry Andric     result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
40130b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
40140b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
40150b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
40160b57cec5SDimitry Andric     return r;
40170b57cec5SDimitry Andric }
40180b57cec5SDimitry Andric 
40190b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::result
40200b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::do_unshift(state_type&,
40210b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
40220b57cec5SDimitry Andric {
40230b57cec5SDimitry Andric     to_nxt = to;
40240b57cec5SDimitry Andric     return noconv;
40250b57cec5SDimitry Andric }
40260b57cec5SDimitry Andric 
40270b57cec5SDimitry Andric int
40280b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::do_encoding() const  _NOEXCEPT
40290b57cec5SDimitry Andric {
40300b57cec5SDimitry Andric     return 0;
40310b57cec5SDimitry Andric }
40320b57cec5SDimitry Andric 
40330b57cec5SDimitry Andric bool
40340b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::do_always_noconv() const  _NOEXCEPT
40350b57cec5SDimitry Andric {
40360b57cec5SDimitry Andric     return false;
40370b57cec5SDimitry Andric }
40380b57cec5SDimitry Andric 
40390b57cec5SDimitry Andric int
40400b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::do_length(state_type&,
40410b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
40420b57cec5SDimitry Andric {
40430b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
40440b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
40450b57cec5SDimitry Andric     return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
40460b57cec5SDimitry Andric }
40470b57cec5SDimitry Andric 
40480b57cec5SDimitry Andric int
40490b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::do_max_length() const  _NOEXCEPT
40500b57cec5SDimitry Andric {
40510b57cec5SDimitry Andric     if (_Mode_ & consume_header)
40520b57cec5SDimitry Andric         return 6;
40530b57cec5SDimitry Andric     return 4;
40540b57cec5SDimitry Andric }
40550b57cec5SDimitry Andric 
40560b57cec5SDimitry Andric // __codecvt_utf16<char32_t, true>
40570b57cec5SDimitry Andric 
40580b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::result
40590b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::do_out(state_type&,
40600b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
40610b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
40620b57cec5SDimitry Andric {
40630b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
40640b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
40650b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
40660b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
40670b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
40680b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
40690b57cec5SDimitry Andric     result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
40700b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
40710b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
40720b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
40730b57cec5SDimitry Andric     return r;
40740b57cec5SDimitry Andric }
40750b57cec5SDimitry Andric 
40760b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::result
40770b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::do_in(state_type&,
40780b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
40790b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
40800b57cec5SDimitry Andric {
40810b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
40820b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
40830b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
40840b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
40850b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
40860b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
40870b57cec5SDimitry Andric     result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
40880b57cec5SDimitry Andric                                _Maxcode_, _Mode_);
40890b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
40900b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
40910b57cec5SDimitry Andric     return r;
40920b57cec5SDimitry Andric }
40930b57cec5SDimitry Andric 
40940b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::result
40950b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::do_unshift(state_type&,
40960b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
40970b57cec5SDimitry Andric {
40980b57cec5SDimitry Andric     to_nxt = to;
40990b57cec5SDimitry Andric     return noconv;
41000b57cec5SDimitry Andric }
41010b57cec5SDimitry Andric 
41020b57cec5SDimitry Andric int
41030b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::do_encoding() const  _NOEXCEPT
41040b57cec5SDimitry Andric {
41050b57cec5SDimitry Andric     return 0;
41060b57cec5SDimitry Andric }
41070b57cec5SDimitry Andric 
41080b57cec5SDimitry Andric bool
41090b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::do_always_noconv() const  _NOEXCEPT
41100b57cec5SDimitry Andric {
41110b57cec5SDimitry Andric     return false;
41120b57cec5SDimitry Andric }
41130b57cec5SDimitry Andric 
41140b57cec5SDimitry Andric int
41150b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::do_length(state_type&,
41160b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
41170b57cec5SDimitry Andric {
41180b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
41190b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
41200b57cec5SDimitry Andric     return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
41210b57cec5SDimitry Andric }
41220b57cec5SDimitry Andric 
41230b57cec5SDimitry Andric int
41240b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::do_max_length() const  _NOEXCEPT
41250b57cec5SDimitry Andric {
41260b57cec5SDimitry Andric     if (_Mode_ & consume_header)
41270b57cec5SDimitry Andric         return 6;
41280b57cec5SDimitry Andric     return 4;
41290b57cec5SDimitry Andric }
41300b57cec5SDimitry Andric 
41310b57cec5SDimitry Andric // __codecvt_utf8_utf16<wchar_t>
41320b57cec5SDimitry Andric 
41330b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::result
41340b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
41350b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
41360b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
41370b57cec5SDimitry Andric {
41380b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
41390b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
41400b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
41410b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
41420b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
41430b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
41440b57cec5SDimitry Andric     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
41450b57cec5SDimitry Andric                              _Maxcode_, _Mode_);
41460b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
41470b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
41480b57cec5SDimitry Andric     return r;
41490b57cec5SDimitry Andric }
41500b57cec5SDimitry Andric 
41510b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::result
41520b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
41530b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
41540b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
41550b57cec5SDimitry Andric {
41560b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
41570b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
41580b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
41590b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
41600b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
41610b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
41620b57cec5SDimitry Andric     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
41630b57cec5SDimitry Andric                              _Maxcode_, _Mode_);
41640b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
41650b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
41660b57cec5SDimitry Andric     return r;
41670b57cec5SDimitry Andric }
41680b57cec5SDimitry Andric 
41690b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::result
41700b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
41710b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
41720b57cec5SDimitry Andric {
41730b57cec5SDimitry Andric     to_nxt = to;
41740b57cec5SDimitry Andric     return noconv;
41750b57cec5SDimitry Andric }
41760b57cec5SDimitry Andric 
41770b57cec5SDimitry Andric int
41780b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_encoding() const  _NOEXCEPT
41790b57cec5SDimitry Andric {
41800b57cec5SDimitry Andric     return 0;
41810b57cec5SDimitry Andric }
41820b57cec5SDimitry Andric 
41830b57cec5SDimitry Andric bool
41840b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const  _NOEXCEPT
41850b57cec5SDimitry Andric {
41860b57cec5SDimitry Andric     return false;
41870b57cec5SDimitry Andric }
41880b57cec5SDimitry Andric 
41890b57cec5SDimitry Andric int
41900b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
41910b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
41920b57cec5SDimitry Andric {
41930b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
41940b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
41950b57cec5SDimitry Andric     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
41960b57cec5SDimitry Andric }
41970b57cec5SDimitry Andric 
41980b57cec5SDimitry Andric int
41990b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_max_length() const  _NOEXCEPT
42000b57cec5SDimitry Andric {
42010b57cec5SDimitry Andric     if (_Mode_ & consume_header)
42020b57cec5SDimitry Andric         return 7;
42030b57cec5SDimitry Andric     return 4;
42040b57cec5SDimitry Andric }
42050b57cec5SDimitry Andric 
42060b57cec5SDimitry Andric // __codecvt_utf8_utf16<char16_t>
42070b57cec5SDimitry Andric 
42080b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::result
42090b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::do_out(state_type&,
42100b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
42110b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
42120b57cec5SDimitry Andric {
42130b57cec5SDimitry Andric     const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
42140b57cec5SDimitry Andric     const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
42150b57cec5SDimitry Andric     const uint16_t* _frm_nxt = _frm;
42160b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
42170b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
42180b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
42190b57cec5SDimitry Andric     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
42200b57cec5SDimitry Andric                              _Maxcode_, _Mode_);
42210b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
42220b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
42230b57cec5SDimitry Andric     return r;
42240b57cec5SDimitry Andric }
42250b57cec5SDimitry Andric 
42260b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::result
42270b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::do_in(state_type&,
42280b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
42290b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
42300b57cec5SDimitry Andric {
42310b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
42320b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
42330b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
42340b57cec5SDimitry Andric     uint16_t* _to = reinterpret_cast<uint16_t*>(to);
42350b57cec5SDimitry Andric     uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
42360b57cec5SDimitry Andric     uint16_t* _to_nxt = _to;
42370b57cec5SDimitry Andric     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
42380b57cec5SDimitry Andric                              _Maxcode_, _Mode_);
42390b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
42400b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
42410b57cec5SDimitry Andric     return r;
42420b57cec5SDimitry Andric }
42430b57cec5SDimitry Andric 
42440b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::result
42450b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
42460b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
42470b57cec5SDimitry Andric {
42480b57cec5SDimitry Andric     to_nxt = to;
42490b57cec5SDimitry Andric     return noconv;
42500b57cec5SDimitry Andric }
42510b57cec5SDimitry Andric 
42520b57cec5SDimitry Andric int
42530b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::do_encoding() const  _NOEXCEPT
42540b57cec5SDimitry Andric {
42550b57cec5SDimitry Andric     return 0;
42560b57cec5SDimitry Andric }
42570b57cec5SDimitry Andric 
42580b57cec5SDimitry Andric bool
42590b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::do_always_noconv() const  _NOEXCEPT
42600b57cec5SDimitry Andric {
42610b57cec5SDimitry Andric     return false;
42620b57cec5SDimitry Andric }
42630b57cec5SDimitry Andric 
42640b57cec5SDimitry Andric int
42650b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::do_length(state_type&,
42660b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
42670b57cec5SDimitry Andric {
42680b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
42690b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
42700b57cec5SDimitry Andric     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
42710b57cec5SDimitry Andric }
42720b57cec5SDimitry Andric 
42730b57cec5SDimitry Andric int
42740b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::do_max_length() const  _NOEXCEPT
42750b57cec5SDimitry Andric {
42760b57cec5SDimitry Andric     if (_Mode_ & consume_header)
42770b57cec5SDimitry Andric         return 7;
42780b57cec5SDimitry Andric     return 4;
42790b57cec5SDimitry Andric }
42800b57cec5SDimitry Andric 
42810b57cec5SDimitry Andric // __codecvt_utf8_utf16<char32_t>
42820b57cec5SDimitry Andric 
42830b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::result
42840b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::do_out(state_type&,
42850b57cec5SDimitry Andric     const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
42860b57cec5SDimitry Andric     extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
42870b57cec5SDimitry Andric {
42880b57cec5SDimitry Andric     const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
42890b57cec5SDimitry Andric     const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
42900b57cec5SDimitry Andric     const uint32_t* _frm_nxt = _frm;
42910b57cec5SDimitry Andric     uint8_t* _to = reinterpret_cast<uint8_t*>(to);
42920b57cec5SDimitry Andric     uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
42930b57cec5SDimitry Andric     uint8_t* _to_nxt = _to;
42940b57cec5SDimitry Andric     result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
42950b57cec5SDimitry Andric                              _Maxcode_, _Mode_);
42960b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
42970b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
42980b57cec5SDimitry Andric     return r;
42990b57cec5SDimitry Andric }
43000b57cec5SDimitry Andric 
43010b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::result
43020b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::do_in(state_type&,
43030b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
43040b57cec5SDimitry Andric     intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
43050b57cec5SDimitry Andric {
43060b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
43070b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
43080b57cec5SDimitry Andric     const uint8_t* _frm_nxt = _frm;
43090b57cec5SDimitry Andric     uint32_t* _to = reinterpret_cast<uint32_t*>(to);
43100b57cec5SDimitry Andric     uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
43110b57cec5SDimitry Andric     uint32_t* _to_nxt = _to;
43120b57cec5SDimitry Andric     result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
43130b57cec5SDimitry Andric                              _Maxcode_, _Mode_);
43140b57cec5SDimitry Andric     frm_nxt = frm + (_frm_nxt - _frm);
43150b57cec5SDimitry Andric     to_nxt = to + (_to_nxt - _to);
43160b57cec5SDimitry Andric     return r;
43170b57cec5SDimitry Andric }
43180b57cec5SDimitry Andric 
43190b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::result
43200b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
43210b57cec5SDimitry Andric     extern_type* to, extern_type*, extern_type*& to_nxt) const
43220b57cec5SDimitry Andric {
43230b57cec5SDimitry Andric     to_nxt = to;
43240b57cec5SDimitry Andric     return noconv;
43250b57cec5SDimitry Andric }
43260b57cec5SDimitry Andric 
43270b57cec5SDimitry Andric int
43280b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::do_encoding() const  _NOEXCEPT
43290b57cec5SDimitry Andric {
43300b57cec5SDimitry Andric     return 0;
43310b57cec5SDimitry Andric }
43320b57cec5SDimitry Andric 
43330b57cec5SDimitry Andric bool
43340b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::do_always_noconv() const  _NOEXCEPT
43350b57cec5SDimitry Andric {
43360b57cec5SDimitry Andric     return false;
43370b57cec5SDimitry Andric }
43380b57cec5SDimitry Andric 
43390b57cec5SDimitry Andric int
43400b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::do_length(state_type&,
43410b57cec5SDimitry Andric     const extern_type* frm, const extern_type* frm_end, size_t mx) const
43420b57cec5SDimitry Andric {
43430b57cec5SDimitry Andric     const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
43440b57cec5SDimitry Andric     const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
43450b57cec5SDimitry Andric     return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
43460b57cec5SDimitry Andric }
43470b57cec5SDimitry Andric 
43480b57cec5SDimitry Andric int
43490b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::do_max_length() const  _NOEXCEPT
43500b57cec5SDimitry Andric {
43510b57cec5SDimitry Andric     if (_Mode_ & consume_header)
43520b57cec5SDimitry Andric         return 7;
43530b57cec5SDimitry Andric     return 4;
43540b57cec5SDimitry Andric }
43550b57cec5SDimitry Andric 
43560b57cec5SDimitry Andric // __narrow_to_utf8<16>
43570b57cec5SDimitry Andric 
43580b57cec5SDimitry Andric __narrow_to_utf8<16>::~__narrow_to_utf8()
43590b57cec5SDimitry Andric {
43600b57cec5SDimitry Andric }
43610b57cec5SDimitry Andric 
43620b57cec5SDimitry Andric // __narrow_to_utf8<32>
43630b57cec5SDimitry Andric 
43640b57cec5SDimitry Andric __narrow_to_utf8<32>::~__narrow_to_utf8()
43650b57cec5SDimitry Andric {
43660b57cec5SDimitry Andric }
43670b57cec5SDimitry Andric 
43680b57cec5SDimitry Andric // __widen_from_utf8<16>
43690b57cec5SDimitry Andric 
43700b57cec5SDimitry Andric __widen_from_utf8<16>::~__widen_from_utf8()
43710b57cec5SDimitry Andric {
43720b57cec5SDimitry Andric }
43730b57cec5SDimitry Andric 
43740b57cec5SDimitry Andric // __widen_from_utf8<32>
43750b57cec5SDimitry Andric 
43760b57cec5SDimitry Andric __widen_from_utf8<32>::~__widen_from_utf8()
43770b57cec5SDimitry Andric {
43780b57cec5SDimitry Andric }
43790b57cec5SDimitry Andric 
43800b57cec5SDimitry Andric 
43810b57cec5SDimitry Andric static bool checked_string_to_wchar_convert(wchar_t& dest,
43820b57cec5SDimitry Andric                                             const char* ptr,
43830b57cec5SDimitry Andric                                             locale_t loc) {
43840b57cec5SDimitry Andric   if (*ptr == '\0')
43850b57cec5SDimitry Andric     return false;
43860b57cec5SDimitry Andric   mbstate_t mb = {};
43870b57cec5SDimitry Andric   wchar_t out;
43880b57cec5SDimitry Andric   size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
43890b57cec5SDimitry Andric   if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
43900b57cec5SDimitry Andric     return false;
43910b57cec5SDimitry Andric   }
43920b57cec5SDimitry Andric   dest = out;
43930b57cec5SDimitry Andric   return true;
43940b57cec5SDimitry Andric }
43950b57cec5SDimitry Andric 
43960b57cec5SDimitry Andric static bool checked_string_to_char_convert(char& dest,
43970b57cec5SDimitry Andric                                            const char* ptr,
43980b57cec5SDimitry Andric                                            locale_t __loc) {
43990b57cec5SDimitry Andric   if (*ptr == '\0')
44000b57cec5SDimitry Andric     return false;
44010b57cec5SDimitry Andric   if (!ptr[1]) {
44020b57cec5SDimitry Andric     dest = *ptr;
44030b57cec5SDimitry Andric     return true;
44040b57cec5SDimitry Andric   }
44050b57cec5SDimitry Andric   // First convert the MBS into a wide char then attempt to narrow it using
44060b57cec5SDimitry Andric   // wctob_l.
44070b57cec5SDimitry Andric   wchar_t wout;
44080b57cec5SDimitry Andric   if (!checked_string_to_wchar_convert(wout, ptr, __loc))
44090b57cec5SDimitry Andric     return false;
44100b57cec5SDimitry Andric   int res;
44110b57cec5SDimitry Andric   if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
44120b57cec5SDimitry Andric     dest = res;
44130b57cec5SDimitry Andric     return true;
44140b57cec5SDimitry Andric   }
44150b57cec5SDimitry Andric   // FIXME: Work around specific multibyte sequences that we can reasonable
44160b57cec5SDimitry Andric   // translate into a different single byte.
44170b57cec5SDimitry Andric   switch (wout) {
44180b57cec5SDimitry Andric   case L'\u202F': // narrow non-breaking space
44190b57cec5SDimitry Andric   case L'\u00A0': // non-breaking space
44200b57cec5SDimitry Andric     dest = ' ';
44210b57cec5SDimitry Andric     return true;
44220b57cec5SDimitry Andric   default:
44230b57cec5SDimitry Andric     return false;
44240b57cec5SDimitry Andric   }
44250b57cec5SDimitry Andric   _LIBCPP_UNREACHABLE();
44260b57cec5SDimitry Andric }
44270b57cec5SDimitry Andric 
44280b57cec5SDimitry Andric 
44290b57cec5SDimitry Andric // numpunct<char> && numpunct<wchar_t>
44300b57cec5SDimitry Andric 
44310b57cec5SDimitry Andric locale::id numpunct< char  >::id;
44320b57cec5SDimitry Andric locale::id numpunct<wchar_t>::id;
44330b57cec5SDimitry Andric 
44340b57cec5SDimitry Andric numpunct<char>::numpunct(size_t refs)
44350b57cec5SDimitry Andric     : locale::facet(refs),
44360b57cec5SDimitry Andric       __decimal_point_('.'),
44370b57cec5SDimitry Andric       __thousands_sep_(',')
44380b57cec5SDimitry Andric {
44390b57cec5SDimitry Andric }
44400b57cec5SDimitry Andric 
44410b57cec5SDimitry Andric numpunct<wchar_t>::numpunct(size_t refs)
44420b57cec5SDimitry Andric     : locale::facet(refs),
44430b57cec5SDimitry Andric       __decimal_point_(L'.'),
44440b57cec5SDimitry Andric       __thousands_sep_(L',')
44450b57cec5SDimitry Andric {
44460b57cec5SDimitry Andric }
44470b57cec5SDimitry Andric 
44480b57cec5SDimitry Andric numpunct<char>::~numpunct()
44490b57cec5SDimitry Andric {
44500b57cec5SDimitry Andric }
44510b57cec5SDimitry Andric 
44520b57cec5SDimitry Andric numpunct<wchar_t>::~numpunct()
44530b57cec5SDimitry Andric {
44540b57cec5SDimitry Andric }
44550b57cec5SDimitry Andric 
44560b57cec5SDimitry Andric  char   numpunct< char  >::do_decimal_point() const {return __decimal_point_;}
44570b57cec5SDimitry Andric wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
44580b57cec5SDimitry Andric 
44590b57cec5SDimitry Andric  char   numpunct< char  >::do_thousands_sep() const {return __thousands_sep_;}
44600b57cec5SDimitry Andric wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
44610b57cec5SDimitry Andric 
44620b57cec5SDimitry Andric string numpunct< char  >::do_grouping() const {return __grouping_;}
44630b57cec5SDimitry Andric string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
44640b57cec5SDimitry Andric 
44650b57cec5SDimitry Andric  string numpunct< char  >::do_truename() const {return "true";}
44660b57cec5SDimitry Andric wstring numpunct<wchar_t>::do_truename() const {return L"true";}
44670b57cec5SDimitry Andric 
44680b57cec5SDimitry Andric  string numpunct< char  >::do_falsename() const {return "false";}
44690b57cec5SDimitry Andric wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
44700b57cec5SDimitry Andric 
44710b57cec5SDimitry Andric // numpunct_byname<char>
44720b57cec5SDimitry Andric 
44730b57cec5SDimitry Andric numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
44740b57cec5SDimitry Andric     : numpunct<char>(refs)
44750b57cec5SDimitry Andric {
44760b57cec5SDimitry Andric     __init(nm);
44770b57cec5SDimitry Andric }
44780b57cec5SDimitry Andric 
44790b57cec5SDimitry Andric numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
44800b57cec5SDimitry Andric     : numpunct<char>(refs)
44810b57cec5SDimitry Andric {
44820b57cec5SDimitry Andric     __init(nm.c_str());
44830b57cec5SDimitry Andric }
44840b57cec5SDimitry Andric 
44850b57cec5SDimitry Andric numpunct_byname<char>::~numpunct_byname()
44860b57cec5SDimitry Andric {
44870b57cec5SDimitry Andric }
44880b57cec5SDimitry Andric 
44890b57cec5SDimitry Andric void
44900b57cec5SDimitry Andric numpunct_byname<char>::__init(const char* nm)
44910b57cec5SDimitry Andric {
44920b57cec5SDimitry Andric     if (strcmp(nm, "C") != 0)
44930b57cec5SDimitry Andric     {
44940b57cec5SDimitry Andric         __libcpp_unique_locale loc(nm);
44950b57cec5SDimitry Andric         if (!loc)
44960b57cec5SDimitry Andric             __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
44970b57cec5SDimitry Andric                                 " failed to construct for " + string(nm));
44980b57cec5SDimitry Andric 
44990b57cec5SDimitry Andric         lconv* lc = __libcpp_localeconv_l(loc.get());
45000b57cec5SDimitry Andric         checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
45010b57cec5SDimitry Andric                                        loc.get());
45020b57cec5SDimitry Andric         checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
45030b57cec5SDimitry Andric                                        loc.get());
45040b57cec5SDimitry Andric         __grouping_ = lc->grouping;
45050b57cec5SDimitry Andric         // localization for truename and falsename is not available
45060b57cec5SDimitry Andric     }
45070b57cec5SDimitry Andric }
45080b57cec5SDimitry Andric 
45090b57cec5SDimitry Andric // numpunct_byname<wchar_t>
45100b57cec5SDimitry Andric 
45110b57cec5SDimitry Andric numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
45120b57cec5SDimitry Andric     : numpunct<wchar_t>(refs)
45130b57cec5SDimitry Andric {
45140b57cec5SDimitry Andric     __init(nm);
45150b57cec5SDimitry Andric }
45160b57cec5SDimitry Andric 
45170b57cec5SDimitry Andric numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
45180b57cec5SDimitry Andric     : numpunct<wchar_t>(refs)
45190b57cec5SDimitry Andric {
45200b57cec5SDimitry Andric     __init(nm.c_str());
45210b57cec5SDimitry Andric }
45220b57cec5SDimitry Andric 
45230b57cec5SDimitry Andric numpunct_byname<wchar_t>::~numpunct_byname()
45240b57cec5SDimitry Andric {
45250b57cec5SDimitry Andric }
45260b57cec5SDimitry Andric 
45270b57cec5SDimitry Andric void
45280b57cec5SDimitry Andric numpunct_byname<wchar_t>::__init(const char* nm)
45290b57cec5SDimitry Andric {
45300b57cec5SDimitry Andric     if (strcmp(nm, "C") != 0)
45310b57cec5SDimitry Andric     {
45320b57cec5SDimitry Andric         __libcpp_unique_locale loc(nm);
45330b57cec5SDimitry Andric         if (!loc)
45340b57cec5SDimitry Andric             __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
45350b57cec5SDimitry Andric                                 " failed to construct for " + string(nm));
45360b57cec5SDimitry Andric 
45370b57cec5SDimitry Andric         lconv* lc = __libcpp_localeconv_l(loc.get());
45380b57cec5SDimitry Andric         checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
45390b57cec5SDimitry Andric                                         loc.get());
45400b57cec5SDimitry Andric         checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
45410b57cec5SDimitry Andric                                         loc.get());
45420b57cec5SDimitry Andric         __grouping_ = lc->grouping;
45430b57cec5SDimitry Andric         // localization for truename and falsename is not available
45440b57cec5SDimitry Andric     }
45450b57cec5SDimitry Andric }
45460b57cec5SDimitry Andric 
45470b57cec5SDimitry Andric // num_get helpers
45480b57cec5SDimitry Andric 
45490b57cec5SDimitry Andric int
45500b57cec5SDimitry Andric __num_get_base::__get_base(ios_base& iob)
45510b57cec5SDimitry Andric {
45520b57cec5SDimitry Andric     ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
45530b57cec5SDimitry Andric     if (__basefield == ios_base::oct)
45540b57cec5SDimitry Andric         return 8;
45550b57cec5SDimitry Andric     else if (__basefield == ios_base::hex)
45560b57cec5SDimitry Andric         return 16;
45570b57cec5SDimitry Andric     else if (__basefield == 0)
45580b57cec5SDimitry Andric         return 0;
45590b57cec5SDimitry Andric     return 10;
45600b57cec5SDimitry Andric }
45610b57cec5SDimitry Andric 
45620b57cec5SDimitry Andric const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
45630b57cec5SDimitry Andric 
45640b57cec5SDimitry Andric void
45650b57cec5SDimitry Andric __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
45660b57cec5SDimitry Andric                  ios_base::iostate& __err)
45670b57cec5SDimitry Andric {
45680b57cec5SDimitry Andric //  if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
45690b57cec5SDimitry Andric //  we always have at least a single entry in [__g, __g_end); the end of the input sequence
45700b57cec5SDimitry Andric 	if (__grouping.size() != 0 && __g_end - __g > 1)
45710b57cec5SDimitry Andric     {
45720b57cec5SDimitry Andric         reverse(__g, __g_end);
45730b57cec5SDimitry Andric         const char* __ig = __grouping.data();
45740b57cec5SDimitry Andric         const char* __eg = __ig + __grouping.size();
45750b57cec5SDimitry Andric         for (unsigned* __r = __g; __r < __g_end-1; ++__r)
45760b57cec5SDimitry Andric         {
45770b57cec5SDimitry Andric             if (0 < *__ig && *__ig < numeric_limits<char>::max())
45780b57cec5SDimitry Andric             {
45790b57cec5SDimitry Andric                 if (static_cast<unsigned>(*__ig) != *__r)
45800b57cec5SDimitry Andric                 {
45810b57cec5SDimitry Andric                     __err = ios_base::failbit;
45820b57cec5SDimitry Andric                     return;
45830b57cec5SDimitry Andric                 }
45840b57cec5SDimitry Andric             }
45850b57cec5SDimitry Andric             if (__eg - __ig > 1)
45860b57cec5SDimitry Andric                 ++__ig;
45870b57cec5SDimitry Andric         }
45880b57cec5SDimitry Andric         if (0 < *__ig && *__ig < numeric_limits<char>::max())
45890b57cec5SDimitry Andric         {
45900b57cec5SDimitry Andric             if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
45910b57cec5SDimitry Andric                 __err = ios_base::failbit;
45920b57cec5SDimitry Andric         }
45930b57cec5SDimitry Andric     }
45940b57cec5SDimitry Andric }
45950b57cec5SDimitry Andric 
45960b57cec5SDimitry Andric void
45970b57cec5SDimitry Andric __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
45980b57cec5SDimitry Andric                              ios_base::fmtflags __flags)
45990b57cec5SDimitry Andric {
46000b57cec5SDimitry Andric     if (__flags & ios_base::showpos)
46010b57cec5SDimitry Andric         *__fmtp++ = '+';
46020b57cec5SDimitry Andric     if (__flags & ios_base::showbase)
46030b57cec5SDimitry Andric         *__fmtp++ = '#';
46040b57cec5SDimitry Andric     while(*__len)
46050b57cec5SDimitry Andric         *__fmtp++ = *__len++;
46060b57cec5SDimitry Andric     if ((__flags & ios_base::basefield) == ios_base::oct)
46070b57cec5SDimitry Andric         *__fmtp = 'o';
46080b57cec5SDimitry Andric     else if ((__flags & ios_base::basefield) == ios_base::hex)
46090b57cec5SDimitry Andric     {
46100b57cec5SDimitry Andric         if (__flags & ios_base::uppercase)
46110b57cec5SDimitry Andric             *__fmtp = 'X';
46120b57cec5SDimitry Andric         else
46130b57cec5SDimitry Andric             *__fmtp = 'x';
46140b57cec5SDimitry Andric     }
46150b57cec5SDimitry Andric     else if (__signd)
46160b57cec5SDimitry Andric         *__fmtp = 'd';
46170b57cec5SDimitry Andric     else
46180b57cec5SDimitry Andric         *__fmtp = 'u';
46190b57cec5SDimitry Andric }
46200b57cec5SDimitry Andric 
46210b57cec5SDimitry Andric bool
46220b57cec5SDimitry Andric __num_put_base::__format_float(char* __fmtp, const char* __len,
46230b57cec5SDimitry Andric                                ios_base::fmtflags __flags)
46240b57cec5SDimitry Andric {
46250b57cec5SDimitry Andric     bool specify_precision = true;
46260b57cec5SDimitry Andric     if (__flags & ios_base::showpos)
46270b57cec5SDimitry Andric         *__fmtp++ = '+';
46280b57cec5SDimitry Andric     if (__flags & ios_base::showpoint)
46290b57cec5SDimitry Andric         *__fmtp++ = '#';
46300b57cec5SDimitry Andric     ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
46310b57cec5SDimitry Andric     bool uppercase = (__flags & ios_base::uppercase) != 0;
46320b57cec5SDimitry Andric     if (floatfield == (ios_base::fixed | ios_base::scientific))
46330b57cec5SDimitry Andric         specify_precision = false;
46340b57cec5SDimitry Andric     else
46350b57cec5SDimitry Andric     {
46360b57cec5SDimitry Andric         *__fmtp++ = '.';
46370b57cec5SDimitry Andric         *__fmtp++ = '*';
46380b57cec5SDimitry Andric     }
46390b57cec5SDimitry Andric     while(*__len)
46400b57cec5SDimitry Andric         *__fmtp++ = *__len++;
46410b57cec5SDimitry Andric     if (floatfield == ios_base::fixed)
46420b57cec5SDimitry Andric     {
46430b57cec5SDimitry Andric         if (uppercase)
46440b57cec5SDimitry Andric             *__fmtp = 'F';
46450b57cec5SDimitry Andric         else
46460b57cec5SDimitry Andric             *__fmtp = 'f';
46470b57cec5SDimitry Andric     }
46480b57cec5SDimitry Andric     else if (floatfield == ios_base::scientific)
46490b57cec5SDimitry Andric     {
46500b57cec5SDimitry Andric         if (uppercase)
46510b57cec5SDimitry Andric             *__fmtp = 'E';
46520b57cec5SDimitry Andric         else
46530b57cec5SDimitry Andric             *__fmtp = 'e';
46540b57cec5SDimitry Andric     }
46550b57cec5SDimitry Andric     else if (floatfield == (ios_base::fixed | ios_base::scientific))
46560b57cec5SDimitry Andric     {
46570b57cec5SDimitry Andric         if (uppercase)
46580b57cec5SDimitry Andric             *__fmtp = 'A';
46590b57cec5SDimitry Andric         else
46600b57cec5SDimitry Andric             *__fmtp = 'a';
46610b57cec5SDimitry Andric     }
46620b57cec5SDimitry Andric     else
46630b57cec5SDimitry Andric     {
46640b57cec5SDimitry Andric         if (uppercase)
46650b57cec5SDimitry Andric             *__fmtp = 'G';
46660b57cec5SDimitry Andric         else
46670b57cec5SDimitry Andric             *__fmtp = 'g';
46680b57cec5SDimitry Andric     }
46690b57cec5SDimitry Andric     return specify_precision;
46700b57cec5SDimitry Andric }
46710b57cec5SDimitry Andric 
46720b57cec5SDimitry Andric char*
46730b57cec5SDimitry Andric __num_put_base::__identify_padding(char* __nb, char* __ne,
46740b57cec5SDimitry Andric                                    const ios_base& __iob)
46750b57cec5SDimitry Andric {
46760b57cec5SDimitry Andric     switch (__iob.flags() & ios_base::adjustfield)
46770b57cec5SDimitry Andric     {
46780b57cec5SDimitry Andric     case ios_base::internal:
46790b57cec5SDimitry Andric         if (__nb[0] == '-' || __nb[0] == '+')
46800b57cec5SDimitry Andric             return __nb+1;
46810b57cec5SDimitry Andric         if (__ne - __nb >= 2 && __nb[0] == '0'
46820b57cec5SDimitry Andric                             && (__nb[1] == 'x' || __nb[1] == 'X'))
46830b57cec5SDimitry Andric             return __nb+2;
46840b57cec5SDimitry Andric         break;
46850b57cec5SDimitry Andric     case ios_base::left:
46860b57cec5SDimitry Andric         return __ne;
46870b57cec5SDimitry Andric     case ios_base::right:
46880b57cec5SDimitry Andric     default:
46890b57cec5SDimitry Andric         break;
46900b57cec5SDimitry Andric     }
46910b57cec5SDimitry Andric     return __nb;
46920b57cec5SDimitry Andric }
46930b57cec5SDimitry Andric 
46940b57cec5SDimitry Andric // time_get
46950b57cec5SDimitry Andric 
46960b57cec5SDimitry Andric static
46970b57cec5SDimitry Andric string*
46980b57cec5SDimitry Andric init_weeks()
46990b57cec5SDimitry Andric {
47000b57cec5SDimitry Andric     static string weeks[14];
47010b57cec5SDimitry Andric     weeks[0]  = "Sunday";
47020b57cec5SDimitry Andric     weeks[1]  = "Monday";
47030b57cec5SDimitry Andric     weeks[2]  = "Tuesday";
47040b57cec5SDimitry Andric     weeks[3]  = "Wednesday";
47050b57cec5SDimitry Andric     weeks[4]  = "Thursday";
47060b57cec5SDimitry Andric     weeks[5]  = "Friday";
47070b57cec5SDimitry Andric     weeks[6]  = "Saturday";
47080b57cec5SDimitry Andric     weeks[7]  = "Sun";
47090b57cec5SDimitry Andric     weeks[8]  = "Mon";
47100b57cec5SDimitry Andric     weeks[9]  = "Tue";
47110b57cec5SDimitry Andric     weeks[10] = "Wed";
47120b57cec5SDimitry Andric     weeks[11] = "Thu";
47130b57cec5SDimitry Andric     weeks[12] = "Fri";
47140b57cec5SDimitry Andric     weeks[13] = "Sat";
47150b57cec5SDimitry Andric     return weeks;
47160b57cec5SDimitry Andric }
47170b57cec5SDimitry Andric 
47180b57cec5SDimitry Andric static
47190b57cec5SDimitry Andric wstring*
47200b57cec5SDimitry Andric init_wweeks()
47210b57cec5SDimitry Andric {
47220b57cec5SDimitry Andric     static wstring weeks[14];
47230b57cec5SDimitry Andric     weeks[0]  = L"Sunday";
47240b57cec5SDimitry Andric     weeks[1]  = L"Monday";
47250b57cec5SDimitry Andric     weeks[2]  = L"Tuesday";
47260b57cec5SDimitry Andric     weeks[3]  = L"Wednesday";
47270b57cec5SDimitry Andric     weeks[4]  = L"Thursday";
47280b57cec5SDimitry Andric     weeks[5]  = L"Friday";
47290b57cec5SDimitry Andric     weeks[6]  = L"Saturday";
47300b57cec5SDimitry Andric     weeks[7]  = L"Sun";
47310b57cec5SDimitry Andric     weeks[8]  = L"Mon";
47320b57cec5SDimitry Andric     weeks[9]  = L"Tue";
47330b57cec5SDimitry Andric     weeks[10] = L"Wed";
47340b57cec5SDimitry Andric     weeks[11] = L"Thu";
47350b57cec5SDimitry Andric     weeks[12] = L"Fri";
47360b57cec5SDimitry Andric     weeks[13] = L"Sat";
47370b57cec5SDimitry Andric     return weeks;
47380b57cec5SDimitry Andric }
47390b57cec5SDimitry Andric 
47400b57cec5SDimitry Andric template <>
47410b57cec5SDimitry Andric const string*
47420b57cec5SDimitry Andric __time_get_c_storage<char>::__weeks() const
47430b57cec5SDimitry Andric {
47440b57cec5SDimitry Andric     static const string* weeks = init_weeks();
47450b57cec5SDimitry Andric     return weeks;
47460b57cec5SDimitry Andric }
47470b57cec5SDimitry Andric 
47480b57cec5SDimitry Andric template <>
47490b57cec5SDimitry Andric const wstring*
47500b57cec5SDimitry Andric __time_get_c_storage<wchar_t>::__weeks() const
47510b57cec5SDimitry Andric {
47520b57cec5SDimitry Andric     static const wstring* weeks = init_wweeks();
47530b57cec5SDimitry Andric     return weeks;
47540b57cec5SDimitry Andric }
47550b57cec5SDimitry Andric 
47560b57cec5SDimitry Andric static
47570b57cec5SDimitry Andric string*
47580b57cec5SDimitry Andric init_months()
47590b57cec5SDimitry Andric {
47600b57cec5SDimitry Andric     static string months[24];
47610b57cec5SDimitry Andric     months[0]  = "January";
47620b57cec5SDimitry Andric     months[1]  = "February";
47630b57cec5SDimitry Andric     months[2]  = "March";
47640b57cec5SDimitry Andric     months[3]  = "April";
47650b57cec5SDimitry Andric     months[4]  = "May";
47660b57cec5SDimitry Andric     months[5]  = "June";
47670b57cec5SDimitry Andric     months[6]  = "July";
47680b57cec5SDimitry Andric     months[7]  = "August";
47690b57cec5SDimitry Andric     months[8]  = "September";
47700b57cec5SDimitry Andric     months[9]  = "October";
47710b57cec5SDimitry Andric     months[10] = "November";
47720b57cec5SDimitry Andric     months[11] = "December";
47730b57cec5SDimitry Andric     months[12] = "Jan";
47740b57cec5SDimitry Andric     months[13] = "Feb";
47750b57cec5SDimitry Andric     months[14] = "Mar";
47760b57cec5SDimitry Andric     months[15] = "Apr";
47770b57cec5SDimitry Andric     months[16] = "May";
47780b57cec5SDimitry Andric     months[17] = "Jun";
47790b57cec5SDimitry Andric     months[18] = "Jul";
47800b57cec5SDimitry Andric     months[19] = "Aug";
47810b57cec5SDimitry Andric     months[20] = "Sep";
47820b57cec5SDimitry Andric     months[21] = "Oct";
47830b57cec5SDimitry Andric     months[22] = "Nov";
47840b57cec5SDimitry Andric     months[23] = "Dec";
47850b57cec5SDimitry Andric     return months;
47860b57cec5SDimitry Andric }
47870b57cec5SDimitry Andric 
47880b57cec5SDimitry Andric static
47890b57cec5SDimitry Andric wstring*
47900b57cec5SDimitry Andric init_wmonths()
47910b57cec5SDimitry Andric {
47920b57cec5SDimitry Andric     static wstring months[24];
47930b57cec5SDimitry Andric     months[0]  = L"January";
47940b57cec5SDimitry Andric     months[1]  = L"February";
47950b57cec5SDimitry Andric     months[2]  = L"March";
47960b57cec5SDimitry Andric     months[3]  = L"April";
47970b57cec5SDimitry Andric     months[4]  = L"May";
47980b57cec5SDimitry Andric     months[5]  = L"June";
47990b57cec5SDimitry Andric     months[6]  = L"July";
48000b57cec5SDimitry Andric     months[7]  = L"August";
48010b57cec5SDimitry Andric     months[8]  = L"September";
48020b57cec5SDimitry Andric     months[9]  = L"October";
48030b57cec5SDimitry Andric     months[10] = L"November";
48040b57cec5SDimitry Andric     months[11] = L"December";
48050b57cec5SDimitry Andric     months[12] = L"Jan";
48060b57cec5SDimitry Andric     months[13] = L"Feb";
48070b57cec5SDimitry Andric     months[14] = L"Mar";
48080b57cec5SDimitry Andric     months[15] = L"Apr";
48090b57cec5SDimitry Andric     months[16] = L"May";
48100b57cec5SDimitry Andric     months[17] = L"Jun";
48110b57cec5SDimitry Andric     months[18] = L"Jul";
48120b57cec5SDimitry Andric     months[19] = L"Aug";
48130b57cec5SDimitry Andric     months[20] = L"Sep";
48140b57cec5SDimitry Andric     months[21] = L"Oct";
48150b57cec5SDimitry Andric     months[22] = L"Nov";
48160b57cec5SDimitry Andric     months[23] = L"Dec";
48170b57cec5SDimitry Andric     return months;
48180b57cec5SDimitry Andric }
48190b57cec5SDimitry Andric 
48200b57cec5SDimitry Andric template <>
48210b57cec5SDimitry Andric const string*
48220b57cec5SDimitry Andric __time_get_c_storage<char>::__months() const
48230b57cec5SDimitry Andric {
48240b57cec5SDimitry Andric     static const string* months = init_months();
48250b57cec5SDimitry Andric     return months;
48260b57cec5SDimitry Andric }
48270b57cec5SDimitry Andric 
48280b57cec5SDimitry Andric template <>
48290b57cec5SDimitry Andric const wstring*
48300b57cec5SDimitry Andric __time_get_c_storage<wchar_t>::__months() const
48310b57cec5SDimitry Andric {
48320b57cec5SDimitry Andric     static const wstring* months = init_wmonths();
48330b57cec5SDimitry Andric     return months;
48340b57cec5SDimitry Andric }
48350b57cec5SDimitry Andric 
48360b57cec5SDimitry Andric static
48370b57cec5SDimitry Andric string*
48380b57cec5SDimitry Andric init_am_pm()
48390b57cec5SDimitry Andric {
48400b57cec5SDimitry Andric     static string am_pm[2];
48410b57cec5SDimitry Andric     am_pm[0]  = "AM";
48420b57cec5SDimitry Andric     am_pm[1]  = "PM";
48430b57cec5SDimitry Andric     return am_pm;
48440b57cec5SDimitry Andric }
48450b57cec5SDimitry Andric 
48460b57cec5SDimitry Andric static
48470b57cec5SDimitry Andric wstring*
48480b57cec5SDimitry Andric init_wam_pm()
48490b57cec5SDimitry Andric {
48500b57cec5SDimitry Andric     static wstring am_pm[2];
48510b57cec5SDimitry Andric     am_pm[0]  = L"AM";
48520b57cec5SDimitry Andric     am_pm[1]  = L"PM";
48530b57cec5SDimitry Andric     return am_pm;
48540b57cec5SDimitry Andric }
48550b57cec5SDimitry Andric 
48560b57cec5SDimitry Andric template <>
48570b57cec5SDimitry Andric const string*
48580b57cec5SDimitry Andric __time_get_c_storage<char>::__am_pm() const
48590b57cec5SDimitry Andric {
48600b57cec5SDimitry Andric     static const string* am_pm = init_am_pm();
48610b57cec5SDimitry Andric     return am_pm;
48620b57cec5SDimitry Andric }
48630b57cec5SDimitry Andric 
48640b57cec5SDimitry Andric template <>
48650b57cec5SDimitry Andric const wstring*
48660b57cec5SDimitry Andric __time_get_c_storage<wchar_t>::__am_pm() const
48670b57cec5SDimitry Andric {
48680b57cec5SDimitry Andric     static const wstring* am_pm = init_wam_pm();
48690b57cec5SDimitry Andric     return am_pm;
48700b57cec5SDimitry Andric }
48710b57cec5SDimitry Andric 
48720b57cec5SDimitry Andric template <>
48730b57cec5SDimitry Andric const string&
48740b57cec5SDimitry Andric __time_get_c_storage<char>::__x() const
48750b57cec5SDimitry Andric {
48760b57cec5SDimitry Andric     static string s("%m/%d/%y");
48770b57cec5SDimitry Andric     return s;
48780b57cec5SDimitry Andric }
48790b57cec5SDimitry Andric 
48800b57cec5SDimitry Andric template <>
48810b57cec5SDimitry Andric const wstring&
48820b57cec5SDimitry Andric __time_get_c_storage<wchar_t>::__x() const
48830b57cec5SDimitry Andric {
48840b57cec5SDimitry Andric     static wstring s(L"%m/%d/%y");
48850b57cec5SDimitry Andric     return s;
48860b57cec5SDimitry Andric }
48870b57cec5SDimitry Andric 
48880b57cec5SDimitry Andric template <>
48890b57cec5SDimitry Andric const string&
48900b57cec5SDimitry Andric __time_get_c_storage<char>::__X() const
48910b57cec5SDimitry Andric {
48920b57cec5SDimitry Andric     static string s("%H:%M:%S");
48930b57cec5SDimitry Andric     return s;
48940b57cec5SDimitry Andric }
48950b57cec5SDimitry Andric 
48960b57cec5SDimitry Andric template <>
48970b57cec5SDimitry Andric const wstring&
48980b57cec5SDimitry Andric __time_get_c_storage<wchar_t>::__X() const
48990b57cec5SDimitry Andric {
49000b57cec5SDimitry Andric     static wstring s(L"%H:%M:%S");
49010b57cec5SDimitry Andric     return s;
49020b57cec5SDimitry Andric }
49030b57cec5SDimitry Andric 
49040b57cec5SDimitry Andric template <>
49050b57cec5SDimitry Andric const string&
49060b57cec5SDimitry Andric __time_get_c_storage<char>::__c() const
49070b57cec5SDimitry Andric {
49080b57cec5SDimitry Andric     static string s("%a %b %d %H:%M:%S %Y");
49090b57cec5SDimitry Andric     return s;
49100b57cec5SDimitry Andric }
49110b57cec5SDimitry Andric 
49120b57cec5SDimitry Andric template <>
49130b57cec5SDimitry Andric const wstring&
49140b57cec5SDimitry Andric __time_get_c_storage<wchar_t>::__c() const
49150b57cec5SDimitry Andric {
49160b57cec5SDimitry Andric     static wstring s(L"%a %b %d %H:%M:%S %Y");
49170b57cec5SDimitry Andric     return s;
49180b57cec5SDimitry Andric }
49190b57cec5SDimitry Andric 
49200b57cec5SDimitry Andric template <>
49210b57cec5SDimitry Andric const string&
49220b57cec5SDimitry Andric __time_get_c_storage<char>::__r() const
49230b57cec5SDimitry Andric {
49240b57cec5SDimitry Andric     static string s("%I:%M:%S %p");
49250b57cec5SDimitry Andric     return s;
49260b57cec5SDimitry Andric }
49270b57cec5SDimitry Andric 
49280b57cec5SDimitry Andric template <>
49290b57cec5SDimitry Andric const wstring&
49300b57cec5SDimitry Andric __time_get_c_storage<wchar_t>::__r() const
49310b57cec5SDimitry Andric {
49320b57cec5SDimitry Andric     static wstring s(L"%I:%M:%S %p");
49330b57cec5SDimitry Andric     return s;
49340b57cec5SDimitry Andric }
49350b57cec5SDimitry Andric 
49360b57cec5SDimitry Andric // time_get_byname
49370b57cec5SDimitry Andric 
49380b57cec5SDimitry Andric __time_get::__time_get(const char* nm)
49390b57cec5SDimitry Andric     : __loc_(newlocale(LC_ALL_MASK, nm, 0))
49400b57cec5SDimitry Andric {
49410b57cec5SDimitry Andric     if (__loc_ == 0)
49420b57cec5SDimitry Andric         __throw_runtime_error("time_get_byname"
49430b57cec5SDimitry Andric                             " failed to construct for " + string(nm));
49440b57cec5SDimitry Andric }
49450b57cec5SDimitry Andric 
49460b57cec5SDimitry Andric __time_get::__time_get(const string& nm)
49470b57cec5SDimitry Andric     : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
49480b57cec5SDimitry Andric {
49490b57cec5SDimitry Andric     if (__loc_ == 0)
49500b57cec5SDimitry Andric         __throw_runtime_error("time_get_byname"
49510b57cec5SDimitry Andric                             " failed to construct for " + nm);
49520b57cec5SDimitry Andric }
49530b57cec5SDimitry Andric 
49540b57cec5SDimitry Andric __time_get::~__time_get()
49550b57cec5SDimitry Andric {
49560b57cec5SDimitry Andric     freelocale(__loc_);
49570b57cec5SDimitry Andric }
49580b57cec5SDimitry Andric #if defined(__clang__)
49590b57cec5SDimitry Andric #pragma clang diagnostic ignored "-Wmissing-field-initializers"
49600b57cec5SDimitry Andric #endif
49610b57cec5SDimitry Andric #if defined(__GNUG__)
49620b57cec5SDimitry Andric #pragma GCC   diagnostic ignored "-Wmissing-field-initializers"
49630b57cec5SDimitry Andric #endif
49640b57cec5SDimitry Andric 
49650b57cec5SDimitry Andric template <>
49660b57cec5SDimitry Andric string
49670b57cec5SDimitry Andric __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
49680b57cec5SDimitry Andric {
49690b57cec5SDimitry Andric     tm t = {0};
49700b57cec5SDimitry Andric     t.tm_sec = 59;
49710b57cec5SDimitry Andric     t.tm_min = 55;
49720b57cec5SDimitry Andric     t.tm_hour = 23;
49730b57cec5SDimitry Andric     t.tm_mday = 31;
49740b57cec5SDimitry Andric     t.tm_mon = 11;
49750b57cec5SDimitry Andric     t.tm_year = 161;
49760b57cec5SDimitry Andric     t.tm_wday = 6;
49770b57cec5SDimitry Andric     t.tm_yday = 364;
49780b57cec5SDimitry Andric     t.tm_isdst = -1;
49790b57cec5SDimitry Andric     char buf[100];
49800b57cec5SDimitry Andric     char f[3] = {0};
49810b57cec5SDimitry Andric     f[0] = '%';
49820b57cec5SDimitry Andric     f[1] = fmt;
49830b57cec5SDimitry Andric     size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
49840b57cec5SDimitry Andric     char* bb = buf;
49850b57cec5SDimitry Andric     char* be = buf + n;
49860b57cec5SDimitry Andric     string result;
49870b57cec5SDimitry Andric     while (bb != be)
49880b57cec5SDimitry Andric     {
49890b57cec5SDimitry Andric         if (ct.is(ctype_base::space, *bb))
49900b57cec5SDimitry Andric         {
49910b57cec5SDimitry Andric             result.push_back(' ');
49920b57cec5SDimitry Andric             for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
49930b57cec5SDimitry Andric                 ;
49940b57cec5SDimitry Andric             continue;
49950b57cec5SDimitry Andric         }
49960b57cec5SDimitry Andric         char* w = bb;
49970b57cec5SDimitry Andric         ios_base::iostate err = ios_base::goodbit;
49980b57cec5SDimitry Andric         ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
49990b57cec5SDimitry Andric                                ct, err, false)
50000b57cec5SDimitry Andric                                - this->__weeks_;
50010b57cec5SDimitry Andric         if (i < 14)
50020b57cec5SDimitry Andric         {
50030b57cec5SDimitry Andric             result.push_back('%');
50040b57cec5SDimitry Andric             if (i < 7)
50050b57cec5SDimitry Andric                 result.push_back('A');
50060b57cec5SDimitry Andric             else
50070b57cec5SDimitry Andric                 result.push_back('a');
50080b57cec5SDimitry Andric             bb = w;
50090b57cec5SDimitry Andric             continue;
50100b57cec5SDimitry Andric         }
50110b57cec5SDimitry Andric         w = bb;
50120b57cec5SDimitry Andric         i = __scan_keyword(w, be, this->__months_, this->__months_+24,
50130b57cec5SDimitry Andric                            ct, err, false)
50140b57cec5SDimitry Andric                            - this->__months_;
50150b57cec5SDimitry Andric         if (i < 24)
50160b57cec5SDimitry Andric         {
50170b57cec5SDimitry Andric             result.push_back('%');
50180b57cec5SDimitry Andric             if (i < 12)
50190b57cec5SDimitry Andric                 result.push_back('B');
50200b57cec5SDimitry Andric             else
50210b57cec5SDimitry Andric                 result.push_back('b');
50220b57cec5SDimitry Andric             if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
50230b57cec5SDimitry Andric                 result.back() = 'm';
50240b57cec5SDimitry Andric             bb = w;
50250b57cec5SDimitry Andric             continue;
50260b57cec5SDimitry Andric         }
50270b57cec5SDimitry Andric         if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
50280b57cec5SDimitry Andric         {
50290b57cec5SDimitry Andric             w = bb;
50300b57cec5SDimitry Andric             i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
50310b57cec5SDimitry Andric                                ct, err, false) - this->__am_pm_;
50320b57cec5SDimitry Andric             if (i < 2)
50330b57cec5SDimitry Andric             {
50340b57cec5SDimitry Andric                 result.push_back('%');
50350b57cec5SDimitry Andric                 result.push_back('p');
50360b57cec5SDimitry Andric                 bb = w;
50370b57cec5SDimitry Andric                 continue;
50380b57cec5SDimitry Andric             }
50390b57cec5SDimitry Andric         }
50400b57cec5SDimitry Andric         w = bb;
50410b57cec5SDimitry Andric         if (ct.is(ctype_base::digit, *bb))
50420b57cec5SDimitry Andric         {
50430b57cec5SDimitry Andric             switch(__get_up_to_n_digits(bb, be, err, ct, 4))
50440b57cec5SDimitry Andric             {
50450b57cec5SDimitry Andric             case 6:
50460b57cec5SDimitry Andric                 result.push_back('%');
50470b57cec5SDimitry Andric                 result.push_back('w');
50480b57cec5SDimitry Andric                 break;
50490b57cec5SDimitry Andric             case 7:
50500b57cec5SDimitry Andric                 result.push_back('%');
50510b57cec5SDimitry Andric                 result.push_back('u');
50520b57cec5SDimitry Andric                 break;
50530b57cec5SDimitry Andric             case 11:
50540b57cec5SDimitry Andric                 result.push_back('%');
50550b57cec5SDimitry Andric                 result.push_back('I');
50560b57cec5SDimitry Andric                 break;
50570b57cec5SDimitry Andric             case 12:
50580b57cec5SDimitry Andric                 result.push_back('%');
50590b57cec5SDimitry Andric                 result.push_back('m');
50600b57cec5SDimitry Andric                 break;
50610b57cec5SDimitry Andric             case 23:
50620b57cec5SDimitry Andric                 result.push_back('%');
50630b57cec5SDimitry Andric                 result.push_back('H');
50640b57cec5SDimitry Andric                 break;
50650b57cec5SDimitry Andric             case 31:
50660b57cec5SDimitry Andric                 result.push_back('%');
50670b57cec5SDimitry Andric                 result.push_back('d');
50680b57cec5SDimitry Andric                 break;
50690b57cec5SDimitry Andric             case 55:
50700b57cec5SDimitry Andric                 result.push_back('%');
50710b57cec5SDimitry Andric                 result.push_back('M');
50720b57cec5SDimitry Andric                 break;
50730b57cec5SDimitry Andric             case 59:
50740b57cec5SDimitry Andric                 result.push_back('%');
50750b57cec5SDimitry Andric                 result.push_back('S');
50760b57cec5SDimitry Andric                 break;
50770b57cec5SDimitry Andric             case 61:
50780b57cec5SDimitry Andric                 result.push_back('%');
50790b57cec5SDimitry Andric                 result.push_back('y');
50800b57cec5SDimitry Andric                 break;
50810b57cec5SDimitry Andric             case 364:
50820b57cec5SDimitry Andric                 result.push_back('%');
50830b57cec5SDimitry Andric                 result.push_back('j');
50840b57cec5SDimitry Andric                 break;
50850b57cec5SDimitry Andric             case 2061:
50860b57cec5SDimitry Andric                 result.push_back('%');
50870b57cec5SDimitry Andric                 result.push_back('Y');
50880b57cec5SDimitry Andric                 break;
50890b57cec5SDimitry Andric             default:
50900b57cec5SDimitry Andric                 for (; w != bb; ++w)
50910b57cec5SDimitry Andric                     result.push_back(*w);
50920b57cec5SDimitry Andric                 break;
50930b57cec5SDimitry Andric             }
50940b57cec5SDimitry Andric             continue;
50950b57cec5SDimitry Andric         }
50960b57cec5SDimitry Andric         if (*bb == '%')
50970b57cec5SDimitry Andric         {
50980b57cec5SDimitry Andric             result.push_back('%');
50990b57cec5SDimitry Andric             result.push_back('%');
51000b57cec5SDimitry Andric             ++bb;
51010b57cec5SDimitry Andric             continue;
51020b57cec5SDimitry Andric         }
51030b57cec5SDimitry Andric         result.push_back(*bb);
51040b57cec5SDimitry Andric         ++bb;
51050b57cec5SDimitry Andric     }
51060b57cec5SDimitry Andric     return result;
51070b57cec5SDimitry Andric }
51080b57cec5SDimitry Andric 
51090b57cec5SDimitry Andric #if defined(__clang__)
51100b57cec5SDimitry Andric #pragma clang diagnostic ignored "-Wmissing-braces"
51110b57cec5SDimitry Andric #endif
51120b57cec5SDimitry Andric 
51130b57cec5SDimitry Andric template <>
51140b57cec5SDimitry Andric wstring
51150b57cec5SDimitry Andric __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
51160b57cec5SDimitry Andric {
51170b57cec5SDimitry Andric     tm t = {0};
51180b57cec5SDimitry Andric     t.tm_sec = 59;
51190b57cec5SDimitry Andric     t.tm_min = 55;
51200b57cec5SDimitry Andric     t.tm_hour = 23;
51210b57cec5SDimitry Andric     t.tm_mday = 31;
51220b57cec5SDimitry Andric     t.tm_mon = 11;
51230b57cec5SDimitry Andric     t.tm_year = 161;
51240b57cec5SDimitry Andric     t.tm_wday = 6;
51250b57cec5SDimitry Andric     t.tm_yday = 364;
51260b57cec5SDimitry Andric     t.tm_isdst = -1;
51270b57cec5SDimitry Andric     char buf[100];
51280b57cec5SDimitry Andric     char f[3] = {0};
51290b57cec5SDimitry Andric     f[0] = '%';
51300b57cec5SDimitry Andric     f[1] = fmt;
51310b57cec5SDimitry Andric     strftime_l(buf, countof(buf), f, &t, __loc_);
51320b57cec5SDimitry Andric     wchar_t wbuf[100];
51330b57cec5SDimitry Andric     wchar_t* wbb = wbuf;
51340b57cec5SDimitry Andric     mbstate_t mb = {0};
51350b57cec5SDimitry Andric     const char* bb = buf;
51360b57cec5SDimitry Andric     size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
51370b57cec5SDimitry Andric     if (j == size_t(-1))
51380b57cec5SDimitry Andric         __throw_runtime_error("locale not supported");
51390b57cec5SDimitry Andric     wchar_t* wbe = wbb + j;
51400b57cec5SDimitry Andric     wstring result;
51410b57cec5SDimitry Andric     while (wbb != wbe)
51420b57cec5SDimitry Andric     {
51430b57cec5SDimitry Andric         if (ct.is(ctype_base::space, *wbb))
51440b57cec5SDimitry Andric         {
51450b57cec5SDimitry Andric             result.push_back(L' ');
51460b57cec5SDimitry Andric             for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
51470b57cec5SDimitry Andric                 ;
51480b57cec5SDimitry Andric             continue;
51490b57cec5SDimitry Andric         }
51500b57cec5SDimitry Andric         wchar_t* w = wbb;
51510b57cec5SDimitry Andric         ios_base::iostate err = ios_base::goodbit;
51520b57cec5SDimitry Andric         ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
51530b57cec5SDimitry Andric                                ct, err, false)
51540b57cec5SDimitry Andric                                - this->__weeks_;
51550b57cec5SDimitry Andric         if (i < 14)
51560b57cec5SDimitry Andric         {
51570b57cec5SDimitry Andric             result.push_back(L'%');
51580b57cec5SDimitry Andric             if (i < 7)
51590b57cec5SDimitry Andric                 result.push_back(L'A');
51600b57cec5SDimitry Andric             else
51610b57cec5SDimitry Andric                 result.push_back(L'a');
51620b57cec5SDimitry Andric             wbb = w;
51630b57cec5SDimitry Andric             continue;
51640b57cec5SDimitry Andric         }
51650b57cec5SDimitry Andric         w = wbb;
51660b57cec5SDimitry Andric         i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
51670b57cec5SDimitry Andric                            ct, err, false)
51680b57cec5SDimitry Andric                            - this->__months_;
51690b57cec5SDimitry Andric         if (i < 24)
51700b57cec5SDimitry Andric         {
51710b57cec5SDimitry Andric             result.push_back(L'%');
51720b57cec5SDimitry Andric             if (i < 12)
51730b57cec5SDimitry Andric                 result.push_back(L'B');
51740b57cec5SDimitry Andric             else
51750b57cec5SDimitry Andric                 result.push_back(L'b');
51760b57cec5SDimitry Andric             if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
51770b57cec5SDimitry Andric                 result.back() = L'm';
51780b57cec5SDimitry Andric             wbb = w;
51790b57cec5SDimitry Andric             continue;
51800b57cec5SDimitry Andric         }
51810b57cec5SDimitry Andric         if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
51820b57cec5SDimitry Andric         {
51830b57cec5SDimitry Andric             w = wbb;
51840b57cec5SDimitry Andric             i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
51850b57cec5SDimitry Andric                                ct, err, false) - this->__am_pm_;
51860b57cec5SDimitry Andric             if (i < 2)
51870b57cec5SDimitry Andric             {
51880b57cec5SDimitry Andric                 result.push_back(L'%');
51890b57cec5SDimitry Andric                 result.push_back(L'p');
51900b57cec5SDimitry Andric                 wbb = w;
51910b57cec5SDimitry Andric                 continue;
51920b57cec5SDimitry Andric             }
51930b57cec5SDimitry Andric         }
51940b57cec5SDimitry Andric         w = wbb;
51950b57cec5SDimitry Andric         if (ct.is(ctype_base::digit, *wbb))
51960b57cec5SDimitry Andric         {
51970b57cec5SDimitry Andric             switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
51980b57cec5SDimitry Andric             {
51990b57cec5SDimitry Andric             case 6:
52000b57cec5SDimitry Andric                 result.push_back(L'%');
52010b57cec5SDimitry Andric                 result.push_back(L'w');
52020b57cec5SDimitry Andric                 break;
52030b57cec5SDimitry Andric             case 7:
52040b57cec5SDimitry Andric                 result.push_back(L'%');
52050b57cec5SDimitry Andric                 result.push_back(L'u');
52060b57cec5SDimitry Andric                 break;
52070b57cec5SDimitry Andric             case 11:
52080b57cec5SDimitry Andric                 result.push_back(L'%');
52090b57cec5SDimitry Andric                 result.push_back(L'I');
52100b57cec5SDimitry Andric                 break;
52110b57cec5SDimitry Andric             case 12:
52120b57cec5SDimitry Andric                 result.push_back(L'%');
52130b57cec5SDimitry Andric                 result.push_back(L'm');
52140b57cec5SDimitry Andric                 break;
52150b57cec5SDimitry Andric             case 23:
52160b57cec5SDimitry Andric                 result.push_back(L'%');
52170b57cec5SDimitry Andric                 result.push_back(L'H');
52180b57cec5SDimitry Andric                 break;
52190b57cec5SDimitry Andric             case 31:
52200b57cec5SDimitry Andric                 result.push_back(L'%');
52210b57cec5SDimitry Andric                 result.push_back(L'd');
52220b57cec5SDimitry Andric                 break;
52230b57cec5SDimitry Andric             case 55:
52240b57cec5SDimitry Andric                 result.push_back(L'%');
52250b57cec5SDimitry Andric                 result.push_back(L'M');
52260b57cec5SDimitry Andric                 break;
52270b57cec5SDimitry Andric             case 59:
52280b57cec5SDimitry Andric                 result.push_back(L'%');
52290b57cec5SDimitry Andric                 result.push_back(L'S');
52300b57cec5SDimitry Andric                 break;
52310b57cec5SDimitry Andric             case 61:
52320b57cec5SDimitry Andric                 result.push_back(L'%');
52330b57cec5SDimitry Andric                 result.push_back(L'y');
52340b57cec5SDimitry Andric                 break;
52350b57cec5SDimitry Andric             case 364:
52360b57cec5SDimitry Andric                 result.push_back(L'%');
52370b57cec5SDimitry Andric                 result.push_back(L'j');
52380b57cec5SDimitry Andric                 break;
52390b57cec5SDimitry Andric             case 2061:
52400b57cec5SDimitry Andric                 result.push_back(L'%');
52410b57cec5SDimitry Andric                 result.push_back(L'Y');
52420b57cec5SDimitry Andric                 break;
52430b57cec5SDimitry Andric             default:
52440b57cec5SDimitry Andric                 for (; w != wbb; ++w)
52450b57cec5SDimitry Andric                     result.push_back(*w);
52460b57cec5SDimitry Andric                 break;
52470b57cec5SDimitry Andric             }
52480b57cec5SDimitry Andric             continue;
52490b57cec5SDimitry Andric         }
52500b57cec5SDimitry Andric         if (ct.narrow(*wbb, 0) == '%')
52510b57cec5SDimitry Andric         {
52520b57cec5SDimitry Andric             result.push_back(L'%');
52530b57cec5SDimitry Andric             result.push_back(L'%');
52540b57cec5SDimitry Andric             ++wbb;
52550b57cec5SDimitry Andric             continue;
52560b57cec5SDimitry Andric         }
52570b57cec5SDimitry Andric         result.push_back(*wbb);
52580b57cec5SDimitry Andric         ++wbb;
52590b57cec5SDimitry Andric     }
52600b57cec5SDimitry Andric     return result;
52610b57cec5SDimitry Andric }
52620b57cec5SDimitry Andric 
52630b57cec5SDimitry Andric template <>
52640b57cec5SDimitry Andric void
52650b57cec5SDimitry Andric __time_get_storage<char>::init(const ctype<char>& ct)
52660b57cec5SDimitry Andric {
52670b57cec5SDimitry Andric     tm t = {0};
52680b57cec5SDimitry Andric     char buf[100];
52690b57cec5SDimitry Andric     // __weeks_
52700b57cec5SDimitry Andric     for (int i = 0; i < 7; ++i)
52710b57cec5SDimitry Andric     {
52720b57cec5SDimitry Andric         t.tm_wday = i;
52730b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%A", &t, __loc_);
52740b57cec5SDimitry Andric         __weeks_[i] = buf;
52750b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%a", &t, __loc_);
52760b57cec5SDimitry Andric         __weeks_[i+7] = buf;
52770b57cec5SDimitry Andric     }
52780b57cec5SDimitry Andric     // __months_
52790b57cec5SDimitry Andric     for (int i = 0; i < 12; ++i)
52800b57cec5SDimitry Andric     {
52810b57cec5SDimitry Andric         t.tm_mon = i;
52820b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%B", &t, __loc_);
52830b57cec5SDimitry Andric         __months_[i] = buf;
52840b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%b", &t, __loc_);
52850b57cec5SDimitry Andric         __months_[i+12] = buf;
52860b57cec5SDimitry Andric     }
52870b57cec5SDimitry Andric     // __am_pm_
52880b57cec5SDimitry Andric     t.tm_hour = 1;
52890b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%p", &t, __loc_);
52900b57cec5SDimitry Andric     __am_pm_[0] = buf;
52910b57cec5SDimitry Andric     t.tm_hour = 13;
52920b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%p", &t, __loc_);
52930b57cec5SDimitry Andric     __am_pm_[1] = buf;
52940b57cec5SDimitry Andric     __c_ = __analyze('c', ct);
52950b57cec5SDimitry Andric     __r_ = __analyze('r', ct);
52960b57cec5SDimitry Andric     __x_ = __analyze('x', ct);
52970b57cec5SDimitry Andric     __X_ = __analyze('X', ct);
52980b57cec5SDimitry Andric }
52990b57cec5SDimitry Andric 
53000b57cec5SDimitry Andric template <>
53010b57cec5SDimitry Andric void
53020b57cec5SDimitry Andric __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
53030b57cec5SDimitry Andric {
53040b57cec5SDimitry Andric     tm t = {0};
53050b57cec5SDimitry Andric     char buf[100];
53060b57cec5SDimitry Andric     wchar_t wbuf[100];
53070b57cec5SDimitry Andric     wchar_t* wbe;
53080b57cec5SDimitry Andric     mbstate_t mb = {0};
53090b57cec5SDimitry Andric     // __weeks_
53100b57cec5SDimitry Andric     for (int i = 0; i < 7; ++i)
53110b57cec5SDimitry Andric     {
53120b57cec5SDimitry Andric         t.tm_wday = i;
53130b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%A", &t, __loc_);
53140b57cec5SDimitry Andric         mb = mbstate_t();
53150b57cec5SDimitry Andric         const char* bb = buf;
53160b57cec5SDimitry Andric         size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5317*e8d8bef9SDimitry Andric         if (j == size_t(-1) || j == 0)
53180b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
53190b57cec5SDimitry Andric         wbe = wbuf + j;
53200b57cec5SDimitry Andric         __weeks_[i].assign(wbuf, wbe);
53210b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%a", &t, __loc_);
53220b57cec5SDimitry Andric         mb = mbstate_t();
53230b57cec5SDimitry Andric         bb = buf;
53240b57cec5SDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5325*e8d8bef9SDimitry Andric         if (j == size_t(-1) || j == 0)
53260b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
53270b57cec5SDimitry Andric         wbe = wbuf + j;
53280b57cec5SDimitry Andric         __weeks_[i+7].assign(wbuf, wbe);
53290b57cec5SDimitry Andric     }
53300b57cec5SDimitry Andric     // __months_
53310b57cec5SDimitry Andric     for (int i = 0; i < 12; ++i)
53320b57cec5SDimitry Andric     {
53330b57cec5SDimitry Andric         t.tm_mon = i;
53340b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%B", &t, __loc_);
53350b57cec5SDimitry Andric         mb = mbstate_t();
53360b57cec5SDimitry Andric         const char* bb = buf;
53370b57cec5SDimitry Andric         size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5338*e8d8bef9SDimitry Andric         if (j == size_t(-1) || j == 0)
53390b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
53400b57cec5SDimitry Andric         wbe = wbuf + j;
53410b57cec5SDimitry Andric         __months_[i].assign(wbuf, wbe);
53420b57cec5SDimitry Andric         strftime_l(buf, countof(buf), "%b", &t, __loc_);
53430b57cec5SDimitry Andric         mb = mbstate_t();
53440b57cec5SDimitry Andric         bb = buf;
53450b57cec5SDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5346*e8d8bef9SDimitry Andric         if (j == size_t(-1) || j == 0)
53470b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
53480b57cec5SDimitry Andric         wbe = wbuf + j;
53490b57cec5SDimitry Andric         __months_[i+12].assign(wbuf, wbe);
53500b57cec5SDimitry Andric     }
53510b57cec5SDimitry Andric     // __am_pm_
53520b57cec5SDimitry Andric     t.tm_hour = 1;
53530b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%p", &t, __loc_);
53540b57cec5SDimitry Andric     mb = mbstate_t();
53550b57cec5SDimitry Andric     const char* bb = buf;
53560b57cec5SDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
53570b57cec5SDimitry Andric     if (j == size_t(-1))
53580b57cec5SDimitry Andric         __throw_runtime_error("locale not supported");
53590b57cec5SDimitry Andric     wbe = wbuf + j;
53600b57cec5SDimitry Andric     __am_pm_[0].assign(wbuf, wbe);
53610b57cec5SDimitry Andric     t.tm_hour = 13;
53620b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%p", &t, __loc_);
53630b57cec5SDimitry Andric     mb = mbstate_t();
53640b57cec5SDimitry Andric     bb = buf;
53650b57cec5SDimitry Andric     j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
53660b57cec5SDimitry Andric     if (j == size_t(-1))
53670b57cec5SDimitry Andric         __throw_runtime_error("locale not supported");
53680b57cec5SDimitry Andric     wbe = wbuf + j;
53690b57cec5SDimitry Andric     __am_pm_[1].assign(wbuf, wbe);
53700b57cec5SDimitry Andric     __c_ = __analyze('c', ct);
53710b57cec5SDimitry Andric     __r_ = __analyze('r', ct);
53720b57cec5SDimitry Andric     __x_ = __analyze('x', ct);
53730b57cec5SDimitry Andric     __X_ = __analyze('X', ct);
53740b57cec5SDimitry Andric }
53750b57cec5SDimitry Andric 
53760b57cec5SDimitry Andric template <class CharT>
53770b57cec5SDimitry Andric struct _LIBCPP_HIDDEN __time_get_temp
53780b57cec5SDimitry Andric     : public ctype_byname<CharT>
53790b57cec5SDimitry Andric {
53800b57cec5SDimitry Andric     explicit __time_get_temp(const char* nm)
53810b57cec5SDimitry Andric         : ctype_byname<CharT>(nm, 1) {}
53820b57cec5SDimitry Andric     explicit __time_get_temp(const string& nm)
53830b57cec5SDimitry Andric         : ctype_byname<CharT>(nm, 1) {}
53840b57cec5SDimitry Andric };
53850b57cec5SDimitry Andric 
53860b57cec5SDimitry Andric template <>
53870b57cec5SDimitry Andric __time_get_storage<char>::__time_get_storage(const char* __nm)
53880b57cec5SDimitry Andric     : __time_get(__nm)
53890b57cec5SDimitry Andric {
53900b57cec5SDimitry Andric     const __time_get_temp<char> ct(__nm);
53910b57cec5SDimitry Andric     init(ct);
53920b57cec5SDimitry Andric }
53930b57cec5SDimitry Andric 
53940b57cec5SDimitry Andric template <>
53950b57cec5SDimitry Andric __time_get_storage<char>::__time_get_storage(const string& __nm)
53960b57cec5SDimitry Andric     : __time_get(__nm)
53970b57cec5SDimitry Andric {
53980b57cec5SDimitry Andric     const __time_get_temp<char> ct(__nm);
53990b57cec5SDimitry Andric     init(ct);
54000b57cec5SDimitry Andric }
54010b57cec5SDimitry Andric 
54020b57cec5SDimitry Andric template <>
54030b57cec5SDimitry Andric __time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
54040b57cec5SDimitry Andric     : __time_get(__nm)
54050b57cec5SDimitry Andric {
54060b57cec5SDimitry Andric     const __time_get_temp<wchar_t> ct(__nm);
54070b57cec5SDimitry Andric     init(ct);
54080b57cec5SDimitry Andric }
54090b57cec5SDimitry Andric 
54100b57cec5SDimitry Andric template <>
54110b57cec5SDimitry Andric __time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
54120b57cec5SDimitry Andric     : __time_get(__nm)
54130b57cec5SDimitry Andric {
54140b57cec5SDimitry Andric     const __time_get_temp<wchar_t> ct(__nm);
54150b57cec5SDimitry Andric     init(ct);
54160b57cec5SDimitry Andric }
54170b57cec5SDimitry Andric 
54180b57cec5SDimitry Andric template <>
54190b57cec5SDimitry Andric time_base::dateorder
54200b57cec5SDimitry Andric __time_get_storage<char>::__do_date_order() const
54210b57cec5SDimitry Andric {
54220b57cec5SDimitry Andric     unsigned i;
54230b57cec5SDimitry Andric     for (i = 0; i < __x_.size(); ++i)
54240b57cec5SDimitry Andric         if (__x_[i] == '%')
54250b57cec5SDimitry Andric             break;
54260b57cec5SDimitry Andric     ++i;
54270b57cec5SDimitry Andric     switch (__x_[i])
54280b57cec5SDimitry Andric     {
54290b57cec5SDimitry Andric     case 'y':
54300b57cec5SDimitry Andric     case 'Y':
54310b57cec5SDimitry Andric         for (++i; i < __x_.size(); ++i)
54320b57cec5SDimitry Andric             if (__x_[i] == '%')
54330b57cec5SDimitry Andric                 break;
54340b57cec5SDimitry Andric         if (i == __x_.size())
54350b57cec5SDimitry Andric             break;
54360b57cec5SDimitry Andric         ++i;
54370b57cec5SDimitry Andric         switch (__x_[i])
54380b57cec5SDimitry Andric         {
54390b57cec5SDimitry Andric         case 'm':
54400b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
54410b57cec5SDimitry Andric                 if (__x_[i] == '%')
54420b57cec5SDimitry Andric                     break;
54430b57cec5SDimitry Andric             if (i == __x_.size())
54440b57cec5SDimitry Andric                 break;
54450b57cec5SDimitry Andric             ++i;
54460b57cec5SDimitry Andric             if (__x_[i] == 'd')
54470b57cec5SDimitry Andric                 return time_base::ymd;
54480b57cec5SDimitry Andric             break;
54490b57cec5SDimitry Andric         case 'd':
54500b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
54510b57cec5SDimitry Andric                 if (__x_[i] == '%')
54520b57cec5SDimitry Andric                     break;
54530b57cec5SDimitry Andric             if (i == __x_.size())
54540b57cec5SDimitry Andric                 break;
54550b57cec5SDimitry Andric             ++i;
54560b57cec5SDimitry Andric             if (__x_[i] == 'm')
54570b57cec5SDimitry Andric                 return time_base::ydm;
54580b57cec5SDimitry Andric             break;
54590b57cec5SDimitry Andric         }
54600b57cec5SDimitry Andric         break;
54610b57cec5SDimitry Andric     case 'm':
54620b57cec5SDimitry Andric         for (++i; i < __x_.size(); ++i)
54630b57cec5SDimitry Andric             if (__x_[i] == '%')
54640b57cec5SDimitry Andric                 break;
54650b57cec5SDimitry Andric         if (i == __x_.size())
54660b57cec5SDimitry Andric             break;
54670b57cec5SDimitry Andric         ++i;
54680b57cec5SDimitry Andric         if (__x_[i] == 'd')
54690b57cec5SDimitry Andric         {
54700b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
54710b57cec5SDimitry Andric                 if (__x_[i] == '%')
54720b57cec5SDimitry Andric                     break;
54730b57cec5SDimitry Andric             if (i == __x_.size())
54740b57cec5SDimitry Andric                 break;
54750b57cec5SDimitry Andric             ++i;
54760b57cec5SDimitry Andric             if (__x_[i] == 'y' || __x_[i] == 'Y')
54770b57cec5SDimitry Andric                 return time_base::mdy;
54780b57cec5SDimitry Andric             break;
54790b57cec5SDimitry Andric         }
54800b57cec5SDimitry Andric         break;
54810b57cec5SDimitry Andric     case 'd':
54820b57cec5SDimitry Andric         for (++i; i < __x_.size(); ++i)
54830b57cec5SDimitry Andric             if (__x_[i] == '%')
54840b57cec5SDimitry Andric                 break;
54850b57cec5SDimitry Andric         if (i == __x_.size())
54860b57cec5SDimitry Andric             break;
54870b57cec5SDimitry Andric         ++i;
54880b57cec5SDimitry Andric         if (__x_[i] == 'm')
54890b57cec5SDimitry Andric         {
54900b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
54910b57cec5SDimitry Andric                 if (__x_[i] == '%')
54920b57cec5SDimitry Andric                     break;
54930b57cec5SDimitry Andric             if (i == __x_.size())
54940b57cec5SDimitry Andric                 break;
54950b57cec5SDimitry Andric             ++i;
54960b57cec5SDimitry Andric             if (__x_[i] == 'y' || __x_[i] == 'Y')
54970b57cec5SDimitry Andric                 return time_base::dmy;
54980b57cec5SDimitry Andric             break;
54990b57cec5SDimitry Andric         }
55000b57cec5SDimitry Andric         break;
55010b57cec5SDimitry Andric     }
55020b57cec5SDimitry Andric     return time_base::no_order;
55030b57cec5SDimitry Andric }
55040b57cec5SDimitry Andric 
55050b57cec5SDimitry Andric template <>
55060b57cec5SDimitry Andric time_base::dateorder
55070b57cec5SDimitry Andric __time_get_storage<wchar_t>::__do_date_order() const
55080b57cec5SDimitry Andric {
55090b57cec5SDimitry Andric     unsigned i;
55100b57cec5SDimitry Andric     for (i = 0; i < __x_.size(); ++i)
55110b57cec5SDimitry Andric         if (__x_[i] == L'%')
55120b57cec5SDimitry Andric             break;
55130b57cec5SDimitry Andric     ++i;
55140b57cec5SDimitry Andric     switch (__x_[i])
55150b57cec5SDimitry Andric     {
55160b57cec5SDimitry Andric     case L'y':
55170b57cec5SDimitry Andric     case L'Y':
55180b57cec5SDimitry Andric         for (++i; i < __x_.size(); ++i)
55190b57cec5SDimitry Andric             if (__x_[i] == L'%')
55200b57cec5SDimitry Andric                 break;
55210b57cec5SDimitry Andric         if (i == __x_.size())
55220b57cec5SDimitry Andric             break;
55230b57cec5SDimitry Andric         ++i;
55240b57cec5SDimitry Andric         switch (__x_[i])
55250b57cec5SDimitry Andric         {
55260b57cec5SDimitry Andric         case L'm':
55270b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
55280b57cec5SDimitry Andric                 if (__x_[i] == L'%')
55290b57cec5SDimitry Andric                     break;
55300b57cec5SDimitry Andric             if (i == __x_.size())
55310b57cec5SDimitry Andric                 break;
55320b57cec5SDimitry Andric             ++i;
55330b57cec5SDimitry Andric             if (__x_[i] == L'd')
55340b57cec5SDimitry Andric                 return time_base::ymd;
55350b57cec5SDimitry Andric             break;
55360b57cec5SDimitry Andric         case L'd':
55370b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
55380b57cec5SDimitry Andric                 if (__x_[i] == L'%')
55390b57cec5SDimitry Andric                     break;
55400b57cec5SDimitry Andric             if (i == __x_.size())
55410b57cec5SDimitry Andric                 break;
55420b57cec5SDimitry Andric             ++i;
55430b57cec5SDimitry Andric             if (__x_[i] == L'm')
55440b57cec5SDimitry Andric                 return time_base::ydm;
55450b57cec5SDimitry Andric             break;
55460b57cec5SDimitry Andric         }
55470b57cec5SDimitry Andric         break;
55480b57cec5SDimitry Andric     case L'm':
55490b57cec5SDimitry Andric         for (++i; i < __x_.size(); ++i)
55500b57cec5SDimitry Andric             if (__x_[i] == L'%')
55510b57cec5SDimitry Andric                 break;
55520b57cec5SDimitry Andric         if (i == __x_.size())
55530b57cec5SDimitry Andric             break;
55540b57cec5SDimitry Andric         ++i;
55550b57cec5SDimitry Andric         if (__x_[i] == L'd')
55560b57cec5SDimitry Andric         {
55570b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
55580b57cec5SDimitry Andric                 if (__x_[i] == L'%')
55590b57cec5SDimitry Andric                     break;
55600b57cec5SDimitry Andric             if (i == __x_.size())
55610b57cec5SDimitry Andric                 break;
55620b57cec5SDimitry Andric             ++i;
55630b57cec5SDimitry Andric             if (__x_[i] == L'y' || __x_[i] == L'Y')
55640b57cec5SDimitry Andric                 return time_base::mdy;
55650b57cec5SDimitry Andric             break;
55660b57cec5SDimitry Andric         }
55670b57cec5SDimitry Andric         break;
55680b57cec5SDimitry Andric     case L'd':
55690b57cec5SDimitry Andric         for (++i; i < __x_.size(); ++i)
55700b57cec5SDimitry Andric             if (__x_[i] == L'%')
55710b57cec5SDimitry Andric                 break;
55720b57cec5SDimitry Andric         if (i == __x_.size())
55730b57cec5SDimitry Andric             break;
55740b57cec5SDimitry Andric         ++i;
55750b57cec5SDimitry Andric         if (__x_[i] == L'm')
55760b57cec5SDimitry Andric         {
55770b57cec5SDimitry Andric             for (++i; i < __x_.size(); ++i)
55780b57cec5SDimitry Andric                 if (__x_[i] == L'%')
55790b57cec5SDimitry Andric                     break;
55800b57cec5SDimitry Andric             if (i == __x_.size())
55810b57cec5SDimitry Andric                 break;
55820b57cec5SDimitry Andric             ++i;
55830b57cec5SDimitry Andric             if (__x_[i] == L'y' || __x_[i] == L'Y')
55840b57cec5SDimitry Andric                 return time_base::dmy;
55850b57cec5SDimitry Andric             break;
55860b57cec5SDimitry Andric         }
55870b57cec5SDimitry Andric         break;
55880b57cec5SDimitry Andric     }
55890b57cec5SDimitry Andric     return time_base::no_order;
55900b57cec5SDimitry Andric }
55910b57cec5SDimitry Andric 
55920b57cec5SDimitry Andric // time_put
55930b57cec5SDimitry Andric 
55940b57cec5SDimitry Andric __time_put::__time_put(const char* nm)
55950b57cec5SDimitry Andric     : __loc_(newlocale(LC_ALL_MASK, nm, 0))
55960b57cec5SDimitry Andric {
55970b57cec5SDimitry Andric     if (__loc_ == 0)
55980b57cec5SDimitry Andric         __throw_runtime_error("time_put_byname"
55990b57cec5SDimitry Andric                             " failed to construct for " + string(nm));
56000b57cec5SDimitry Andric }
56010b57cec5SDimitry Andric 
56020b57cec5SDimitry Andric __time_put::__time_put(const string& nm)
56030b57cec5SDimitry Andric     : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
56040b57cec5SDimitry Andric {
56050b57cec5SDimitry Andric     if (__loc_ == 0)
56060b57cec5SDimitry Andric         __throw_runtime_error("time_put_byname"
56070b57cec5SDimitry Andric                             " failed to construct for " + nm);
56080b57cec5SDimitry Andric }
56090b57cec5SDimitry Andric 
56100b57cec5SDimitry Andric __time_put::~__time_put()
56110b57cec5SDimitry Andric {
56120b57cec5SDimitry Andric     if (__loc_ != _LIBCPP_GET_C_LOCALE)
56130b57cec5SDimitry Andric         freelocale(__loc_);
56140b57cec5SDimitry Andric }
56150b57cec5SDimitry Andric 
56160b57cec5SDimitry Andric void
56170b57cec5SDimitry Andric __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
56180b57cec5SDimitry Andric                      char __fmt, char __mod) const
56190b57cec5SDimitry Andric {
56200b57cec5SDimitry Andric     char fmt[] = {'%', __fmt, __mod, 0};
56210b57cec5SDimitry Andric     if (__mod != 0)
56220b57cec5SDimitry Andric         swap(fmt[1], fmt[2]);
56230b57cec5SDimitry Andric     size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
56240b57cec5SDimitry Andric     __ne = __nb + n;
56250b57cec5SDimitry Andric }
56260b57cec5SDimitry Andric 
56270b57cec5SDimitry Andric void
56280b57cec5SDimitry Andric __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
56290b57cec5SDimitry Andric                      char __fmt, char __mod) const
56300b57cec5SDimitry Andric {
56310b57cec5SDimitry Andric     char __nar[100];
56320b57cec5SDimitry Andric     char* __ne = __nar + 100;
56330b57cec5SDimitry Andric     __do_put(__nar, __ne, __tm, __fmt, __mod);
56340b57cec5SDimitry Andric     mbstate_t mb = {0};
56350b57cec5SDimitry Andric     const char* __nb = __nar;
56360b57cec5SDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
56370b57cec5SDimitry Andric     if (j == size_t(-1))
56380b57cec5SDimitry Andric         __throw_runtime_error("locale not supported");
56390b57cec5SDimitry Andric     __we = __wb + j;
56400b57cec5SDimitry Andric }
56410b57cec5SDimitry Andric 
56420b57cec5SDimitry Andric // moneypunct_byname
56430b57cec5SDimitry Andric 
56440b57cec5SDimitry Andric template <class charT>
56450b57cec5SDimitry Andric static
56460b57cec5SDimitry Andric void
56470b57cec5SDimitry Andric __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
56480b57cec5SDimitry Andric            bool intl, char cs_precedes, char sep_by_space, char sign_posn,
56490b57cec5SDimitry Andric            charT space_char)
56500b57cec5SDimitry Andric {
56510b57cec5SDimitry Andric     const char sign = static_cast<char>(money_base::sign);
56520b57cec5SDimitry Andric     const char space = static_cast<char>(money_base::space);
56530b57cec5SDimitry Andric     const char none = static_cast<char>(money_base::none);
56540b57cec5SDimitry Andric     const char symbol = static_cast<char>(money_base::symbol);
56550b57cec5SDimitry Andric     const char value = static_cast<char>(money_base::value);
56560b57cec5SDimitry Andric     const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
56570b57cec5SDimitry Andric 
56580b57cec5SDimitry Andric     // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
56590b57cec5SDimitry Andric     // function'. "Space between sign and symbol or value" means that
56600b57cec5SDimitry Andric     // if the sign is adjacent to the symbol, there's a space between
56610b57cec5SDimitry Andric     // them, and otherwise there's a space between the sign and value.
56620b57cec5SDimitry Andric     //
56630b57cec5SDimitry Andric     // C11's localeconv specifies that the fourth character of an
56640b57cec5SDimitry Andric     // international curr_symbol is used to separate the sign and
56650b57cec5SDimitry Andric     // value when sep_by_space says to do so. C++ can't represent
56660b57cec5SDimitry Andric     // that, so we just use a space.  When sep_by_space says to
56670b57cec5SDimitry Andric     // separate the symbol and value-or-sign with a space, we rearrange the
56680b57cec5SDimitry Andric     // curr_symbol to put its spacing character on the correct side of
56690b57cec5SDimitry Andric     // the symbol.
56700b57cec5SDimitry Andric     //
56710b57cec5SDimitry Andric     // We also need to avoid adding an extra space between the sign
56720b57cec5SDimitry Andric     // and value when the currency symbol is suppressed (by not
56730b57cec5SDimitry Andric     // setting showbase).  We match glibc's strfmon by interpreting
56740b57cec5SDimitry Andric     // sep_by_space==1 as "omit the space when the currency symbol is
56750b57cec5SDimitry Andric     // absent".
56760b57cec5SDimitry Andric     //
56770b57cec5SDimitry Andric     // Users who want to get this right should use ICU instead.
56780b57cec5SDimitry Andric 
56790b57cec5SDimitry Andric     switch (cs_precedes)
56800b57cec5SDimitry Andric     {
56810b57cec5SDimitry Andric     case 0:  // value before curr_symbol
56820b57cec5SDimitry Andric         if (symbol_contains_sep) {
56830b57cec5SDimitry Andric             // Move the separator to before the symbol, to place it
56840b57cec5SDimitry Andric             // between the value and symbol.
56850b57cec5SDimitry Andric             rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
56860b57cec5SDimitry Andric                    __curr_symbol_.end());
56870b57cec5SDimitry Andric         }
56880b57cec5SDimitry Andric         switch (sign_posn)
56890b57cec5SDimitry Andric         {
56900b57cec5SDimitry Andric         case 0:  // Parentheses surround the quantity and currency symbol.
56910b57cec5SDimitry Andric             pat.field[0] = sign;
56920b57cec5SDimitry Andric             pat.field[1] = value;
56930b57cec5SDimitry Andric             pat.field[2] = none;  // Any space appears in the symbol.
56940b57cec5SDimitry Andric             pat.field[3] = symbol;
56950b57cec5SDimitry Andric             switch (sep_by_space)
56960b57cec5SDimitry Andric             {
56970b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
56980b57cec5SDimitry Andric                 // This case may have changed between C99 and C11;
56990b57cec5SDimitry Andric                 // assume the currency symbol matches the intention.
57000b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
57010b57cec5SDimitry Andric                 // The "sign" is two parentheses, so no space here either.
57020b57cec5SDimitry Andric                 return;
57030b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
57040b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
57050b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
57060b57cec5SDimitry Andric                     // setting pat.field[2]=space so that when
57070b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
57080b57cec5SDimitry Andric                     __curr_symbol_.insert(0, 1, space_char);
57090b57cec5SDimitry Andric                 }
57100b57cec5SDimitry Andric                 return;
57110b57cec5SDimitry Andric             default:
57120b57cec5SDimitry Andric                 break;
57130b57cec5SDimitry Andric             }
57140b57cec5SDimitry Andric             break;
57150b57cec5SDimitry Andric         case 1:  // The sign string precedes the quantity and currency symbol.
57160b57cec5SDimitry Andric             pat.field[0] = sign;
57170b57cec5SDimitry Andric             pat.field[3] = symbol;
57180b57cec5SDimitry Andric             switch (sep_by_space)
57190b57cec5SDimitry Andric             {
57200b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
57210b57cec5SDimitry Andric                 pat.field[1] = value;
57220b57cec5SDimitry Andric                 pat.field[2] = none;
57230b57cec5SDimitry Andric                 return;
57240b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
57250b57cec5SDimitry Andric                 pat.field[1] = value;
57260b57cec5SDimitry Andric                 pat.field[2] = none;
57270b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
57280b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
57290b57cec5SDimitry Andric                     // setting pat.field[2]=space so that when
57300b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
57310b57cec5SDimitry Andric                     __curr_symbol_.insert(0, 1, space_char);
57320b57cec5SDimitry Andric                 }
57330b57cec5SDimitry Andric                 return;
57340b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
57350b57cec5SDimitry Andric                 pat.field[1] = space;
57360b57cec5SDimitry Andric                 pat.field[2] = value;
57370b57cec5SDimitry Andric                 if (symbol_contains_sep) {
57380b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
57390b57cec5SDimitry Andric                     // has already appeared after the sign.
57400b57cec5SDimitry Andric                     __curr_symbol_.erase(__curr_symbol_.begin());
57410b57cec5SDimitry Andric                 }
57420b57cec5SDimitry Andric                 return;
57430b57cec5SDimitry Andric             default:
57440b57cec5SDimitry Andric                 break;
57450b57cec5SDimitry Andric             }
57460b57cec5SDimitry Andric             break;
57470b57cec5SDimitry Andric         case 2:  // The sign string succeeds the quantity and currency symbol.
57480b57cec5SDimitry Andric             pat.field[0] = value;
57490b57cec5SDimitry Andric             pat.field[3] = sign;
57500b57cec5SDimitry Andric             switch (sep_by_space)
57510b57cec5SDimitry Andric             {
57520b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
57530b57cec5SDimitry Andric                 pat.field[1] = none;
57540b57cec5SDimitry Andric                 pat.field[2] = symbol;
57550b57cec5SDimitry Andric                 return;
57560b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
57570b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
57580b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
57590b57cec5SDimitry Andric                     // setting pat.field[1]=space so that when
57600b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
57610b57cec5SDimitry Andric                     __curr_symbol_.insert(0, 1, space_char);
57620b57cec5SDimitry Andric                 }
57630b57cec5SDimitry Andric                 pat.field[1] = none;
57640b57cec5SDimitry Andric                 pat.field[2] = symbol;
57650b57cec5SDimitry Andric                 return;
57660b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
57670b57cec5SDimitry Andric                 pat.field[1] = symbol;
57680b57cec5SDimitry Andric                 pat.field[2] = space;
57690b57cec5SDimitry Andric                 if (symbol_contains_sep) {
57700b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
57710b57cec5SDimitry Andric                     // should not be removed if showbase is absent.
57720b57cec5SDimitry Andric                     __curr_symbol_.erase(__curr_symbol_.begin());
57730b57cec5SDimitry Andric                 }
57740b57cec5SDimitry Andric                 return;
57750b57cec5SDimitry Andric             default:
57760b57cec5SDimitry Andric                 break;
57770b57cec5SDimitry Andric             }
57780b57cec5SDimitry Andric             break;
57790b57cec5SDimitry Andric         case 3:  // The sign string immediately precedes the currency symbol.
57800b57cec5SDimitry Andric             pat.field[0] = value;
57810b57cec5SDimitry Andric             pat.field[3] = symbol;
57820b57cec5SDimitry Andric             switch (sep_by_space)
57830b57cec5SDimitry Andric             {
57840b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
57850b57cec5SDimitry Andric                 pat.field[1] = none;
57860b57cec5SDimitry Andric                 pat.field[2] = sign;
57870b57cec5SDimitry Andric                 return;
57880b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
57890b57cec5SDimitry Andric                 pat.field[1] = space;
57900b57cec5SDimitry Andric                 pat.field[2] = sign;
57910b57cec5SDimitry Andric                 if (symbol_contains_sep) {
57920b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
57930b57cec5SDimitry Andric                     // has already appeared before the sign.
57940b57cec5SDimitry Andric                     __curr_symbol_.erase(__curr_symbol_.begin());
57950b57cec5SDimitry Andric                 }
57960b57cec5SDimitry Andric                 return;
57970b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
57980b57cec5SDimitry Andric                 pat.field[1] = sign;
57990b57cec5SDimitry Andric                 pat.field[2] = none;
58000b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
58010b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
58020b57cec5SDimitry Andric                     // setting pat.field[2]=space so that when
58030b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
58040b57cec5SDimitry Andric                     __curr_symbol_.insert(0, 1, space_char);
58050b57cec5SDimitry Andric                 }
58060b57cec5SDimitry Andric                 return;
58070b57cec5SDimitry Andric             default:
58080b57cec5SDimitry Andric                 break;
58090b57cec5SDimitry Andric             }
58100b57cec5SDimitry Andric             break;
58110b57cec5SDimitry Andric         case 4:  // The sign string immediately succeeds the currency symbol.
58120b57cec5SDimitry Andric             pat.field[0] = value;
58130b57cec5SDimitry Andric             pat.field[3] = sign;
58140b57cec5SDimitry Andric             switch (sep_by_space)
58150b57cec5SDimitry Andric             {
58160b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
58170b57cec5SDimitry Andric                 pat.field[1] = none;
58180b57cec5SDimitry Andric                 pat.field[2] = symbol;
58190b57cec5SDimitry Andric                 return;
58200b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
58210b57cec5SDimitry Andric                 pat.field[1] = none;
58220b57cec5SDimitry Andric                 pat.field[2] = symbol;
58230b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
58240b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
58250b57cec5SDimitry Andric                     // setting pat.field[1]=space so that when
58260b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
58270b57cec5SDimitry Andric                     __curr_symbol_.insert(0, 1, space_char);
58280b57cec5SDimitry Andric                 }
58290b57cec5SDimitry Andric                 return;
58300b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
58310b57cec5SDimitry Andric                 pat.field[1] = symbol;
58320b57cec5SDimitry Andric                 pat.field[2] = space;
58330b57cec5SDimitry Andric                 if (symbol_contains_sep) {
58340b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
58350b57cec5SDimitry Andric                     // should not disappear when showbase is absent.
58360b57cec5SDimitry Andric                     __curr_symbol_.erase(__curr_symbol_.begin());
58370b57cec5SDimitry Andric                 }
58380b57cec5SDimitry Andric                 return;
58390b57cec5SDimitry Andric             default:
58400b57cec5SDimitry Andric                 break;
58410b57cec5SDimitry Andric             }
58420b57cec5SDimitry Andric             break;
58430b57cec5SDimitry Andric         default:
58440b57cec5SDimitry Andric             break;
58450b57cec5SDimitry Andric         }
58460b57cec5SDimitry Andric         break;
58470b57cec5SDimitry Andric     case 1:  // curr_symbol before value
58480b57cec5SDimitry Andric         switch (sign_posn)
58490b57cec5SDimitry Andric         {
58500b57cec5SDimitry Andric         case 0:  // Parentheses surround the quantity and currency symbol.
58510b57cec5SDimitry Andric             pat.field[0] = sign;
58520b57cec5SDimitry Andric             pat.field[1] = symbol;
58530b57cec5SDimitry Andric             pat.field[2] = none;  // Any space appears in the symbol.
58540b57cec5SDimitry Andric             pat.field[3] = value;
58550b57cec5SDimitry Andric             switch (sep_by_space)
58560b57cec5SDimitry Andric             {
58570b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
58580b57cec5SDimitry Andric                 // This case may have changed between C99 and C11;
58590b57cec5SDimitry Andric                 // assume the currency symbol matches the intention.
58600b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
58610b57cec5SDimitry Andric                 // The "sign" is two parentheses, so no space here either.
58620b57cec5SDimitry Andric                 return;
58630b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
58640b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
58650b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
58660b57cec5SDimitry Andric                     // setting pat.field[2]=space so that when
58670b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
58680b57cec5SDimitry Andric                     __curr_symbol_.insert(0, 1, space_char);
58690b57cec5SDimitry Andric                 }
58700b57cec5SDimitry Andric                 return;
58710b57cec5SDimitry Andric             default:
58720b57cec5SDimitry Andric                 break;
58730b57cec5SDimitry Andric             }
58740b57cec5SDimitry Andric             break;
58750b57cec5SDimitry Andric         case 1:  // The sign string precedes the quantity and currency symbol.
58760b57cec5SDimitry Andric             pat.field[0] = sign;
58770b57cec5SDimitry Andric             pat.field[3] = value;
58780b57cec5SDimitry Andric             switch (sep_by_space)
58790b57cec5SDimitry Andric             {
58800b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
58810b57cec5SDimitry Andric                 pat.field[1] = symbol;
58820b57cec5SDimitry Andric                 pat.field[2] = none;
58830b57cec5SDimitry Andric                 return;
58840b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
58850b57cec5SDimitry Andric                 pat.field[1] = symbol;
58860b57cec5SDimitry Andric                 pat.field[2] = none;
58870b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
58880b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
58890b57cec5SDimitry Andric                     // setting pat.field[2]=space so that when
58900b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
58910b57cec5SDimitry Andric                     __curr_symbol_.push_back(space_char);
58920b57cec5SDimitry Andric                 }
58930b57cec5SDimitry Andric                 return;
58940b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
58950b57cec5SDimitry Andric                 pat.field[1] = space;
58960b57cec5SDimitry Andric                 pat.field[2] = symbol;
58970b57cec5SDimitry Andric                 if (symbol_contains_sep) {
58980b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
58990b57cec5SDimitry Andric                     // has already appeared after the sign.
59000b57cec5SDimitry Andric                     __curr_symbol_.pop_back();
59010b57cec5SDimitry Andric                 }
59020b57cec5SDimitry Andric                 return;
59030b57cec5SDimitry Andric             default:
59040b57cec5SDimitry Andric                 break;
59050b57cec5SDimitry Andric             }
59060b57cec5SDimitry Andric             break;
59070b57cec5SDimitry Andric         case 2:  // The sign string succeeds the quantity and currency symbol.
59080b57cec5SDimitry Andric             pat.field[0] = symbol;
59090b57cec5SDimitry Andric             pat.field[3] = sign;
59100b57cec5SDimitry Andric             switch (sep_by_space)
59110b57cec5SDimitry Andric             {
59120b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
59130b57cec5SDimitry Andric                 pat.field[1] = none;
59140b57cec5SDimitry Andric                 pat.field[2] = value;
59150b57cec5SDimitry Andric                 return;
59160b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
59170b57cec5SDimitry Andric                 pat.field[1] = none;
59180b57cec5SDimitry Andric                 pat.field[2] = value;
59190b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
59200b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
59210b57cec5SDimitry Andric                     // setting pat.field[1]=space so that when
59220b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
59230b57cec5SDimitry Andric                     __curr_symbol_.push_back(space_char);
59240b57cec5SDimitry Andric                 }
59250b57cec5SDimitry Andric                 return;
59260b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
59270b57cec5SDimitry Andric                 pat.field[1] = value;
59280b57cec5SDimitry Andric                 pat.field[2] = space;
59290b57cec5SDimitry Andric                 if (symbol_contains_sep) {
59300b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
59310b57cec5SDimitry Andric                     // will appear before the sign.
59320b57cec5SDimitry Andric                     __curr_symbol_.pop_back();
59330b57cec5SDimitry Andric                 }
59340b57cec5SDimitry Andric                 return;
59350b57cec5SDimitry Andric             default:
59360b57cec5SDimitry Andric                 break;
59370b57cec5SDimitry Andric             }
59380b57cec5SDimitry Andric             break;
59390b57cec5SDimitry Andric         case 3:  // The sign string immediately precedes the currency symbol.
59400b57cec5SDimitry Andric             pat.field[0] = sign;
59410b57cec5SDimitry Andric             pat.field[3] = value;
59420b57cec5SDimitry Andric             switch (sep_by_space)
59430b57cec5SDimitry Andric             {
59440b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
59450b57cec5SDimitry Andric                 pat.field[1] = symbol;
59460b57cec5SDimitry Andric                 pat.field[2] = none;
59470b57cec5SDimitry Andric                 return;
59480b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
59490b57cec5SDimitry Andric                 pat.field[1] = symbol;
59500b57cec5SDimitry Andric                 pat.field[2] = none;
59510b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
59520b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
59530b57cec5SDimitry Andric                     // setting pat.field[2]=space so that when
59540b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
59550b57cec5SDimitry Andric                     __curr_symbol_.push_back(space_char);
59560b57cec5SDimitry Andric                 }
59570b57cec5SDimitry Andric                 return;
59580b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
59590b57cec5SDimitry Andric                 pat.field[1] = space;
59600b57cec5SDimitry Andric                 pat.field[2] = symbol;
59610b57cec5SDimitry Andric                 if (symbol_contains_sep) {
59620b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
59630b57cec5SDimitry Andric                     // has already appeared after the sign.
59640b57cec5SDimitry Andric                     __curr_symbol_.pop_back();
59650b57cec5SDimitry Andric                 }
59660b57cec5SDimitry Andric                 return;
59670b57cec5SDimitry Andric             default:
59680b57cec5SDimitry Andric                 break;
59690b57cec5SDimitry Andric             }
59700b57cec5SDimitry Andric             break;
59710b57cec5SDimitry Andric         case 4:  // The sign string immediately succeeds the currency symbol.
59720b57cec5SDimitry Andric             pat.field[0] = symbol;
59730b57cec5SDimitry Andric             pat.field[3] = value;
59740b57cec5SDimitry Andric             switch (sep_by_space)
59750b57cec5SDimitry Andric             {
59760b57cec5SDimitry Andric             case 0:  // No space separates the currency symbol and value.
59770b57cec5SDimitry Andric                 pat.field[1] = sign;
59780b57cec5SDimitry Andric                 pat.field[2] = none;
59790b57cec5SDimitry Andric                 return;
59800b57cec5SDimitry Andric             case 1:  // Space between currency-and-sign or currency and value.
59810b57cec5SDimitry Andric                 pat.field[1] = sign;
59820b57cec5SDimitry Andric                 pat.field[2] = space;
59830b57cec5SDimitry Andric                 if (symbol_contains_sep) {
59840b57cec5SDimitry Andric                     // Remove the separator from the symbol, since it
59850b57cec5SDimitry Andric                     // should not disappear when showbase is absent.
59860b57cec5SDimitry Andric                     __curr_symbol_.pop_back();
59870b57cec5SDimitry Andric                 }
59880b57cec5SDimitry Andric                 return;
59890b57cec5SDimitry Andric             case 2:  // Space between sign and currency or value.
59900b57cec5SDimitry Andric                 pat.field[1] = none;
59910b57cec5SDimitry Andric                 pat.field[2] = sign;
59920b57cec5SDimitry Andric                 if (!symbol_contains_sep) {
59930b57cec5SDimitry Andric                     // We insert the space into the symbol instead of
59940b57cec5SDimitry Andric                     // setting pat.field[1]=space so that when
59950b57cec5SDimitry Andric                     // showbase is not set, the space goes away too.
59960b57cec5SDimitry Andric                     __curr_symbol_.push_back(space_char);
59970b57cec5SDimitry Andric                 }
59980b57cec5SDimitry Andric                 return;
59990b57cec5SDimitry Andric            default:
60000b57cec5SDimitry Andric                 break;
60010b57cec5SDimitry Andric             }
60020b57cec5SDimitry Andric             break;
60030b57cec5SDimitry Andric         default:
60040b57cec5SDimitry Andric             break;
60050b57cec5SDimitry Andric         }
60060b57cec5SDimitry Andric         break;
60070b57cec5SDimitry Andric     default:
60080b57cec5SDimitry Andric         break;
60090b57cec5SDimitry Andric     }
60100b57cec5SDimitry Andric     pat.field[0] = symbol;
60110b57cec5SDimitry Andric     pat.field[1] = sign;
60120b57cec5SDimitry Andric     pat.field[2] = none;
60130b57cec5SDimitry Andric     pat.field[3] = value;
60140b57cec5SDimitry Andric }
60150b57cec5SDimitry Andric 
60160b57cec5SDimitry Andric template<>
60170b57cec5SDimitry Andric void
60180b57cec5SDimitry Andric moneypunct_byname<char, false>::init(const char* nm)
60190b57cec5SDimitry Andric {
60200b57cec5SDimitry Andric     typedef moneypunct<char, false> base;
60210b57cec5SDimitry Andric     __libcpp_unique_locale loc(nm);
60220b57cec5SDimitry Andric     if (!loc)
60230b57cec5SDimitry Andric         __throw_runtime_error("moneypunct_byname"
60240b57cec5SDimitry Andric                             " failed to construct for " + string(nm));
60250b57cec5SDimitry Andric 
60260b57cec5SDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
60270b57cec5SDimitry Andric     if (!checked_string_to_char_convert(__decimal_point_,
60280b57cec5SDimitry Andric                                         lc->mon_decimal_point,
60290b57cec5SDimitry Andric                                         loc.get()))
60300b57cec5SDimitry Andric       __decimal_point_ = base::do_decimal_point();
60310b57cec5SDimitry Andric     if (!checked_string_to_char_convert(__thousands_sep_,
60320b57cec5SDimitry Andric                                         lc->mon_thousands_sep,
60330b57cec5SDimitry Andric                                         loc.get()))
60340b57cec5SDimitry Andric       __thousands_sep_ = base::do_thousands_sep();
60350b57cec5SDimitry Andric 
60360b57cec5SDimitry Andric     __grouping_ = lc->mon_grouping;
60370b57cec5SDimitry Andric     __curr_symbol_ = lc->currency_symbol;
60380b57cec5SDimitry Andric     if (lc->frac_digits != CHAR_MAX)
60390b57cec5SDimitry Andric         __frac_digits_ = lc->frac_digits;
60400b57cec5SDimitry Andric     else
60410b57cec5SDimitry Andric         __frac_digits_ = base::do_frac_digits();
60420b57cec5SDimitry Andric     if (lc->p_sign_posn == 0)
60430b57cec5SDimitry Andric         __positive_sign_ = "()";
60440b57cec5SDimitry Andric     else
60450b57cec5SDimitry Andric         __positive_sign_ = lc->positive_sign;
60460b57cec5SDimitry Andric     if (lc->n_sign_posn == 0)
60470b57cec5SDimitry Andric         __negative_sign_ = "()";
60480b57cec5SDimitry Andric     else
60490b57cec5SDimitry Andric         __negative_sign_ = lc->negative_sign;
60500b57cec5SDimitry Andric     // Assume the positive and negative formats will want spaces in
60510b57cec5SDimitry Andric     // the same places in curr_symbol since there's no way to
60520b57cec5SDimitry Andric     // represent anything else.
60530b57cec5SDimitry Andric     string_type __dummy_curr_symbol = __curr_symbol_;
60540b57cec5SDimitry Andric     __init_pat(__pos_format_, __dummy_curr_symbol, false,
60550b57cec5SDimitry Andric                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
60560b57cec5SDimitry Andric     __init_pat(__neg_format_, __curr_symbol_, false,
60570b57cec5SDimitry Andric                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
60580b57cec5SDimitry Andric }
60590b57cec5SDimitry Andric 
60600b57cec5SDimitry Andric template<>
60610b57cec5SDimitry Andric void
60620b57cec5SDimitry Andric moneypunct_byname<char, true>::init(const char* nm)
60630b57cec5SDimitry Andric {
60640b57cec5SDimitry Andric     typedef moneypunct<char, true> base;
60650b57cec5SDimitry Andric     __libcpp_unique_locale loc(nm);
60660b57cec5SDimitry Andric     if (!loc)
60670b57cec5SDimitry Andric         __throw_runtime_error("moneypunct_byname"
60680b57cec5SDimitry Andric                             " failed to construct for " + string(nm));
60690b57cec5SDimitry Andric 
60700b57cec5SDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
60710b57cec5SDimitry Andric     if (!checked_string_to_char_convert(__decimal_point_,
60720b57cec5SDimitry Andric                                         lc->mon_decimal_point,
60730b57cec5SDimitry Andric                                         loc.get()))
60740b57cec5SDimitry Andric       __decimal_point_ = base::do_decimal_point();
60750b57cec5SDimitry Andric     if (!checked_string_to_char_convert(__thousands_sep_,
60760b57cec5SDimitry Andric                                         lc->mon_thousands_sep,
60770b57cec5SDimitry Andric                                         loc.get()))
60780b57cec5SDimitry Andric       __thousands_sep_ = base::do_thousands_sep();
60790b57cec5SDimitry Andric     __grouping_ = lc->mon_grouping;
60800b57cec5SDimitry Andric     __curr_symbol_ = lc->int_curr_symbol;
60810b57cec5SDimitry Andric     if (lc->int_frac_digits != CHAR_MAX)
60820b57cec5SDimitry Andric         __frac_digits_ = lc->int_frac_digits;
60830b57cec5SDimitry Andric     else
60840b57cec5SDimitry Andric         __frac_digits_ = base::do_frac_digits();
60850b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
60860b57cec5SDimitry Andric     if (lc->p_sign_posn == 0)
60870b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT
60880b57cec5SDimitry Andric     if (lc->int_p_sign_posn == 0)
60890b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
60900b57cec5SDimitry Andric         __positive_sign_ = "()";
60910b57cec5SDimitry Andric     else
60920b57cec5SDimitry Andric         __positive_sign_ = lc->positive_sign;
60930b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
60940b57cec5SDimitry Andric     if(lc->n_sign_posn == 0)
60950b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT
60960b57cec5SDimitry Andric     if (lc->int_n_sign_posn == 0)
60970b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
60980b57cec5SDimitry Andric         __negative_sign_ = "()";
60990b57cec5SDimitry Andric     else
61000b57cec5SDimitry Andric         __negative_sign_ = lc->negative_sign;
61010b57cec5SDimitry Andric     // Assume the positive and negative formats will want spaces in
61020b57cec5SDimitry Andric     // the same places in curr_symbol since there's no way to
61030b57cec5SDimitry Andric     // represent anything else.
61040b57cec5SDimitry Andric     string_type __dummy_curr_symbol = __curr_symbol_;
61050b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
61060b57cec5SDimitry Andric     __init_pat(__pos_format_, __dummy_curr_symbol, true,
61070b57cec5SDimitry Andric                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
61080b57cec5SDimitry Andric     __init_pat(__neg_format_, __curr_symbol_, true,
61090b57cec5SDimitry Andric                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
61100b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT
61110b57cec5SDimitry Andric     __init_pat(__pos_format_, __dummy_curr_symbol, true,
61120b57cec5SDimitry Andric                lc->int_p_cs_precedes, lc->int_p_sep_by_space,
61130b57cec5SDimitry Andric                lc->int_p_sign_posn, ' ');
61140b57cec5SDimitry Andric     __init_pat(__neg_format_, __curr_symbol_, true,
61150b57cec5SDimitry Andric                lc->int_n_cs_precedes, lc->int_n_sep_by_space,
61160b57cec5SDimitry Andric                lc->int_n_sign_posn, ' ');
61170b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
61180b57cec5SDimitry Andric }
61190b57cec5SDimitry Andric 
61200b57cec5SDimitry Andric template<>
61210b57cec5SDimitry Andric void
61220b57cec5SDimitry Andric moneypunct_byname<wchar_t, false>::init(const char* nm)
61230b57cec5SDimitry Andric {
61240b57cec5SDimitry Andric     typedef moneypunct<wchar_t, false> base;
61250b57cec5SDimitry Andric     __libcpp_unique_locale loc(nm);
61260b57cec5SDimitry Andric     if (!loc)
61270b57cec5SDimitry Andric         __throw_runtime_error("moneypunct_byname"
61280b57cec5SDimitry Andric                             " failed to construct for " + string(nm));
61290b57cec5SDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
61300b57cec5SDimitry Andric     if (!checked_string_to_wchar_convert(__decimal_point_,
61310b57cec5SDimitry Andric                                          lc->mon_decimal_point,
61320b57cec5SDimitry Andric                                          loc.get()))
61330b57cec5SDimitry Andric       __decimal_point_ = base::do_decimal_point();
61340b57cec5SDimitry Andric     if (!checked_string_to_wchar_convert(__thousands_sep_,
61350b57cec5SDimitry Andric                                          lc->mon_thousands_sep,
61360b57cec5SDimitry Andric                                          loc.get()))
61370b57cec5SDimitry Andric       __thousands_sep_ = base::do_thousands_sep();
61380b57cec5SDimitry Andric     __grouping_ = lc->mon_grouping;
61390b57cec5SDimitry Andric     wchar_t wbuf[100];
61400b57cec5SDimitry Andric     mbstate_t mb = {0};
61410b57cec5SDimitry Andric     const char* bb = lc->currency_symbol;
61420b57cec5SDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
61430b57cec5SDimitry Andric     if (j == size_t(-1))
61440b57cec5SDimitry Andric         __throw_runtime_error("locale not supported");
61450b57cec5SDimitry Andric     wchar_t* wbe = wbuf + j;
61460b57cec5SDimitry Andric     __curr_symbol_.assign(wbuf, wbe);
61470b57cec5SDimitry Andric     if (lc->frac_digits != CHAR_MAX)
61480b57cec5SDimitry Andric         __frac_digits_ = lc->frac_digits;
61490b57cec5SDimitry Andric     else
61500b57cec5SDimitry Andric         __frac_digits_ = base::do_frac_digits();
61510b57cec5SDimitry Andric     if (lc->p_sign_posn == 0)
61520b57cec5SDimitry Andric         __positive_sign_ = L"()";
61530b57cec5SDimitry Andric     else
61540b57cec5SDimitry Andric     {
61550b57cec5SDimitry Andric         mb = mbstate_t();
61560b57cec5SDimitry Andric         bb = lc->positive_sign;
61570b57cec5SDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
61580b57cec5SDimitry Andric         if (j == size_t(-1))
61590b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
61600b57cec5SDimitry Andric         wbe = wbuf + j;
61610b57cec5SDimitry Andric         __positive_sign_.assign(wbuf, wbe);
61620b57cec5SDimitry Andric     }
61630b57cec5SDimitry Andric     if (lc->n_sign_posn == 0)
61640b57cec5SDimitry Andric         __negative_sign_ = L"()";
61650b57cec5SDimitry Andric     else
61660b57cec5SDimitry Andric     {
61670b57cec5SDimitry Andric         mb = mbstate_t();
61680b57cec5SDimitry Andric         bb = lc->negative_sign;
61690b57cec5SDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
61700b57cec5SDimitry Andric         if (j == size_t(-1))
61710b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
61720b57cec5SDimitry Andric         wbe = wbuf + j;
61730b57cec5SDimitry Andric         __negative_sign_.assign(wbuf, wbe);
61740b57cec5SDimitry Andric     }
61750b57cec5SDimitry Andric     // Assume the positive and negative formats will want spaces in
61760b57cec5SDimitry Andric     // the same places in curr_symbol since there's no way to
61770b57cec5SDimitry Andric     // represent anything else.
61780b57cec5SDimitry Andric     string_type __dummy_curr_symbol = __curr_symbol_;
61790b57cec5SDimitry Andric     __init_pat(__pos_format_, __dummy_curr_symbol, false,
61800b57cec5SDimitry Andric                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
61810b57cec5SDimitry Andric     __init_pat(__neg_format_, __curr_symbol_, false,
61820b57cec5SDimitry Andric                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
61830b57cec5SDimitry Andric }
61840b57cec5SDimitry Andric 
61850b57cec5SDimitry Andric template<>
61860b57cec5SDimitry Andric void
61870b57cec5SDimitry Andric moneypunct_byname<wchar_t, true>::init(const char* nm)
61880b57cec5SDimitry Andric {
61890b57cec5SDimitry Andric     typedef moneypunct<wchar_t, true> base;
61900b57cec5SDimitry Andric     __libcpp_unique_locale loc(nm);
61910b57cec5SDimitry Andric     if (!loc)
61920b57cec5SDimitry Andric         __throw_runtime_error("moneypunct_byname"
61930b57cec5SDimitry Andric                             " failed to construct for " + string(nm));
61940b57cec5SDimitry Andric 
61950b57cec5SDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
61960b57cec5SDimitry Andric     if (!checked_string_to_wchar_convert(__decimal_point_,
61970b57cec5SDimitry Andric                                          lc->mon_decimal_point,
61980b57cec5SDimitry Andric                                          loc.get()))
61990b57cec5SDimitry Andric       __decimal_point_ = base::do_decimal_point();
62000b57cec5SDimitry Andric     if (!checked_string_to_wchar_convert(__thousands_sep_,
62010b57cec5SDimitry Andric                                          lc->mon_thousands_sep,
62020b57cec5SDimitry Andric                                          loc.get()))
62030b57cec5SDimitry Andric       __thousands_sep_ = base::do_thousands_sep();
62040b57cec5SDimitry Andric     __grouping_ = lc->mon_grouping;
62050b57cec5SDimitry Andric     wchar_t wbuf[100];
62060b57cec5SDimitry Andric     mbstate_t mb = {0};
62070b57cec5SDimitry Andric     const char* bb = lc->int_curr_symbol;
62080b57cec5SDimitry Andric     size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
62090b57cec5SDimitry Andric     if (j == size_t(-1))
62100b57cec5SDimitry Andric         __throw_runtime_error("locale not supported");
62110b57cec5SDimitry Andric     wchar_t* wbe = wbuf + j;
62120b57cec5SDimitry Andric     __curr_symbol_.assign(wbuf, wbe);
62130b57cec5SDimitry Andric     if (lc->int_frac_digits != CHAR_MAX)
62140b57cec5SDimitry Andric         __frac_digits_ = lc->int_frac_digits;
62150b57cec5SDimitry Andric     else
62160b57cec5SDimitry Andric         __frac_digits_ = base::do_frac_digits();
62170b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
62180b57cec5SDimitry Andric     if (lc->p_sign_posn == 0)
62190b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT
62200b57cec5SDimitry Andric     if (lc->int_p_sign_posn == 0)
62210b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
62220b57cec5SDimitry Andric         __positive_sign_ = L"()";
62230b57cec5SDimitry Andric     else
62240b57cec5SDimitry Andric     {
62250b57cec5SDimitry Andric         mb = mbstate_t();
62260b57cec5SDimitry Andric         bb = lc->positive_sign;
62270b57cec5SDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
62280b57cec5SDimitry Andric         if (j == size_t(-1))
62290b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
62300b57cec5SDimitry Andric         wbe = wbuf + j;
62310b57cec5SDimitry Andric         __positive_sign_.assign(wbuf, wbe);
62320b57cec5SDimitry Andric     }
62330b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
62340b57cec5SDimitry Andric     if (lc->n_sign_posn == 0)
62350b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT
62360b57cec5SDimitry Andric     if (lc->int_n_sign_posn == 0)
62370b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
62380b57cec5SDimitry Andric         __negative_sign_ = L"()";
62390b57cec5SDimitry Andric     else
62400b57cec5SDimitry Andric     {
62410b57cec5SDimitry Andric         mb = mbstate_t();
62420b57cec5SDimitry Andric         bb = lc->negative_sign;
62430b57cec5SDimitry Andric         j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
62440b57cec5SDimitry Andric         if (j == size_t(-1))
62450b57cec5SDimitry Andric             __throw_runtime_error("locale not supported");
62460b57cec5SDimitry Andric         wbe = wbuf + j;
62470b57cec5SDimitry Andric         __negative_sign_.assign(wbuf, wbe);
62480b57cec5SDimitry Andric     }
62490b57cec5SDimitry Andric     // Assume the positive and negative formats will want spaces in
62500b57cec5SDimitry Andric     // the same places in curr_symbol since there's no way to
62510b57cec5SDimitry Andric     // represent anything else.
62520b57cec5SDimitry Andric     string_type __dummy_curr_symbol = __curr_symbol_;
62530b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
62540b57cec5SDimitry Andric     __init_pat(__pos_format_, __dummy_curr_symbol, true,
62550b57cec5SDimitry Andric                lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
62560b57cec5SDimitry Andric     __init_pat(__neg_format_, __curr_symbol_, true,
62570b57cec5SDimitry Andric                lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
62580b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT
62590b57cec5SDimitry Andric     __init_pat(__pos_format_, __dummy_curr_symbol, true,
62600b57cec5SDimitry Andric                lc->int_p_cs_precedes, lc->int_p_sep_by_space,
62610b57cec5SDimitry Andric                lc->int_p_sign_posn, L' ');
62620b57cec5SDimitry Andric     __init_pat(__neg_format_, __curr_symbol_, true,
62630b57cec5SDimitry Andric                lc->int_n_cs_precedes, lc->int_n_sep_by_space,
62640b57cec5SDimitry Andric                lc->int_n_sign_posn, L' ');
62650b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
62660b57cec5SDimitry Andric }
62670b57cec5SDimitry Andric 
62680b57cec5SDimitry Andric void __do_nothing(void*) {}
62690b57cec5SDimitry Andric 
62700b57cec5SDimitry Andric void __throw_runtime_error(const char* msg)
62710b57cec5SDimitry Andric {
62720b57cec5SDimitry Andric #ifndef _LIBCPP_NO_EXCEPTIONS
62730b57cec5SDimitry Andric     throw runtime_error(msg);
62740b57cec5SDimitry Andric #else
62750b57cec5SDimitry Andric     (void)msg;
62760b57cec5SDimitry Andric     _VSTD::abort();
62770b57cec5SDimitry Andric #endif
62780b57cec5SDimitry Andric }
62790b57cec5SDimitry Andric 
62800b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
62810b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
62820b57cec5SDimitry Andric 
62830b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
62840b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
62850b57cec5SDimitry Andric 
62860b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
62870b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
62880b57cec5SDimitry Andric 
62890b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
62900b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
62910b57cec5SDimitry Andric 
62920b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
62930b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
62940b57cec5SDimitry Andric 
62950b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
62960b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
62970b57cec5SDimitry Andric 
62980b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
62990b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
63000b57cec5SDimitry Andric 
63010b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
63020b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
63030b57cec5SDimitry Andric 
63040b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
63050b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
63060b57cec5SDimitry Andric 
63070b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
63080b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
63090b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
63100b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
63110b57cec5SDimitry Andric 
63120b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
63130b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
63140b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
63150b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
63160b57cec5SDimitry Andric 
63170b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
63180b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
63190b57cec5SDimitry Andric 
63200b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
63210b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
63220b57cec5SDimitry Andric 
63230b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
63240b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
63250b57cec5SDimitry Andric 
63260b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
63270b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
63280b57cec5SDimitry Andric 
63290b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
63300b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
63310b57cec5SDimitry Andric 
63320b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
63330b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
63340b57cec5SDimitry Andric 
63350b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
63360b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6337*e8d8bef9SDimitry Andric template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6338*e8d8bef9SDimitry Andric template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
6339*e8d8bef9SDimitry Andric #ifndef _LIBCPP_NO_HAS_CHAR8_T
6340*e8d8bef9SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6341*e8d8bef9SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6342*e8d8bef9SDimitry Andric #endif
63430b57cec5SDimitry Andric 
63440b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
6345