1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 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 95f757f3fSDimitry Andric #include <__utility/no_destroy.h> 1081ad6265SDimitry Andric #include <algorithm> 1181ad6265SDimitry Andric #include <clocale> 1281ad6265SDimitry Andric #include <codecvt> 135f757f3fSDimitry Andric #include <cstddef> 1481ad6265SDimitry Andric #include <cstdio> 1581ad6265SDimitry Andric #include <cstdlib> 1681ad6265SDimitry Andric #include <cstring> 1781ad6265SDimitry Andric #include <locale> 185f757f3fSDimitry Andric #include <new> 1981ad6265SDimitry Andric #include <string> 2081ad6265SDimitry Andric #include <type_traits> 2181ad6265SDimitry Andric #include <typeinfo> 225f757f3fSDimitry Andric #include <utility> 2381ad6265SDimitry Andric #include <vector> 24349cc55cSDimitry Andric 25349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2681ad6265SDimitry Andric # include <cwctype> 27349cc55cSDimitry Andric #endif 28349cc55cSDimitry Andric 29349cc55cSDimitry Andric #if defined(_AIX) 30349cc55cSDimitry Andric # include <sys/localedef.h> // for __lc_ctype_ptr 31349cc55cSDimitry Andric #endif 32349cc55cSDimitry Andric 330b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) 340b57cec5SDimitry Andric # define _CTYPE_DISABLE_MACROS 350b57cec5SDimitry Andric #endif 36349cc55cSDimitry Andric 370b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 38d409305fSDimitry Andric # include "__support/win32/locale_win32.h" 39e8d8bef9SDimitry Andric #elif !defined(__BIONIC__) && !defined(__NuttX__) 400b57cec5SDimitry Andric # include <langinfo.h> 410b57cec5SDimitry Andric #endif 42349cc55cSDimitry Andric 430b57cec5SDimitry Andric #include "include/atomic_support.h" 44fe6060f1SDimitry Andric #include "include/sso_allocator.h" 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric // On Linux, wint_t and wchar_t have different signed-ness, and this causes 470b57cec5SDimitry Andric // lots of noise in the build log, but no bugs that I know of. 4881ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion") 4981ad6265SDimitry Andric 5081ad6265SDimitry Andric _LIBCPP_PUSH_MACROS 5181ad6265SDimitry Andric #include <__undef_macros> 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric struct __libcpp_unique_locale { 560b57cec5SDimitry Andric __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {} 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric ~__libcpp_unique_locale() { 590b57cec5SDimitry Andric if (__loc_) 600b57cec5SDimitry Andric freelocale(__loc_); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric explicit operator bool() const { return __loc_; } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric locale_t& get() { return __loc_; } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric locale_t __loc_; 68*cb14a3feSDimitry Andric 690b57cec5SDimitry Andric private: 700b57cec5SDimitry Andric __libcpp_unique_locale(__libcpp_unique_locale const&); 710b57cec5SDimitry Andric __libcpp_unique_locale& operator=(__libcpp_unique_locale const&); 720b57cec5SDimitry Andric }; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric #ifdef __cloc_defined 750b57cec5SDimitry Andric locale_t __cloc() { 760b57cec5SDimitry Andric // In theory this could create a race condition. In practice 770b57cec5SDimitry Andric // the race condition is non-fatal since it will just create 780b57cec5SDimitry Andric // a little resource leak. Better approach would be appreciated. 790b57cec5SDimitry Andric static locale_t result = newlocale(LC_ALL_MASK, "C", 0); 800b57cec5SDimitry Andric return result; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric #endif // __cloc_defined 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric namespace { 850b57cec5SDimitry Andric 865f757f3fSDimitry Andric struct releaser { 870b57cec5SDimitry Andric void operator()(locale::facet* p) { p->__release_shared(); } 880b57cec5SDimitry Andric }; 890b57cec5SDimitry Andric 90349cc55cSDimitry Andric template <class T, class... Args> 91*cb14a3feSDimitry Andric T& make(Args... args) { 925f757f3fSDimitry Andric alignas(T) static std::byte buf[sizeof(T)]; 93349cc55cSDimitry Andric auto* obj = ::new (&buf) T(args...); 940b57cec5SDimitry Andric return *obj; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric template <typename T, size_t N> 98*cb14a3feSDimitry Andric inline constexpr size_t countof(const T (&)[N]) { 990b57cec5SDimitry Andric return N; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric template <typename T> 103*cb14a3feSDimitry Andric inline constexpr size_t countof(const T* const begin, const T* const end) { 1040b57cec5SDimitry Andric return static_cast<size_t>(end - begin); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 107*cb14a3feSDimitry Andric } // namespace 1080b57cec5SDimitry Andric 109*cb14a3feSDimitry Andric string build_name(const string& other, const string& one, locale::category c) { 11006c3fb27SDimitry Andric if (other == "*" || one == "*") 11106c3fb27SDimitry Andric return "*"; 11206c3fb27SDimitry Andric if (c == locale::none || other == one) 11306c3fb27SDimitry Andric return other; 11406c3fb27SDimitry Andric 11506c3fb27SDimitry Andric // FIXME: Handle the more complicated cases, such as when the locale has 11606c3fb27SDimitry Andric // different names for different categories. 11706c3fb27SDimitry Andric return "*"; 11806c3fb27SDimitry Andric } 11906c3fb27SDimitry Andric 1200b57cec5SDimitry Andric const locale::category locale::none; 1210b57cec5SDimitry Andric const locale::category locale::collate; 1220b57cec5SDimitry Andric const locale::category locale::ctype; 1230b57cec5SDimitry Andric const locale::category locale::monetary; 1240b57cec5SDimitry Andric const locale::category locale::numeric; 1250b57cec5SDimitry Andric const locale::category locale::time; 1260b57cec5SDimitry Andric const locale::category locale::messages; 1270b57cec5SDimitry Andric const locale::category locale::all; 1280b57cec5SDimitry Andric 129*cb14a3feSDimitry Andric class _LIBCPP_HIDDEN locale::__imp : public facet { 130e8d8bef9SDimitry Andric enum { N = 30 }; 1310b57cec5SDimitry Andric vector<facet*, __sso_allocator<facet*, N> > facets_; 1320b57cec5SDimitry Andric string name_; 133*cb14a3feSDimitry Andric 1340b57cec5SDimitry Andric public: 1350b57cec5SDimitry Andric explicit __imp(size_t refs = 0); 1360b57cec5SDimitry Andric explicit __imp(const string& name, size_t refs = 0); 1370b57cec5SDimitry Andric __imp(const __imp&); 1380b57cec5SDimitry Andric __imp(const __imp&, const string&, locale::category c); 1390b57cec5SDimitry Andric __imp(const __imp& other, const __imp& one, locale::category c); 1400b57cec5SDimitry Andric __imp(const __imp&, facet* f, long id); 1410b57cec5SDimitry Andric ~__imp(); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric const string& name() const { return name_; } 144*cb14a3feSDimitry Andric bool has_facet(long id) const { return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)]; } 1450b57cec5SDimitry Andric const locale::facet* use_facet(long id) const; 1460b57cec5SDimitry Andric 1475f757f3fSDimitry Andric void acquire(); 1485f757f3fSDimitry Andric void release(); 1495f757f3fSDimitry Andric static __no_destroy<__imp> classic_locale_imp_; 1505f757f3fSDimitry Andric 1510b57cec5SDimitry Andric private: 1520b57cec5SDimitry Andric void install(facet* f, long id); 153*cb14a3feSDimitry Andric template <class F> 154*cb14a3feSDimitry Andric void install(F* f) { 155*cb14a3feSDimitry Andric install(f, f->id.__get()); 156*cb14a3feSDimitry Andric } 157*cb14a3feSDimitry Andric template <class F> 158*cb14a3feSDimitry Andric void install_from(const __imp& other); 1590b57cec5SDimitry Andric }; 1600b57cec5SDimitry Andric 161*cb14a3feSDimitry Andric locale::__imp::__imp(size_t refs) : facet(refs), facets_(N), name_("C") { 1620b57cec5SDimitry Andric facets_.clear(); 1635f757f3fSDimitry Andric install(&make<std::collate<char> >(1u)); 164349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1655f757f3fSDimitry Andric install(&make<std::collate<wchar_t> >(1u)); 166349cc55cSDimitry Andric #endif 1675f757f3fSDimitry Andric install(&make<std::ctype<char> >(nullptr, false, 1u)); 168349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1695f757f3fSDimitry Andric install(&make<std::ctype<wchar_t> >(1u)); 170349cc55cSDimitry Andric #endif 1710b57cec5SDimitry Andric install(&make<codecvt<char, char, mbstate_t> >(1u)); 172349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1730b57cec5SDimitry Andric install(&make<codecvt<wchar_t, char, mbstate_t> >(1u)); 174349cc55cSDimitry Andric #endif 175e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 1760b57cec5SDimitry Andric install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); 1770b57cec5SDimitry Andric install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); 178e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 179fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 180e8d8bef9SDimitry Andric install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u)); 181e8d8bef9SDimitry Andric install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u)); 182e8d8bef9SDimitry Andric #endif 1830b57cec5SDimitry Andric install(&make<numpunct<char> >(1u)); 184349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1850b57cec5SDimitry Andric install(&make<numpunct<wchar_t> >(1u)); 186349cc55cSDimitry Andric #endif 1870b57cec5SDimitry Andric install(&make<num_get<char> >(1u)); 188349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1890b57cec5SDimitry Andric install(&make<num_get<wchar_t> >(1u)); 190349cc55cSDimitry Andric #endif 1910b57cec5SDimitry Andric install(&make<num_put<char> >(1u)); 192349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1930b57cec5SDimitry Andric install(&make<num_put<wchar_t> >(1u)); 194349cc55cSDimitry Andric #endif 1950b57cec5SDimitry Andric install(&make<moneypunct<char, false> >(1u)); 1960b57cec5SDimitry Andric install(&make<moneypunct<char, true> >(1u)); 197349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 1980b57cec5SDimitry Andric install(&make<moneypunct<wchar_t, false> >(1u)); 1990b57cec5SDimitry Andric install(&make<moneypunct<wchar_t, true> >(1u)); 200349cc55cSDimitry Andric #endif 2010b57cec5SDimitry Andric install(&make<money_get<char> >(1u)); 202349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2030b57cec5SDimitry Andric install(&make<money_get<wchar_t> >(1u)); 204349cc55cSDimitry Andric #endif 2050b57cec5SDimitry Andric install(&make<money_put<char> >(1u)); 206349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2070b57cec5SDimitry Andric install(&make<money_put<wchar_t> >(1u)); 208349cc55cSDimitry Andric #endif 2090b57cec5SDimitry Andric install(&make<time_get<char> >(1u)); 210349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2110b57cec5SDimitry Andric install(&make<time_get<wchar_t> >(1u)); 212349cc55cSDimitry Andric #endif 2130b57cec5SDimitry Andric install(&make<time_put<char> >(1u)); 214349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2150b57cec5SDimitry Andric install(&make<time_put<wchar_t> >(1u)); 216349cc55cSDimitry Andric #endif 2175f757f3fSDimitry Andric install(&make<std::messages<char> >(1u)); 218349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2195f757f3fSDimitry Andric install(&make<std::messages<wchar_t> >(1u)); 220349cc55cSDimitry Andric #endif 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 223*cb14a3feSDimitry Andric locale::__imp::__imp(const string& name, size_t refs) : facet(refs), facets_(N), name_(name) { 22406c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 225*cb14a3feSDimitry Andric try { 22606c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 2270b57cec5SDimitry Andric facets_ = locale::classic().__locale_->facets_; 2280b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 2290b57cec5SDimitry Andric if (facets_[i]) 2300b57cec5SDimitry Andric facets_[i]->__add_shared(); 2310b57cec5SDimitry Andric install(new collate_byname<char>(name_)); 232349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2330b57cec5SDimitry Andric install(new collate_byname<wchar_t>(name_)); 234349cc55cSDimitry Andric #endif 2350b57cec5SDimitry Andric install(new ctype_byname<char>(name_)); 236349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2370b57cec5SDimitry Andric install(new ctype_byname<wchar_t>(name_)); 238349cc55cSDimitry Andric #endif 2390b57cec5SDimitry Andric install(new codecvt_byname<char, char, mbstate_t>(name_)); 240349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2410b57cec5SDimitry Andric install(new codecvt_byname<wchar_t, char, mbstate_t>(name_)); 242349cc55cSDimitry Andric #endif 243e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 2440b57cec5SDimitry Andric install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); 2450b57cec5SDimitry Andric install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); 246e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 247fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 248e8d8bef9SDimitry Andric install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_)); 249e8d8bef9SDimitry Andric install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_)); 250e8d8bef9SDimitry Andric #endif 2510b57cec5SDimitry Andric install(new numpunct_byname<char>(name_)); 252349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2530b57cec5SDimitry Andric install(new numpunct_byname<wchar_t>(name_)); 254349cc55cSDimitry Andric #endif 2550b57cec5SDimitry Andric install(new moneypunct_byname<char, false>(name_)); 2560b57cec5SDimitry Andric install(new moneypunct_byname<char, true>(name_)); 257349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2580b57cec5SDimitry Andric install(new moneypunct_byname<wchar_t, false>(name_)); 2590b57cec5SDimitry Andric install(new moneypunct_byname<wchar_t, true>(name_)); 260349cc55cSDimitry Andric #endif 2610b57cec5SDimitry Andric install(new time_get_byname<char>(name_)); 262349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2630b57cec5SDimitry Andric install(new time_get_byname<wchar_t>(name_)); 264349cc55cSDimitry Andric #endif 2650b57cec5SDimitry Andric install(new time_put_byname<char>(name_)); 266349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2670b57cec5SDimitry Andric install(new time_put_byname<wchar_t>(name_)); 268349cc55cSDimitry Andric #endif 2690b57cec5SDimitry Andric install(new messages_byname<char>(name_)); 270349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2710b57cec5SDimitry Andric install(new messages_byname<wchar_t>(name_)); 272349cc55cSDimitry Andric #endif 27306c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 274*cb14a3feSDimitry Andric } catch (...) { 2750b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 2760b57cec5SDimitry Andric if (facets_[i]) 2770b57cec5SDimitry Andric facets_[i]->__release_shared(); 2780b57cec5SDimitry Andric throw; 2790b57cec5SDimitry Andric } 28006c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 283*cb14a3feSDimitry Andric locale::__imp::__imp(const __imp& other) : facets_(max<size_t>(N, other.facets_.size())), name_(other.name_) { 2840b57cec5SDimitry Andric facets_ = other.facets_; 2850b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 2860b57cec5SDimitry Andric if (facets_[i]) 2870b57cec5SDimitry Andric facets_[i]->__add_shared(); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, const string& name, locale::category c) 291*cb14a3feSDimitry Andric : facets_(N), name_(build_name(other.name_, name, c)) { 2920b57cec5SDimitry Andric facets_ = other.facets_; 2930b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 2940b57cec5SDimitry Andric if (facets_[i]) 2950b57cec5SDimitry Andric facets_[i]->__add_shared(); 29606c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 297*cb14a3feSDimitry Andric try { 29806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 299*cb14a3feSDimitry Andric if (c & locale::collate) { 3000b57cec5SDimitry Andric install(new collate_byname<char>(name)); 301349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3020b57cec5SDimitry Andric install(new collate_byname<wchar_t>(name)); 303349cc55cSDimitry Andric #endif 3040b57cec5SDimitry Andric } 305*cb14a3feSDimitry Andric if (c & locale::ctype) { 3060b57cec5SDimitry Andric install(new ctype_byname<char>(name)); 307349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3080b57cec5SDimitry Andric install(new ctype_byname<wchar_t>(name)); 309349cc55cSDimitry Andric #endif 3100b57cec5SDimitry Andric install(new codecvt_byname<char, char, mbstate_t>(name)); 311349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3120b57cec5SDimitry Andric install(new codecvt_byname<wchar_t, char, mbstate_t>(name)); 313349cc55cSDimitry Andric #endif 314e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3150b57cec5SDimitry Andric install(new codecvt_byname<char16_t, char, mbstate_t>(name)); 3160b57cec5SDimitry Andric install(new codecvt_byname<char32_t, char, mbstate_t>(name)); 317e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 318fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 319e8d8bef9SDimitry Andric install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name)); 320e8d8bef9SDimitry Andric install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name)); 321e8d8bef9SDimitry Andric #endif 3220b57cec5SDimitry Andric } 323*cb14a3feSDimitry Andric if (c & locale::monetary) { 3240b57cec5SDimitry Andric install(new moneypunct_byname<char, false>(name)); 3250b57cec5SDimitry Andric install(new moneypunct_byname<char, true>(name)); 326349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3270b57cec5SDimitry Andric install(new moneypunct_byname<wchar_t, false>(name)); 3280b57cec5SDimitry Andric install(new moneypunct_byname<wchar_t, true>(name)); 329349cc55cSDimitry Andric #endif 3300b57cec5SDimitry Andric } 331*cb14a3feSDimitry Andric if (c & locale::numeric) { 3320b57cec5SDimitry Andric install(new numpunct_byname<char>(name)); 333349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3340b57cec5SDimitry Andric install(new numpunct_byname<wchar_t>(name)); 335349cc55cSDimitry Andric #endif 3360b57cec5SDimitry Andric } 337*cb14a3feSDimitry Andric if (c & locale::time) { 3380b57cec5SDimitry Andric install(new time_get_byname<char>(name)); 339349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3400b57cec5SDimitry Andric install(new time_get_byname<wchar_t>(name)); 341349cc55cSDimitry Andric #endif 3420b57cec5SDimitry Andric install(new time_put_byname<char>(name)); 343349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3440b57cec5SDimitry Andric install(new time_put_byname<wchar_t>(name)); 345349cc55cSDimitry Andric #endif 3460b57cec5SDimitry Andric } 347*cb14a3feSDimitry Andric if (c & locale::messages) { 3480b57cec5SDimitry Andric install(new messages_byname<char>(name)); 349349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3500b57cec5SDimitry Andric install(new messages_byname<wchar_t>(name)); 351349cc55cSDimitry Andric #endif 3520b57cec5SDimitry Andric } 35306c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 354*cb14a3feSDimitry Andric } catch (...) { 3550b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 3560b57cec5SDimitry Andric if (facets_[i]) 3570b57cec5SDimitry Andric facets_[i]->__release_shared(); 3580b57cec5SDimitry Andric throw; 3590b57cec5SDimitry Andric } 36006c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric template <class F> 364*cb14a3feSDimitry Andric inline void locale::__imp::install_from(const locale::__imp& one) { 3650b57cec5SDimitry Andric long id = F::id.__get(); 3660b57cec5SDimitry Andric install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id); 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) 370*cb14a3feSDimitry Andric : facets_(N), name_(build_name(other.name_, one.name_, c)) { 3710b57cec5SDimitry Andric facets_ = other.facets_; 3720b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 3730b57cec5SDimitry Andric if (facets_[i]) 3740b57cec5SDimitry Andric facets_[i]->__add_shared(); 37506c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 376*cb14a3feSDimitry Andric try { 37706c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 378*cb14a3feSDimitry Andric if (c & locale::collate) { 3795f757f3fSDimitry Andric install_from<std::collate<char> >(one); 380349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3815f757f3fSDimitry Andric install_from<std::collate<wchar_t> >(one); 382349cc55cSDimitry Andric #endif 3830b57cec5SDimitry Andric } 384*cb14a3feSDimitry Andric if (c & locale::ctype) { 3855f757f3fSDimitry Andric install_from<std::ctype<char> >(one); 386349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3875f757f3fSDimitry Andric install_from<std::ctype<wchar_t> >(one); 388349cc55cSDimitry Andric #endif 3895f757f3fSDimitry Andric install_from<std::codecvt<char, char, mbstate_t> >(one); 390e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3915f757f3fSDimitry Andric install_from<std::codecvt<char16_t, char, mbstate_t> >(one); 3925f757f3fSDimitry Andric install_from<std::codecvt<char32_t, char, mbstate_t> >(one); 393e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 394fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 3955f757f3fSDimitry Andric install_from<std::codecvt<char16_t, char8_t, mbstate_t> >(one); 3965f757f3fSDimitry Andric install_from<std::codecvt<char32_t, char8_t, mbstate_t> >(one); 397e8d8bef9SDimitry Andric #endif 398349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3995f757f3fSDimitry Andric install_from<std::codecvt<wchar_t, char, mbstate_t> >(one); 400349cc55cSDimitry Andric #endif 4010b57cec5SDimitry Andric } 402*cb14a3feSDimitry Andric if (c & locale::monetary) { 4030b57cec5SDimitry Andric install_from<moneypunct<char, false> >(one); 4040b57cec5SDimitry Andric install_from<moneypunct<char, true> >(one); 405349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4060b57cec5SDimitry Andric install_from<moneypunct<wchar_t, false> >(one); 4070b57cec5SDimitry Andric install_from<moneypunct<wchar_t, true> >(one); 408349cc55cSDimitry Andric #endif 4090b57cec5SDimitry Andric install_from<money_get<char> >(one); 410349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4110b57cec5SDimitry Andric install_from<money_get<wchar_t> >(one); 412349cc55cSDimitry Andric #endif 4130b57cec5SDimitry Andric install_from<money_put<char> >(one); 414349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4150b57cec5SDimitry Andric install_from<money_put<wchar_t> >(one); 416349cc55cSDimitry Andric #endif 4170b57cec5SDimitry Andric } 418*cb14a3feSDimitry Andric if (c & locale::numeric) { 4190b57cec5SDimitry Andric install_from<numpunct<char> >(one); 420349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4210b57cec5SDimitry Andric install_from<numpunct<wchar_t> >(one); 422349cc55cSDimitry Andric #endif 4230b57cec5SDimitry Andric install_from<num_get<char> >(one); 424349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4250b57cec5SDimitry Andric install_from<num_get<wchar_t> >(one); 426349cc55cSDimitry Andric #endif 4270b57cec5SDimitry Andric install_from<num_put<char> >(one); 428349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4290b57cec5SDimitry Andric install_from<num_put<wchar_t> >(one); 430349cc55cSDimitry Andric #endif 4310b57cec5SDimitry Andric } 432*cb14a3feSDimitry Andric if (c & locale::time) { 4330b57cec5SDimitry Andric install_from<time_get<char> >(one); 434349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4350b57cec5SDimitry Andric install_from<time_get<wchar_t> >(one); 436349cc55cSDimitry Andric #endif 4370b57cec5SDimitry Andric install_from<time_put<char> >(one); 438349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4390b57cec5SDimitry Andric install_from<time_put<wchar_t> >(one); 440349cc55cSDimitry Andric #endif 4410b57cec5SDimitry Andric } 442*cb14a3feSDimitry Andric if (c & locale::messages) { 4435f757f3fSDimitry Andric install_from<std::messages<char> >(one); 444349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4455f757f3fSDimitry Andric install_from<std::messages<wchar_t> >(one); 446349cc55cSDimitry Andric #endif 4470b57cec5SDimitry Andric } 44806c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 449*cb14a3feSDimitry Andric } catch (...) { 4500b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 4510b57cec5SDimitry Andric if (facets_[i]) 4520b57cec5SDimitry Andric facets_[i]->__release_shared(); 4530b57cec5SDimitry Andric throw; 4540b57cec5SDimitry Andric } 45506c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, facet* f, long id) 459*cb14a3feSDimitry Andric : facets_(max<size_t>(N, other.facets_.size() + 1)), name_("*") { 4600b57cec5SDimitry Andric f->__add_shared(); 4615f757f3fSDimitry Andric unique_ptr<facet, releaser> hold(f); 4620b57cec5SDimitry Andric facets_ = other.facets_; 4630b57cec5SDimitry Andric for (unsigned i = 0; i < other.facets_.size(); ++i) 4640b57cec5SDimitry Andric if (facets_[i]) 4650b57cec5SDimitry Andric facets_[i]->__add_shared(); 4660b57cec5SDimitry Andric install(hold.get(), id); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 469*cb14a3feSDimitry Andric locale::__imp::~__imp() { 4700b57cec5SDimitry Andric for (unsigned i = 0; i < facets_.size(); ++i) 4710b57cec5SDimitry Andric if (facets_[i]) 4720b57cec5SDimitry Andric facets_[i]->__release_shared(); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 475*cb14a3feSDimitry Andric void locale::__imp::install(facet* f, long id) { 4760b57cec5SDimitry Andric f->__add_shared(); 4775f757f3fSDimitry Andric unique_ptr<facet, releaser> hold(f); 4780b57cec5SDimitry Andric if (static_cast<size_t>(id) >= facets_.size()) 4790b57cec5SDimitry Andric facets_.resize(static_cast<size_t>(id + 1)); 4800b57cec5SDimitry Andric if (facets_[static_cast<size_t>(id)]) 4810b57cec5SDimitry Andric facets_[static_cast<size_t>(id)]->__release_shared(); 4820b57cec5SDimitry Andric facets_[static_cast<size_t>(id)] = hold.release(); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 485*cb14a3feSDimitry Andric const locale::facet* locale::__imp::use_facet(long id) const { 4860b57cec5SDimitry Andric if (!has_facet(id)) 4870b57cec5SDimitry Andric __throw_bad_cast(); 4880b57cec5SDimitry Andric return facets_[static_cast<size_t>(id)]; 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric // locale 4920b57cec5SDimitry Andric 4935f757f3fSDimitry Andric // We don't do reference counting on the classic locale. 4945f757f3fSDimitry Andric // It's never destroyed anyway, but atomic reference counting may be very 4955f757f3fSDimitry Andric // expensive in parallel applications. The classic locale is used by default 4965f757f3fSDimitry Andric // in all streams. Note: if a new global locale is installed, then we lose 4975f757f3fSDimitry Andric // the benefit of no reference counting. 4985f757f3fSDimitry Andric constinit __no_destroy<locale::__imp> 4995f757f3fSDimitry Andric locale::__imp::classic_locale_imp_(__uninitialized_tag{}); // initialized below in classic() 5005f757f3fSDimitry Andric 5015f757f3fSDimitry Andric const locale& locale::classic() { 5025f757f3fSDimitry Andric static const __no_destroy<locale> classic_locale(__private_tag{}, [] { 5035f757f3fSDimitry Andric // executed exactly once on first initialization of `classic_locale` 5045f757f3fSDimitry Andric locale::__imp::classic_locale_imp_.__emplace(1u); 5055f757f3fSDimitry Andric return &locale::__imp::classic_locale_imp_.__get(); 5065f757f3fSDimitry Andric }()); 5075f757f3fSDimitry Andric return classic_locale.__get(); 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5105f757f3fSDimitry Andric locale& locale::__global() { 5115f757f3fSDimitry Andric static __no_destroy<locale> g(locale::classic()); 5125f757f3fSDimitry Andric return g.__get(); 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5155f757f3fSDimitry Andric void locale::__imp::acquire() { 5165f757f3fSDimitry Andric if (this != &locale::__imp::classic_locale_imp_.__get()) 5175f757f3fSDimitry Andric __add_shared(); 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric 5205f757f3fSDimitry Andric void locale::__imp::release() { 5215f757f3fSDimitry Andric if (this != &locale::__imp::classic_locale_imp_.__get()) 5225f757f3fSDimitry Andric __release_shared(); 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5255f757f3fSDimitry Andric locale::locale() noexcept : __locale_(__global().__locale_) { __locale_->acquire(); } 5260b57cec5SDimitry Andric 5275f757f3fSDimitry Andric locale::locale(const locale& l) noexcept : __locale_(l.__locale_) { __locale_->acquire(); } 5280b57cec5SDimitry Andric 5295f757f3fSDimitry Andric locale::~locale() { __locale_->release(); } 5300b57cec5SDimitry Andric 531*cb14a3feSDimitry Andric const locale& locale::operator=(const locale& other) noexcept { 5325f757f3fSDimitry Andric other.__locale_->acquire(); 5335f757f3fSDimitry Andric __locale_->release(); 5340b57cec5SDimitry Andric __locale_ = other.__locale_; 5350b57cec5SDimitry Andric return *this; 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric locale::locale(const char* name) 539*cb14a3feSDimitry Andric : __locale_(name ? new __imp(name) : (__throw_runtime_error("locale constructed with null"), nullptr)) { 5405f757f3fSDimitry Andric __locale_->acquire(); 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric 5435f757f3fSDimitry Andric locale::locale(const string& name) : __locale_(new __imp(name)) { __locale_->acquire(); } 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric locale::locale(const locale& other, const char* name, category c) 5460b57cec5SDimitry Andric : __locale_(name ? new __imp(*other.__locale_, name, c) 547*cb14a3feSDimitry Andric : (__throw_runtime_error("locale constructed with null"), nullptr)) { 5485f757f3fSDimitry Andric __locale_->acquire(); 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 551*cb14a3feSDimitry Andric locale::locale(const locale& other, const string& name, category c) : __locale_(new __imp(*other.__locale_, name, c)) { 5525f757f3fSDimitry Andric __locale_->acquire(); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric locale::locale(const locale& other, const locale& one, category c) 556*cb14a3feSDimitry Andric : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) { 5575f757f3fSDimitry Andric __locale_->acquire(); 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 560*cb14a3feSDimitry Andric string locale::name() const { return __locale_->name(); } 5610b57cec5SDimitry Andric 562*cb14a3feSDimitry Andric void locale::__install_ctor(const locale& other, facet* f, long id) { 5630b57cec5SDimitry Andric if (f) 5640b57cec5SDimitry Andric __locale_ = new __imp(*other.__locale_, f, id); 5650b57cec5SDimitry Andric else 5660b57cec5SDimitry Andric __locale_ = other.__locale_; 5675f757f3fSDimitry Andric __locale_->acquire(); 5680b57cec5SDimitry Andric } 5690b57cec5SDimitry Andric 570*cb14a3feSDimitry Andric locale locale::global(const locale& loc) { 5710b57cec5SDimitry Andric locale& g = __global(); 5720b57cec5SDimitry Andric locale r = g; 5730b57cec5SDimitry Andric g = loc; 5740b57cec5SDimitry Andric if (g.name() != "*") 5750b57cec5SDimitry Andric setlocale(LC_ALL, g.name().c_str()); 5760b57cec5SDimitry Andric return r; 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 579*cb14a3feSDimitry Andric bool locale::has_facet(id& x) const { return __locale_->has_facet(x.__get()); } 5800b57cec5SDimitry Andric 581*cb14a3feSDimitry Andric const locale::facet* locale::use_facet(id& x) const { return __locale_->use_facet(x.__get()); } 5820b57cec5SDimitry Andric 583*cb14a3feSDimitry Andric bool locale::operator==(const locale& y) const { 584*cb14a3feSDimitry Andric return (__locale_ == y.__locale_) || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name()); 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric // locale::facet 5880b57cec5SDimitry Andric 589*cb14a3feSDimitry Andric locale::facet::~facet() {} 5900b57cec5SDimitry Andric 591*cb14a3feSDimitry Andric void locale::facet::__on_zero_shared() noexcept { delete this; } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric // locale::id 5940b57cec5SDimitry Andric 5955f757f3fSDimitry Andric constinit int32_t locale::id::__next_id = 0; 5960b57cec5SDimitry Andric 5975f757f3fSDimitry Andric long locale::id::__get() { 5985f757f3fSDimitry Andric call_once(__flag_, [&] { __id_ = __libcpp_atomic_add(&__next_id, 1); }); 5990b57cec5SDimitry Andric return __id_ - 1; 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric // template <> class collate_byname<char> 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric collate_byname<char>::collate_byname(const char* n, size_t refs) 605*cb14a3feSDimitry Andric : collate<char>(refs), __l_(newlocale(LC_ALL_MASK, n, 0)) { 606bdd1243dSDimitry Andric if (__l_ == 0) 607*cb14a3feSDimitry Andric __throw_runtime_error( 608*cb14a3feSDimitry Andric ("collate_byname<char>::collate_byname" 609*cb14a3feSDimitry Andric " failed to construct for " + 610*cb14a3feSDimitry Andric string(n)) 611*cb14a3feSDimitry Andric .c_str()); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric collate_byname<char>::collate_byname(const string& name, size_t refs) 615*cb14a3feSDimitry Andric : collate<char>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) { 616bdd1243dSDimitry Andric if (__l_ == 0) 617*cb14a3feSDimitry Andric __throw_runtime_error( 618*cb14a3feSDimitry Andric ("collate_byname<char>::collate_byname" 619*cb14a3feSDimitry Andric " failed to construct for " + 620*cb14a3feSDimitry Andric name) 621*cb14a3feSDimitry Andric .c_str()); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 624*cb14a3feSDimitry Andric collate_byname<char>::~collate_byname() { freelocale(__l_); } 6250b57cec5SDimitry Andric 626*cb14a3feSDimitry Andric int collate_byname<char>::do_compare( 627*cb14a3feSDimitry Andric const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const { 6280b57cec5SDimitry Andric string_type lhs(__lo1, __hi1); 6290b57cec5SDimitry Andric string_type rhs(__lo2, __hi2); 630bdd1243dSDimitry Andric int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l_); 6310b57cec5SDimitry Andric if (r < 0) 6320b57cec5SDimitry Andric return -1; 6330b57cec5SDimitry Andric if (r > 0) 6340b57cec5SDimitry Andric return 1; 6350b57cec5SDimitry Andric return r; 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 638*cb14a3feSDimitry Andric collate_byname<char>::string_type collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const { 6390b57cec5SDimitry Andric const string_type in(lo, hi); 640bdd1243dSDimitry Andric string_type out(strxfrm_l(0, in.c_str(), 0, __l_), char()); 641bdd1243dSDimitry Andric strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size() + 1, __l_); 6420b57cec5SDimitry Andric return out; 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric // template <> class collate_byname<wchar_t> 6460b57cec5SDimitry Andric 647349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 6480b57cec5SDimitry Andric collate_byname<wchar_t>::collate_byname(const char* n, size_t refs) 649*cb14a3feSDimitry Andric : collate<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, n, 0)) { 650bdd1243dSDimitry Andric if (__l_ == 0) 651*cb14a3feSDimitry Andric __throw_runtime_error( 652*cb14a3feSDimitry Andric ("collate_byname<wchar_t>::collate_byname(size_t refs)" 653*cb14a3feSDimitry Andric " failed to construct for " + 654*cb14a3feSDimitry Andric string(n)) 655*cb14a3feSDimitry Andric .c_str()); 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric collate_byname<wchar_t>::collate_byname(const string& name, size_t refs) 659*cb14a3feSDimitry Andric : collate<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) { 660bdd1243dSDimitry Andric if (__l_ == 0) 661*cb14a3feSDimitry Andric __throw_runtime_error( 662*cb14a3feSDimitry Andric ("collate_byname<wchar_t>::collate_byname(size_t refs)" 663*cb14a3feSDimitry Andric " failed to construct for " + 664*cb14a3feSDimitry Andric name) 665*cb14a3feSDimitry Andric .c_str()); 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric 668*cb14a3feSDimitry Andric collate_byname<wchar_t>::~collate_byname() { freelocale(__l_); } 6690b57cec5SDimitry Andric 670*cb14a3feSDimitry Andric int collate_byname<wchar_t>::do_compare( 671*cb14a3feSDimitry Andric const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const { 6720b57cec5SDimitry Andric string_type lhs(__lo1, __hi1); 6730b57cec5SDimitry Andric string_type rhs(__lo2, __hi2); 674bdd1243dSDimitry Andric int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l_); 6750b57cec5SDimitry Andric if (r < 0) 6760b57cec5SDimitry Andric return -1; 6770b57cec5SDimitry Andric if (r > 0) 6780b57cec5SDimitry Andric return 1; 6790b57cec5SDimitry Andric return r; 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric 6820b57cec5SDimitry Andric collate_byname<wchar_t>::string_type 683*cb14a3feSDimitry Andric collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const { 6840b57cec5SDimitry Andric const string_type in(lo, hi); 685bdd1243dSDimitry Andric string_type out(wcsxfrm_l(0, in.c_str(), 0, __l_), wchar_t()); 686bdd1243dSDimitry Andric wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size() + 1, __l_); 6870b57cec5SDimitry Andric return out; 6880b57cec5SDimitry Andric } 689349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric const ctype_base::mask ctype_base::space; 6920b57cec5SDimitry Andric const ctype_base::mask ctype_base::print; 6930b57cec5SDimitry Andric const ctype_base::mask ctype_base::cntrl; 6940b57cec5SDimitry Andric const ctype_base::mask ctype_base::upper; 6950b57cec5SDimitry Andric const ctype_base::mask ctype_base::lower; 6960b57cec5SDimitry Andric const ctype_base::mask ctype_base::alpha; 6970b57cec5SDimitry Andric const ctype_base::mask ctype_base::digit; 6980b57cec5SDimitry Andric const ctype_base::mask ctype_base::punct; 6990b57cec5SDimitry Andric const ctype_base::mask ctype_base::xdigit; 7000b57cec5SDimitry Andric const ctype_base::mask ctype_base::blank; 7010b57cec5SDimitry Andric const ctype_base::mask ctype_base::alnum; 7020b57cec5SDimitry Andric const ctype_base::mask ctype_base::graph; 7030b57cec5SDimitry Andric 704349cc55cSDimitry Andric // template <> class ctype<wchar_t>; 705349cc55cSDimitry Andric 706349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 7075f757f3fSDimitry Andric constinit locale::id ctype<wchar_t>::id; 7080b57cec5SDimitry Andric 709*cb14a3feSDimitry Andric ctype<wchar_t>::~ctype() {} 7100b57cec5SDimitry Andric 711*cb14a3feSDimitry Andric bool ctype<wchar_t>::do_is(mask m, char_type c) const { 7120b57cec5SDimitry Andric return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric 715*cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const { 7160b57cec5SDimitry Andric for (; low != high; ++low, ++vec) 717*cb14a3feSDimitry Andric *vec = static_cast<mask>(isascii(*low) ? ctype<char>::classic_table()[*low] : 0); 7180b57cec5SDimitry Andric return low; 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 721*cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const { 7220b57cec5SDimitry Andric for (; low != high; ++low) 7230b57cec5SDimitry Andric if (isascii(*low) && (ctype<char>::classic_table()[*low] & m)) 7240b57cec5SDimitry Andric break; 7250b57cec5SDimitry Andric return low; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 728*cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const { 7290b57cec5SDimitry Andric for (; low != high; ++low) 7300b57cec5SDimitry Andric if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m))) 7310b57cec5SDimitry Andric break; 7320b57cec5SDimitry Andric return low; 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 735*cb14a3feSDimitry Andric wchar_t ctype<wchar_t>::do_toupper(char_type c) const { 7360b57cec5SDimitry Andric # ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 7370b57cec5SDimitry Andric return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; 738*cb14a3feSDimitry Andric # elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__) 7390b57cec5SDimitry Andric return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; 7400b57cec5SDimitry Andric # else 7410b57cec5SDimitry Andric return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c - L'a' + L'A' : c; 7420b57cec5SDimitry Andric # endif 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric 745*cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const { 7460b57cec5SDimitry Andric for (; low != high; ++low) 7470b57cec5SDimitry Andric # ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 7480b57cec5SDimitry Andric *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; 749*cb14a3feSDimitry Andric # elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__) 750*cb14a3feSDimitry Andric *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] : *low; 7510b57cec5SDimitry Andric # else 7520b57cec5SDimitry Andric *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low - L'a' + L'A') : *low; 7530b57cec5SDimitry Andric # endif 7540b57cec5SDimitry Andric return low; 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 757*cb14a3feSDimitry Andric wchar_t ctype<wchar_t>::do_tolower(char_type c) const { 7580b57cec5SDimitry Andric # ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 7590b57cec5SDimitry Andric return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; 760*cb14a3feSDimitry Andric # elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__) 7610b57cec5SDimitry Andric return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; 7620b57cec5SDimitry Andric # else 7630b57cec5SDimitry Andric return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c - L'A' + 'a' : c; 7640b57cec5SDimitry Andric # endif 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 767*cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const { 7680b57cec5SDimitry Andric for (; low != high; ++low) 7690b57cec5SDimitry Andric # ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 7700b57cec5SDimitry Andric *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; 771*cb14a3feSDimitry Andric # elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__) 772*cb14a3feSDimitry Andric *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] : *low; 7730b57cec5SDimitry Andric # else 7740b57cec5SDimitry Andric *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - L'A' + L'a' : *low; 7750b57cec5SDimitry Andric # endif 7760b57cec5SDimitry Andric return low; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 779*cb14a3feSDimitry Andric wchar_t ctype<wchar_t>::do_widen(char c) const { return c; } 7800b57cec5SDimitry Andric 781*cb14a3feSDimitry Andric const char* ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const { 7820b57cec5SDimitry Andric for (; low != high; ++low, ++dest) 7830b57cec5SDimitry Andric *dest = *low; 7840b57cec5SDimitry Andric return low; 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 787*cb14a3feSDimitry Andric char ctype<wchar_t>::do_narrow(char_type c, char dfault) const { 7880b57cec5SDimitry Andric if (isascii(c)) 7890b57cec5SDimitry Andric return static_cast<char>(c); 7900b57cec5SDimitry Andric return dfault; 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 793*cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const { 7940b57cec5SDimitry Andric for (; low != high; ++low, ++dest) 7950b57cec5SDimitry Andric if (isascii(*low)) 7960b57cec5SDimitry Andric *dest = static_cast<char>(*low); 7970b57cec5SDimitry Andric else 7980b57cec5SDimitry Andric *dest = dfault; 7990b57cec5SDimitry Andric return low; 8000b57cec5SDimitry Andric } 801349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric // template <> class ctype<char>; 8040b57cec5SDimitry Andric 8055f757f3fSDimitry Andric constinit locale::id ctype<char>::id; 8060b57cec5SDimitry Andric 807349cc55cSDimitry Andric const size_t ctype<char>::table_size; 808349cc55cSDimitry Andric 809*cb14a3feSDimitry Andric ctype<char>::ctype(const mask* tab, bool del, size_t refs) : locale::facet(refs), __tab_(tab), __del_(del) { 8100b57cec5SDimitry Andric if (__tab_ == 0) 8110b57cec5SDimitry Andric __tab_ = classic_table(); 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 814*cb14a3feSDimitry Andric ctype<char>::~ctype() { 8150b57cec5SDimitry Andric if (__tab_ && __del_) 8160b57cec5SDimitry Andric delete[] __tab_; 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 819*cb14a3feSDimitry Andric char ctype<char>::do_toupper(char_type c) const { 8200b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 821*cb14a3feSDimitry Andric return isascii(c) ? static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c; 8220b57cec5SDimitry Andric #elif defined(__NetBSD__) 8230b57cec5SDimitry Andric return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]); 82404eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__) 825*cb14a3feSDimitry Andric return isascii(c) ? static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c; 8260b57cec5SDimitry Andric #else 8270b57cec5SDimitry Andric return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c - 'a' + 'A' : c; 8280b57cec5SDimitry Andric #endif 8290b57cec5SDimitry Andric } 8300b57cec5SDimitry Andric 831*cb14a3feSDimitry Andric const char* ctype<char>::do_toupper(char_type* low, const char_type* high) const { 8320b57cec5SDimitry Andric for (; low != high; ++low) 8330b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 834*cb14a3feSDimitry Andric *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low; 8350b57cec5SDimitry Andric #elif defined(__NetBSD__) 8360b57cec5SDimitry Andric *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]); 83704eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__) 838*cb14a3feSDimitry Andric *low = isascii(*low) ? static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low; 8390b57cec5SDimitry Andric #else 8400b57cec5SDimitry Andric *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'a' + 'A' : *low; 8410b57cec5SDimitry Andric #endif 8420b57cec5SDimitry Andric return low; 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 845*cb14a3feSDimitry Andric char ctype<char>::do_tolower(char_type c) const { 8460b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 847*cb14a3feSDimitry Andric return isascii(c) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c; 8480b57cec5SDimitry Andric #elif defined(__NetBSD__) 8490b57cec5SDimitry Andric return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]); 85004eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__) 851*cb14a3feSDimitry Andric return isascii(c) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c; 8520b57cec5SDimitry Andric #else 8530b57cec5SDimitry Andric return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c - 'A' + 'a' : c; 8540b57cec5SDimitry Andric #endif 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric 857*cb14a3feSDimitry Andric const char* ctype<char>::do_tolower(char_type* low, const char_type* high) const { 8580b57cec5SDimitry Andric for (; low != high; ++low) 8590b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE 8600b57cec5SDimitry Andric *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low; 8610b57cec5SDimitry Andric #elif defined(__NetBSD__) 8620b57cec5SDimitry Andric *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]); 86304eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__) 8640b57cec5SDimitry Andric *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low; 8650b57cec5SDimitry Andric #else 8660b57cec5SDimitry Andric *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'A' + 'a' : *low; 8670b57cec5SDimitry Andric #endif 8680b57cec5SDimitry Andric return low; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 871*cb14a3feSDimitry Andric char ctype<char>::do_widen(char c) const { return c; } 8720b57cec5SDimitry Andric 873*cb14a3feSDimitry Andric const char* ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const { 8740b57cec5SDimitry Andric for (; low != high; ++low, ++dest) 8750b57cec5SDimitry Andric *dest = *low; 8760b57cec5SDimitry Andric return low; 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric 879*cb14a3feSDimitry Andric char ctype<char>::do_narrow(char_type c, char dfault) const { 8800b57cec5SDimitry Andric if (isascii(c)) 8810b57cec5SDimitry Andric return static_cast<char>(c); 8820b57cec5SDimitry Andric return dfault; 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric 885*cb14a3feSDimitry Andric const char* ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const { 8860b57cec5SDimitry Andric for (; low != high; ++low, ++dest) 8870b57cec5SDimitry Andric if (isascii(*low)) 8880b57cec5SDimitry Andric *dest = *low; 8890b57cec5SDimitry Andric else 8900b57cec5SDimitry Andric *dest = dfault; 8910b57cec5SDimitry Andric return low; 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric #if defined(__EMSCRIPTEN__) 8950b57cec5SDimitry Andric extern "C" const unsigned short** __ctype_b_loc(); 8960b57cec5SDimitry Andric extern "C" const int** __ctype_tolower_loc(); 8970b57cec5SDimitry Andric extern "C" const int** __ctype_toupper_loc(); 8980b57cec5SDimitry Andric #endif 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE 901*cb14a3feSDimitry Andric const ctype<char>::mask* ctype<char>::classic_table() noexcept { 9025f757f3fSDimitry Andric // clang-format off 9035f757f3fSDimitry Andric static constexpr const ctype<char>::mask builtin_table[table_size] = { 9040b57cec5SDimitry Andric cntrl, cntrl, 9050b57cec5SDimitry Andric cntrl, cntrl, 9060b57cec5SDimitry Andric cntrl, cntrl, 9070b57cec5SDimitry Andric cntrl, cntrl, 9080b57cec5SDimitry Andric cntrl, cntrl | space | blank, 9090b57cec5SDimitry Andric cntrl | space, cntrl | space, 9100b57cec5SDimitry Andric cntrl | space, cntrl | space, 9110b57cec5SDimitry Andric cntrl, cntrl, 9120b57cec5SDimitry Andric cntrl, cntrl, 9130b57cec5SDimitry Andric cntrl, cntrl, 9140b57cec5SDimitry Andric cntrl, cntrl, 9150b57cec5SDimitry Andric cntrl, cntrl, 9160b57cec5SDimitry Andric cntrl, cntrl, 9170b57cec5SDimitry Andric cntrl, cntrl, 9180b57cec5SDimitry Andric cntrl, cntrl, 9190b57cec5SDimitry Andric cntrl, cntrl, 9200b57cec5SDimitry Andric space | blank | print, punct | print, 9210b57cec5SDimitry Andric punct | print, punct | print, 9220b57cec5SDimitry Andric punct | print, punct | print, 9230b57cec5SDimitry Andric punct | print, punct | print, 9240b57cec5SDimitry Andric punct | print, punct | print, 9250b57cec5SDimitry Andric punct | print, punct | print, 9260b57cec5SDimitry Andric punct | print, punct | print, 9270b57cec5SDimitry Andric punct | print, punct | print, 9280b57cec5SDimitry Andric digit | print | xdigit, digit | print | xdigit, 9290b57cec5SDimitry Andric digit | print | xdigit, digit | print | xdigit, 9300b57cec5SDimitry Andric digit | print | xdigit, digit | print | xdigit, 9310b57cec5SDimitry Andric digit | print | xdigit, digit | print | xdigit, 9320b57cec5SDimitry Andric digit | print | xdigit, digit | print | xdigit, 9330b57cec5SDimitry Andric punct | print, punct | print, 9340b57cec5SDimitry Andric punct | print, punct | print, 9350b57cec5SDimitry Andric punct | print, punct | print, 9360b57cec5SDimitry Andric punct | print, upper | xdigit | print | alpha, 9370b57cec5SDimitry Andric upper | xdigit | print | alpha, upper | xdigit | print | alpha, 9380b57cec5SDimitry Andric upper | xdigit | print | alpha, upper | xdigit | print | alpha, 9390b57cec5SDimitry Andric upper | xdigit | print | alpha, upper | print | alpha, 9400b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9410b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9420b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9430b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9440b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9450b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9460b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9470b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9480b57cec5SDimitry Andric upper | print | alpha, upper | print | alpha, 9490b57cec5SDimitry Andric upper | print | alpha, punct | print, 9500b57cec5SDimitry Andric punct | print, punct | print, 9510b57cec5SDimitry Andric punct | print, punct | print, 9520b57cec5SDimitry Andric punct | print, lower | xdigit | print | alpha, 9530b57cec5SDimitry Andric lower | xdigit | print | alpha, lower | xdigit | print | alpha, 9540b57cec5SDimitry Andric lower | xdigit | print | alpha, lower | xdigit | print | alpha, 9550b57cec5SDimitry Andric lower | xdigit | print | alpha, lower | print | alpha, 9560b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9570b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9580b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9590b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9600b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9610b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9620b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9630b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9640b57cec5SDimitry Andric lower | print | alpha, lower | print | alpha, 9650b57cec5SDimitry Andric lower | print | alpha, punct | print, 9660b57cec5SDimitry Andric punct | print, punct | print, 9670b57cec5SDimitry Andric punct | print, cntrl, 9680b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9690b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9700b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9710b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9720b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9730b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9740b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9750b57cec5SDimitry Andric 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 9760b57cec5SDimitry Andric }; 9775f757f3fSDimitry Andric // clang-format on 9780b57cec5SDimitry Andric return builtin_table; 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric #else 981*cb14a3feSDimitry Andric const ctype<char>::mask* ctype<char>::classic_table() noexcept { 9820b57cec5SDimitry Andric # if defined(__APPLE__) || defined(__FreeBSD__) 9830b57cec5SDimitry Andric return _DefaultRuneLocale.__runetype; 9840b57cec5SDimitry Andric # elif defined(__NetBSD__) 9850b57cec5SDimitry Andric return _C_ctype_tab_ + 1; 9860b57cec5SDimitry Andric # elif defined(__GLIBC__) 9870b57cec5SDimitry Andric return _LIBCPP_GET_C_LOCALE->__ctype_b; 9880b57cec5SDimitry Andric # elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 9890b57cec5SDimitry Andric return __pctype_func(); 9900b57cec5SDimitry Andric # elif defined(__EMSCRIPTEN__) 9910b57cec5SDimitry Andric return *__ctype_b_loc(); 9920b57cec5SDimitry Andric # elif defined(_NEWLIB_VERSION) 9930b57cec5SDimitry Andric // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1]. 9940b57cec5SDimitry Andric return _ctype_ + 1; 9950b57cec5SDimitry Andric # elif defined(_AIX) 9960b57cec5SDimitry Andric return (const unsigned int*)__lc_ctype_ptr->obj->mask; 99704eeddc0SDimitry Andric # elif defined(__MVS__) 99804eeddc0SDimitry Andric # if defined(__NATIVE_ASCII_F) 99904eeddc0SDimitry Andric return const_cast<const ctype<char>::mask*>(__OBJ_DATA(__lc_ctype_a)->mask); 100004eeddc0SDimitry Andric # else 100104eeddc0SDimitry Andric return const_cast<const ctype<char>::mask*>(__ctypec); 100204eeddc0SDimitry Andric # endif 10030b57cec5SDimitry Andric # else 10040b57cec5SDimitry Andric // Platform not supported: abort so the person doing the port knows what to 10050b57cec5SDimitry Andric // fix 10060b57cec5SDimitry Andric # warning ctype<char>::classic_table() is not implemented 10070b57cec5SDimitry Andric printf("ctype<char>::classic_table() is not implemented\n"); 10080b57cec5SDimitry Andric abort(); 10090b57cec5SDimitry Andric return NULL; 10100b57cec5SDimitry Andric # endif 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric #endif 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric #if defined(__GLIBC__) 1015*cb14a3feSDimitry Andric const int* ctype<char>::__classic_lower_table() noexcept { return _LIBCPP_GET_C_LOCALE->__ctype_tolower; } 10160b57cec5SDimitry Andric 1017*cb14a3feSDimitry Andric const int* ctype<char>::__classic_upper_table() noexcept { return _LIBCPP_GET_C_LOCALE->__ctype_toupper; } 1018e8d8bef9SDimitry Andric #elif defined(__NetBSD__) 1019*cb14a3feSDimitry Andric const short* ctype<char>::__classic_lower_table() noexcept { return _C_tolower_tab_ + 1; } 10200b57cec5SDimitry Andric 1021*cb14a3feSDimitry Andric const short* ctype<char>::__classic_upper_table() noexcept { return _C_toupper_tab_ + 1; } 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric #elif defined(__EMSCRIPTEN__) 1024*cb14a3feSDimitry Andric const int* ctype<char>::__classic_lower_table() noexcept { return *__ctype_tolower_loc(); } 10250b57cec5SDimitry Andric 1026*cb14a3feSDimitry Andric const int* ctype<char>::__classic_upper_table() noexcept { return *__ctype_toupper_loc(); } 102704eeddc0SDimitry Andric #elif defined(__MVS__) 1028*cb14a3feSDimitry Andric const unsigned short* ctype<char>::__classic_lower_table() _NOEXCEPT { 102904eeddc0SDimitry Andric # if defined(__NATIVE_ASCII_F) 103004eeddc0SDimitry Andric return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower); 103104eeddc0SDimitry Andric # else 103204eeddc0SDimitry Andric return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX); 103304eeddc0SDimitry Andric # endif 103404eeddc0SDimitry Andric } 1035*cb14a3feSDimitry Andric const unsigned short* ctype<char>::__classic_upper_table() _NOEXCEPT { 103604eeddc0SDimitry Andric # if defined(__NATIVE_ASCII_F) 103704eeddc0SDimitry Andric return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper); 103804eeddc0SDimitry Andric # else 103904eeddc0SDimitry Andric return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX); 104004eeddc0SDimitry Andric # endif 104104eeddc0SDimitry Andric } 104204eeddc0SDimitry Andric #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__ 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric // template <> class ctype_byname<char> 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric ctype_byname<char>::ctype_byname(const char* name, size_t refs) 1047*cb14a3feSDimitry Andric : ctype<char>(0, false, refs), __l_(newlocale(LC_ALL_MASK, name, 0)) { 1048bdd1243dSDimitry Andric if (__l_ == 0) 1049*cb14a3feSDimitry Andric __throw_runtime_error( 1050*cb14a3feSDimitry Andric ("ctype_byname<char>::ctype_byname" 1051*cb14a3feSDimitry Andric " failed to construct for " + 1052*cb14a3feSDimitry Andric string(name)) 1053*cb14a3feSDimitry Andric .c_str()); 10540b57cec5SDimitry Andric } 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric ctype_byname<char>::ctype_byname(const string& name, size_t refs) 1057*cb14a3feSDimitry Andric : ctype<char>(0, false, refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) { 1058bdd1243dSDimitry Andric if (__l_ == 0) 1059*cb14a3feSDimitry Andric __throw_runtime_error( 1060*cb14a3feSDimitry Andric ("ctype_byname<char>::ctype_byname" 1061*cb14a3feSDimitry Andric " failed to construct for " + 1062*cb14a3feSDimitry Andric name) 1063*cb14a3feSDimitry Andric .c_str()); 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 1066*cb14a3feSDimitry Andric ctype_byname<char>::~ctype_byname() { freelocale(__l_); } 10670b57cec5SDimitry Andric 1068*cb14a3feSDimitry Andric char ctype_byname<char>::do_toupper(char_type c) const { 1069bdd1243dSDimitry Andric return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l_)); 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric 1072*cb14a3feSDimitry Andric const char* ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const { 10730b57cec5SDimitry Andric for (; low != high; ++low) 1074bdd1243dSDimitry Andric *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l_)); 10750b57cec5SDimitry Andric return low; 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 1078*cb14a3feSDimitry Andric char ctype_byname<char>::do_tolower(char_type c) const { 1079bdd1243dSDimitry Andric return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l_)); 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric 1082*cb14a3feSDimitry Andric const char* ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const { 10830b57cec5SDimitry Andric for (; low != high; ++low) 1084bdd1243dSDimitry Andric *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l_)); 10850b57cec5SDimitry Andric return low; 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric // template <> class ctype_byname<wchar_t> 10890b57cec5SDimitry Andric 1090349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 10910b57cec5SDimitry Andric ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs) 1092*cb14a3feSDimitry Andric : ctype<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name, 0)) { 1093bdd1243dSDimitry Andric if (__l_ == 0) 1094*cb14a3feSDimitry Andric __throw_runtime_error( 1095*cb14a3feSDimitry Andric ("ctype_byname<wchar_t>::ctype_byname" 1096*cb14a3feSDimitry Andric " failed to construct for " + 1097*cb14a3feSDimitry Andric string(name)) 1098*cb14a3feSDimitry Andric .c_str()); 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs) 1102*cb14a3feSDimitry Andric : ctype<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) { 1103bdd1243dSDimitry Andric if (__l_ == 0) 1104*cb14a3feSDimitry Andric __throw_runtime_error( 1105*cb14a3feSDimitry Andric ("ctype_byname<wchar_t>::ctype_byname" 1106*cb14a3feSDimitry Andric " failed to construct for " + 1107*cb14a3feSDimitry Andric name) 1108*cb14a3feSDimitry Andric .c_str()); 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric 1111*cb14a3feSDimitry Andric ctype_byname<wchar_t>::~ctype_byname() { freelocale(__l_); } 11120b57cec5SDimitry Andric 1113*cb14a3feSDimitry Andric bool ctype_byname<wchar_t>::do_is(mask m, char_type c) const { 11140b57cec5SDimitry Andric # ifdef _LIBCPP_WCTYPE_IS_MASK 1115bdd1243dSDimitry Andric return static_cast<bool>(iswctype_l(c, m, __l_)); 11160b57cec5SDimitry Andric # else 11170b57cec5SDimitry Andric bool result = false; 11180b57cec5SDimitry Andric wint_t ch = static_cast<wint_t>(c); 1119*cb14a3feSDimitry Andric if ((m & space) == space) 1120*cb14a3feSDimitry Andric result |= (iswspace_l(ch, __l_) != 0); 1121*cb14a3feSDimitry Andric if ((m & print) == print) 1122*cb14a3feSDimitry Andric result |= (iswprint_l(ch, __l_) != 0); 1123*cb14a3feSDimitry Andric if ((m & cntrl) == cntrl) 1124*cb14a3feSDimitry Andric result |= (iswcntrl_l(ch, __l_) != 0); 1125*cb14a3feSDimitry Andric if ((m & upper) == upper) 1126*cb14a3feSDimitry Andric result |= (iswupper_l(ch, __l_) != 0); 1127*cb14a3feSDimitry Andric if ((m & lower) == lower) 1128*cb14a3feSDimitry Andric result |= (iswlower_l(ch, __l_) != 0); 1129*cb14a3feSDimitry Andric if ((m & alpha) == alpha) 1130*cb14a3feSDimitry Andric result |= (iswalpha_l(ch, __l_) != 0); 1131*cb14a3feSDimitry Andric if ((m & digit) == digit) 1132*cb14a3feSDimitry Andric result |= (iswdigit_l(ch, __l_) != 0); 1133*cb14a3feSDimitry Andric if ((m & punct) == punct) 1134*cb14a3feSDimitry Andric result |= (iswpunct_l(ch, __l_) != 0); 1135*cb14a3feSDimitry Andric if ((m & xdigit) == xdigit) 1136*cb14a3feSDimitry Andric result |= (iswxdigit_l(ch, __l_) != 0); 1137*cb14a3feSDimitry Andric if ((m & blank) == blank) 1138*cb14a3feSDimitry Andric result |= (iswblank_l(ch, __l_) != 0); 11390b57cec5SDimitry Andric return result; 11400b57cec5SDimitry Andric # endif 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric 1143*cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const { 1144*cb14a3feSDimitry Andric for (; low != high; ++low, ++vec) { 11450b57cec5SDimitry Andric if (isascii(*low)) 11460b57cec5SDimitry Andric *vec = static_cast<mask>(ctype<char>::classic_table()[*low]); 1147*cb14a3feSDimitry Andric else { 11480b57cec5SDimitry Andric *vec = 0; 11490b57cec5SDimitry Andric wint_t ch = static_cast<wint_t>(*low); 1150bdd1243dSDimitry Andric if (iswspace_l(ch, __l_)) 11510b57cec5SDimitry Andric *vec |= space; 11520b57cec5SDimitry Andric # ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT 1153bdd1243dSDimitry Andric if (iswprint_l(ch, __l_)) 11540b57cec5SDimitry Andric *vec |= print; 11550b57cec5SDimitry Andric # endif 1156bdd1243dSDimitry Andric if (iswcntrl_l(ch, __l_)) 11570b57cec5SDimitry Andric *vec |= cntrl; 1158bdd1243dSDimitry Andric if (iswupper_l(ch, __l_)) 11590b57cec5SDimitry Andric *vec |= upper; 1160bdd1243dSDimitry Andric if (iswlower_l(ch, __l_)) 11610b57cec5SDimitry Andric *vec |= lower; 11620b57cec5SDimitry Andric # ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA 1163bdd1243dSDimitry Andric if (iswalpha_l(ch, __l_)) 11640b57cec5SDimitry Andric *vec |= alpha; 11650b57cec5SDimitry Andric # endif 1166bdd1243dSDimitry Andric if (iswdigit_l(ch, __l_)) 11670b57cec5SDimitry Andric *vec |= digit; 1168bdd1243dSDimitry Andric if (iswpunct_l(ch, __l_)) 11690b57cec5SDimitry Andric *vec |= punct; 11700b57cec5SDimitry Andric # ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT 1171bdd1243dSDimitry Andric if (iswxdigit_l(ch, __l_)) 11720b57cec5SDimitry Andric *vec |= xdigit; 11730b57cec5SDimitry Andric # endif 1174bdd1243dSDimitry Andric if (iswblank_l(ch, __l_)) 11750b57cec5SDimitry Andric *vec |= blank; 11760b57cec5SDimitry Andric } 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric return low; 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric 1181*cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const { 1182*cb14a3feSDimitry Andric for (; low != high; ++low) { 11830b57cec5SDimitry Andric # ifdef _LIBCPP_WCTYPE_IS_MASK 1184bdd1243dSDimitry Andric if (iswctype_l(*low, m, __l_)) 11850b57cec5SDimitry Andric break; 11860b57cec5SDimitry Andric # else 11870b57cec5SDimitry Andric wint_t ch = static_cast<wint_t>(*low); 1188*cb14a3feSDimitry Andric if ((m & space) == space && iswspace_l(ch, __l_)) 1189*cb14a3feSDimitry Andric break; 1190*cb14a3feSDimitry Andric if ((m & print) == print && iswprint_l(ch, __l_)) 1191*cb14a3feSDimitry Andric break; 1192*cb14a3feSDimitry Andric if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) 1193*cb14a3feSDimitry Andric break; 1194*cb14a3feSDimitry Andric if ((m & upper) == upper && iswupper_l(ch, __l_)) 1195*cb14a3feSDimitry Andric break; 1196*cb14a3feSDimitry Andric if ((m & lower) == lower && iswlower_l(ch, __l_)) 1197*cb14a3feSDimitry Andric break; 1198*cb14a3feSDimitry Andric if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) 1199*cb14a3feSDimitry Andric break; 1200*cb14a3feSDimitry Andric if ((m & digit) == digit && iswdigit_l(ch, __l_)) 1201*cb14a3feSDimitry Andric break; 1202*cb14a3feSDimitry Andric if ((m & punct) == punct && iswpunct_l(ch, __l_)) 1203*cb14a3feSDimitry Andric break; 1204*cb14a3feSDimitry Andric if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) 1205*cb14a3feSDimitry Andric break; 1206*cb14a3feSDimitry Andric if ((m & blank) == blank && iswblank_l(ch, __l_)) 1207*cb14a3feSDimitry Andric break; 12080b57cec5SDimitry Andric # endif 12090b57cec5SDimitry Andric } 12100b57cec5SDimitry Andric return low; 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric 1213*cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const { 1214*cb14a3feSDimitry Andric for (; low != high; ++low) { 12150b57cec5SDimitry Andric # ifdef _LIBCPP_WCTYPE_IS_MASK 1216bdd1243dSDimitry Andric if (!iswctype_l(*low, m, __l_)) 12170b57cec5SDimitry Andric break; 12180b57cec5SDimitry Andric # else 12190b57cec5SDimitry Andric wint_t ch = static_cast<wint_t>(*low); 1220*cb14a3feSDimitry Andric if ((m & space) == space && iswspace_l(ch, __l_)) 1221*cb14a3feSDimitry Andric continue; 1222*cb14a3feSDimitry Andric if ((m & print) == print && iswprint_l(ch, __l_)) 1223*cb14a3feSDimitry Andric continue; 1224*cb14a3feSDimitry Andric if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) 1225*cb14a3feSDimitry Andric continue; 1226*cb14a3feSDimitry Andric if ((m & upper) == upper && iswupper_l(ch, __l_)) 1227*cb14a3feSDimitry Andric continue; 1228*cb14a3feSDimitry Andric if ((m & lower) == lower && iswlower_l(ch, __l_)) 1229*cb14a3feSDimitry Andric continue; 1230*cb14a3feSDimitry Andric if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) 1231*cb14a3feSDimitry Andric continue; 1232*cb14a3feSDimitry Andric if ((m & digit) == digit && iswdigit_l(ch, __l_)) 1233*cb14a3feSDimitry Andric continue; 1234*cb14a3feSDimitry Andric if ((m & punct) == punct && iswpunct_l(ch, __l_)) 1235*cb14a3feSDimitry Andric continue; 1236*cb14a3feSDimitry Andric if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) 1237*cb14a3feSDimitry Andric continue; 1238*cb14a3feSDimitry Andric if ((m & blank) == blank && iswblank_l(ch, __l_)) 1239*cb14a3feSDimitry Andric continue; 12400b57cec5SDimitry Andric break; 12410b57cec5SDimitry Andric # endif 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric return low; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric 1246*cb14a3feSDimitry Andric wchar_t ctype_byname<wchar_t>::do_toupper(char_type c) const { return towupper_l(c, __l_); } 12470b57cec5SDimitry Andric 1248*cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const { 12490b57cec5SDimitry Andric for (; low != high; ++low) 1250bdd1243dSDimitry Andric *low = towupper_l(*low, __l_); 12510b57cec5SDimitry Andric return low; 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric 1254*cb14a3feSDimitry Andric wchar_t ctype_byname<wchar_t>::do_tolower(char_type c) const { return towlower_l(c, __l_); } 12550b57cec5SDimitry Andric 1256*cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const { 12570b57cec5SDimitry Andric for (; low != high; ++low) 1258bdd1243dSDimitry Andric *low = towlower_l(*low, __l_); 12590b57cec5SDimitry Andric return low; 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 1262*cb14a3feSDimitry Andric wchar_t ctype_byname<wchar_t>::do_widen(char c) const { return __libcpp_btowc_l(c, __l_); } 12630b57cec5SDimitry Andric 1264*cb14a3feSDimitry Andric const char* ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const { 12650b57cec5SDimitry Andric for (; low != high; ++low, ++dest) 1266bdd1243dSDimitry Andric *dest = __libcpp_btowc_l(*low, __l_); 12670b57cec5SDimitry Andric return low; 12680b57cec5SDimitry Andric } 12690b57cec5SDimitry Andric 1270*cb14a3feSDimitry Andric char ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const { 1271bdd1243dSDimitry Andric int r = __libcpp_wctob_l(c, __l_); 127281ad6265SDimitry Andric return (r != EOF) ? static_cast<char>(r) : dfault; 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric const wchar_t* 1276*cb14a3feSDimitry Andric ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const { 1277*cb14a3feSDimitry Andric for (; low != high; ++low, ++dest) { 1278bdd1243dSDimitry Andric int r = __libcpp_wctob_l(*low, __l_); 127981ad6265SDimitry Andric *dest = (r != EOF) ? static_cast<char>(r) : dfault; 12800b57cec5SDimitry Andric } 12810b57cec5SDimitry Andric return low; 12820b57cec5SDimitry Andric } 1283349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 12840b57cec5SDimitry Andric 12850b57cec5SDimitry Andric // template <> class codecvt<char, char, mbstate_t> 12860b57cec5SDimitry Andric 12875f757f3fSDimitry Andric constinit locale::id codecvt<char, char, mbstate_t>::id; 12880b57cec5SDimitry Andric 1289*cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::~codecvt() {} 1290*cb14a3feSDimitry Andric 1291*cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::result codecvt<char, char, mbstate_t>::do_out( 1292*cb14a3feSDimitry Andric state_type&, 1293*cb14a3feSDimitry Andric const intern_type* frm, 1294*cb14a3feSDimitry Andric const intern_type*, 1295*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 1296*cb14a3feSDimitry Andric extern_type* to, 1297*cb14a3feSDimitry Andric extern_type*, 1298*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 1299*cb14a3feSDimitry Andric frm_nxt = frm; 1300*cb14a3feSDimitry Andric to_nxt = to; 1301*cb14a3feSDimitry Andric return noconv; 13020b57cec5SDimitry Andric } 13030b57cec5SDimitry Andric 1304*cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::result codecvt<char, char, mbstate_t>::do_in( 1305*cb14a3feSDimitry Andric state_type&, 1306*cb14a3feSDimitry Andric const extern_type* frm, 1307*cb14a3feSDimitry Andric const extern_type*, 1308*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 1309*cb14a3feSDimitry Andric intern_type* to, 1310*cb14a3feSDimitry Andric intern_type*, 1311*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 13120b57cec5SDimitry Andric frm_nxt = frm; 13130b57cec5SDimitry Andric to_nxt = to; 13140b57cec5SDimitry Andric return noconv; 13150b57cec5SDimitry Andric } 13160b57cec5SDimitry Andric 13170b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::result 1318*cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 13190b57cec5SDimitry Andric to_nxt = to; 13200b57cec5SDimitry Andric return noconv; 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 1323*cb14a3feSDimitry Andric int codecvt<char, char, mbstate_t>::do_encoding() const noexcept { return 1; } 13240b57cec5SDimitry Andric 1325*cb14a3feSDimitry Andric bool codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept { return true; } 13260b57cec5SDimitry Andric 1327*cb14a3feSDimitry Andric int codecvt<char, char, mbstate_t>::do_length( 1328*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* end, size_t mx) const { 13290b57cec5SDimitry Andric return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end - frm))); 13300b57cec5SDimitry Andric } 13310b57cec5SDimitry Andric 1332*cb14a3feSDimitry Andric int codecvt<char, char, mbstate_t>::do_max_length() const noexcept { return 1; } 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric // template <> class codecvt<wchar_t, char, mbstate_t> 13350b57cec5SDimitry Andric 1336349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 13375f757f3fSDimitry Andric constinit locale::id codecvt<wchar_t, char, mbstate_t>::id; 13380b57cec5SDimitry Andric 1339*cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) : locale::facet(refs), __l_(_LIBCPP_GET_C_LOCALE) {} 13400b57cec5SDimitry Andric 13410b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs) 1342*cb14a3feSDimitry Andric : locale::facet(refs), __l_(newlocale(LC_ALL_MASK, nm, 0)) { 1343bdd1243dSDimitry Andric if (__l_ == 0) 1344*cb14a3feSDimitry Andric __throw_runtime_error( 1345*cb14a3feSDimitry Andric ("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname" 1346*cb14a3feSDimitry Andric " failed to construct for " + 1347*cb14a3feSDimitry Andric string(nm)) 1348*cb14a3feSDimitry Andric .c_str()); 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric 1351*cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::~codecvt() { 1352bdd1243dSDimitry Andric if (__l_ != _LIBCPP_GET_C_LOCALE) 1353bdd1243dSDimitry Andric freelocale(__l_); 13540b57cec5SDimitry Andric } 13550b57cec5SDimitry Andric 1356*cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_out( 1357*cb14a3feSDimitry Andric state_type& st, 1358*cb14a3feSDimitry Andric const intern_type* frm, 1359*cb14a3feSDimitry Andric const intern_type* frm_end, 1360*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 1361*cb14a3feSDimitry Andric extern_type* to, 1362*cb14a3feSDimitry Andric extern_type* to_end, 1363*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 13640b57cec5SDimitry Andric // look for first internal null in frm 13650b57cec5SDimitry Andric const intern_type* fend = frm; 13660b57cec5SDimitry Andric for (; fend != frm_end; ++fend) 13670b57cec5SDimitry Andric if (*fend == 0) 13680b57cec5SDimitry Andric break; 13690b57cec5SDimitry Andric // loop over all null-terminated sequences in frm 13700b57cec5SDimitry Andric to_nxt = to; 1371*cb14a3feSDimitry Andric for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) { 13720b57cec5SDimitry Andric // save state in case it is needed to recover to_nxt on error 13730b57cec5SDimitry Andric mbstate_t save_state = st; 1374*cb14a3feSDimitry Andric size_t n = __libcpp_wcsnrtombs_l( 1375*cb14a3feSDimitry Andric to, &frm_nxt, static_cast<size_t>(fend - frm), static_cast<size_t>(to_end - to), &st, __l_); 1376*cb14a3feSDimitry Andric if (n == size_t(-1)) { 13770b57cec5SDimitry Andric // need to recover to_nxt 1378*cb14a3feSDimitry Andric for (to_nxt = to; frm != frm_nxt; ++frm) { 1379bdd1243dSDimitry Andric n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l_); 13800b57cec5SDimitry Andric if (n == size_t(-1)) 13810b57cec5SDimitry Andric break; 13820b57cec5SDimitry Andric to_nxt += n; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric frm_nxt = frm; 13850b57cec5SDimitry Andric return error; 13860b57cec5SDimitry Andric } 13870b57cec5SDimitry Andric if (n == 0) 13880b57cec5SDimitry Andric return partial; 13890b57cec5SDimitry Andric to_nxt += n; 13900b57cec5SDimitry Andric if (to_nxt == to_end) 13910b57cec5SDimitry Andric break; 13920b57cec5SDimitry Andric if (fend != frm_end) // set up next null terminated sequence 13930b57cec5SDimitry Andric { 13940b57cec5SDimitry Andric // Try to write the terminating null 13950b57cec5SDimitry Andric extern_type tmp[MB_LEN_MAX]; 1396bdd1243dSDimitry Andric n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_); 13970b57cec5SDimitry Andric if (n == size_t(-1)) // on error 13980b57cec5SDimitry Andric return error; 13990b57cec5SDimitry Andric if (n > static_cast<size_t>(to_end - to_nxt)) // is there room? 14000b57cec5SDimitry Andric return partial; 14010b57cec5SDimitry Andric for (extern_type* p = tmp; n; --n) // write it 14020b57cec5SDimitry Andric *to_nxt++ = *p++; 14030b57cec5SDimitry Andric ++frm_nxt; 14040b57cec5SDimitry Andric // look for next null in frm 14050b57cec5SDimitry Andric for (fend = frm_nxt; fend != frm_end; ++fend) 14060b57cec5SDimitry Andric if (*fend == 0) 14070b57cec5SDimitry Andric break; 14080b57cec5SDimitry Andric } 14090b57cec5SDimitry Andric } 14100b57cec5SDimitry Andric return frm_nxt == frm_end ? ok : partial; 14110b57cec5SDimitry Andric } 14120b57cec5SDimitry Andric 1413*cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_in( 1414*cb14a3feSDimitry Andric state_type& st, 1415*cb14a3feSDimitry Andric const extern_type* frm, 1416*cb14a3feSDimitry Andric const extern_type* frm_end, 1417*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 1418*cb14a3feSDimitry Andric intern_type* to, 1419*cb14a3feSDimitry Andric intern_type* to_end, 1420*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 14210b57cec5SDimitry Andric // look for first internal null in frm 14220b57cec5SDimitry Andric const extern_type* fend = frm; 14230b57cec5SDimitry Andric for (; fend != frm_end; ++fend) 14240b57cec5SDimitry Andric if (*fend == 0) 14250b57cec5SDimitry Andric break; 14260b57cec5SDimitry Andric // loop over all null-terminated sequences in frm 14270b57cec5SDimitry Andric to_nxt = to; 1428*cb14a3feSDimitry Andric for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) { 14290b57cec5SDimitry Andric // save state in case it is needed to recover to_nxt on error 14300b57cec5SDimitry Andric mbstate_t save_state = st; 1431*cb14a3feSDimitry Andric size_t n = __libcpp_mbsnrtowcs_l( 1432*cb14a3feSDimitry Andric to, &frm_nxt, static_cast<size_t>(fend - frm), static_cast<size_t>(to_end - to), &st, __l_); 1433*cb14a3feSDimitry Andric if (n == size_t(-1)) { 14340b57cec5SDimitry Andric // need to recover to_nxt 1435*cb14a3feSDimitry Andric for (to_nxt = to; frm != frm_nxt; ++to_nxt) { 1436*cb14a3feSDimitry Andric n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend - frm), &save_state, __l_); 1437*cb14a3feSDimitry Andric switch (n) { 14380b57cec5SDimitry Andric case 0: 14390b57cec5SDimitry Andric ++frm; 14400b57cec5SDimitry Andric break; 14410b57cec5SDimitry Andric case size_t(-1): 14420b57cec5SDimitry Andric frm_nxt = frm; 14430b57cec5SDimitry Andric return error; 14440b57cec5SDimitry Andric case size_t(-2): 14450b57cec5SDimitry Andric frm_nxt = frm; 14460b57cec5SDimitry Andric return partial; 14470b57cec5SDimitry Andric default: 14480b57cec5SDimitry Andric frm += n; 14490b57cec5SDimitry Andric break; 14500b57cec5SDimitry Andric } 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric frm_nxt = frm; 14530b57cec5SDimitry Andric return frm_nxt == frm_end ? ok : partial; 14540b57cec5SDimitry Andric } 14550b57cec5SDimitry Andric if (n == size_t(-1)) 14560b57cec5SDimitry Andric return error; 14570b57cec5SDimitry Andric to_nxt += n; 14580b57cec5SDimitry Andric if (to_nxt == to_end) 14590b57cec5SDimitry Andric break; 14600b57cec5SDimitry Andric if (fend != frm_end) // set up next null terminated sequence 14610b57cec5SDimitry Andric { 14620b57cec5SDimitry Andric // Try to write the terminating null 1463bdd1243dSDimitry Andric n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l_); 14640b57cec5SDimitry Andric if (n != 0) // on error 14650b57cec5SDimitry Andric return error; 14660b57cec5SDimitry Andric ++to_nxt; 14670b57cec5SDimitry Andric ++frm_nxt; 14680b57cec5SDimitry Andric // look for next null in frm 14690b57cec5SDimitry Andric for (fend = frm_nxt; fend != frm_end; ++fend) 14700b57cec5SDimitry Andric if (*fend == 0) 14710b57cec5SDimitry Andric break; 14720b57cec5SDimitry Andric } 14730b57cec5SDimitry Andric } 14740b57cec5SDimitry Andric return frm_nxt == frm_end ? ok : partial; 14750b57cec5SDimitry Andric } 14760b57cec5SDimitry Andric 1477*cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_unshift( 1478*cb14a3feSDimitry Andric state_type& st, extern_type* to, extern_type* to_end, extern_type*& to_nxt) const { 14790b57cec5SDimitry Andric to_nxt = to; 14800b57cec5SDimitry Andric extern_type tmp[MB_LEN_MAX]; 1481bdd1243dSDimitry Andric size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_); 14820b57cec5SDimitry Andric if (n == size_t(-1) || n == 0) // on error 14830b57cec5SDimitry Andric return error; 14840b57cec5SDimitry Andric --n; 14850b57cec5SDimitry Andric if (n > static_cast<size_t>(to_end - to_nxt)) // is there room? 14860b57cec5SDimitry Andric return partial; 14870b57cec5SDimitry Andric for (extern_type* p = tmp; n; --n) // write it 14880b57cec5SDimitry Andric *to_nxt++ = *p++; 14890b57cec5SDimitry Andric return ok; 14900b57cec5SDimitry Andric } 14910b57cec5SDimitry Andric 1492*cb14a3feSDimitry Andric int codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept { 1493bdd1243dSDimitry Andric if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l_) != 0) 14940b57cec5SDimitry Andric return -1; 14950b57cec5SDimitry Andric 14960b57cec5SDimitry Andric // stateless encoding 1497bdd1243dSDimitry Andric if (__l_ == 0 || __libcpp_mb_cur_max_l(__l_) == 1) // there are no known constant length encodings 14980b57cec5SDimitry Andric return 1; // which take more than 1 char to form a wchar_t 14990b57cec5SDimitry Andric return 0; 15000b57cec5SDimitry Andric } 15010b57cec5SDimitry Andric 1502*cb14a3feSDimitry Andric bool codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; } 15030b57cec5SDimitry Andric 1504*cb14a3feSDimitry Andric int codecvt<wchar_t, char, mbstate_t>::do_length( 1505*cb14a3feSDimitry Andric state_type& st, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 15060b57cec5SDimitry Andric int nbytes = 0; 1507*cb14a3feSDimitry Andric for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) { 1508bdd1243dSDimitry Andric size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end - frm), &st, __l_); 1509*cb14a3feSDimitry Andric switch (n) { 15100b57cec5SDimitry Andric case 0: 15110b57cec5SDimitry Andric ++nbytes; 15120b57cec5SDimitry Andric ++frm; 15130b57cec5SDimitry Andric break; 15140b57cec5SDimitry Andric case size_t(-1): 15150b57cec5SDimitry Andric case size_t(-2): 15160b57cec5SDimitry Andric return nbytes; 15170b57cec5SDimitry Andric default: 15180b57cec5SDimitry Andric nbytes += n; 15190b57cec5SDimitry Andric frm += n; 15200b57cec5SDimitry Andric break; 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric } 15230b57cec5SDimitry Andric return nbytes; 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric 1526*cb14a3feSDimitry Andric int codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept { 1527bdd1243dSDimitry Andric return __l_ == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l_)); 15280b57cec5SDimitry Andric } 1529349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric // Valid UTF ranges 15320b57cec5SDimitry Andric // UTF-32 UTF-16 UTF-8 # of code points 15330b57cec5SDimitry Andric // first second first second third fourth 15340b57cec5SDimitry Andric // 000000 - 00007F 0000 - 007F 00 - 7F 127 15350b57cec5SDimitry Andric // 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920 15360b57cec5SDimitry Andric // 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048 15370b57cec5SDimitry Andric // 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152 15380b57cec5SDimitry Andric // 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048 15390b57cec5SDimitry Andric // 00D800 - 00DFFF invalid 15400b57cec5SDimitry Andric // 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192 15410b57cec5SDimitry Andric // 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608 15420b57cec5SDimitry Andric // 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432 15430b57cec5SDimitry Andric // 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536 15440b57cec5SDimitry Andric 154581ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 1546*cb14a3feSDimitry Andric static codecvt_base::result utf16_to_utf8( 1547*cb14a3feSDimitry Andric const uint16_t* frm, 1548*cb14a3feSDimitry Andric const uint16_t* frm_end, 1549*cb14a3feSDimitry Andric const uint16_t*& frm_nxt, 1550*cb14a3feSDimitry Andric uint8_t* to, 1551*cb14a3feSDimitry Andric uint8_t* to_end, 1552*cb14a3feSDimitry Andric uint8_t*& to_nxt, 1553*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 1554*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 15550b57cec5SDimitry Andric frm_nxt = frm; 15560b57cec5SDimitry Andric to_nxt = to; 1557*cb14a3feSDimitry Andric if (mode & generate_header) { 15580b57cec5SDimitry Andric if (to_end - to_nxt < 3) 15590b57cec5SDimitry Andric return codecvt_base::partial; 15600b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xEF); 15610b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBB); 15620b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBF); 15630b57cec5SDimitry Andric } 1564*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 15650b57cec5SDimitry Andric uint16_t wc1 = *frm_nxt; 15660b57cec5SDimitry Andric if (wc1 > Maxcode) 15670b57cec5SDimitry Andric return codecvt_base::error; 1568*cb14a3feSDimitry Andric if (wc1 < 0x0080) { 15690b57cec5SDimitry Andric if (to_end - to_nxt < 1) 15700b57cec5SDimitry Andric return codecvt_base::partial; 15710b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc1); 1572*cb14a3feSDimitry Andric } else if (wc1 < 0x0800) { 15730b57cec5SDimitry Andric if (to_end - to_nxt < 2) 15740b57cec5SDimitry Andric return codecvt_base::partial; 15750b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); 15760b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); 1577*cb14a3feSDimitry Andric } else if (wc1 < 0xD800) { 15780b57cec5SDimitry Andric if (to_end - to_nxt < 3) 15790b57cec5SDimitry Andric return codecvt_base::partial; 15800b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 15810b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 15820b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 1583*cb14a3feSDimitry Andric } else if (wc1 < 0xDC00) { 15840b57cec5SDimitry Andric if (frm_end - frm_nxt < 2) 15850b57cec5SDimitry Andric return codecvt_base::partial; 15860b57cec5SDimitry Andric uint16_t wc2 = frm_nxt[1]; 15870b57cec5SDimitry Andric if ((wc2 & 0xFC00) != 0xDC00) 15880b57cec5SDimitry Andric return codecvt_base::error; 15890b57cec5SDimitry Andric if (to_end - to_nxt < 4) 15900b57cec5SDimitry Andric return codecvt_base::partial; 1591*cb14a3feSDimitry Andric if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) 15920b57cec5SDimitry Andric return codecvt_base::error; 15930b57cec5SDimitry Andric ++frm_nxt; 15940b57cec5SDimitry Andric uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; 15950b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); 15960b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); 15970b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); 15980b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); 1599*cb14a3feSDimitry Andric } else if (wc1 < 0xE000) { 16000b57cec5SDimitry Andric return codecvt_base::error; 1601*cb14a3feSDimitry Andric } else { 16020b57cec5SDimitry Andric if (to_end - to_nxt < 3) 16030b57cec5SDimitry Andric return codecvt_base::partial; 16040b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 16050b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 16060b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 16070b57cec5SDimitry Andric } 16080b57cec5SDimitry Andric } 16090b57cec5SDimitry Andric return codecvt_base::ok; 16100b57cec5SDimitry Andric } 16110b57cec5SDimitry Andric 1612*cb14a3feSDimitry Andric static codecvt_base::result utf16_to_utf8( 1613*cb14a3feSDimitry Andric const uint32_t* frm, 1614*cb14a3feSDimitry Andric const uint32_t* frm_end, 1615*cb14a3feSDimitry Andric const uint32_t*& frm_nxt, 1616*cb14a3feSDimitry Andric uint8_t* to, 1617*cb14a3feSDimitry Andric uint8_t* to_end, 1618*cb14a3feSDimitry Andric uint8_t*& to_nxt, 1619*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 1620*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 16210b57cec5SDimitry Andric frm_nxt = frm; 16220b57cec5SDimitry Andric to_nxt = to; 1623*cb14a3feSDimitry Andric if (mode & generate_header) { 16240b57cec5SDimitry Andric if (to_end - to_nxt < 3) 16250b57cec5SDimitry Andric return codecvt_base::partial; 16260b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xEF); 16270b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBB); 16280b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBF); 16290b57cec5SDimitry Andric } 1630*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 16310b57cec5SDimitry Andric uint16_t wc1 = static_cast<uint16_t>(*frm_nxt); 16320b57cec5SDimitry Andric if (wc1 > Maxcode) 16330b57cec5SDimitry Andric return codecvt_base::error; 1634*cb14a3feSDimitry Andric if (wc1 < 0x0080) { 16350b57cec5SDimitry Andric if (to_end - to_nxt < 1) 16360b57cec5SDimitry Andric return codecvt_base::partial; 16370b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc1); 1638*cb14a3feSDimitry Andric } else if (wc1 < 0x0800) { 16390b57cec5SDimitry Andric if (to_end - to_nxt < 2) 16400b57cec5SDimitry Andric return codecvt_base::partial; 16410b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); 16420b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); 1643*cb14a3feSDimitry Andric } else if (wc1 < 0xD800) { 16440b57cec5SDimitry Andric if (to_end - to_nxt < 3) 16450b57cec5SDimitry Andric return codecvt_base::partial; 16460b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 16470b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 16480b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 1649*cb14a3feSDimitry Andric } else if (wc1 < 0xDC00) { 16500b57cec5SDimitry Andric if (frm_end - frm_nxt < 2) 16510b57cec5SDimitry Andric return codecvt_base::partial; 16520b57cec5SDimitry Andric uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]); 16530b57cec5SDimitry Andric if ((wc2 & 0xFC00) != 0xDC00) 16540b57cec5SDimitry Andric return codecvt_base::error; 16550b57cec5SDimitry Andric if (to_end - to_nxt < 4) 16560b57cec5SDimitry Andric return codecvt_base::partial; 1657*cb14a3feSDimitry Andric if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) 16580b57cec5SDimitry Andric return codecvt_base::error; 16590b57cec5SDimitry Andric ++frm_nxt; 16600b57cec5SDimitry Andric uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; 16610b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); 16620b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); 16630b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); 16640b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); 1665*cb14a3feSDimitry Andric } else if (wc1 < 0xE000) { 16660b57cec5SDimitry Andric return codecvt_base::error; 1667*cb14a3feSDimitry Andric } else { 16680b57cec5SDimitry Andric if (to_end - to_nxt < 3) 16690b57cec5SDimitry Andric return codecvt_base::partial; 16700b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); 16710b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); 16720b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); 16730b57cec5SDimitry Andric } 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric return codecvt_base::ok; 16760b57cec5SDimitry Andric } 16770b57cec5SDimitry Andric 1678*cb14a3feSDimitry Andric static codecvt_base::result utf8_to_utf16( 1679*cb14a3feSDimitry Andric const uint8_t* frm, 1680*cb14a3feSDimitry Andric const uint8_t* frm_end, 1681*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 1682*cb14a3feSDimitry Andric uint16_t* to, 1683*cb14a3feSDimitry Andric uint16_t* to_end, 1684*cb14a3feSDimitry Andric uint16_t*& to_nxt, 1685*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 1686*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 16870b57cec5SDimitry Andric frm_nxt = frm; 16880b57cec5SDimitry Andric to_nxt = to; 1689*cb14a3feSDimitry Andric if (mode & consume_header) { 1690*cb14a3feSDimitry Andric if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF) 16910b57cec5SDimitry Andric frm_nxt += 3; 16920b57cec5SDimitry Andric } 1693*cb14a3feSDimitry Andric for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) { 16940b57cec5SDimitry Andric uint8_t c1 = *frm_nxt; 16950b57cec5SDimitry Andric if (c1 > Maxcode) 16960b57cec5SDimitry Andric return codecvt_base::error; 1697*cb14a3feSDimitry Andric if (c1 < 0x80) { 16980b57cec5SDimitry Andric *to_nxt = static_cast<uint16_t>(c1); 16990b57cec5SDimitry Andric ++frm_nxt; 1700*cb14a3feSDimitry Andric } else if (c1 < 0xC2) { 17010b57cec5SDimitry Andric return codecvt_base::error; 1702*cb14a3feSDimitry Andric } else if (c1 < 0xE0) { 17030b57cec5SDimitry Andric if (frm_end - frm_nxt < 2) 17040b57cec5SDimitry Andric return codecvt_base::partial; 17050b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 17060b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 17070b57cec5SDimitry Andric return codecvt_base::error; 17080b57cec5SDimitry Andric uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); 17090b57cec5SDimitry Andric if (t > Maxcode) 17100b57cec5SDimitry Andric return codecvt_base::error; 17110b57cec5SDimitry Andric *to_nxt = t; 17120b57cec5SDimitry Andric frm_nxt += 2; 1713*cb14a3feSDimitry Andric } else if (c1 < 0xF0) { 17145f757f3fSDimitry Andric if (frm_end - frm_nxt < 2) 17150b57cec5SDimitry Andric return codecvt_base::partial; 17160b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 1717*cb14a3feSDimitry Andric switch (c1) { 17180b57cec5SDimitry Andric case 0xE0: 17190b57cec5SDimitry Andric if ((c2 & 0xE0) != 0xA0) 17200b57cec5SDimitry Andric return codecvt_base::error; 17210b57cec5SDimitry Andric break; 17220b57cec5SDimitry Andric case 0xED: 17230b57cec5SDimitry Andric if ((c2 & 0xE0) != 0x80) 17240b57cec5SDimitry Andric return codecvt_base::error; 17250b57cec5SDimitry Andric break; 17260b57cec5SDimitry Andric default: 17270b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 17280b57cec5SDimitry Andric return codecvt_base::error; 17290b57cec5SDimitry Andric break; 17300b57cec5SDimitry Andric } 17315f757f3fSDimitry Andric if (frm_end - frm_nxt < 3) 17325f757f3fSDimitry Andric return codecvt_base::partial; 17335f757f3fSDimitry Andric uint8_t c3 = frm_nxt[2]; 17340b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80) 17350b57cec5SDimitry Andric return codecvt_base::error; 1736*cb14a3feSDimitry Andric uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); 17370b57cec5SDimitry Andric if (t > Maxcode) 17380b57cec5SDimitry Andric return codecvt_base::error; 17390b57cec5SDimitry Andric *to_nxt = t; 17400b57cec5SDimitry Andric frm_nxt += 3; 1741*cb14a3feSDimitry Andric } else if (c1 < 0xF5) { 17425f757f3fSDimitry Andric if (frm_end - frm_nxt < 2) 17430b57cec5SDimitry Andric return codecvt_base::partial; 17440b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 1745*cb14a3feSDimitry Andric switch (c1) { 17460b57cec5SDimitry Andric case 0xF0: 17470b57cec5SDimitry Andric if (!(0x90 <= c2 && c2 <= 0xBF)) 17480b57cec5SDimitry Andric return codecvt_base::error; 17490b57cec5SDimitry Andric break; 17500b57cec5SDimitry Andric case 0xF4: 17510b57cec5SDimitry Andric if ((c2 & 0xF0) != 0x80) 17520b57cec5SDimitry Andric return codecvt_base::error; 17530b57cec5SDimitry Andric break; 17540b57cec5SDimitry Andric default: 17550b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 17560b57cec5SDimitry Andric return codecvt_base::error; 17570b57cec5SDimitry Andric break; 17580b57cec5SDimitry Andric } 17595f757f3fSDimitry Andric if (frm_end - frm_nxt < 3) 17605f757f3fSDimitry Andric return codecvt_base::partial; 17615f757f3fSDimitry Andric uint8_t c3 = frm_nxt[2]; 17625f757f3fSDimitry Andric if ((c3 & 0xC0) != 0x80) 17635f757f3fSDimitry Andric return codecvt_base::error; 17645f757f3fSDimitry Andric if (frm_end - frm_nxt < 4) 17655f757f3fSDimitry Andric return codecvt_base::partial; 17665f757f3fSDimitry Andric uint8_t c4 = frm_nxt[3]; 17675f757f3fSDimitry Andric if ((c4 & 0xC0) != 0x80) 17680b57cec5SDimitry Andric return codecvt_base::error; 17690b57cec5SDimitry Andric if (to_end - to_nxt < 2) 17700b57cec5SDimitry Andric return codecvt_base::partial; 1771*cb14a3feSDimitry Andric if ((((c1 & 7UL) << 18) + ((c2 & 0x3FUL) << 12) + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) 17720b57cec5SDimitry Andric return codecvt_base::error; 17730b57cec5SDimitry Andric *to_nxt = static_cast<uint16_t>( 1774*cb14a3feSDimitry Andric 0xD800 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) | ((c2 & 0x0F) << 2) | ((c3 & 0x30) >> 4)); 1775*cb14a3feSDimitry Andric *++to_nxt = static_cast<uint16_t>(0xDC00 | ((c3 & 0x0F) << 6) | (c4 & 0x3F)); 17760b57cec5SDimitry Andric frm_nxt += 4; 1777*cb14a3feSDimitry Andric } else { 17780b57cec5SDimitry Andric return codecvt_base::error; 17790b57cec5SDimitry Andric } 17800b57cec5SDimitry Andric } 17810b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric 1784*cb14a3feSDimitry Andric static codecvt_base::result utf8_to_utf16( 1785*cb14a3feSDimitry Andric const uint8_t* frm, 1786*cb14a3feSDimitry Andric const uint8_t* frm_end, 1787*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 1788*cb14a3feSDimitry Andric uint32_t* to, 1789*cb14a3feSDimitry Andric uint32_t* to_end, 1790*cb14a3feSDimitry Andric uint32_t*& to_nxt, 1791*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 1792*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 17930b57cec5SDimitry Andric frm_nxt = frm; 17940b57cec5SDimitry Andric to_nxt = to; 1795*cb14a3feSDimitry Andric if (mode & consume_header) { 1796*cb14a3feSDimitry Andric if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF) 17970b57cec5SDimitry Andric frm_nxt += 3; 17980b57cec5SDimitry Andric } 1799*cb14a3feSDimitry Andric for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) { 18000b57cec5SDimitry Andric uint8_t c1 = *frm_nxt; 18010b57cec5SDimitry Andric if (c1 > Maxcode) 18020b57cec5SDimitry Andric return codecvt_base::error; 1803*cb14a3feSDimitry Andric if (c1 < 0x80) { 18040b57cec5SDimitry Andric *to_nxt = static_cast<uint32_t>(c1); 18050b57cec5SDimitry Andric ++frm_nxt; 1806*cb14a3feSDimitry Andric } else if (c1 < 0xC2) { 18070b57cec5SDimitry Andric return codecvt_base::error; 1808*cb14a3feSDimitry Andric } else if (c1 < 0xE0) { 18090b57cec5SDimitry Andric if (frm_end - frm_nxt < 2) 18100b57cec5SDimitry Andric return codecvt_base::partial; 18110b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 18120b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 18130b57cec5SDimitry Andric return codecvt_base::error; 18140b57cec5SDimitry Andric uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); 18150b57cec5SDimitry Andric if (t > Maxcode) 18160b57cec5SDimitry Andric return codecvt_base::error; 18170b57cec5SDimitry Andric *to_nxt = static_cast<uint32_t>(t); 18180b57cec5SDimitry Andric frm_nxt += 2; 1819*cb14a3feSDimitry Andric } else if (c1 < 0xF0) { 18205f757f3fSDimitry Andric if (frm_end - frm_nxt < 2) 18210b57cec5SDimitry Andric return codecvt_base::partial; 18220b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 1823*cb14a3feSDimitry Andric switch (c1) { 18240b57cec5SDimitry Andric case 0xE0: 18250b57cec5SDimitry Andric if ((c2 & 0xE0) != 0xA0) 18260b57cec5SDimitry Andric return codecvt_base::error; 18270b57cec5SDimitry Andric break; 18280b57cec5SDimitry Andric case 0xED: 18290b57cec5SDimitry Andric if ((c2 & 0xE0) != 0x80) 18300b57cec5SDimitry Andric return codecvt_base::error; 18310b57cec5SDimitry Andric break; 18320b57cec5SDimitry Andric default: 18330b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 18340b57cec5SDimitry Andric return codecvt_base::error; 18350b57cec5SDimitry Andric break; 18360b57cec5SDimitry Andric } 18375f757f3fSDimitry Andric if (frm_end - frm_nxt < 3) 18385f757f3fSDimitry Andric return codecvt_base::partial; 18395f757f3fSDimitry Andric uint8_t c3 = frm_nxt[2]; 18400b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80) 18410b57cec5SDimitry Andric return codecvt_base::error; 1842*cb14a3feSDimitry Andric uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); 18430b57cec5SDimitry Andric if (t > Maxcode) 18440b57cec5SDimitry Andric return codecvt_base::error; 18450b57cec5SDimitry Andric *to_nxt = static_cast<uint32_t>(t); 18460b57cec5SDimitry Andric frm_nxt += 3; 1847*cb14a3feSDimitry Andric } else if (c1 < 0xF5) { 18485f757f3fSDimitry Andric if (frm_end - frm_nxt < 2) 18490b57cec5SDimitry Andric return codecvt_base::partial; 18500b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 1851*cb14a3feSDimitry Andric switch (c1) { 18520b57cec5SDimitry Andric case 0xF0: 18530b57cec5SDimitry Andric if (!(0x90 <= c2 && c2 <= 0xBF)) 18540b57cec5SDimitry Andric return codecvt_base::error; 18550b57cec5SDimitry Andric break; 18560b57cec5SDimitry Andric case 0xF4: 18570b57cec5SDimitry Andric if ((c2 & 0xF0) != 0x80) 18580b57cec5SDimitry Andric return codecvt_base::error; 18590b57cec5SDimitry Andric break; 18600b57cec5SDimitry Andric default: 18610b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 18620b57cec5SDimitry Andric return codecvt_base::error; 18630b57cec5SDimitry Andric break; 18640b57cec5SDimitry Andric } 18655f757f3fSDimitry Andric if (frm_end - frm_nxt < 3) 18665f757f3fSDimitry Andric return codecvt_base::partial; 18675f757f3fSDimitry Andric uint8_t c3 = frm_nxt[2]; 18685f757f3fSDimitry Andric if ((c3 & 0xC0) != 0x80) 18695f757f3fSDimitry Andric return codecvt_base::error; 18705f757f3fSDimitry Andric if (frm_end - frm_nxt < 4) 18715f757f3fSDimitry Andric return codecvt_base::partial; 18725f757f3fSDimitry Andric uint8_t c4 = frm_nxt[3]; 18735f757f3fSDimitry Andric if ((c4 & 0xC0) != 0x80) 18740b57cec5SDimitry Andric return codecvt_base::error; 18750b57cec5SDimitry Andric if (to_end - to_nxt < 2) 18760b57cec5SDimitry Andric return codecvt_base::partial; 1877*cb14a3feSDimitry Andric if ((((c1 & 7UL) << 18) + ((c2 & 0x3FUL) << 12) + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) 18780b57cec5SDimitry Andric return codecvt_base::error; 18790b57cec5SDimitry Andric *to_nxt = static_cast<uint32_t>( 1880*cb14a3feSDimitry Andric 0xD800 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) | ((c2 & 0x0F) << 2) | ((c3 & 0x30) >> 4)); 1881*cb14a3feSDimitry Andric *++to_nxt = static_cast<uint32_t>(0xDC00 | ((c3 & 0x0F) << 6) | (c4 & 0x3F)); 18820b57cec5SDimitry Andric frm_nxt += 4; 1883*cb14a3feSDimitry Andric } else { 18840b57cec5SDimitry Andric return codecvt_base::error; 18850b57cec5SDimitry Andric } 18860b57cec5SDimitry Andric } 18870b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 18880b57cec5SDimitry Andric } 18890b57cec5SDimitry Andric 1890*cb14a3feSDimitry Andric static int utf8_to_utf16_length( 1891*cb14a3feSDimitry Andric const uint8_t* frm, 1892*cb14a3feSDimitry Andric const uint8_t* frm_end, 1893*cb14a3feSDimitry Andric size_t mx, 1894*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 1895*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 18960b57cec5SDimitry Andric const uint8_t* frm_nxt = frm; 1897*cb14a3feSDimitry Andric if (mode & consume_header) { 1898*cb14a3feSDimitry Andric if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF) 18990b57cec5SDimitry Andric frm_nxt += 3; 19000b57cec5SDimitry Andric } 1901*cb14a3feSDimitry Andric for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) { 19020b57cec5SDimitry Andric uint8_t c1 = *frm_nxt; 19030b57cec5SDimitry Andric if (c1 > Maxcode) 19040b57cec5SDimitry Andric break; 1905*cb14a3feSDimitry Andric if (c1 < 0x80) { 19060b57cec5SDimitry Andric ++frm_nxt; 1907*cb14a3feSDimitry Andric } else if (c1 < 0xC2) { 19080b57cec5SDimitry Andric break; 1909*cb14a3feSDimitry Andric } else if (c1 < 0xE0) { 19100b57cec5SDimitry Andric if ((frm_end - frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80) 19110b57cec5SDimitry Andric break; 19120b57cec5SDimitry Andric uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)); 19130b57cec5SDimitry Andric if (t > Maxcode) 19140b57cec5SDimitry Andric break; 19150b57cec5SDimitry Andric frm_nxt += 2; 1916*cb14a3feSDimitry Andric } else if (c1 < 0xF0) { 19170b57cec5SDimitry Andric if (frm_end - frm_nxt < 3) 19180b57cec5SDimitry Andric break; 19190b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 19200b57cec5SDimitry Andric uint8_t c3 = frm_nxt[2]; 1921*cb14a3feSDimitry Andric switch (c1) { 19220b57cec5SDimitry Andric case 0xE0: 19230b57cec5SDimitry Andric if ((c2 & 0xE0) != 0xA0) 19240b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 19250b57cec5SDimitry Andric break; 19260b57cec5SDimitry Andric case 0xED: 19270b57cec5SDimitry Andric if ((c2 & 0xE0) != 0x80) 19280b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 19290b57cec5SDimitry Andric break; 19300b57cec5SDimitry Andric default: 19310b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 19320b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 19330b57cec5SDimitry Andric break; 19340b57cec5SDimitry Andric } 19350b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80) 19360b57cec5SDimitry Andric break; 19370b57cec5SDimitry Andric if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) 19380b57cec5SDimitry Andric break; 19390b57cec5SDimitry Andric frm_nxt += 3; 1940*cb14a3feSDimitry Andric } else if (c1 < 0xF5) { 19410b57cec5SDimitry Andric if (frm_end - frm_nxt < 4 || mx - nchar16_t < 2) 19420b57cec5SDimitry Andric break; 19430b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 19440b57cec5SDimitry Andric uint8_t c3 = frm_nxt[2]; 19450b57cec5SDimitry Andric uint8_t c4 = frm_nxt[3]; 1946*cb14a3feSDimitry Andric switch (c1) { 19470b57cec5SDimitry Andric case 0xF0: 19480b57cec5SDimitry Andric if (!(0x90 <= c2 && c2 <= 0xBF)) 19490b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 19500b57cec5SDimitry Andric break; 19510b57cec5SDimitry Andric case 0xF4: 19520b57cec5SDimitry Andric if ((c2 & 0xF0) != 0x80) 19530b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 19540b57cec5SDimitry Andric break; 19550b57cec5SDimitry Andric default: 19560b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 19570b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 19580b57cec5SDimitry Andric break; 19590b57cec5SDimitry Andric } 19600b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) 19610b57cec5SDimitry Andric break; 1962*cb14a3feSDimitry Andric if ((((c1 & 7UL) << 18) + ((c2 & 0x3FUL) << 12) + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) 19630b57cec5SDimitry Andric break; 19640b57cec5SDimitry Andric ++nchar16_t; 19650b57cec5SDimitry Andric frm_nxt += 4; 1966*cb14a3feSDimitry Andric } else { 19670b57cec5SDimitry Andric break; 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric } 19700b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 19710b57cec5SDimitry Andric } 19720b57cec5SDimitry Andric 1973*cb14a3feSDimitry Andric static codecvt_base::result ucs4_to_utf8( 1974*cb14a3feSDimitry Andric const uint32_t* frm, 1975*cb14a3feSDimitry Andric const uint32_t* frm_end, 1976*cb14a3feSDimitry Andric const uint32_t*& frm_nxt, 1977*cb14a3feSDimitry Andric uint8_t* to, 1978*cb14a3feSDimitry Andric uint8_t* to_end, 1979*cb14a3feSDimitry Andric uint8_t*& to_nxt, 1980*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 1981*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 19820b57cec5SDimitry Andric frm_nxt = frm; 19830b57cec5SDimitry Andric to_nxt = to; 1984*cb14a3feSDimitry Andric if (mode & generate_header) { 19850b57cec5SDimitry Andric if (to_end - to_nxt < 3) 19860b57cec5SDimitry Andric return codecvt_base::partial; 19870b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xEF); 19880b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBB); 19890b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBF); 19900b57cec5SDimitry Andric } 1991*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 19920b57cec5SDimitry Andric uint32_t wc = *frm_nxt; 19930b57cec5SDimitry Andric if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) 19940b57cec5SDimitry Andric return codecvt_base::error; 1995*cb14a3feSDimitry Andric if (wc < 0x000080) { 19960b57cec5SDimitry Andric if (to_end - to_nxt < 1) 19970b57cec5SDimitry Andric return codecvt_base::partial; 19980b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc); 1999*cb14a3feSDimitry Andric } else if (wc < 0x000800) { 20000b57cec5SDimitry Andric if (to_end - to_nxt < 2) 20010b57cec5SDimitry Andric return codecvt_base::partial; 20020b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); 20030b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); 2004*cb14a3feSDimitry Andric } else if (wc < 0x010000) { 20050b57cec5SDimitry Andric if (to_end - to_nxt < 3) 20060b57cec5SDimitry Andric return codecvt_base::partial; 20070b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); 20080b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); 20090b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); 2010*cb14a3feSDimitry Andric } else // if (wc < 0x110000) 20110b57cec5SDimitry Andric { 20120b57cec5SDimitry Andric if (to_end - to_nxt < 4) 20130b57cec5SDimitry Andric return codecvt_base::partial; 20140b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18)); 20150b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12)); 20160b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6)); 20170b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F)); 20180b57cec5SDimitry Andric } 20190b57cec5SDimitry Andric } 20200b57cec5SDimitry Andric return codecvt_base::ok; 20210b57cec5SDimitry Andric } 20220b57cec5SDimitry Andric 2023*cb14a3feSDimitry Andric static codecvt_base::result utf8_to_ucs4( 2024*cb14a3feSDimitry Andric const uint8_t* frm, 2025*cb14a3feSDimitry Andric const uint8_t* frm_end, 2026*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 2027*cb14a3feSDimitry Andric uint32_t* to, 2028*cb14a3feSDimitry Andric uint32_t* to_end, 2029*cb14a3feSDimitry Andric uint32_t*& to_nxt, 2030*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2031*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 20320b57cec5SDimitry Andric frm_nxt = frm; 20330b57cec5SDimitry Andric to_nxt = to; 2034*cb14a3feSDimitry Andric if (mode & consume_header) { 2035*cb14a3feSDimitry Andric if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF) 20360b57cec5SDimitry Andric frm_nxt += 3; 20370b57cec5SDimitry Andric } 2038*cb14a3feSDimitry Andric for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) { 20390b57cec5SDimitry Andric uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2040*cb14a3feSDimitry Andric if (c1 < 0x80) { 20410b57cec5SDimitry Andric if (c1 > Maxcode) 20420b57cec5SDimitry Andric return codecvt_base::error; 20430b57cec5SDimitry Andric *to_nxt = static_cast<uint32_t>(c1); 20440b57cec5SDimitry Andric ++frm_nxt; 2045*cb14a3feSDimitry Andric } else if (c1 < 0xC2) { 20460b57cec5SDimitry Andric return codecvt_base::error; 2047*cb14a3feSDimitry Andric } else if (c1 < 0xE0) { 20480b57cec5SDimitry Andric if (frm_end - frm_nxt < 2) 20490b57cec5SDimitry Andric return codecvt_base::partial; 20500b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 20510b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 20520b57cec5SDimitry Andric return codecvt_base::error; 2053*cb14a3feSDimitry Andric uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); 20540b57cec5SDimitry Andric if (t > Maxcode) 20550b57cec5SDimitry Andric return codecvt_base::error; 20560b57cec5SDimitry Andric *to_nxt = t; 20570b57cec5SDimitry Andric frm_nxt += 2; 2058*cb14a3feSDimitry Andric } else if (c1 < 0xF0) { 20595f757f3fSDimitry Andric if (frm_end - frm_nxt < 2) 20600b57cec5SDimitry Andric return codecvt_base::partial; 20610b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 2062*cb14a3feSDimitry Andric switch (c1) { 20630b57cec5SDimitry Andric case 0xE0: 20640b57cec5SDimitry Andric if ((c2 & 0xE0) != 0xA0) 20650b57cec5SDimitry Andric return codecvt_base::error; 20660b57cec5SDimitry Andric break; 20670b57cec5SDimitry Andric case 0xED: 20680b57cec5SDimitry Andric if ((c2 & 0xE0) != 0x80) 20690b57cec5SDimitry Andric return codecvt_base::error; 20700b57cec5SDimitry Andric break; 20710b57cec5SDimitry Andric default: 20720b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 20730b57cec5SDimitry Andric return codecvt_base::error; 20740b57cec5SDimitry Andric break; 20750b57cec5SDimitry Andric } 20765f757f3fSDimitry Andric if (frm_end - frm_nxt < 3) 20775f757f3fSDimitry Andric return codecvt_base::partial; 20785f757f3fSDimitry Andric uint8_t c3 = frm_nxt[2]; 20790b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80) 20800b57cec5SDimitry Andric return codecvt_base::error; 2081*cb14a3feSDimitry Andric uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); 20820b57cec5SDimitry Andric if (t > Maxcode) 20830b57cec5SDimitry Andric return codecvt_base::error; 20840b57cec5SDimitry Andric *to_nxt = t; 20850b57cec5SDimitry Andric frm_nxt += 3; 2086*cb14a3feSDimitry Andric } else if (c1 < 0xF5) { 20875f757f3fSDimitry Andric if (frm_end - frm_nxt < 2) 20880b57cec5SDimitry Andric return codecvt_base::partial; 20890b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 2090*cb14a3feSDimitry Andric switch (c1) { 20910b57cec5SDimitry Andric case 0xF0: 20920b57cec5SDimitry Andric if (!(0x90 <= c2 && c2 <= 0xBF)) 20930b57cec5SDimitry Andric return codecvt_base::error; 20940b57cec5SDimitry Andric break; 20950b57cec5SDimitry Andric case 0xF4: 20960b57cec5SDimitry Andric if ((c2 & 0xF0) != 0x80) 20970b57cec5SDimitry Andric return codecvt_base::error; 20980b57cec5SDimitry Andric break; 20990b57cec5SDimitry Andric default: 21000b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 21010b57cec5SDimitry Andric return codecvt_base::error; 21020b57cec5SDimitry Andric break; 21030b57cec5SDimitry Andric } 21045f757f3fSDimitry Andric if (frm_end - frm_nxt < 3) 21055f757f3fSDimitry Andric return codecvt_base::partial; 21065f757f3fSDimitry Andric uint8_t c3 = frm_nxt[2]; 21075f757f3fSDimitry Andric if ((c3 & 0xC0) != 0x80) 21085f757f3fSDimitry Andric return codecvt_base::error; 21095f757f3fSDimitry Andric if (frm_end - frm_nxt < 4) 21105f757f3fSDimitry Andric return codecvt_base::partial; 21115f757f3fSDimitry Andric uint8_t c4 = frm_nxt[3]; 21125f757f3fSDimitry Andric if ((c4 & 0xC0) != 0x80) 21130b57cec5SDimitry Andric return codecvt_base::error; 2114*cb14a3feSDimitry Andric uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) | (c4 & 0x3F)); 21150b57cec5SDimitry Andric if (t > Maxcode) 21160b57cec5SDimitry Andric return codecvt_base::error; 21170b57cec5SDimitry Andric *to_nxt = t; 21180b57cec5SDimitry Andric frm_nxt += 4; 2119*cb14a3feSDimitry Andric } else { 21200b57cec5SDimitry Andric return codecvt_base::error; 21210b57cec5SDimitry Andric } 21220b57cec5SDimitry Andric } 21230b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 21240b57cec5SDimitry Andric } 21250b57cec5SDimitry Andric 2126*cb14a3feSDimitry Andric static int utf8_to_ucs4_length( 2127*cb14a3feSDimitry Andric const uint8_t* frm, 2128*cb14a3feSDimitry Andric const uint8_t* frm_end, 2129*cb14a3feSDimitry Andric size_t mx, 2130*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2131*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 21320b57cec5SDimitry Andric const uint8_t* frm_nxt = frm; 2133*cb14a3feSDimitry Andric if (mode & consume_header) { 2134*cb14a3feSDimitry Andric if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF) 21350b57cec5SDimitry Andric frm_nxt += 3; 21360b57cec5SDimitry Andric } 2137*cb14a3feSDimitry Andric for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) { 21380b57cec5SDimitry Andric uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2139*cb14a3feSDimitry Andric if (c1 < 0x80) { 21400b57cec5SDimitry Andric if (c1 > Maxcode) 21410b57cec5SDimitry Andric break; 21420b57cec5SDimitry Andric ++frm_nxt; 2143*cb14a3feSDimitry Andric } else if (c1 < 0xC2) { 21440b57cec5SDimitry Andric break; 2145*cb14a3feSDimitry Andric } else if (c1 < 0xE0) { 21460b57cec5SDimitry Andric if ((frm_end - frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) 21470b57cec5SDimitry Andric break; 21480b57cec5SDimitry Andric if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) 21490b57cec5SDimitry Andric break; 21500b57cec5SDimitry Andric frm_nxt += 2; 2151*cb14a3feSDimitry Andric } else if (c1 < 0xF0) { 21520b57cec5SDimitry Andric if (frm_end - frm_nxt < 3) 21530b57cec5SDimitry Andric break; 21540b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 21550b57cec5SDimitry Andric uint8_t c3 = frm_nxt[2]; 2156*cb14a3feSDimitry Andric switch (c1) { 21570b57cec5SDimitry Andric case 0xE0: 21580b57cec5SDimitry Andric if ((c2 & 0xE0) != 0xA0) 21590b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 21600b57cec5SDimitry Andric break; 21610b57cec5SDimitry Andric case 0xED: 21620b57cec5SDimitry Andric if ((c2 & 0xE0) != 0x80) 21630b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 21640b57cec5SDimitry Andric break; 21650b57cec5SDimitry Andric default: 21660b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 21670b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 21680b57cec5SDimitry Andric break; 21690b57cec5SDimitry Andric } 21700b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80) 21710b57cec5SDimitry Andric break; 21720b57cec5SDimitry Andric if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) 21730b57cec5SDimitry Andric break; 21740b57cec5SDimitry Andric frm_nxt += 3; 2175*cb14a3feSDimitry Andric } else if (c1 < 0xF5) { 21760b57cec5SDimitry Andric if (frm_end - frm_nxt < 4) 21770b57cec5SDimitry Andric break; 21780b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 21790b57cec5SDimitry Andric uint8_t c3 = frm_nxt[2]; 21800b57cec5SDimitry Andric uint8_t c4 = frm_nxt[3]; 2181*cb14a3feSDimitry Andric switch (c1) { 21820b57cec5SDimitry Andric case 0xF0: 21830b57cec5SDimitry Andric if (!(0x90 <= c2 && c2 <= 0xBF)) 21840b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 21850b57cec5SDimitry Andric break; 21860b57cec5SDimitry Andric case 0xF4: 21870b57cec5SDimitry Andric if ((c2 & 0xF0) != 0x80) 21880b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 21890b57cec5SDimitry Andric break; 21900b57cec5SDimitry Andric default: 21910b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 21920b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 21930b57cec5SDimitry Andric break; 21940b57cec5SDimitry Andric } 21950b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) 21960b57cec5SDimitry Andric break; 2197*cb14a3feSDimitry Andric if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode) 21980b57cec5SDimitry Andric break; 21990b57cec5SDimitry Andric frm_nxt += 4; 2200*cb14a3feSDimitry Andric } else { 22010b57cec5SDimitry Andric break; 22020b57cec5SDimitry Andric } 22030b57cec5SDimitry Andric } 22040b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 22050b57cec5SDimitry Andric } 22060b57cec5SDimitry Andric 2207*cb14a3feSDimitry Andric static codecvt_base::result ucs2_to_utf8( 2208*cb14a3feSDimitry Andric const uint16_t* frm, 2209*cb14a3feSDimitry Andric const uint16_t* frm_end, 2210*cb14a3feSDimitry Andric const uint16_t*& frm_nxt, 2211*cb14a3feSDimitry Andric uint8_t* to, 2212*cb14a3feSDimitry Andric uint8_t* to_end, 2213*cb14a3feSDimitry Andric uint8_t*& to_nxt, 2214*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2215*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 22160b57cec5SDimitry Andric frm_nxt = frm; 22170b57cec5SDimitry Andric to_nxt = to; 2218*cb14a3feSDimitry Andric if (mode & generate_header) { 22190b57cec5SDimitry Andric if (to_end - to_nxt < 3) 22200b57cec5SDimitry Andric return codecvt_base::partial; 22210b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xEF); 22220b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBB); 22230b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xBF); 22240b57cec5SDimitry Andric } 2225*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 22260b57cec5SDimitry Andric uint16_t wc = *frm_nxt; 22270b57cec5SDimitry Andric if ((wc & 0xF800) == 0xD800 || wc > Maxcode) 22280b57cec5SDimitry Andric return codecvt_base::error; 2229*cb14a3feSDimitry Andric if (wc < 0x0080) { 22300b57cec5SDimitry Andric if (to_end - to_nxt < 1) 22310b57cec5SDimitry Andric return codecvt_base::partial; 22320b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc); 2233*cb14a3feSDimitry Andric } else if (wc < 0x0800) { 22340b57cec5SDimitry Andric if (to_end - to_nxt < 2) 22350b57cec5SDimitry Andric return codecvt_base::partial; 22360b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); 22370b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); 2238*cb14a3feSDimitry Andric } else // if (wc <= 0xFFFF) 22390b57cec5SDimitry Andric { 22400b57cec5SDimitry Andric if (to_end - to_nxt < 3) 22410b57cec5SDimitry Andric return codecvt_base::partial; 22420b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); 22430b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); 22440b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); 22450b57cec5SDimitry Andric } 22460b57cec5SDimitry Andric } 22470b57cec5SDimitry Andric return codecvt_base::ok; 22480b57cec5SDimitry Andric } 22490b57cec5SDimitry Andric 2250*cb14a3feSDimitry Andric static codecvt_base::result utf8_to_ucs2( 2251*cb14a3feSDimitry Andric const uint8_t* frm, 2252*cb14a3feSDimitry Andric const uint8_t* frm_end, 2253*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 2254*cb14a3feSDimitry Andric uint16_t* to, 2255*cb14a3feSDimitry Andric uint16_t* to_end, 2256*cb14a3feSDimitry Andric uint16_t*& to_nxt, 2257*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2258*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 22590b57cec5SDimitry Andric frm_nxt = frm; 22600b57cec5SDimitry Andric to_nxt = to; 2261*cb14a3feSDimitry Andric if (mode & consume_header) { 2262*cb14a3feSDimitry Andric if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF) 22630b57cec5SDimitry Andric frm_nxt += 3; 22640b57cec5SDimitry Andric } 2265*cb14a3feSDimitry Andric for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) { 22660b57cec5SDimitry Andric uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2267*cb14a3feSDimitry Andric if (c1 < 0x80) { 22680b57cec5SDimitry Andric if (c1 > Maxcode) 22690b57cec5SDimitry Andric return codecvt_base::error; 22700b57cec5SDimitry Andric *to_nxt = static_cast<uint16_t>(c1); 22710b57cec5SDimitry Andric ++frm_nxt; 2272*cb14a3feSDimitry Andric } else if (c1 < 0xC2) { 22730b57cec5SDimitry Andric return codecvt_base::error; 2274*cb14a3feSDimitry Andric } else if (c1 < 0xE0) { 22750b57cec5SDimitry Andric if (frm_end - frm_nxt < 2) 22760b57cec5SDimitry Andric return codecvt_base::partial; 22770b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 22780b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 22790b57cec5SDimitry Andric return codecvt_base::error; 2280*cb14a3feSDimitry Andric uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); 22810b57cec5SDimitry Andric if (t > Maxcode) 22820b57cec5SDimitry Andric return codecvt_base::error; 22830b57cec5SDimitry Andric *to_nxt = t; 22840b57cec5SDimitry Andric frm_nxt += 2; 2285*cb14a3feSDimitry Andric } else if (c1 < 0xF0) { 22865f757f3fSDimitry Andric if (frm_end - frm_nxt < 2) 22870b57cec5SDimitry Andric return codecvt_base::partial; 22880b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 2289*cb14a3feSDimitry Andric switch (c1) { 22900b57cec5SDimitry Andric case 0xE0: 22910b57cec5SDimitry Andric if ((c2 & 0xE0) != 0xA0) 22920b57cec5SDimitry Andric return codecvt_base::error; 22930b57cec5SDimitry Andric break; 22940b57cec5SDimitry Andric case 0xED: 22950b57cec5SDimitry Andric if ((c2 & 0xE0) != 0x80) 22960b57cec5SDimitry Andric return codecvt_base::error; 22970b57cec5SDimitry Andric break; 22980b57cec5SDimitry Andric default: 22990b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 23000b57cec5SDimitry Andric return codecvt_base::error; 23010b57cec5SDimitry Andric break; 23020b57cec5SDimitry Andric } 23035f757f3fSDimitry Andric if (frm_end - frm_nxt < 3) 23045f757f3fSDimitry Andric return codecvt_base::partial; 23055f757f3fSDimitry Andric uint8_t c3 = frm_nxt[2]; 23060b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80) 23070b57cec5SDimitry Andric return codecvt_base::error; 2308*cb14a3feSDimitry Andric uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)); 23090b57cec5SDimitry Andric if (t > Maxcode) 23100b57cec5SDimitry Andric return codecvt_base::error; 23110b57cec5SDimitry Andric *to_nxt = t; 23120b57cec5SDimitry Andric frm_nxt += 3; 2313*cb14a3feSDimitry Andric } else { 23140b57cec5SDimitry Andric return codecvt_base::error; 23150b57cec5SDimitry Andric } 23160b57cec5SDimitry Andric } 23170b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 23180b57cec5SDimitry Andric } 23190b57cec5SDimitry Andric 2320*cb14a3feSDimitry Andric static int utf8_to_ucs2_length( 2321*cb14a3feSDimitry Andric const uint8_t* frm, 2322*cb14a3feSDimitry Andric const uint8_t* frm_end, 2323*cb14a3feSDimitry Andric size_t mx, 2324*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2325*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 23260b57cec5SDimitry Andric const uint8_t* frm_nxt = frm; 2327*cb14a3feSDimitry Andric if (mode & consume_header) { 2328*cb14a3feSDimitry Andric if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF) 23290b57cec5SDimitry Andric frm_nxt += 3; 23300b57cec5SDimitry Andric } 2331*cb14a3feSDimitry Andric for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) { 23320b57cec5SDimitry Andric uint8_t c1 = static_cast<uint8_t>(*frm_nxt); 2333*cb14a3feSDimitry Andric if (c1 < 0x80) { 23340b57cec5SDimitry Andric if (c1 > Maxcode) 23350b57cec5SDimitry Andric break; 23360b57cec5SDimitry Andric ++frm_nxt; 2337*cb14a3feSDimitry Andric } else if (c1 < 0xC2) { 23380b57cec5SDimitry Andric break; 2339*cb14a3feSDimitry Andric } else if (c1 < 0xE0) { 23400b57cec5SDimitry Andric if ((frm_end - frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) 23410b57cec5SDimitry Andric break; 23420b57cec5SDimitry Andric if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) 23430b57cec5SDimitry Andric break; 23440b57cec5SDimitry Andric frm_nxt += 2; 2345*cb14a3feSDimitry Andric } else if (c1 < 0xF0) { 23460b57cec5SDimitry Andric if (frm_end - frm_nxt < 3) 23470b57cec5SDimitry Andric break; 23480b57cec5SDimitry Andric uint8_t c2 = frm_nxt[1]; 23490b57cec5SDimitry Andric uint8_t c3 = frm_nxt[2]; 2350*cb14a3feSDimitry Andric switch (c1) { 23510b57cec5SDimitry Andric case 0xE0: 23520b57cec5SDimitry Andric if ((c2 & 0xE0) != 0xA0) 23530b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 23540b57cec5SDimitry Andric break; 23550b57cec5SDimitry Andric case 0xED: 23560b57cec5SDimitry Andric if ((c2 & 0xE0) != 0x80) 23570b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 23580b57cec5SDimitry Andric break; 23590b57cec5SDimitry Andric default: 23600b57cec5SDimitry Andric if ((c2 & 0xC0) != 0x80) 23610b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 23620b57cec5SDimitry Andric break; 23630b57cec5SDimitry Andric } 23640b57cec5SDimitry Andric if ((c3 & 0xC0) != 0x80) 23650b57cec5SDimitry Andric break; 23660b57cec5SDimitry Andric if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) 23670b57cec5SDimitry Andric break; 23680b57cec5SDimitry Andric frm_nxt += 3; 2369*cb14a3feSDimitry Andric } else { 23700b57cec5SDimitry Andric break; 23710b57cec5SDimitry Andric } 23720b57cec5SDimitry Andric } 23730b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric 2376*cb14a3feSDimitry Andric static codecvt_base::result ucs4_to_utf16be( 2377*cb14a3feSDimitry Andric const uint32_t* frm, 2378*cb14a3feSDimitry Andric const uint32_t* frm_end, 2379*cb14a3feSDimitry Andric const uint32_t*& frm_nxt, 2380*cb14a3feSDimitry Andric uint8_t* to, 2381*cb14a3feSDimitry Andric uint8_t* to_end, 2382*cb14a3feSDimitry Andric uint8_t*& to_nxt, 2383*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2384*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 23850b57cec5SDimitry Andric frm_nxt = frm; 23860b57cec5SDimitry Andric to_nxt = to; 2387*cb14a3feSDimitry Andric if (mode & generate_header) { 23880b57cec5SDimitry Andric if (to_end - to_nxt < 2) 23890b57cec5SDimitry Andric return codecvt_base::partial; 23900b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFE); 23910b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFF); 23920b57cec5SDimitry Andric } 2393*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 23940b57cec5SDimitry Andric uint32_t wc = *frm_nxt; 23950b57cec5SDimitry Andric if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) 23960b57cec5SDimitry Andric return codecvt_base::error; 2397*cb14a3feSDimitry Andric if (wc < 0x010000) { 23980b57cec5SDimitry Andric if (to_end - to_nxt < 2) 23990b57cec5SDimitry Andric return codecvt_base::partial; 24000b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc >> 8); 24010b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc); 2402*cb14a3feSDimitry Andric } else { 24030b57cec5SDimitry Andric if (to_end - to_nxt < 4) 24040b57cec5SDimitry Andric return codecvt_base::partial; 2405*cb14a3feSDimitry Andric uint16_t t = static_cast<uint16_t>(0xD800 | ((((wc & 0x1F0000) >> 16) - 1) << 6) | ((wc & 0x00FC00) >> 10)); 24060b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t >> 8); 24070b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t); 24080b57cec5SDimitry Andric t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); 24090b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t >> 8); 24100b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t); 24110b57cec5SDimitry Andric } 24120b57cec5SDimitry Andric } 24130b57cec5SDimitry Andric return codecvt_base::ok; 24140b57cec5SDimitry Andric } 24150b57cec5SDimitry Andric 2416*cb14a3feSDimitry Andric static codecvt_base::result utf16be_to_ucs4( 2417*cb14a3feSDimitry Andric const uint8_t* frm, 2418*cb14a3feSDimitry Andric const uint8_t* frm_end, 2419*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 2420*cb14a3feSDimitry Andric uint32_t* to, 2421*cb14a3feSDimitry Andric uint32_t* to_end, 2422*cb14a3feSDimitry Andric uint32_t*& to_nxt, 2423*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2424*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 24250b57cec5SDimitry Andric frm_nxt = frm; 24260b57cec5SDimitry Andric to_nxt = to; 2427*cb14a3feSDimitry Andric if (mode & consume_header) { 24280b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 24290b57cec5SDimitry Andric frm_nxt += 2; 24300b57cec5SDimitry Andric } 2431*cb14a3feSDimitry Andric for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) { 24320b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 24330b57cec5SDimitry Andric if ((c1 & 0xFC00) == 0xDC00) 24340b57cec5SDimitry Andric return codecvt_base::error; 2435*cb14a3feSDimitry Andric if ((c1 & 0xFC00) != 0xD800) { 24360b57cec5SDimitry Andric if (c1 > Maxcode) 24370b57cec5SDimitry Andric return codecvt_base::error; 24380b57cec5SDimitry Andric *to_nxt = static_cast<uint32_t>(c1); 24390b57cec5SDimitry Andric frm_nxt += 2; 2440*cb14a3feSDimitry Andric } else { 24410b57cec5SDimitry Andric if (frm_end - frm_nxt < 4) 24420b57cec5SDimitry Andric return codecvt_base::partial; 24430b57cec5SDimitry Andric uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); 24440b57cec5SDimitry Andric if ((c2 & 0xFC00) != 0xDC00) 24450b57cec5SDimitry Andric return codecvt_base::error; 2446*cb14a3feSDimitry Andric uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF)); 24470b57cec5SDimitry Andric if (t > Maxcode) 24480b57cec5SDimitry Andric return codecvt_base::error; 24490b57cec5SDimitry Andric *to_nxt = t; 24500b57cec5SDimitry Andric frm_nxt += 4; 24510b57cec5SDimitry Andric } 24520b57cec5SDimitry Andric } 24530b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 24540b57cec5SDimitry Andric } 24550b57cec5SDimitry Andric 2456*cb14a3feSDimitry Andric static int utf16be_to_ucs4_length( 2457*cb14a3feSDimitry Andric const uint8_t* frm, 2458*cb14a3feSDimitry Andric const uint8_t* frm_end, 2459*cb14a3feSDimitry Andric size_t mx, 2460*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2461*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 24620b57cec5SDimitry Andric const uint8_t* frm_nxt = frm; 2463*cb14a3feSDimitry Andric if (mode & consume_header) { 24640b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 24650b57cec5SDimitry Andric frm_nxt += 2; 24660b57cec5SDimitry Andric } 2467*cb14a3feSDimitry Andric for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) { 24680b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 24690b57cec5SDimitry Andric if ((c1 & 0xFC00) == 0xDC00) 24700b57cec5SDimitry Andric break; 2471*cb14a3feSDimitry Andric if ((c1 & 0xFC00) != 0xD800) { 24720b57cec5SDimitry Andric if (c1 > Maxcode) 24730b57cec5SDimitry Andric break; 24740b57cec5SDimitry Andric frm_nxt += 2; 2475*cb14a3feSDimitry Andric } else { 24760b57cec5SDimitry Andric if (frm_end - frm_nxt < 4) 24770b57cec5SDimitry Andric break; 24780b57cec5SDimitry Andric uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); 24790b57cec5SDimitry Andric if ((c2 & 0xFC00) != 0xDC00) 24800b57cec5SDimitry Andric break; 2481*cb14a3feSDimitry Andric uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF)); 24820b57cec5SDimitry Andric if (t > Maxcode) 24830b57cec5SDimitry Andric break; 24840b57cec5SDimitry Andric frm_nxt += 4; 24850b57cec5SDimitry Andric } 24860b57cec5SDimitry Andric } 24870b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 24880b57cec5SDimitry Andric } 24890b57cec5SDimitry Andric 2490*cb14a3feSDimitry Andric static codecvt_base::result ucs4_to_utf16le( 2491*cb14a3feSDimitry Andric const uint32_t* frm, 2492*cb14a3feSDimitry Andric const uint32_t* frm_end, 2493*cb14a3feSDimitry Andric const uint32_t*& frm_nxt, 2494*cb14a3feSDimitry Andric uint8_t* to, 2495*cb14a3feSDimitry Andric uint8_t* to_end, 2496*cb14a3feSDimitry Andric uint8_t*& to_nxt, 2497*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2498*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 24990b57cec5SDimitry Andric frm_nxt = frm; 25000b57cec5SDimitry Andric to_nxt = to; 2501*cb14a3feSDimitry Andric if (mode & generate_header) { 25020b57cec5SDimitry Andric if (to_end - to_nxt < 2) 25030b57cec5SDimitry Andric return codecvt_base::partial; 25040b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFF); 25050b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFE); 25060b57cec5SDimitry Andric } 2507*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 25080b57cec5SDimitry Andric uint32_t wc = *frm_nxt; 25090b57cec5SDimitry Andric if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) 25100b57cec5SDimitry Andric return codecvt_base::error; 2511*cb14a3feSDimitry Andric if (wc < 0x010000) { 25120b57cec5SDimitry Andric if (to_end - to_nxt < 2) 25130b57cec5SDimitry Andric return codecvt_base::partial; 25140b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc); 25150b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc >> 8); 2516*cb14a3feSDimitry Andric } else { 25170b57cec5SDimitry Andric if (to_end - to_nxt < 4) 25180b57cec5SDimitry Andric return codecvt_base::partial; 2519*cb14a3feSDimitry Andric uint16_t t = static_cast<uint16_t>(0xD800 | ((((wc & 0x1F0000) >> 16) - 1) << 6) | ((wc & 0x00FC00) >> 10)); 25200b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t); 25210b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t >> 8); 25220b57cec5SDimitry Andric t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); 25230b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t); 25240b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(t >> 8); 25250b57cec5SDimitry Andric } 25260b57cec5SDimitry Andric } 25270b57cec5SDimitry Andric return codecvt_base::ok; 25280b57cec5SDimitry Andric } 25290b57cec5SDimitry Andric 2530*cb14a3feSDimitry Andric static codecvt_base::result utf16le_to_ucs4( 2531*cb14a3feSDimitry Andric const uint8_t* frm, 2532*cb14a3feSDimitry Andric const uint8_t* frm_end, 2533*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 2534*cb14a3feSDimitry Andric uint32_t* to, 2535*cb14a3feSDimitry Andric uint32_t* to_end, 2536*cb14a3feSDimitry Andric uint32_t*& to_nxt, 2537*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2538*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 25390b57cec5SDimitry Andric frm_nxt = frm; 25400b57cec5SDimitry Andric to_nxt = to; 2541*cb14a3feSDimitry Andric if (mode & consume_header) { 25420b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 25430b57cec5SDimitry Andric frm_nxt += 2; 25440b57cec5SDimitry Andric } 2545*cb14a3feSDimitry Andric for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) { 25460b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 25470b57cec5SDimitry Andric if ((c1 & 0xFC00) == 0xDC00) 25480b57cec5SDimitry Andric return codecvt_base::error; 2549*cb14a3feSDimitry Andric if ((c1 & 0xFC00) != 0xD800) { 25500b57cec5SDimitry Andric if (c1 > Maxcode) 25510b57cec5SDimitry Andric return codecvt_base::error; 25520b57cec5SDimitry Andric *to_nxt = static_cast<uint32_t>(c1); 25530b57cec5SDimitry Andric frm_nxt += 2; 2554*cb14a3feSDimitry Andric } else { 25550b57cec5SDimitry Andric if (frm_end - frm_nxt < 4) 25560b57cec5SDimitry Andric return codecvt_base::partial; 25570b57cec5SDimitry Andric uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); 25580b57cec5SDimitry Andric if ((c2 & 0xFC00) != 0xDC00) 25590b57cec5SDimitry Andric return codecvt_base::error; 2560*cb14a3feSDimitry Andric uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF)); 25610b57cec5SDimitry Andric if (t > Maxcode) 25620b57cec5SDimitry Andric return codecvt_base::error; 25630b57cec5SDimitry Andric *to_nxt = t; 25640b57cec5SDimitry Andric frm_nxt += 4; 25650b57cec5SDimitry Andric } 25660b57cec5SDimitry Andric } 25670b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 25680b57cec5SDimitry Andric } 25690b57cec5SDimitry Andric 2570*cb14a3feSDimitry Andric static int utf16le_to_ucs4_length( 2571*cb14a3feSDimitry Andric const uint8_t* frm, 2572*cb14a3feSDimitry Andric const uint8_t* frm_end, 2573*cb14a3feSDimitry Andric size_t mx, 2574*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2575*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 25760b57cec5SDimitry Andric const uint8_t* frm_nxt = frm; 2577*cb14a3feSDimitry Andric if (mode & consume_header) { 25780b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 25790b57cec5SDimitry Andric frm_nxt += 2; 25800b57cec5SDimitry Andric } 2581*cb14a3feSDimitry Andric for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) { 25820b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 25830b57cec5SDimitry Andric if ((c1 & 0xFC00) == 0xDC00) 25840b57cec5SDimitry Andric break; 2585*cb14a3feSDimitry Andric if ((c1 & 0xFC00) != 0xD800) { 25860b57cec5SDimitry Andric if (c1 > Maxcode) 25870b57cec5SDimitry Andric break; 25880b57cec5SDimitry Andric frm_nxt += 2; 2589*cb14a3feSDimitry Andric } else { 25900b57cec5SDimitry Andric if (frm_end - frm_nxt < 4) 25910b57cec5SDimitry Andric break; 25920b57cec5SDimitry Andric uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); 25930b57cec5SDimitry Andric if ((c2 & 0xFC00) != 0xDC00) 25940b57cec5SDimitry Andric break; 2595*cb14a3feSDimitry Andric uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF)); 25960b57cec5SDimitry Andric if (t > Maxcode) 25970b57cec5SDimitry Andric break; 25980b57cec5SDimitry Andric frm_nxt += 4; 25990b57cec5SDimitry Andric } 26000b57cec5SDimitry Andric } 26010b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 26020b57cec5SDimitry Andric } 26030b57cec5SDimitry Andric 2604*cb14a3feSDimitry Andric static codecvt_base::result ucs2_to_utf16be( 2605*cb14a3feSDimitry Andric const uint16_t* frm, 2606*cb14a3feSDimitry Andric const uint16_t* frm_end, 2607*cb14a3feSDimitry Andric const uint16_t*& frm_nxt, 2608*cb14a3feSDimitry Andric uint8_t* to, 2609*cb14a3feSDimitry Andric uint8_t* to_end, 2610*cb14a3feSDimitry Andric uint8_t*& to_nxt, 2611*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2612*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 26130b57cec5SDimitry Andric frm_nxt = frm; 26140b57cec5SDimitry Andric to_nxt = to; 2615*cb14a3feSDimitry Andric if (mode & generate_header) { 26160b57cec5SDimitry Andric if (to_end - to_nxt < 2) 26170b57cec5SDimitry Andric return codecvt_base::partial; 26180b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFE); 26190b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFF); 26200b57cec5SDimitry Andric } 2621*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 26220b57cec5SDimitry Andric uint16_t wc = *frm_nxt; 26230b57cec5SDimitry Andric if ((wc & 0xF800) == 0xD800 || wc > Maxcode) 26240b57cec5SDimitry Andric return codecvt_base::error; 26250b57cec5SDimitry Andric if (to_end - to_nxt < 2) 26260b57cec5SDimitry Andric return codecvt_base::partial; 26270b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc >> 8); 26280b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc); 26290b57cec5SDimitry Andric } 26300b57cec5SDimitry Andric return codecvt_base::ok; 26310b57cec5SDimitry Andric } 26320b57cec5SDimitry Andric 2633*cb14a3feSDimitry Andric static codecvt_base::result utf16be_to_ucs2( 2634*cb14a3feSDimitry Andric const uint8_t* frm, 2635*cb14a3feSDimitry Andric const uint8_t* frm_end, 2636*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 2637*cb14a3feSDimitry Andric uint16_t* to, 2638*cb14a3feSDimitry Andric uint16_t* to_end, 2639*cb14a3feSDimitry Andric uint16_t*& to_nxt, 2640*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2641*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 26420b57cec5SDimitry Andric frm_nxt = frm; 26430b57cec5SDimitry Andric to_nxt = to; 2644*cb14a3feSDimitry Andric if (mode & consume_header) { 26450b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 26460b57cec5SDimitry Andric frm_nxt += 2; 26470b57cec5SDimitry Andric } 2648*cb14a3feSDimitry Andric for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) { 26490b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 26500b57cec5SDimitry Andric if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 26510b57cec5SDimitry Andric return codecvt_base::error; 26520b57cec5SDimitry Andric *to_nxt = c1; 26530b57cec5SDimitry Andric frm_nxt += 2; 26540b57cec5SDimitry Andric } 26550b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 26560b57cec5SDimitry Andric } 26570b57cec5SDimitry Andric 2658*cb14a3feSDimitry Andric static int utf16be_to_ucs2_length( 2659*cb14a3feSDimitry Andric const uint8_t* frm, 2660*cb14a3feSDimitry Andric const uint8_t* frm_end, 2661*cb14a3feSDimitry Andric size_t mx, 2662*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2663*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 26640b57cec5SDimitry Andric const uint8_t* frm_nxt = frm; 2665*cb14a3feSDimitry Andric if (mode & consume_header) { 26660b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) 26670b57cec5SDimitry Andric frm_nxt += 2; 26680b57cec5SDimitry Andric } 2669*cb14a3feSDimitry Andric for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) { 26700b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); 26710b57cec5SDimitry Andric if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 26720b57cec5SDimitry Andric break; 26730b57cec5SDimitry Andric frm_nxt += 2; 26740b57cec5SDimitry Andric } 26750b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 26760b57cec5SDimitry Andric } 26770b57cec5SDimitry Andric 2678*cb14a3feSDimitry Andric static codecvt_base::result ucs2_to_utf16le( 2679*cb14a3feSDimitry Andric const uint16_t* frm, 2680*cb14a3feSDimitry Andric const uint16_t* frm_end, 2681*cb14a3feSDimitry Andric const uint16_t*& frm_nxt, 2682*cb14a3feSDimitry Andric uint8_t* to, 2683*cb14a3feSDimitry Andric uint8_t* to_end, 2684*cb14a3feSDimitry Andric uint8_t*& to_nxt, 2685*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2686*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 26870b57cec5SDimitry Andric frm_nxt = frm; 26880b57cec5SDimitry Andric to_nxt = to; 2689*cb14a3feSDimitry Andric if (mode & generate_header) { 26900b57cec5SDimitry Andric if (to_end - to_nxt < 2) 26910b57cec5SDimitry Andric return codecvt_base::partial; 26920b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFF); 26930b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(0xFE); 26940b57cec5SDimitry Andric } 2695*cb14a3feSDimitry Andric for (; frm_nxt < frm_end; ++frm_nxt) { 26960b57cec5SDimitry Andric uint16_t wc = *frm_nxt; 26970b57cec5SDimitry Andric if ((wc & 0xF800) == 0xD800 || wc > Maxcode) 26980b57cec5SDimitry Andric return codecvt_base::error; 26990b57cec5SDimitry Andric if (to_end - to_nxt < 2) 27000b57cec5SDimitry Andric return codecvt_base::partial; 27010b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc); 27020b57cec5SDimitry Andric *to_nxt++ = static_cast<uint8_t>(wc >> 8); 27030b57cec5SDimitry Andric } 27040b57cec5SDimitry Andric return codecvt_base::ok; 27050b57cec5SDimitry Andric } 27060b57cec5SDimitry Andric 2707*cb14a3feSDimitry Andric static codecvt_base::result utf16le_to_ucs2( 2708*cb14a3feSDimitry Andric const uint8_t* frm, 2709*cb14a3feSDimitry Andric const uint8_t* frm_end, 2710*cb14a3feSDimitry Andric const uint8_t*& frm_nxt, 2711*cb14a3feSDimitry Andric uint16_t* to, 2712*cb14a3feSDimitry Andric uint16_t* to_end, 2713*cb14a3feSDimitry Andric uint16_t*& to_nxt, 2714*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2715*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 27160b57cec5SDimitry Andric frm_nxt = frm; 27170b57cec5SDimitry Andric to_nxt = to; 2718*cb14a3feSDimitry Andric if (mode & consume_header) { 27190b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 27200b57cec5SDimitry Andric frm_nxt += 2; 27210b57cec5SDimitry Andric } 2722*cb14a3feSDimitry Andric for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) { 27230b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 27240b57cec5SDimitry Andric if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 27250b57cec5SDimitry Andric return codecvt_base::error; 27260b57cec5SDimitry Andric *to_nxt = c1; 27270b57cec5SDimitry Andric frm_nxt += 2; 27280b57cec5SDimitry Andric } 27290b57cec5SDimitry Andric return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; 27300b57cec5SDimitry Andric } 27310b57cec5SDimitry Andric 2732*cb14a3feSDimitry Andric static int utf16le_to_ucs2_length( 2733*cb14a3feSDimitry Andric const uint8_t* frm, 2734*cb14a3feSDimitry Andric const uint8_t* frm_end, 2735*cb14a3feSDimitry Andric size_t mx, 2736*cb14a3feSDimitry Andric unsigned long Maxcode = 0x10FFFF, 2737*cb14a3feSDimitry Andric codecvt_mode mode = codecvt_mode(0)) { 27380b57cec5SDimitry Andric const uint8_t* frm_nxt = frm; 27390b57cec5SDimitry Andric frm_nxt = frm; 2740*cb14a3feSDimitry Andric if (mode & consume_header) { 27410b57cec5SDimitry Andric if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) 27420b57cec5SDimitry Andric frm_nxt += 2; 27430b57cec5SDimitry Andric } 2744*cb14a3feSDimitry Andric for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) { 27450b57cec5SDimitry Andric uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); 27460b57cec5SDimitry Andric if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) 27470b57cec5SDimitry Andric break; 27480b57cec5SDimitry Andric frm_nxt += 2; 27490b57cec5SDimitry Andric } 27500b57cec5SDimitry Andric return static_cast<int>(frm_nxt - frm); 27510b57cec5SDimitry Andric } 27520b57cec5SDimitry Andric 275381ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 275481ad6265SDimitry Andric 27550b57cec5SDimitry Andric // template <> class codecvt<char16_t, char, mbstate_t> 27560b57cec5SDimitry Andric 27575f757f3fSDimitry Andric constinit locale::id codecvt<char16_t, char, mbstate_t>::id; 27580b57cec5SDimitry Andric 2759*cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::~codecvt() {} 27600b57cec5SDimitry Andric 2761*cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::result codecvt<char16_t, char, mbstate_t>::do_out( 2762*cb14a3feSDimitry Andric state_type&, 2763*cb14a3feSDimitry Andric const intern_type* frm, 2764*cb14a3feSDimitry Andric const intern_type* frm_end, 2765*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 2766*cb14a3feSDimitry Andric extern_type* to, 2767*cb14a3feSDimitry Andric extern_type* to_end, 2768*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 27690b57cec5SDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 27700b57cec5SDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 27710b57cec5SDimitry Andric const uint16_t* _frm_nxt = _frm; 27720b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 27730b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 27740b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 27750b57cec5SDimitry Andric result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 27760b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 27770b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 27780b57cec5SDimitry Andric return r; 27790b57cec5SDimitry Andric } 27800b57cec5SDimitry Andric 2781*cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::result codecvt<char16_t, char, mbstate_t>::do_in( 2782*cb14a3feSDimitry Andric state_type&, 2783*cb14a3feSDimitry Andric const extern_type* frm, 2784*cb14a3feSDimitry Andric const extern_type* frm_end, 2785*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 2786*cb14a3feSDimitry Andric intern_type* to, 2787*cb14a3feSDimitry Andric intern_type* to_end, 2788*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 27890b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 27900b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 27910b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 27920b57cec5SDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 27930b57cec5SDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 27940b57cec5SDimitry Andric uint16_t* _to_nxt = _to; 27950b57cec5SDimitry Andric result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 27960b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 27970b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 27980b57cec5SDimitry Andric return r; 27990b57cec5SDimitry Andric } 28000b57cec5SDimitry Andric 28010b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::result 2802*cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 28030b57cec5SDimitry Andric to_nxt = to; 28040b57cec5SDimitry Andric return noconv; 28050b57cec5SDimitry Andric } 28060b57cec5SDimitry Andric 2807*cb14a3feSDimitry Andric int codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept { return 0; } 28080b57cec5SDimitry Andric 2809*cb14a3feSDimitry Andric bool codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; } 28100b57cec5SDimitry Andric 2811*cb14a3feSDimitry Andric int codecvt<char16_t, char, mbstate_t>::do_length( 2812*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 28130b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 28140b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 28150b57cec5SDimitry Andric return utf8_to_utf16_length(_frm, _frm_end, mx); 28160b57cec5SDimitry Andric } 28170b57cec5SDimitry Andric 2818*cb14a3feSDimitry Andric int codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept { return 4; } 28190b57cec5SDimitry Andric 2820fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 2821e8d8bef9SDimitry Andric 2822e8d8bef9SDimitry Andric // template <> class codecvt<char16_t, char8_t, mbstate_t> 2823e8d8bef9SDimitry Andric 28245f757f3fSDimitry Andric constinit locale::id codecvt<char16_t, char8_t, mbstate_t>::id; 2825e8d8bef9SDimitry Andric 2826*cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::~codecvt() {} 2827e8d8bef9SDimitry Andric 2828*cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result codecvt<char16_t, char8_t, mbstate_t>::do_out( 2829*cb14a3feSDimitry Andric state_type&, 2830*cb14a3feSDimitry Andric const intern_type* frm, 2831*cb14a3feSDimitry Andric const intern_type* frm_end, 2832*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 2833*cb14a3feSDimitry Andric extern_type* to, 2834*cb14a3feSDimitry Andric extern_type* to_end, 2835*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 2836e8d8bef9SDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 2837e8d8bef9SDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 2838e8d8bef9SDimitry Andric const uint16_t* _frm_nxt = _frm; 2839e8d8bef9SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 2840e8d8bef9SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 2841e8d8bef9SDimitry Andric uint8_t* _to_nxt = _to; 2842e8d8bef9SDimitry Andric result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 2843e8d8bef9SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 2844e8d8bef9SDimitry Andric to_nxt = to + (_to_nxt - _to); 2845e8d8bef9SDimitry Andric return r; 2846e8d8bef9SDimitry Andric } 2847e8d8bef9SDimitry Andric 2848*cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result codecvt<char16_t, char8_t, mbstate_t>::do_in( 2849*cb14a3feSDimitry Andric state_type&, 2850*cb14a3feSDimitry Andric const extern_type* frm, 2851*cb14a3feSDimitry Andric const extern_type* frm_end, 2852*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 2853*cb14a3feSDimitry Andric intern_type* to, 2854*cb14a3feSDimitry Andric intern_type* to_end, 2855*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 2856e8d8bef9SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 2857e8d8bef9SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 2858e8d8bef9SDimitry Andric const uint8_t* _frm_nxt = _frm; 2859e8d8bef9SDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 2860e8d8bef9SDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 2861e8d8bef9SDimitry Andric uint16_t* _to_nxt = _to; 2862e8d8bef9SDimitry Andric result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 2863e8d8bef9SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 2864e8d8bef9SDimitry Andric to_nxt = to + (_to_nxt - _to); 2865e8d8bef9SDimitry Andric return r; 2866e8d8bef9SDimitry Andric } 2867e8d8bef9SDimitry Andric 2868*cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result codecvt<char16_t, char8_t, mbstate_t>::do_unshift( 2869*cb14a3feSDimitry Andric state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 2870e8d8bef9SDimitry Andric to_nxt = to; 2871e8d8bef9SDimitry Andric return noconv; 2872e8d8bef9SDimitry Andric } 2873e8d8bef9SDimitry Andric 2874*cb14a3feSDimitry Andric int codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept { return 0; } 2875e8d8bef9SDimitry Andric 2876*cb14a3feSDimitry Andric bool codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept { return false; } 2877e8d8bef9SDimitry Andric 2878*cb14a3feSDimitry Andric int codecvt<char16_t, char8_t, mbstate_t>::do_length( 2879*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 2880e8d8bef9SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 2881e8d8bef9SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 2882e8d8bef9SDimitry Andric return utf8_to_utf16_length(_frm, _frm_end, mx); 2883e8d8bef9SDimitry Andric } 2884e8d8bef9SDimitry Andric 2885*cb14a3feSDimitry Andric int codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept { return 4; } 2886e8d8bef9SDimitry Andric 2887e8d8bef9SDimitry Andric #endif 2888e8d8bef9SDimitry Andric 28890b57cec5SDimitry Andric // template <> class codecvt<char32_t, char, mbstate_t> 28900b57cec5SDimitry Andric 28915f757f3fSDimitry Andric constinit locale::id codecvt<char32_t, char, mbstate_t>::id; 28920b57cec5SDimitry Andric 2893*cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::~codecvt() {} 28940b57cec5SDimitry Andric 2895*cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::result codecvt<char32_t, char, mbstate_t>::do_out( 2896*cb14a3feSDimitry Andric state_type&, 2897*cb14a3feSDimitry Andric const intern_type* frm, 2898*cb14a3feSDimitry Andric const intern_type* frm_end, 2899*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 2900*cb14a3feSDimitry Andric extern_type* to, 2901*cb14a3feSDimitry Andric extern_type* to_end, 2902*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 29030b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 29040b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 29050b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 29060b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 29070b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 29080b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 29090b57cec5SDimitry Andric result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 29100b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 29110b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 29120b57cec5SDimitry Andric return r; 29130b57cec5SDimitry Andric } 29140b57cec5SDimitry Andric 2915*cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::result codecvt<char32_t, char, mbstate_t>::do_in( 2916*cb14a3feSDimitry Andric state_type&, 2917*cb14a3feSDimitry Andric const extern_type* frm, 2918*cb14a3feSDimitry Andric const extern_type* frm_end, 2919*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 2920*cb14a3feSDimitry Andric intern_type* to, 2921*cb14a3feSDimitry Andric intern_type* to_end, 2922*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 29230b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 29240b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 29250b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 29260b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 29270b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 29280b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 29290b57cec5SDimitry Andric result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 29300b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 29310b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 29320b57cec5SDimitry Andric return r; 29330b57cec5SDimitry Andric } 29340b57cec5SDimitry Andric 29350b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::result 2936*cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 29370b57cec5SDimitry Andric to_nxt = to; 29380b57cec5SDimitry Andric return noconv; 29390b57cec5SDimitry Andric } 29400b57cec5SDimitry Andric 2941*cb14a3feSDimitry Andric int codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept { return 0; } 29420b57cec5SDimitry Andric 2943*cb14a3feSDimitry Andric bool codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; } 29440b57cec5SDimitry Andric 2945*cb14a3feSDimitry Andric int codecvt<char32_t, char, mbstate_t>::do_length( 2946*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 29470b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 29480b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 29490b57cec5SDimitry Andric return utf8_to_ucs4_length(_frm, _frm_end, mx); 29500b57cec5SDimitry Andric } 29510b57cec5SDimitry Andric 2952*cb14a3feSDimitry Andric int codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept { return 4; } 29530b57cec5SDimitry Andric 2954fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 2955e8d8bef9SDimitry Andric 2956e8d8bef9SDimitry Andric // template <> class codecvt<char32_t, char8_t, mbstate_t> 2957e8d8bef9SDimitry Andric 29585f757f3fSDimitry Andric constinit locale::id codecvt<char32_t, char8_t, mbstate_t>::id; 2959e8d8bef9SDimitry Andric 2960*cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::~codecvt() {} 2961e8d8bef9SDimitry Andric 2962*cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result codecvt<char32_t, char8_t, mbstate_t>::do_out( 2963*cb14a3feSDimitry Andric state_type&, 2964*cb14a3feSDimitry Andric const intern_type* frm, 2965*cb14a3feSDimitry Andric const intern_type* frm_end, 2966*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 2967*cb14a3feSDimitry Andric extern_type* to, 2968*cb14a3feSDimitry Andric extern_type* to_end, 2969*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 2970e8d8bef9SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 2971e8d8bef9SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 2972e8d8bef9SDimitry Andric const uint32_t* _frm_nxt = _frm; 2973e8d8bef9SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 2974e8d8bef9SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 2975e8d8bef9SDimitry Andric uint8_t* _to_nxt = _to; 2976e8d8bef9SDimitry Andric result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 2977e8d8bef9SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 2978e8d8bef9SDimitry Andric to_nxt = to + (_to_nxt - _to); 2979e8d8bef9SDimitry Andric return r; 2980e8d8bef9SDimitry Andric } 2981e8d8bef9SDimitry Andric 2982*cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result codecvt<char32_t, char8_t, mbstate_t>::do_in( 2983*cb14a3feSDimitry Andric state_type&, 2984*cb14a3feSDimitry Andric const extern_type* frm, 2985*cb14a3feSDimitry Andric const extern_type* frm_end, 2986*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 2987*cb14a3feSDimitry Andric intern_type* to, 2988*cb14a3feSDimitry Andric intern_type* to_end, 2989*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 2990e8d8bef9SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 2991e8d8bef9SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 2992e8d8bef9SDimitry Andric const uint8_t* _frm_nxt = _frm; 2993e8d8bef9SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 2994e8d8bef9SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 2995e8d8bef9SDimitry Andric uint32_t* _to_nxt = _to; 2996e8d8bef9SDimitry Andric result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); 2997e8d8bef9SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 2998e8d8bef9SDimitry Andric to_nxt = to + (_to_nxt - _to); 2999e8d8bef9SDimitry Andric return r; 3000e8d8bef9SDimitry Andric } 3001e8d8bef9SDimitry Andric 3002*cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result codecvt<char32_t, char8_t, mbstate_t>::do_unshift( 3003*cb14a3feSDimitry Andric state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 3004e8d8bef9SDimitry Andric to_nxt = to; 3005e8d8bef9SDimitry Andric return noconv; 3006e8d8bef9SDimitry Andric } 3007e8d8bef9SDimitry Andric 3008*cb14a3feSDimitry Andric int codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept { return 0; } 3009e8d8bef9SDimitry Andric 3010*cb14a3feSDimitry Andric bool codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept { return false; } 3011e8d8bef9SDimitry Andric 3012*cb14a3feSDimitry Andric int codecvt<char32_t, char8_t, mbstate_t>::do_length( 3013*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 3014e8d8bef9SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 3015e8d8bef9SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3016e8d8bef9SDimitry Andric return utf8_to_ucs4_length(_frm, _frm_end, mx); 3017e8d8bef9SDimitry Andric } 3018e8d8bef9SDimitry Andric 3019*cb14a3feSDimitry Andric int codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept { return 4; } 3020e8d8bef9SDimitry Andric 3021e8d8bef9SDimitry Andric #endif 3022e8d8bef9SDimitry Andric 30230b57cec5SDimitry Andric // __codecvt_utf8<wchar_t> 30240b57cec5SDimitry Andric 3025349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3026*cb14a3feSDimitry Andric __codecvt_utf8<wchar_t>::result __codecvt_utf8<wchar_t>::do_out( 3027*cb14a3feSDimitry Andric state_type&, 3028*cb14a3feSDimitry Andric const intern_type* frm, 3029*cb14a3feSDimitry Andric const intern_type* frm_end, 3030*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3031*cb14a3feSDimitry Andric extern_type* to, 3032*cb14a3feSDimitry Andric extern_type* to_end, 3033*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 30340b57cec5SDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 30350b57cec5SDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 30360b57cec5SDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 30370b57cec5SDimitry Andric const uint16_t* _frm_nxt = _frm; 30380b57cec5SDimitry Andric # else 30390b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 30400b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 30410b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 30420b57cec5SDimitry Andric # endif 30430b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 30440b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 30450b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 30460b57cec5SDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3047*cb14a3feSDimitry Andric result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 30480b57cec5SDimitry Andric # else 3049*cb14a3feSDimitry Andric result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 30500b57cec5SDimitry Andric # endif 30510b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 30520b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 30530b57cec5SDimitry Andric return r; 30540b57cec5SDimitry Andric } 30550b57cec5SDimitry Andric 3056*cb14a3feSDimitry Andric __codecvt_utf8<wchar_t>::result __codecvt_utf8<wchar_t>::do_in( 3057*cb14a3feSDimitry Andric state_type&, 3058*cb14a3feSDimitry Andric const extern_type* frm, 3059*cb14a3feSDimitry Andric const extern_type* frm_end, 3060*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3061*cb14a3feSDimitry Andric intern_type* to, 3062*cb14a3feSDimitry Andric intern_type* to_end, 3063*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 30640b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 30650b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 30660b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 30670b57cec5SDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 30680b57cec5SDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 30690b57cec5SDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 30700b57cec5SDimitry Andric uint16_t* _to_nxt = _to; 3071*cb14a3feSDimitry Andric result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 30720b57cec5SDimitry Andric # else 30730b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 30740b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 30750b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3076*cb14a3feSDimitry Andric result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 30770b57cec5SDimitry Andric # endif 30780b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 30790b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 30800b57cec5SDimitry Andric return r; 30810b57cec5SDimitry Andric } 30820b57cec5SDimitry Andric 30830b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::result 3084*cb14a3feSDimitry Andric __codecvt_utf8<wchar_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 30850b57cec5SDimitry Andric to_nxt = to; 30860b57cec5SDimitry Andric return noconv; 30870b57cec5SDimitry Andric } 30880b57cec5SDimitry Andric 3089*cb14a3feSDimitry Andric int __codecvt_utf8<wchar_t>::do_encoding() const noexcept { return 0; } 30900b57cec5SDimitry Andric 3091*cb14a3feSDimitry Andric bool __codecvt_utf8<wchar_t>::do_always_noconv() const noexcept { return false; } 30920b57cec5SDimitry Andric 3093*cb14a3feSDimitry Andric int __codecvt_utf8<wchar_t>::do_length( 3094*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 30950b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 30960b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3097349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3098bdd1243dSDimitry Andric return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_); 3099349cc55cSDimitry Andric # else 3100bdd1243dSDimitry Andric return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_); 3101349cc55cSDimitry Andric # endif 31020b57cec5SDimitry Andric } 31030b57cec5SDimitry Andric 310481ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3105*cb14a3feSDimitry Andric int __codecvt_utf8<wchar_t>::do_max_length() const noexcept { 3106349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3107bdd1243dSDimitry Andric if (__mode_ & consume_header) 3108349cc55cSDimitry Andric return 6; 3109349cc55cSDimitry Andric return 3; 3110349cc55cSDimitry Andric # else 3111bdd1243dSDimitry Andric if (__mode_ & consume_header) 31120b57cec5SDimitry Andric return 7; 31130b57cec5SDimitry Andric return 4; 3114349cc55cSDimitry Andric # endif 31150b57cec5SDimitry Andric } 3116349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 31170b57cec5SDimitry Andric 31180b57cec5SDimitry Andric // __codecvt_utf8<char16_t> 31190b57cec5SDimitry Andric 3120*cb14a3feSDimitry Andric __codecvt_utf8<char16_t>::result __codecvt_utf8<char16_t>::do_out( 3121*cb14a3feSDimitry Andric state_type&, 3122*cb14a3feSDimitry Andric const intern_type* frm, 3123*cb14a3feSDimitry Andric const intern_type* frm_end, 3124*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3125*cb14a3feSDimitry Andric extern_type* to, 3126*cb14a3feSDimitry Andric extern_type* to_end, 3127*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 31280b57cec5SDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 31290b57cec5SDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 31300b57cec5SDimitry Andric const uint16_t* _frm_nxt = _frm; 31310b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 31320b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 31330b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3134*cb14a3feSDimitry Andric result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 31350b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 31360b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 31370b57cec5SDimitry Andric return r; 31380b57cec5SDimitry Andric } 31390b57cec5SDimitry Andric 3140*cb14a3feSDimitry Andric __codecvt_utf8<char16_t>::result __codecvt_utf8<char16_t>::do_in( 3141*cb14a3feSDimitry Andric state_type&, 3142*cb14a3feSDimitry Andric const extern_type* frm, 3143*cb14a3feSDimitry Andric const extern_type* frm_end, 3144*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3145*cb14a3feSDimitry Andric intern_type* to, 3146*cb14a3feSDimitry Andric intern_type* to_end, 3147*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 31480b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 31490b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 31500b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 31510b57cec5SDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 31520b57cec5SDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 31530b57cec5SDimitry Andric uint16_t* _to_nxt = _to; 3154*cb14a3feSDimitry Andric result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 31550b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 31560b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 31570b57cec5SDimitry Andric return r; 31580b57cec5SDimitry Andric } 31590b57cec5SDimitry Andric 31600b57cec5SDimitry Andric __codecvt_utf8<char16_t>::result 3161*cb14a3feSDimitry Andric __codecvt_utf8<char16_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 31620b57cec5SDimitry Andric to_nxt = to; 31630b57cec5SDimitry Andric return noconv; 31640b57cec5SDimitry Andric } 31650b57cec5SDimitry Andric 3166*cb14a3feSDimitry Andric int __codecvt_utf8<char16_t>::do_encoding() const noexcept { return 0; } 31670b57cec5SDimitry Andric 3168*cb14a3feSDimitry Andric bool __codecvt_utf8<char16_t>::do_always_noconv() const noexcept { return false; } 31690b57cec5SDimitry Andric 3170*cb14a3feSDimitry Andric int __codecvt_utf8<char16_t>::do_length( 3171*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 31720b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 31730b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3174bdd1243dSDimitry Andric return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_); 31750b57cec5SDimitry Andric } 31760b57cec5SDimitry Andric 317781ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3178*cb14a3feSDimitry Andric int __codecvt_utf8<char16_t>::do_max_length() const noexcept { 3179bdd1243dSDimitry Andric if (__mode_ & consume_header) 31800b57cec5SDimitry Andric return 6; 31810b57cec5SDimitry Andric return 3; 31820b57cec5SDimitry Andric } 318381ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 31840b57cec5SDimitry Andric 31850b57cec5SDimitry Andric // __codecvt_utf8<char32_t> 31860b57cec5SDimitry Andric 3187*cb14a3feSDimitry Andric __codecvt_utf8<char32_t>::result __codecvt_utf8<char32_t>::do_out( 3188*cb14a3feSDimitry Andric state_type&, 3189*cb14a3feSDimitry Andric const intern_type* frm, 3190*cb14a3feSDimitry Andric const intern_type* frm_end, 3191*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3192*cb14a3feSDimitry Andric extern_type* to, 3193*cb14a3feSDimitry Andric extern_type* to_end, 3194*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 31950b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 31960b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 31970b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 31980b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 31990b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 32000b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3201*cb14a3feSDimitry Andric result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 32020b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 32030b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 32040b57cec5SDimitry Andric return r; 32050b57cec5SDimitry Andric } 32060b57cec5SDimitry Andric 3207*cb14a3feSDimitry Andric __codecvt_utf8<char32_t>::result __codecvt_utf8<char32_t>::do_in( 3208*cb14a3feSDimitry Andric state_type&, 3209*cb14a3feSDimitry Andric const extern_type* frm, 3210*cb14a3feSDimitry Andric const extern_type* frm_end, 3211*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3212*cb14a3feSDimitry Andric intern_type* to, 3213*cb14a3feSDimitry Andric intern_type* to_end, 3214*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 32150b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 32160b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 32170b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 32180b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 32190b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 32200b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3221*cb14a3feSDimitry Andric result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 32220b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 32230b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 32240b57cec5SDimitry Andric return r; 32250b57cec5SDimitry Andric } 32260b57cec5SDimitry Andric 32270b57cec5SDimitry Andric __codecvt_utf8<char32_t>::result 3228*cb14a3feSDimitry Andric __codecvt_utf8<char32_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 32290b57cec5SDimitry Andric to_nxt = to; 32300b57cec5SDimitry Andric return noconv; 32310b57cec5SDimitry Andric } 32320b57cec5SDimitry Andric 3233*cb14a3feSDimitry Andric int __codecvt_utf8<char32_t>::do_encoding() const noexcept { return 0; } 32340b57cec5SDimitry Andric 3235*cb14a3feSDimitry Andric bool __codecvt_utf8<char32_t>::do_always_noconv() const noexcept { return false; } 32360b57cec5SDimitry Andric 3237*cb14a3feSDimitry Andric int __codecvt_utf8<char32_t>::do_length( 3238*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 32390b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 32400b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3241bdd1243dSDimitry Andric return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_); 32420b57cec5SDimitry Andric } 32430b57cec5SDimitry Andric 324481ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3245*cb14a3feSDimitry Andric int __codecvt_utf8<char32_t>::do_max_length() const noexcept { 3246bdd1243dSDimitry Andric if (__mode_ & consume_header) 32470b57cec5SDimitry Andric return 7; 32480b57cec5SDimitry Andric return 4; 32490b57cec5SDimitry Andric } 325081ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 32510b57cec5SDimitry Andric 32520b57cec5SDimitry Andric // __codecvt_utf16<wchar_t, false> 32530b57cec5SDimitry Andric 3254349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3255*cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, false>::result __codecvt_utf16<wchar_t, false>::do_out( 3256*cb14a3feSDimitry Andric state_type&, 3257*cb14a3feSDimitry Andric const intern_type* frm, 3258*cb14a3feSDimitry Andric const intern_type* frm_end, 3259*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3260*cb14a3feSDimitry Andric extern_type* to, 3261*cb14a3feSDimitry Andric extern_type* to_end, 3262*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 3263349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3264349cc55cSDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3265349cc55cSDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3266349cc55cSDimitry Andric const uint16_t* _frm_nxt = _frm; 3267349cc55cSDimitry Andric # else 32680b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 32690b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 32700b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 3271349cc55cSDimitry Andric # endif 32720b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 32730b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 32740b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3275349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3276*cb14a3feSDimitry Andric result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3277349cc55cSDimitry Andric # else 3278*cb14a3feSDimitry Andric result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3279349cc55cSDimitry Andric # endif 32800b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 32810b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 32820b57cec5SDimitry Andric return r; 32830b57cec5SDimitry Andric } 32840b57cec5SDimitry Andric 3285*cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, false>::result __codecvt_utf16<wchar_t, false>::do_in( 3286*cb14a3feSDimitry Andric state_type&, 3287*cb14a3feSDimitry Andric const extern_type* frm, 3288*cb14a3feSDimitry Andric const extern_type* frm_end, 3289*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3290*cb14a3feSDimitry Andric intern_type* to, 3291*cb14a3feSDimitry Andric intern_type* to_end, 3292*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 32930b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 32940b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 32950b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 3296349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3297349cc55cSDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3298349cc55cSDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3299349cc55cSDimitry Andric uint16_t* _to_nxt = _to; 3300*cb14a3feSDimitry Andric result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3301349cc55cSDimitry Andric # else 33020b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 33030b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 33040b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3305*cb14a3feSDimitry Andric result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3306349cc55cSDimitry Andric # endif 33070b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 33080b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 33090b57cec5SDimitry Andric return r; 33100b57cec5SDimitry Andric } 33110b57cec5SDimitry Andric 33120b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::result 3313*cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, false>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 33140b57cec5SDimitry Andric to_nxt = to; 33150b57cec5SDimitry Andric return noconv; 33160b57cec5SDimitry Andric } 33170b57cec5SDimitry Andric 3318*cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, false>::do_encoding() const noexcept { return 0; } 33190b57cec5SDimitry Andric 3320*cb14a3feSDimitry Andric bool __codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept { return false; } 33210b57cec5SDimitry Andric 3322*cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, false>::do_length( 3323*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 33240b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 33250b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3326349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3327bdd1243dSDimitry Andric return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_); 3328349cc55cSDimitry Andric # else 3329bdd1243dSDimitry Andric return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_); 3330349cc55cSDimitry Andric # endif 33310b57cec5SDimitry Andric } 33320b57cec5SDimitry Andric 3333*cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, false>::do_max_length() const noexcept { 3334349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3335bdd1243dSDimitry Andric if (__mode_ & consume_header) 3336349cc55cSDimitry Andric return 4; 3337349cc55cSDimitry Andric return 2; 3338349cc55cSDimitry Andric # else 3339bdd1243dSDimitry Andric if (__mode_ & consume_header) 33400b57cec5SDimitry Andric return 6; 33410b57cec5SDimitry Andric return 4; 3342349cc55cSDimitry Andric # endif 33430b57cec5SDimitry Andric } 33440b57cec5SDimitry Andric 33450b57cec5SDimitry Andric // __codecvt_utf16<wchar_t, true> 33460b57cec5SDimitry Andric 3347*cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, true>::result __codecvt_utf16<wchar_t, true>::do_out( 3348*cb14a3feSDimitry Andric state_type&, 3349*cb14a3feSDimitry Andric const intern_type* frm, 3350*cb14a3feSDimitry Andric const intern_type* frm_end, 3351*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3352*cb14a3feSDimitry Andric extern_type* to, 3353*cb14a3feSDimitry Andric extern_type* to_end, 3354*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 3355349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3356349cc55cSDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3357349cc55cSDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3358349cc55cSDimitry Andric const uint16_t* _frm_nxt = _frm; 3359349cc55cSDimitry Andric # else 33600b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 33610b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 33620b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 3363349cc55cSDimitry Andric # endif 33640b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 33650b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 33660b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3367349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3368*cb14a3feSDimitry Andric result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3369349cc55cSDimitry Andric # else 3370*cb14a3feSDimitry Andric result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3371349cc55cSDimitry Andric # endif 33720b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 33730b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 33740b57cec5SDimitry Andric return r; 33750b57cec5SDimitry Andric } 33760b57cec5SDimitry Andric 3377*cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, true>::result __codecvt_utf16<wchar_t, true>::do_in( 3378*cb14a3feSDimitry Andric state_type&, 3379*cb14a3feSDimitry Andric const extern_type* frm, 3380*cb14a3feSDimitry Andric const extern_type* frm_end, 3381*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3382*cb14a3feSDimitry Andric intern_type* to, 3383*cb14a3feSDimitry Andric intern_type* to_end, 3384*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 33850b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 33860b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 33870b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 3388349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3389349cc55cSDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3390349cc55cSDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3391349cc55cSDimitry Andric uint16_t* _to_nxt = _to; 3392*cb14a3feSDimitry Andric result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3393349cc55cSDimitry Andric # else 33940b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 33950b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 33960b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3397*cb14a3feSDimitry Andric result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 3398349cc55cSDimitry Andric # endif 33990b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 34000b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 34010b57cec5SDimitry Andric return r; 34020b57cec5SDimitry Andric } 34030b57cec5SDimitry Andric 34040b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::result 3405*cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, true>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 34060b57cec5SDimitry Andric to_nxt = to; 34070b57cec5SDimitry Andric return noconv; 34080b57cec5SDimitry Andric } 34090b57cec5SDimitry Andric 3410*cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, true>::do_encoding() const noexcept { return 0; } 34110b57cec5SDimitry Andric 3412*cb14a3feSDimitry Andric bool __codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept { return false; } 34130b57cec5SDimitry Andric 3414*cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, true>::do_length( 3415*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 34160b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 34170b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3418349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3419bdd1243dSDimitry Andric return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_); 3420349cc55cSDimitry Andric # else 3421bdd1243dSDimitry Andric return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_); 3422349cc55cSDimitry Andric # endif 34230b57cec5SDimitry Andric } 34240b57cec5SDimitry Andric 3425*cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, true>::do_max_length() const noexcept { 3426349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3427bdd1243dSDimitry Andric if (__mode_ & consume_header) 3428349cc55cSDimitry Andric return 4; 3429349cc55cSDimitry Andric return 2; 3430349cc55cSDimitry Andric # else 3431bdd1243dSDimitry Andric if (__mode_ & consume_header) 34320b57cec5SDimitry Andric return 6; 34330b57cec5SDimitry Andric return 4; 3434349cc55cSDimitry Andric # endif 34350b57cec5SDimitry Andric } 3436349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 34370b57cec5SDimitry Andric 34380b57cec5SDimitry Andric // __codecvt_utf16<char16_t, false> 34390b57cec5SDimitry Andric 3440*cb14a3feSDimitry Andric __codecvt_utf16<char16_t, false>::result __codecvt_utf16<char16_t, false>::do_out( 3441*cb14a3feSDimitry Andric state_type&, 3442*cb14a3feSDimitry Andric const intern_type* frm, 3443*cb14a3feSDimitry Andric const intern_type* frm_end, 3444*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3445*cb14a3feSDimitry Andric extern_type* to, 3446*cb14a3feSDimitry Andric extern_type* to_end, 3447*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 34480b57cec5SDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 34490b57cec5SDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 34500b57cec5SDimitry Andric const uint16_t* _frm_nxt = _frm; 34510b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 34520b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 34530b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3454*cb14a3feSDimitry Andric result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 34550b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 34560b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 34570b57cec5SDimitry Andric return r; 34580b57cec5SDimitry Andric } 34590b57cec5SDimitry Andric 3460*cb14a3feSDimitry Andric __codecvt_utf16<char16_t, false>::result __codecvt_utf16<char16_t, false>::do_in( 3461*cb14a3feSDimitry Andric state_type&, 3462*cb14a3feSDimitry Andric const extern_type* frm, 3463*cb14a3feSDimitry Andric const extern_type* frm_end, 3464*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3465*cb14a3feSDimitry Andric intern_type* to, 3466*cb14a3feSDimitry Andric intern_type* to_end, 3467*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 34680b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 34690b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 34700b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 34710b57cec5SDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 34720b57cec5SDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 34730b57cec5SDimitry Andric uint16_t* _to_nxt = _to; 3474*cb14a3feSDimitry Andric result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 34750b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 34760b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 34770b57cec5SDimitry Andric return r; 34780b57cec5SDimitry Andric } 34790b57cec5SDimitry Andric 34800b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::result 3481*cb14a3feSDimitry Andric __codecvt_utf16<char16_t, false>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 34820b57cec5SDimitry Andric to_nxt = to; 34830b57cec5SDimitry Andric return noconv; 34840b57cec5SDimitry Andric } 34850b57cec5SDimitry Andric 3486*cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, false>::do_encoding() const noexcept { return 0; } 34870b57cec5SDimitry Andric 3488*cb14a3feSDimitry Andric bool __codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept { return false; } 34890b57cec5SDimitry Andric 3490*cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, false>::do_length( 3491*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 34920b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 34930b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3494bdd1243dSDimitry Andric return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_); 34950b57cec5SDimitry Andric } 34960b57cec5SDimitry Andric 349781ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3498*cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, false>::do_max_length() const noexcept { 3499bdd1243dSDimitry Andric if (__mode_ & consume_header) 35000b57cec5SDimitry Andric return 4; 35010b57cec5SDimitry Andric return 2; 35020b57cec5SDimitry Andric } 350381ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 35040b57cec5SDimitry Andric 35050b57cec5SDimitry Andric // __codecvt_utf16<char16_t, true> 35060b57cec5SDimitry Andric 3507*cb14a3feSDimitry Andric __codecvt_utf16<char16_t, true>::result __codecvt_utf16<char16_t, true>::do_out( 3508*cb14a3feSDimitry Andric state_type&, 3509*cb14a3feSDimitry Andric const intern_type* frm, 3510*cb14a3feSDimitry Andric const intern_type* frm_end, 3511*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3512*cb14a3feSDimitry Andric extern_type* to, 3513*cb14a3feSDimitry Andric extern_type* to_end, 3514*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 35150b57cec5SDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 35160b57cec5SDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 35170b57cec5SDimitry Andric const uint16_t* _frm_nxt = _frm; 35180b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 35190b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 35200b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3521*cb14a3feSDimitry Andric result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 35220b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 35230b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 35240b57cec5SDimitry Andric return r; 35250b57cec5SDimitry Andric } 35260b57cec5SDimitry Andric 3527*cb14a3feSDimitry Andric __codecvt_utf16<char16_t, true>::result __codecvt_utf16<char16_t, true>::do_in( 3528*cb14a3feSDimitry Andric state_type&, 3529*cb14a3feSDimitry Andric const extern_type* frm, 3530*cb14a3feSDimitry Andric const extern_type* frm_end, 3531*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3532*cb14a3feSDimitry Andric intern_type* to, 3533*cb14a3feSDimitry Andric intern_type* to_end, 3534*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 35350b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 35360b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 35370b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 35380b57cec5SDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 35390b57cec5SDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 35400b57cec5SDimitry Andric uint16_t* _to_nxt = _to; 3541*cb14a3feSDimitry Andric result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 35420b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 35430b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 35440b57cec5SDimitry Andric return r; 35450b57cec5SDimitry Andric } 35460b57cec5SDimitry Andric 35470b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::result 3548*cb14a3feSDimitry Andric __codecvt_utf16<char16_t, true>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 35490b57cec5SDimitry Andric to_nxt = to; 35500b57cec5SDimitry Andric return noconv; 35510b57cec5SDimitry Andric } 35520b57cec5SDimitry Andric 3553*cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, true>::do_encoding() const noexcept { return 0; } 35540b57cec5SDimitry Andric 3555*cb14a3feSDimitry Andric bool __codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept { return false; } 35560b57cec5SDimitry Andric 3557*cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, true>::do_length( 3558*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 35590b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 35600b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3561bdd1243dSDimitry Andric return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_); 35620b57cec5SDimitry Andric } 35630b57cec5SDimitry Andric 356481ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3565*cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, true>::do_max_length() const noexcept { 3566bdd1243dSDimitry Andric if (__mode_ & consume_header) 35670b57cec5SDimitry Andric return 4; 35680b57cec5SDimitry Andric return 2; 35690b57cec5SDimitry Andric } 357081ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 35710b57cec5SDimitry Andric 35720b57cec5SDimitry Andric // __codecvt_utf16<char32_t, false> 35730b57cec5SDimitry Andric 3574*cb14a3feSDimitry Andric __codecvt_utf16<char32_t, false>::result __codecvt_utf16<char32_t, false>::do_out( 3575*cb14a3feSDimitry Andric state_type&, 3576*cb14a3feSDimitry Andric const intern_type* frm, 3577*cb14a3feSDimitry Andric const intern_type* frm_end, 3578*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3579*cb14a3feSDimitry Andric extern_type* to, 3580*cb14a3feSDimitry Andric extern_type* to_end, 3581*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 35820b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 35830b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 35840b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 35850b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 35860b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 35870b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3588*cb14a3feSDimitry Andric result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 35890b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 35900b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 35910b57cec5SDimitry Andric return r; 35920b57cec5SDimitry Andric } 35930b57cec5SDimitry Andric 3594*cb14a3feSDimitry Andric __codecvt_utf16<char32_t, false>::result __codecvt_utf16<char32_t, false>::do_in( 3595*cb14a3feSDimitry Andric state_type&, 3596*cb14a3feSDimitry Andric const extern_type* frm, 3597*cb14a3feSDimitry Andric const extern_type* frm_end, 3598*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3599*cb14a3feSDimitry Andric intern_type* to, 3600*cb14a3feSDimitry Andric intern_type* to_end, 3601*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 36020b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 36030b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 36040b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 36050b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 36060b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 36070b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3608*cb14a3feSDimitry Andric result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 36090b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 36100b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 36110b57cec5SDimitry Andric return r; 36120b57cec5SDimitry Andric } 36130b57cec5SDimitry Andric 36140b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::result 3615*cb14a3feSDimitry Andric __codecvt_utf16<char32_t, false>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 36160b57cec5SDimitry Andric to_nxt = to; 36170b57cec5SDimitry Andric return noconv; 36180b57cec5SDimitry Andric } 36190b57cec5SDimitry Andric 3620*cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, false>::do_encoding() const noexcept { return 0; } 36210b57cec5SDimitry Andric 3622*cb14a3feSDimitry Andric bool __codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept { return false; } 36230b57cec5SDimitry Andric 3624*cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, false>::do_length( 3625*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 36260b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 36270b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3628bdd1243dSDimitry Andric return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_); 36290b57cec5SDimitry Andric } 36300b57cec5SDimitry Andric 363181ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3632*cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, false>::do_max_length() const noexcept { 3633bdd1243dSDimitry Andric if (__mode_ & consume_header) 36340b57cec5SDimitry Andric return 6; 36350b57cec5SDimitry Andric return 4; 36360b57cec5SDimitry Andric } 363781ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 36380b57cec5SDimitry Andric 36390b57cec5SDimitry Andric // __codecvt_utf16<char32_t, true> 36400b57cec5SDimitry Andric 3641*cb14a3feSDimitry Andric __codecvt_utf16<char32_t, true>::result __codecvt_utf16<char32_t, true>::do_out( 3642*cb14a3feSDimitry Andric state_type&, 3643*cb14a3feSDimitry Andric const intern_type* frm, 3644*cb14a3feSDimitry Andric const intern_type* frm_end, 3645*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3646*cb14a3feSDimitry Andric extern_type* to, 3647*cb14a3feSDimitry Andric extern_type* to_end, 3648*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 36490b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 36500b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 36510b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 36520b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 36530b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 36540b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3655*cb14a3feSDimitry Andric result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 36560b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 36570b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 36580b57cec5SDimitry Andric return r; 36590b57cec5SDimitry Andric } 36600b57cec5SDimitry Andric 3661*cb14a3feSDimitry Andric __codecvt_utf16<char32_t, true>::result __codecvt_utf16<char32_t, true>::do_in( 3662*cb14a3feSDimitry Andric state_type&, 3663*cb14a3feSDimitry Andric const extern_type* frm, 3664*cb14a3feSDimitry Andric const extern_type* frm_end, 3665*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3666*cb14a3feSDimitry Andric intern_type* to, 3667*cb14a3feSDimitry Andric intern_type* to_end, 3668*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 36690b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 36700b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 36710b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 36720b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 36730b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 36740b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3675*cb14a3feSDimitry Andric result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 36760b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 36770b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 36780b57cec5SDimitry Andric return r; 36790b57cec5SDimitry Andric } 36800b57cec5SDimitry Andric 36810b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::result 3682*cb14a3feSDimitry Andric __codecvt_utf16<char32_t, true>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 36830b57cec5SDimitry Andric to_nxt = to; 36840b57cec5SDimitry Andric return noconv; 36850b57cec5SDimitry Andric } 36860b57cec5SDimitry Andric 3687*cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, true>::do_encoding() const noexcept { return 0; } 36880b57cec5SDimitry Andric 3689*cb14a3feSDimitry Andric bool __codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept { return false; } 36900b57cec5SDimitry Andric 3691*cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, true>::do_length( 3692*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 36930b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 36940b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3695bdd1243dSDimitry Andric return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_); 36960b57cec5SDimitry Andric } 36970b57cec5SDimitry Andric 369881ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3699*cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, true>::do_max_length() const noexcept { 3700bdd1243dSDimitry Andric if (__mode_ & consume_header) 37010b57cec5SDimitry Andric return 6; 37020b57cec5SDimitry Andric return 4; 37030b57cec5SDimitry Andric } 370481ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 37050b57cec5SDimitry Andric 37060b57cec5SDimitry Andric // __codecvt_utf8_utf16<wchar_t> 37070b57cec5SDimitry Andric 3708349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3709*cb14a3feSDimitry Andric __codecvt_utf8_utf16<wchar_t>::result __codecvt_utf8_utf16<wchar_t>::do_out( 3710*cb14a3feSDimitry Andric state_type&, 3711*cb14a3feSDimitry Andric const intern_type* frm, 3712*cb14a3feSDimitry Andric const intern_type* frm_end, 3713*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3714*cb14a3feSDimitry Andric extern_type* to, 3715*cb14a3feSDimitry Andric extern_type* to_end, 3716*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 3717349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3718349cc55cSDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 3719349cc55cSDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 3720349cc55cSDimitry Andric const uint16_t* _frm_nxt = _frm; 3721349cc55cSDimitry Andric # else 37220b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 37230b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 37240b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 3725349cc55cSDimitry Andric # endif 37260b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 37270b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 37280b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3729*cb14a3feSDimitry Andric result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 37300b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 37310b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 37320b57cec5SDimitry Andric return r; 37330b57cec5SDimitry Andric } 37340b57cec5SDimitry Andric 3735*cb14a3feSDimitry Andric __codecvt_utf8_utf16<wchar_t>::result __codecvt_utf8_utf16<wchar_t>::do_in( 3736*cb14a3feSDimitry Andric state_type&, 3737*cb14a3feSDimitry Andric const extern_type* frm, 3738*cb14a3feSDimitry Andric const extern_type* frm_end, 3739*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3740*cb14a3feSDimitry Andric intern_type* to, 3741*cb14a3feSDimitry Andric intern_type* to_end, 3742*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 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 const uint8_t* _frm_nxt = _frm; 3746349cc55cSDimitry Andric # if defined(_LIBCPP_SHORT_WCHAR) 3747349cc55cSDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 3748349cc55cSDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 3749349cc55cSDimitry Andric uint16_t* _to_nxt = _to; 3750349cc55cSDimitry Andric # else 37510b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 37520b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 37530b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3754349cc55cSDimitry Andric # endif 3755*cb14a3feSDimitry Andric result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 37560b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 37570b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 37580b57cec5SDimitry Andric return r; 37590b57cec5SDimitry Andric } 37600b57cec5SDimitry Andric 37610b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::result 3762*cb14a3feSDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 37630b57cec5SDimitry Andric to_nxt = to; 37640b57cec5SDimitry Andric return noconv; 37650b57cec5SDimitry Andric } 37660b57cec5SDimitry Andric 3767*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept { return 0; } 37680b57cec5SDimitry Andric 3769*cb14a3feSDimitry Andric bool __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept { return false; } 37700b57cec5SDimitry Andric 3771*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<wchar_t>::do_length( 3772*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 37730b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 37740b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3775bdd1243dSDimitry Andric return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_); 37760b57cec5SDimitry Andric } 37770b57cec5SDimitry Andric 3778*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept { 3779bdd1243dSDimitry Andric if (__mode_ & consume_header) 37800b57cec5SDimitry Andric return 7; 37810b57cec5SDimitry Andric return 4; 37820b57cec5SDimitry Andric } 3783349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 37840b57cec5SDimitry Andric 37850b57cec5SDimitry Andric // __codecvt_utf8_utf16<char16_t> 37860b57cec5SDimitry Andric 3787*cb14a3feSDimitry Andric __codecvt_utf8_utf16<char16_t>::result __codecvt_utf8_utf16<char16_t>::do_out( 3788*cb14a3feSDimitry Andric state_type&, 3789*cb14a3feSDimitry Andric const intern_type* frm, 3790*cb14a3feSDimitry Andric const intern_type* frm_end, 3791*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3792*cb14a3feSDimitry Andric extern_type* to, 3793*cb14a3feSDimitry Andric extern_type* to_end, 3794*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 37950b57cec5SDimitry Andric const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); 37960b57cec5SDimitry Andric const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); 37970b57cec5SDimitry Andric const uint16_t* _frm_nxt = _frm; 37980b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 37990b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 38000b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3801*cb14a3feSDimitry Andric result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 38020b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 38030b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 38040b57cec5SDimitry Andric return r; 38050b57cec5SDimitry Andric } 38060b57cec5SDimitry Andric 3807*cb14a3feSDimitry Andric __codecvt_utf8_utf16<char16_t>::result __codecvt_utf8_utf16<char16_t>::do_in( 3808*cb14a3feSDimitry Andric state_type&, 3809*cb14a3feSDimitry Andric const extern_type* frm, 3810*cb14a3feSDimitry Andric const extern_type* frm_end, 3811*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3812*cb14a3feSDimitry Andric intern_type* to, 3813*cb14a3feSDimitry Andric intern_type* to_end, 3814*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 38150b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 38160b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 38170b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 38180b57cec5SDimitry Andric uint16_t* _to = reinterpret_cast<uint16_t*>(to); 38190b57cec5SDimitry Andric uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); 38200b57cec5SDimitry Andric uint16_t* _to_nxt = _to; 3821*cb14a3feSDimitry Andric result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 38220b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 38230b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 38240b57cec5SDimitry Andric return r; 38250b57cec5SDimitry Andric } 38260b57cec5SDimitry Andric 38270b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::result 3828*cb14a3feSDimitry Andric __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 38290b57cec5SDimitry Andric to_nxt = to; 38300b57cec5SDimitry Andric return noconv; 38310b57cec5SDimitry Andric } 38320b57cec5SDimitry Andric 3833*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept { return 0; } 38340b57cec5SDimitry Andric 3835*cb14a3feSDimitry Andric bool __codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept { return false; } 38360b57cec5SDimitry Andric 3837*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char16_t>::do_length( 3838*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 38390b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 38400b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3841bdd1243dSDimitry Andric return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_); 38420b57cec5SDimitry Andric } 38430b57cec5SDimitry Andric 384481ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3845*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept { 3846bdd1243dSDimitry Andric if (__mode_ & consume_header) 38470b57cec5SDimitry Andric return 7; 38480b57cec5SDimitry Andric return 4; 38490b57cec5SDimitry Andric } 385081ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 38510b57cec5SDimitry Andric 38520b57cec5SDimitry Andric // __codecvt_utf8_utf16<char32_t> 38530b57cec5SDimitry Andric 3854*cb14a3feSDimitry Andric __codecvt_utf8_utf16<char32_t>::result __codecvt_utf8_utf16<char32_t>::do_out( 3855*cb14a3feSDimitry Andric state_type&, 3856*cb14a3feSDimitry Andric const intern_type* frm, 3857*cb14a3feSDimitry Andric const intern_type* frm_end, 3858*cb14a3feSDimitry Andric const intern_type*& frm_nxt, 3859*cb14a3feSDimitry Andric extern_type* to, 3860*cb14a3feSDimitry Andric extern_type* to_end, 3861*cb14a3feSDimitry Andric extern_type*& to_nxt) const { 38620b57cec5SDimitry Andric const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); 38630b57cec5SDimitry Andric const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); 38640b57cec5SDimitry Andric const uint32_t* _frm_nxt = _frm; 38650b57cec5SDimitry Andric uint8_t* _to = reinterpret_cast<uint8_t*>(to); 38660b57cec5SDimitry Andric uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); 38670b57cec5SDimitry Andric uint8_t* _to_nxt = _to; 3868*cb14a3feSDimitry Andric result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 38690b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 38700b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 38710b57cec5SDimitry Andric return r; 38720b57cec5SDimitry Andric } 38730b57cec5SDimitry Andric 3874*cb14a3feSDimitry Andric __codecvt_utf8_utf16<char32_t>::result __codecvt_utf8_utf16<char32_t>::do_in( 3875*cb14a3feSDimitry Andric state_type&, 3876*cb14a3feSDimitry Andric const extern_type* frm, 3877*cb14a3feSDimitry Andric const extern_type* frm_end, 3878*cb14a3feSDimitry Andric const extern_type*& frm_nxt, 3879*cb14a3feSDimitry Andric intern_type* to, 3880*cb14a3feSDimitry Andric intern_type* to_end, 3881*cb14a3feSDimitry Andric intern_type*& to_nxt) const { 38820b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 38830b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 38840b57cec5SDimitry Andric const uint8_t* _frm_nxt = _frm; 38850b57cec5SDimitry Andric uint32_t* _to = reinterpret_cast<uint32_t*>(to); 38860b57cec5SDimitry Andric uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); 38870b57cec5SDimitry Andric uint32_t* _to_nxt = _to; 3888*cb14a3feSDimitry Andric result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_); 38890b57cec5SDimitry Andric frm_nxt = frm + (_frm_nxt - _frm); 38900b57cec5SDimitry Andric to_nxt = to + (_to_nxt - _to); 38910b57cec5SDimitry Andric return r; 38920b57cec5SDimitry Andric } 38930b57cec5SDimitry Andric 38940b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::result 3895*cb14a3feSDimitry Andric __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const { 38960b57cec5SDimitry Andric to_nxt = to; 38970b57cec5SDimitry Andric return noconv; 38980b57cec5SDimitry Andric } 38990b57cec5SDimitry Andric 3900*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept { return 0; } 39010b57cec5SDimitry Andric 3902*cb14a3feSDimitry Andric bool __codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept { return false; } 39030b57cec5SDimitry Andric 3904*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char32_t>::do_length( 3905*cb14a3feSDimitry Andric state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const { 39060b57cec5SDimitry Andric const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); 39070b57cec5SDimitry Andric const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); 3908bdd1243dSDimitry Andric return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_); 39090b57cec5SDimitry Andric } 39100b57cec5SDimitry Andric 391181ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3912*cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept { 3913bdd1243dSDimitry Andric if (__mode_ & consume_header) 39140b57cec5SDimitry Andric return 7; 39150b57cec5SDimitry Andric return 4; 39160b57cec5SDimitry Andric } 391781ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 39180b57cec5SDimitry Andric 39190b57cec5SDimitry Andric // __narrow_to_utf8<16> 39200b57cec5SDimitry Andric 3921*cb14a3feSDimitry Andric __narrow_to_utf8<16>::~__narrow_to_utf8() {} 39220b57cec5SDimitry Andric 39230b57cec5SDimitry Andric // __narrow_to_utf8<32> 39240b57cec5SDimitry Andric 3925*cb14a3feSDimitry Andric __narrow_to_utf8<32>::~__narrow_to_utf8() {} 39260b57cec5SDimitry Andric 39270b57cec5SDimitry Andric // __widen_from_utf8<16> 39280b57cec5SDimitry Andric 3929*cb14a3feSDimitry Andric __widen_from_utf8<16>::~__widen_from_utf8() {} 39300b57cec5SDimitry Andric 39310b57cec5SDimitry Andric // __widen_from_utf8<32> 39320b57cec5SDimitry Andric 3933*cb14a3feSDimitry Andric __widen_from_utf8<32>::~__widen_from_utf8() {} 39340b57cec5SDimitry Andric 3935349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3936*cb14a3feSDimitry Andric static bool checked_string_to_wchar_convert(wchar_t& dest, const char* ptr, locale_t loc) { 39370b57cec5SDimitry Andric if (*ptr == '\0') 39380b57cec5SDimitry Andric return false; 39390b57cec5SDimitry Andric mbstate_t mb = {}; 39400b57cec5SDimitry Andric wchar_t out; 39410b57cec5SDimitry Andric size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc); 39420b57cec5SDimitry Andric if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) { 39430b57cec5SDimitry Andric return false; 39440b57cec5SDimitry Andric } 39450b57cec5SDimitry Andric dest = out; 39460b57cec5SDimitry Andric return true; 39470b57cec5SDimitry Andric } 3948349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 3949349cc55cSDimitry Andric 3950349cc55cSDimitry Andric #ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS 3951349cc55cSDimitry Andric static bool is_narrow_non_breaking_space(const char* ptr) { 3952349cc55cSDimitry Andric // https://www.fileformat.info/info/unicode/char/202f/index.htm 3953349cc55cSDimitry Andric return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf'; 3954349cc55cSDimitry Andric } 3955349cc55cSDimitry Andric 3956349cc55cSDimitry Andric static bool is_non_breaking_space(const char* ptr) { 3957349cc55cSDimitry Andric // https://www.fileformat.info/info/unicode/char/0a/index.htm 3958349cc55cSDimitry Andric return ptr[0] == '\xc2' && ptr[1] == '\xa0'; 3959349cc55cSDimitry Andric } 3960349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 39610b57cec5SDimitry Andric 3962*cb14a3feSDimitry Andric static bool checked_string_to_char_convert(char& dest, const char* ptr, locale_t __loc) { 39630b57cec5SDimitry Andric if (*ptr == '\0') 39640b57cec5SDimitry Andric return false; 39650b57cec5SDimitry Andric if (!ptr[1]) { 39660b57cec5SDimitry Andric dest = *ptr; 39670b57cec5SDimitry Andric return true; 39680b57cec5SDimitry Andric } 3969349cc55cSDimitry Andric 3970349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 39710b57cec5SDimitry Andric // First convert the MBS into a wide char then attempt to narrow it using 39720b57cec5SDimitry Andric // wctob_l. 39730b57cec5SDimitry Andric wchar_t wout; 39740b57cec5SDimitry Andric if (!checked_string_to_wchar_convert(wout, ptr, __loc)) 39750b57cec5SDimitry Andric return false; 39760b57cec5SDimitry Andric int res; 39770b57cec5SDimitry Andric if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) { 39780b57cec5SDimitry Andric dest = res; 39790b57cec5SDimitry Andric return true; 39800b57cec5SDimitry Andric } 3981349cc55cSDimitry Andric // FIXME: Work around specific multibyte sequences that we can reasonably 39820b57cec5SDimitry Andric // translate into a different single byte. 39830b57cec5SDimitry Andric switch (wout) { 39840b57cec5SDimitry Andric case L'\u202F': // narrow non-breaking space 39850b57cec5SDimitry Andric case L'\u00A0': // non-breaking space 39860b57cec5SDimitry Andric dest = ' '; 39870b57cec5SDimitry Andric return true; 39880b57cec5SDimitry Andric default: 39890b57cec5SDimitry Andric return false; 39900b57cec5SDimitry Andric } 3991349cc55cSDimitry Andric #else // _LIBCPP_HAS_NO_WIDE_CHARACTERS 3992349cc55cSDimitry Andric // FIXME: Work around specific multibyte sequences that we can reasonably 3993349cc55cSDimitry Andric // translate into a different single byte. 3994349cc55cSDimitry Andric if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) { 3995349cc55cSDimitry Andric dest = ' '; 3996349cc55cSDimitry Andric return true; 3997349cc55cSDimitry Andric } 3998349cc55cSDimitry Andric 3999349cc55cSDimitry Andric return false; 4000349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 400181ad6265SDimitry Andric __libcpp_unreachable(); 40020b57cec5SDimitry Andric } 40030b57cec5SDimitry Andric 40040b57cec5SDimitry Andric // numpunct<char> && numpunct<wchar_t> 40050b57cec5SDimitry Andric 40065f757f3fSDimitry Andric constinit locale::id numpunct<char>::id; 4007349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 40085f757f3fSDimitry Andric constinit locale::id numpunct<wchar_t>::id; 4009349cc55cSDimitry Andric #endif 40100b57cec5SDimitry Andric 4011*cb14a3feSDimitry Andric numpunct<char>::numpunct(size_t refs) : locale::facet(refs), __decimal_point_('.'), __thousands_sep_(',') {} 40120b57cec5SDimitry Andric 4013349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4014*cb14a3feSDimitry Andric numpunct<wchar_t>::numpunct(size_t refs) : locale::facet(refs), __decimal_point_(L'.'), __thousands_sep_(L',') {} 4015349cc55cSDimitry Andric #endif 40160b57cec5SDimitry Andric 4017*cb14a3feSDimitry Andric numpunct<char>::~numpunct() {} 40180b57cec5SDimitry Andric 4019349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4020*cb14a3feSDimitry Andric numpunct<wchar_t>::~numpunct() {} 4021349cc55cSDimitry Andric #endif 40220b57cec5SDimitry Andric 40230b57cec5SDimitry Andric char numpunct< char >::do_decimal_point() const { return __decimal_point_; } 4024349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 40250b57cec5SDimitry Andric wchar_t numpunct<wchar_t>::do_decimal_point() const { return __decimal_point_; } 4026349cc55cSDimitry Andric #endif 40270b57cec5SDimitry Andric 40280b57cec5SDimitry Andric char numpunct< char >::do_thousands_sep() const { return __thousands_sep_; } 4029349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 40300b57cec5SDimitry Andric wchar_t numpunct<wchar_t>::do_thousands_sep() const { return __thousands_sep_; } 4031349cc55cSDimitry Andric #endif 40320b57cec5SDimitry Andric 40330b57cec5SDimitry Andric string numpunct< char >::do_grouping() const { return __grouping_; } 4034349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 40350b57cec5SDimitry Andric string numpunct<wchar_t>::do_grouping() const { return __grouping_; } 4036349cc55cSDimitry Andric #endif 40370b57cec5SDimitry Andric 40380b57cec5SDimitry Andric string numpunct< char >::do_truename() const { return "true"; } 4039349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 40400b57cec5SDimitry Andric wstring numpunct<wchar_t>::do_truename() const { return L"true"; } 4041349cc55cSDimitry Andric #endif 40420b57cec5SDimitry Andric 40430b57cec5SDimitry Andric string numpunct< char >::do_falsename() const { return "false"; } 4044349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 40450b57cec5SDimitry Andric wstring numpunct<wchar_t>::do_falsename() const { return L"false"; } 4046349cc55cSDimitry Andric #endif 40470b57cec5SDimitry Andric 40480b57cec5SDimitry Andric // numpunct_byname<char> 40490b57cec5SDimitry Andric 4050*cb14a3feSDimitry Andric numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs) : numpunct<char>(refs) { __init(nm); } 40510b57cec5SDimitry Andric 4052*cb14a3feSDimitry Andric numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs) : numpunct<char>(refs) { __init(nm.c_str()); } 40530b57cec5SDimitry Andric 4054*cb14a3feSDimitry Andric numpunct_byname<char>::~numpunct_byname() {} 40550b57cec5SDimitry Andric 4056*cb14a3feSDimitry Andric void numpunct_byname<char>::__init(const char* nm) { 4057349cc55cSDimitry Andric typedef numpunct<char> base; 4058*cb14a3feSDimitry Andric if (strcmp(nm, "C") != 0) { 40590b57cec5SDimitry Andric __libcpp_unique_locale loc(nm); 40600b57cec5SDimitry Andric if (!loc) 4061*cb14a3feSDimitry Andric __throw_runtime_error( 4062*cb14a3feSDimitry Andric ("numpunct_byname<char>::numpunct_byname" 4063*cb14a3feSDimitry Andric " failed to construct for " + 4064*cb14a3feSDimitry Andric string(nm)) 4065*cb14a3feSDimitry Andric .c_str()); 40660b57cec5SDimitry Andric 40670b57cec5SDimitry Andric lconv* lc = __libcpp_localeconv_l(loc.get()); 4068*cb14a3feSDimitry Andric if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point, loc.get())) 4069349cc55cSDimitry Andric __decimal_point_ = base::do_decimal_point(); 4070*cb14a3feSDimitry Andric if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, loc.get())) 4071349cc55cSDimitry Andric __thousands_sep_ = base::do_thousands_sep(); 40720b57cec5SDimitry Andric __grouping_ = lc->grouping; 40730b57cec5SDimitry Andric // localization for truename and falsename is not available 40740b57cec5SDimitry Andric } 40750b57cec5SDimitry Andric } 40760b57cec5SDimitry Andric 40770b57cec5SDimitry Andric // numpunct_byname<wchar_t> 40780b57cec5SDimitry Andric 4079349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4080*cb14a3feSDimitry Andric numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs) : numpunct<wchar_t>(refs) { __init(nm); } 40810b57cec5SDimitry Andric 4082*cb14a3feSDimitry Andric numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs) : numpunct<wchar_t>(refs) { 40830b57cec5SDimitry Andric __init(nm.c_str()); 40840b57cec5SDimitry Andric } 40850b57cec5SDimitry Andric 4086*cb14a3feSDimitry Andric numpunct_byname<wchar_t>::~numpunct_byname() {} 40870b57cec5SDimitry Andric 4088*cb14a3feSDimitry Andric void numpunct_byname<wchar_t>::__init(const char* nm) { 4089*cb14a3feSDimitry Andric if (strcmp(nm, "C") != 0) { 40900b57cec5SDimitry Andric __libcpp_unique_locale loc(nm); 40910b57cec5SDimitry Andric if (!loc) 4092*cb14a3feSDimitry Andric __throw_runtime_error( 4093*cb14a3feSDimitry Andric ("numpunct_byname<wchar_t>::numpunct_byname" 4094*cb14a3feSDimitry Andric " failed to construct for " + 4095*cb14a3feSDimitry Andric string(nm)) 4096*cb14a3feSDimitry Andric .c_str()); 40970b57cec5SDimitry Andric 40980b57cec5SDimitry Andric lconv* lc = __libcpp_localeconv_l(loc.get()); 4099*cb14a3feSDimitry Andric checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, loc.get()); 4100*cb14a3feSDimitry Andric checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, loc.get()); 41010b57cec5SDimitry Andric __grouping_ = lc->grouping; 41020b57cec5SDimitry Andric // localization for truename and falsename is not available 41030b57cec5SDimitry Andric } 41040b57cec5SDimitry Andric } 4105349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 41060b57cec5SDimitry Andric 41070b57cec5SDimitry Andric // num_get helpers 41080b57cec5SDimitry Andric 4109*cb14a3feSDimitry Andric int __num_get_base::__get_base(ios_base& iob) { 41100b57cec5SDimitry Andric ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield; 41110b57cec5SDimitry Andric if (__basefield == ios_base::oct) 41120b57cec5SDimitry Andric return 8; 41130b57cec5SDimitry Andric else if (__basefield == ios_base::hex) 41140b57cec5SDimitry Andric return 16; 41150b57cec5SDimitry Andric else if (__basefield == 0) 41160b57cec5SDimitry Andric return 0; 41170b57cec5SDimitry Andric return 10; 41180b57cec5SDimitry Andric } 41190b57cec5SDimitry Andric 41200b57cec5SDimitry Andric const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN"; 41210b57cec5SDimitry Andric 4122*cb14a3feSDimitry Andric void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err) { 41230b57cec5SDimitry Andric // if the grouping pattern is empty _or_ there are no grouping bits, then do nothing 41240b57cec5SDimitry Andric // we always have at least a single entry in [__g, __g_end); the end of the input sequence 4125*cb14a3feSDimitry Andric if (__grouping.size() != 0 && __g_end - __g > 1) { 41260b57cec5SDimitry Andric reverse(__g, __g_end); 41270b57cec5SDimitry Andric const char* __ig = __grouping.data(); 41280b57cec5SDimitry Andric const char* __eg = __ig + __grouping.size(); 4129*cb14a3feSDimitry Andric for (unsigned* __r = __g; __r < __g_end - 1; ++__r) { 4130*cb14a3feSDimitry Andric if (0 < *__ig && *__ig < numeric_limits<char>::max()) { 4131*cb14a3feSDimitry Andric if (static_cast<unsigned>(*__ig) != *__r) { 41320b57cec5SDimitry Andric __err = ios_base::failbit; 41330b57cec5SDimitry Andric return; 41340b57cec5SDimitry Andric } 41350b57cec5SDimitry Andric } 41360b57cec5SDimitry Andric if (__eg - __ig > 1) 41370b57cec5SDimitry Andric ++__ig; 41380b57cec5SDimitry Andric } 4139*cb14a3feSDimitry Andric if (0 < *__ig && *__ig < numeric_limits<char>::max()) { 41400b57cec5SDimitry Andric if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0) 41410b57cec5SDimitry Andric __err = ios_base::failbit; 41420b57cec5SDimitry Andric } 41430b57cec5SDimitry Andric } 41440b57cec5SDimitry Andric } 41450b57cec5SDimitry Andric 4146*cb14a3feSDimitry Andric void __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, ios_base::fmtflags __flags) { 4147*cb14a3feSDimitry Andric if ((__flags & ios_base::showpos) && (__flags & ios_base::basefield) != ios_base::oct && 4148*cb14a3feSDimitry Andric (__flags & ios_base::basefield) != ios_base::hex && __signd) 41490b57cec5SDimitry Andric *__fmtp++ = '+'; 41500b57cec5SDimitry Andric if (__flags & ios_base::showbase) 41510b57cec5SDimitry Andric *__fmtp++ = '#'; 41520b57cec5SDimitry Andric while (*__len) 41530b57cec5SDimitry Andric *__fmtp++ = *__len++; 41540b57cec5SDimitry Andric if ((__flags & ios_base::basefield) == ios_base::oct) 41550b57cec5SDimitry Andric *__fmtp = 'o'; 4156*cb14a3feSDimitry Andric else if ((__flags & ios_base::basefield) == ios_base::hex) { 41570b57cec5SDimitry Andric if (__flags & ios_base::uppercase) 41580b57cec5SDimitry Andric *__fmtp = 'X'; 41590b57cec5SDimitry Andric else 41600b57cec5SDimitry Andric *__fmtp = 'x'; 4161*cb14a3feSDimitry Andric } else if (__signd) 41620b57cec5SDimitry Andric *__fmtp = 'd'; 41630b57cec5SDimitry Andric else 41640b57cec5SDimitry Andric *__fmtp = 'u'; 41650b57cec5SDimitry Andric } 41660b57cec5SDimitry Andric 4167*cb14a3feSDimitry Andric bool __num_put_base::__format_float(char* __fmtp, const char* __len, ios_base::fmtflags __flags) { 41680b57cec5SDimitry Andric bool specify_precision = true; 41690b57cec5SDimitry Andric if (__flags & ios_base::showpos) 41700b57cec5SDimitry Andric *__fmtp++ = '+'; 41710b57cec5SDimitry Andric if (__flags & ios_base::showpoint) 41720b57cec5SDimitry Andric *__fmtp++ = '#'; 41730b57cec5SDimitry Andric ios_base::fmtflags floatfield = __flags & ios_base::floatfield; 41740b57cec5SDimitry Andric bool uppercase = (__flags & ios_base::uppercase) != 0; 41750b57cec5SDimitry Andric if (floatfield == (ios_base::fixed | ios_base::scientific)) 41760b57cec5SDimitry Andric specify_precision = false; 4177*cb14a3feSDimitry Andric else { 41780b57cec5SDimitry Andric *__fmtp++ = '.'; 41790b57cec5SDimitry Andric *__fmtp++ = '*'; 41800b57cec5SDimitry Andric } 41810b57cec5SDimitry Andric while (*__len) 41820b57cec5SDimitry Andric *__fmtp++ = *__len++; 4183*cb14a3feSDimitry Andric if (floatfield == ios_base::fixed) { 41840b57cec5SDimitry Andric if (uppercase) 41850b57cec5SDimitry Andric *__fmtp = 'F'; 41860b57cec5SDimitry Andric else 41870b57cec5SDimitry Andric *__fmtp = 'f'; 4188*cb14a3feSDimitry Andric } else if (floatfield == ios_base::scientific) { 41890b57cec5SDimitry Andric if (uppercase) 41900b57cec5SDimitry Andric *__fmtp = 'E'; 41910b57cec5SDimitry Andric else 41920b57cec5SDimitry Andric *__fmtp = 'e'; 4193*cb14a3feSDimitry Andric } else if (floatfield == (ios_base::fixed | ios_base::scientific)) { 41940b57cec5SDimitry Andric if (uppercase) 41950b57cec5SDimitry Andric *__fmtp = 'A'; 41960b57cec5SDimitry Andric else 41970b57cec5SDimitry Andric *__fmtp = 'a'; 4198*cb14a3feSDimitry Andric } else { 41990b57cec5SDimitry Andric if (uppercase) 42000b57cec5SDimitry Andric *__fmtp = 'G'; 42010b57cec5SDimitry Andric else 42020b57cec5SDimitry Andric *__fmtp = 'g'; 42030b57cec5SDimitry Andric } 42040b57cec5SDimitry Andric return specify_precision; 42050b57cec5SDimitry Andric } 42060b57cec5SDimitry Andric 4207*cb14a3feSDimitry Andric char* __num_put_base::__identify_padding(char* __nb, char* __ne, const ios_base& __iob) { 4208*cb14a3feSDimitry Andric switch (__iob.flags() & ios_base::adjustfield) { 42090b57cec5SDimitry Andric case ios_base::internal: 42100b57cec5SDimitry Andric if (__nb[0] == '-' || __nb[0] == '+') 42110b57cec5SDimitry Andric return __nb + 1; 4212*cb14a3feSDimitry Andric if (__ne - __nb >= 2 && __nb[0] == '0' && (__nb[1] == 'x' || __nb[1] == 'X')) 42130b57cec5SDimitry Andric return __nb + 2; 42140b57cec5SDimitry Andric break; 42150b57cec5SDimitry Andric case ios_base::left: 42160b57cec5SDimitry Andric return __ne; 42170b57cec5SDimitry Andric case ios_base::right: 42180b57cec5SDimitry Andric default: 42190b57cec5SDimitry Andric break; 42200b57cec5SDimitry Andric } 42210b57cec5SDimitry Andric return __nb; 42220b57cec5SDimitry Andric } 42230b57cec5SDimitry Andric 42240b57cec5SDimitry Andric // time_get 42250b57cec5SDimitry Andric 4226*cb14a3feSDimitry Andric static string* init_weeks() { 42270b57cec5SDimitry Andric static string weeks[14]; 42280b57cec5SDimitry Andric weeks[0] = "Sunday"; 42290b57cec5SDimitry Andric weeks[1] = "Monday"; 42300b57cec5SDimitry Andric weeks[2] = "Tuesday"; 42310b57cec5SDimitry Andric weeks[3] = "Wednesday"; 42320b57cec5SDimitry Andric weeks[4] = "Thursday"; 42330b57cec5SDimitry Andric weeks[5] = "Friday"; 42340b57cec5SDimitry Andric weeks[6] = "Saturday"; 42350b57cec5SDimitry Andric weeks[7] = "Sun"; 42360b57cec5SDimitry Andric weeks[8] = "Mon"; 42370b57cec5SDimitry Andric weeks[9] = "Tue"; 42380b57cec5SDimitry Andric weeks[10] = "Wed"; 42390b57cec5SDimitry Andric weeks[11] = "Thu"; 42400b57cec5SDimitry Andric weeks[12] = "Fri"; 42410b57cec5SDimitry Andric weeks[13] = "Sat"; 42420b57cec5SDimitry Andric return weeks; 42430b57cec5SDimitry Andric } 42440b57cec5SDimitry Andric 4245349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4246*cb14a3feSDimitry Andric static wstring* init_wweeks() { 42470b57cec5SDimitry Andric static wstring weeks[14]; 42480b57cec5SDimitry Andric weeks[0] = L"Sunday"; 42490b57cec5SDimitry Andric weeks[1] = L"Monday"; 42500b57cec5SDimitry Andric weeks[2] = L"Tuesday"; 42510b57cec5SDimitry Andric weeks[3] = L"Wednesday"; 42520b57cec5SDimitry Andric weeks[4] = L"Thursday"; 42530b57cec5SDimitry Andric weeks[5] = L"Friday"; 42540b57cec5SDimitry Andric weeks[6] = L"Saturday"; 42550b57cec5SDimitry Andric weeks[7] = L"Sun"; 42560b57cec5SDimitry Andric weeks[8] = L"Mon"; 42570b57cec5SDimitry Andric weeks[9] = L"Tue"; 42580b57cec5SDimitry Andric weeks[10] = L"Wed"; 42590b57cec5SDimitry Andric weeks[11] = L"Thu"; 42600b57cec5SDimitry Andric weeks[12] = L"Fri"; 42610b57cec5SDimitry Andric weeks[13] = L"Sat"; 42620b57cec5SDimitry Andric return weeks; 42630b57cec5SDimitry Andric } 4264349cc55cSDimitry Andric #endif 42650b57cec5SDimitry Andric 42660b57cec5SDimitry Andric template <> 4267*cb14a3feSDimitry Andric const string* __time_get_c_storage<char>::__weeks() const { 42680b57cec5SDimitry Andric static const string* weeks = init_weeks(); 42690b57cec5SDimitry Andric return weeks; 42700b57cec5SDimitry Andric } 42710b57cec5SDimitry Andric 4272349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 42730b57cec5SDimitry Andric template <> 4274*cb14a3feSDimitry Andric const wstring* __time_get_c_storage<wchar_t>::__weeks() const { 42750b57cec5SDimitry Andric static const wstring* weeks = init_wweeks(); 42760b57cec5SDimitry Andric return weeks; 42770b57cec5SDimitry Andric } 4278349cc55cSDimitry Andric #endif 42790b57cec5SDimitry Andric 4280*cb14a3feSDimitry Andric static string* init_months() { 42810b57cec5SDimitry Andric static string months[24]; 42820b57cec5SDimitry Andric months[0] = "January"; 42830b57cec5SDimitry Andric months[1] = "February"; 42840b57cec5SDimitry Andric months[2] = "March"; 42850b57cec5SDimitry Andric months[3] = "April"; 42860b57cec5SDimitry Andric months[4] = "May"; 42870b57cec5SDimitry Andric months[5] = "June"; 42880b57cec5SDimitry Andric months[6] = "July"; 42890b57cec5SDimitry Andric months[7] = "August"; 42900b57cec5SDimitry Andric months[8] = "September"; 42910b57cec5SDimitry Andric months[9] = "October"; 42920b57cec5SDimitry Andric months[10] = "November"; 42930b57cec5SDimitry Andric months[11] = "December"; 42940b57cec5SDimitry Andric months[12] = "Jan"; 42950b57cec5SDimitry Andric months[13] = "Feb"; 42960b57cec5SDimitry Andric months[14] = "Mar"; 42970b57cec5SDimitry Andric months[15] = "Apr"; 42980b57cec5SDimitry Andric months[16] = "May"; 42990b57cec5SDimitry Andric months[17] = "Jun"; 43000b57cec5SDimitry Andric months[18] = "Jul"; 43010b57cec5SDimitry Andric months[19] = "Aug"; 43020b57cec5SDimitry Andric months[20] = "Sep"; 43030b57cec5SDimitry Andric months[21] = "Oct"; 43040b57cec5SDimitry Andric months[22] = "Nov"; 43050b57cec5SDimitry Andric months[23] = "Dec"; 43060b57cec5SDimitry Andric return months; 43070b57cec5SDimitry Andric } 43080b57cec5SDimitry Andric 4309349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4310*cb14a3feSDimitry Andric static wstring* init_wmonths() { 43110b57cec5SDimitry Andric static wstring months[24]; 43120b57cec5SDimitry Andric months[0] = L"January"; 43130b57cec5SDimitry Andric months[1] = L"February"; 43140b57cec5SDimitry Andric months[2] = L"March"; 43150b57cec5SDimitry Andric months[3] = L"April"; 43160b57cec5SDimitry Andric months[4] = L"May"; 43170b57cec5SDimitry Andric months[5] = L"June"; 43180b57cec5SDimitry Andric months[6] = L"July"; 43190b57cec5SDimitry Andric months[7] = L"August"; 43200b57cec5SDimitry Andric months[8] = L"September"; 43210b57cec5SDimitry Andric months[9] = L"October"; 43220b57cec5SDimitry Andric months[10] = L"November"; 43230b57cec5SDimitry Andric months[11] = L"December"; 43240b57cec5SDimitry Andric months[12] = L"Jan"; 43250b57cec5SDimitry Andric months[13] = L"Feb"; 43260b57cec5SDimitry Andric months[14] = L"Mar"; 43270b57cec5SDimitry Andric months[15] = L"Apr"; 43280b57cec5SDimitry Andric months[16] = L"May"; 43290b57cec5SDimitry Andric months[17] = L"Jun"; 43300b57cec5SDimitry Andric months[18] = L"Jul"; 43310b57cec5SDimitry Andric months[19] = L"Aug"; 43320b57cec5SDimitry Andric months[20] = L"Sep"; 43330b57cec5SDimitry Andric months[21] = L"Oct"; 43340b57cec5SDimitry Andric months[22] = L"Nov"; 43350b57cec5SDimitry Andric months[23] = L"Dec"; 43360b57cec5SDimitry Andric return months; 43370b57cec5SDimitry Andric } 4338349cc55cSDimitry Andric #endif 43390b57cec5SDimitry Andric 43400b57cec5SDimitry Andric template <> 4341*cb14a3feSDimitry Andric const string* __time_get_c_storage<char>::__months() const { 43420b57cec5SDimitry Andric static const string* months = init_months(); 43430b57cec5SDimitry Andric return months; 43440b57cec5SDimitry Andric } 43450b57cec5SDimitry Andric 4346349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 43470b57cec5SDimitry Andric template <> 4348*cb14a3feSDimitry Andric const wstring* __time_get_c_storage<wchar_t>::__months() const { 43490b57cec5SDimitry Andric static const wstring* months = init_wmonths(); 43500b57cec5SDimitry Andric return months; 43510b57cec5SDimitry Andric } 4352349cc55cSDimitry Andric #endif 43530b57cec5SDimitry Andric 4354*cb14a3feSDimitry Andric static string* init_am_pm() { 43550b57cec5SDimitry Andric static string am_pm[2]; 43560b57cec5SDimitry Andric am_pm[0] = "AM"; 43570b57cec5SDimitry Andric am_pm[1] = "PM"; 43580b57cec5SDimitry Andric return am_pm; 43590b57cec5SDimitry Andric } 43600b57cec5SDimitry Andric 4361349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 4362*cb14a3feSDimitry Andric static wstring* init_wam_pm() { 43630b57cec5SDimitry Andric static wstring am_pm[2]; 43640b57cec5SDimitry Andric am_pm[0] = L"AM"; 43650b57cec5SDimitry Andric am_pm[1] = L"PM"; 43660b57cec5SDimitry Andric return am_pm; 43670b57cec5SDimitry Andric } 4368349cc55cSDimitry Andric #endif 43690b57cec5SDimitry Andric 43700b57cec5SDimitry Andric template <> 4371*cb14a3feSDimitry Andric const string* __time_get_c_storage<char>::__am_pm() const { 43720b57cec5SDimitry Andric static const string* am_pm = init_am_pm(); 43730b57cec5SDimitry Andric return am_pm; 43740b57cec5SDimitry Andric } 43750b57cec5SDimitry Andric 4376349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 43770b57cec5SDimitry Andric template <> 4378*cb14a3feSDimitry Andric const wstring* __time_get_c_storage<wchar_t>::__am_pm() const { 43790b57cec5SDimitry Andric static const wstring* am_pm = init_wam_pm(); 43800b57cec5SDimitry Andric return am_pm; 43810b57cec5SDimitry Andric } 4382349cc55cSDimitry Andric #endif 43830b57cec5SDimitry Andric 43840b57cec5SDimitry Andric template <> 4385*cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__x() const { 43860b57cec5SDimitry Andric static string s("%m/%d/%y"); 43870b57cec5SDimitry Andric return s; 43880b57cec5SDimitry Andric } 43890b57cec5SDimitry Andric 4390349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 43910b57cec5SDimitry Andric template <> 4392*cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__x() const { 43930b57cec5SDimitry Andric static wstring s(L"%m/%d/%y"); 43940b57cec5SDimitry Andric return s; 43950b57cec5SDimitry Andric } 4396349cc55cSDimitry Andric #endif 43970b57cec5SDimitry Andric 43980b57cec5SDimitry Andric template <> 4399*cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__X() const { 44000b57cec5SDimitry Andric static string s("%H:%M:%S"); 44010b57cec5SDimitry Andric return s; 44020b57cec5SDimitry Andric } 44030b57cec5SDimitry Andric 4404349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 44050b57cec5SDimitry Andric template <> 4406*cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__X() const { 44070b57cec5SDimitry Andric static wstring s(L"%H:%M:%S"); 44080b57cec5SDimitry Andric return s; 44090b57cec5SDimitry Andric } 4410349cc55cSDimitry Andric #endif 44110b57cec5SDimitry Andric 44120b57cec5SDimitry Andric template <> 4413*cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__c() const { 44140b57cec5SDimitry Andric static string s("%a %b %d %H:%M:%S %Y"); 44150b57cec5SDimitry Andric return s; 44160b57cec5SDimitry Andric } 44170b57cec5SDimitry Andric 4418349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 44190b57cec5SDimitry Andric template <> 4420*cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__c() const { 44210b57cec5SDimitry Andric static wstring s(L"%a %b %d %H:%M:%S %Y"); 44220b57cec5SDimitry Andric return s; 44230b57cec5SDimitry Andric } 4424349cc55cSDimitry Andric #endif 44250b57cec5SDimitry Andric 44260b57cec5SDimitry Andric template <> 4427*cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__r() const { 44280b57cec5SDimitry Andric static string s("%I:%M:%S %p"); 44290b57cec5SDimitry Andric return s; 44300b57cec5SDimitry Andric } 44310b57cec5SDimitry Andric 4432349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 44330b57cec5SDimitry Andric template <> 4434*cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__r() const { 44350b57cec5SDimitry Andric static wstring s(L"%I:%M:%S %p"); 44360b57cec5SDimitry Andric return s; 44370b57cec5SDimitry Andric } 4438349cc55cSDimitry Andric #endif 44390b57cec5SDimitry Andric 44400b57cec5SDimitry Andric // time_get_byname 44410b57cec5SDimitry Andric 4442*cb14a3feSDimitry Andric __time_get::__time_get(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) { 44430b57cec5SDimitry Andric if (__loc_ == 0) 44445f757f3fSDimitry Andric __throw_runtime_error(("time_get_byname failed to construct for " + string(nm)).c_str()); 44450b57cec5SDimitry Andric } 44460b57cec5SDimitry Andric 4447*cb14a3feSDimitry Andric __time_get::__time_get(const string& nm) : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) { 44480b57cec5SDimitry Andric if (__loc_ == 0) 44495f757f3fSDimitry Andric __throw_runtime_error(("time_get_byname failed to construct for " + nm).c_str()); 44500b57cec5SDimitry Andric } 44510b57cec5SDimitry Andric 4452*cb14a3feSDimitry Andric __time_get::~__time_get() { freelocale(__loc_); } 445381ad6265SDimitry Andric 445481ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers") 44550b57cec5SDimitry Andric 44560b57cec5SDimitry Andric template <> 4457*cb14a3feSDimitry Andric string __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) { 44580b57cec5SDimitry Andric tm t = {0}; 44590b57cec5SDimitry Andric t.tm_sec = 59; 44600b57cec5SDimitry Andric t.tm_min = 55; 44610b57cec5SDimitry Andric t.tm_hour = 23; 44620b57cec5SDimitry Andric t.tm_mday = 31; 44630b57cec5SDimitry Andric t.tm_mon = 11; 44640b57cec5SDimitry Andric t.tm_year = 161; 44650b57cec5SDimitry Andric t.tm_wday = 6; 44660b57cec5SDimitry Andric t.tm_yday = 364; 44670b57cec5SDimitry Andric t.tm_isdst = -1; 44680b57cec5SDimitry Andric char buf[100]; 44690b57cec5SDimitry Andric char f[3] = {0}; 44700b57cec5SDimitry Andric f[0] = '%'; 44710b57cec5SDimitry Andric f[1] = fmt; 44720b57cec5SDimitry Andric size_t n = strftime_l(buf, countof(buf), f, &t, __loc_); 44730b57cec5SDimitry Andric char* bb = buf; 44740b57cec5SDimitry Andric char* be = buf + n; 44750b57cec5SDimitry Andric string result; 4476*cb14a3feSDimitry Andric while (bb != be) { 4477*cb14a3feSDimitry Andric if (ct.is(ctype_base::space, *bb)) { 44780b57cec5SDimitry Andric result.push_back(' '); 44790b57cec5SDimitry Andric for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb) 44800b57cec5SDimitry Andric ; 44810b57cec5SDimitry Andric continue; 44820b57cec5SDimitry Andric } 44830b57cec5SDimitry Andric char* w = bb; 44840b57cec5SDimitry Andric ios_base::iostate err = ios_base::goodbit; 4485*cb14a3feSDimitry Andric ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_ + 14, ct, err, false) - this->__weeks_; 4486*cb14a3feSDimitry Andric if (i < 14) { 44870b57cec5SDimitry Andric result.push_back('%'); 44880b57cec5SDimitry Andric if (i < 7) 44890b57cec5SDimitry Andric result.push_back('A'); 44900b57cec5SDimitry Andric else 44910b57cec5SDimitry Andric result.push_back('a'); 44920b57cec5SDimitry Andric bb = w; 44930b57cec5SDimitry Andric continue; 44940b57cec5SDimitry Andric } 44950b57cec5SDimitry Andric w = bb; 4496*cb14a3feSDimitry Andric i = __scan_keyword(w, be, this->__months_, this->__months_ + 24, ct, err, false) - this->__months_; 4497*cb14a3feSDimitry Andric if (i < 24) { 44980b57cec5SDimitry Andric result.push_back('%'); 44990b57cec5SDimitry Andric if (i < 12) 45000b57cec5SDimitry Andric result.push_back('B'); 45010b57cec5SDimitry Andric else 45020b57cec5SDimitry Andric result.push_back('b'); 45030b57cec5SDimitry Andric if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) 45040b57cec5SDimitry Andric result.back() = 'm'; 45050b57cec5SDimitry Andric bb = w; 45060b57cec5SDimitry Andric continue; 45070b57cec5SDimitry Andric } 4508*cb14a3feSDimitry Andric if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) { 45090b57cec5SDimitry Andric w = bb; 4510*cb14a3feSDimitry Andric i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_ + 2, ct, err, false) - this->__am_pm_; 4511*cb14a3feSDimitry Andric if (i < 2) { 45120b57cec5SDimitry Andric result.push_back('%'); 45130b57cec5SDimitry Andric result.push_back('p'); 45140b57cec5SDimitry Andric bb = w; 45150b57cec5SDimitry Andric continue; 45160b57cec5SDimitry Andric } 45170b57cec5SDimitry Andric } 45180b57cec5SDimitry Andric w = bb; 4519*cb14a3feSDimitry Andric if (ct.is(ctype_base::digit, *bb)) { 4520*cb14a3feSDimitry Andric switch (__get_up_to_n_digits(bb, be, err, ct, 4)) { 45210b57cec5SDimitry Andric case 6: 45220b57cec5SDimitry Andric result.push_back('%'); 45230b57cec5SDimitry Andric result.push_back('w'); 45240b57cec5SDimitry Andric break; 45250b57cec5SDimitry Andric case 7: 45260b57cec5SDimitry Andric result.push_back('%'); 45270b57cec5SDimitry Andric result.push_back('u'); 45280b57cec5SDimitry Andric break; 45290b57cec5SDimitry Andric case 11: 45300b57cec5SDimitry Andric result.push_back('%'); 45310b57cec5SDimitry Andric result.push_back('I'); 45320b57cec5SDimitry Andric break; 45330b57cec5SDimitry Andric case 12: 45340b57cec5SDimitry Andric result.push_back('%'); 45350b57cec5SDimitry Andric result.push_back('m'); 45360b57cec5SDimitry Andric break; 45370b57cec5SDimitry Andric case 23: 45380b57cec5SDimitry Andric result.push_back('%'); 45390b57cec5SDimitry Andric result.push_back('H'); 45400b57cec5SDimitry Andric break; 45410b57cec5SDimitry Andric case 31: 45420b57cec5SDimitry Andric result.push_back('%'); 45430b57cec5SDimitry Andric result.push_back('d'); 45440b57cec5SDimitry Andric break; 45450b57cec5SDimitry Andric case 55: 45460b57cec5SDimitry Andric result.push_back('%'); 45470b57cec5SDimitry Andric result.push_back('M'); 45480b57cec5SDimitry Andric break; 45490b57cec5SDimitry Andric case 59: 45500b57cec5SDimitry Andric result.push_back('%'); 45510b57cec5SDimitry Andric result.push_back('S'); 45520b57cec5SDimitry Andric break; 45530b57cec5SDimitry Andric case 61: 45540b57cec5SDimitry Andric result.push_back('%'); 45550b57cec5SDimitry Andric result.push_back('y'); 45560b57cec5SDimitry Andric break; 45570b57cec5SDimitry Andric case 364: 45580b57cec5SDimitry Andric result.push_back('%'); 45590b57cec5SDimitry Andric result.push_back('j'); 45600b57cec5SDimitry Andric break; 45610b57cec5SDimitry Andric case 2061: 45620b57cec5SDimitry Andric result.push_back('%'); 45630b57cec5SDimitry Andric result.push_back('Y'); 45640b57cec5SDimitry Andric break; 45650b57cec5SDimitry Andric default: 45660b57cec5SDimitry Andric for (; w != bb; ++w) 45670b57cec5SDimitry Andric result.push_back(*w); 45680b57cec5SDimitry Andric break; 45690b57cec5SDimitry Andric } 45700b57cec5SDimitry Andric continue; 45710b57cec5SDimitry Andric } 4572*cb14a3feSDimitry Andric if (*bb == '%') { 45730b57cec5SDimitry Andric result.push_back('%'); 45740b57cec5SDimitry Andric result.push_back('%'); 45750b57cec5SDimitry Andric ++bb; 45760b57cec5SDimitry Andric continue; 45770b57cec5SDimitry Andric } 45780b57cec5SDimitry Andric result.push_back(*bb); 45790b57cec5SDimitry Andric ++bb; 45800b57cec5SDimitry Andric } 45810b57cec5SDimitry Andric return result; 45820b57cec5SDimitry Andric } 45830b57cec5SDimitry Andric 458481ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces") 45850b57cec5SDimitry Andric 4586349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 45870b57cec5SDimitry Andric template <> 4588*cb14a3feSDimitry Andric wstring __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) { 45890b57cec5SDimitry Andric tm t = {0}; 45900b57cec5SDimitry Andric t.tm_sec = 59; 45910b57cec5SDimitry Andric t.tm_min = 55; 45920b57cec5SDimitry Andric t.tm_hour = 23; 45930b57cec5SDimitry Andric t.tm_mday = 31; 45940b57cec5SDimitry Andric t.tm_mon = 11; 45950b57cec5SDimitry Andric t.tm_year = 161; 45960b57cec5SDimitry Andric t.tm_wday = 6; 45970b57cec5SDimitry Andric t.tm_yday = 364; 45980b57cec5SDimitry Andric t.tm_isdst = -1; 45990b57cec5SDimitry Andric char buf[100]; 46000b57cec5SDimitry Andric char f[3] = {0}; 46010b57cec5SDimitry Andric f[0] = '%'; 46020b57cec5SDimitry Andric f[1] = fmt; 46030b57cec5SDimitry Andric strftime_l(buf, countof(buf), f, &t, __loc_); 46040b57cec5SDimitry Andric wchar_t wbuf[100]; 46050b57cec5SDimitry Andric wchar_t* wbb = wbuf; 46060b57cec5SDimitry Andric mbstate_t mb = {0}; 46070b57cec5SDimitry Andric const char* bb = buf; 46080b57cec5SDimitry Andric size_t j = __libcpp_mbsrtowcs_l(wbb, &bb, countof(wbuf), &mb, __loc_); 46090b57cec5SDimitry Andric if (j == size_t(-1)) 46100b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 46110b57cec5SDimitry Andric wchar_t* wbe = wbb + j; 46120b57cec5SDimitry Andric wstring result; 4613*cb14a3feSDimitry Andric while (wbb != wbe) { 4614*cb14a3feSDimitry Andric if (ct.is(ctype_base::space, *wbb)) { 46150b57cec5SDimitry Andric result.push_back(L' '); 46160b57cec5SDimitry Andric for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb) 46170b57cec5SDimitry Andric ; 46180b57cec5SDimitry Andric continue; 46190b57cec5SDimitry Andric } 46200b57cec5SDimitry Andric wchar_t* w = wbb; 46210b57cec5SDimitry Andric ios_base::iostate err = ios_base::goodbit; 4622*cb14a3feSDimitry Andric ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_ + 14, ct, err, false) - this->__weeks_; 4623*cb14a3feSDimitry Andric if (i < 14) { 46240b57cec5SDimitry Andric result.push_back(L'%'); 46250b57cec5SDimitry Andric if (i < 7) 46260b57cec5SDimitry Andric result.push_back(L'A'); 46270b57cec5SDimitry Andric else 46280b57cec5SDimitry Andric result.push_back(L'a'); 46290b57cec5SDimitry Andric wbb = w; 46300b57cec5SDimitry Andric continue; 46310b57cec5SDimitry Andric } 46320b57cec5SDimitry Andric w = wbb; 4633*cb14a3feSDimitry Andric i = __scan_keyword(w, wbe, this->__months_, this->__months_ + 24, ct, err, false) - this->__months_; 4634*cb14a3feSDimitry Andric if (i < 24) { 46350b57cec5SDimitry Andric result.push_back(L'%'); 46360b57cec5SDimitry Andric if (i < 12) 46370b57cec5SDimitry Andric result.push_back(L'B'); 46380b57cec5SDimitry Andric else 46390b57cec5SDimitry Andric result.push_back(L'b'); 46400b57cec5SDimitry Andric if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) 46410b57cec5SDimitry Andric result.back() = L'm'; 46420b57cec5SDimitry Andric wbb = w; 46430b57cec5SDimitry Andric continue; 46440b57cec5SDimitry Andric } 4645*cb14a3feSDimitry Andric if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) { 46460b57cec5SDimitry Andric w = wbb; 4647*cb14a3feSDimitry Andric i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_ + 2, ct, err, false) - this->__am_pm_; 4648*cb14a3feSDimitry Andric if (i < 2) { 46490b57cec5SDimitry Andric result.push_back(L'%'); 46500b57cec5SDimitry Andric result.push_back(L'p'); 46510b57cec5SDimitry Andric wbb = w; 46520b57cec5SDimitry Andric continue; 46530b57cec5SDimitry Andric } 46540b57cec5SDimitry Andric } 46550b57cec5SDimitry Andric w = wbb; 4656*cb14a3feSDimitry Andric if (ct.is(ctype_base::digit, *wbb)) { 4657*cb14a3feSDimitry Andric switch (__get_up_to_n_digits(wbb, wbe, err, ct, 4)) { 46580b57cec5SDimitry Andric case 6: 46590b57cec5SDimitry Andric result.push_back(L'%'); 46600b57cec5SDimitry Andric result.push_back(L'w'); 46610b57cec5SDimitry Andric break; 46620b57cec5SDimitry Andric case 7: 46630b57cec5SDimitry Andric result.push_back(L'%'); 46640b57cec5SDimitry Andric result.push_back(L'u'); 46650b57cec5SDimitry Andric break; 46660b57cec5SDimitry Andric case 11: 46670b57cec5SDimitry Andric result.push_back(L'%'); 46680b57cec5SDimitry Andric result.push_back(L'I'); 46690b57cec5SDimitry Andric break; 46700b57cec5SDimitry Andric case 12: 46710b57cec5SDimitry Andric result.push_back(L'%'); 46720b57cec5SDimitry Andric result.push_back(L'm'); 46730b57cec5SDimitry Andric break; 46740b57cec5SDimitry Andric case 23: 46750b57cec5SDimitry Andric result.push_back(L'%'); 46760b57cec5SDimitry Andric result.push_back(L'H'); 46770b57cec5SDimitry Andric break; 46780b57cec5SDimitry Andric case 31: 46790b57cec5SDimitry Andric result.push_back(L'%'); 46800b57cec5SDimitry Andric result.push_back(L'd'); 46810b57cec5SDimitry Andric break; 46820b57cec5SDimitry Andric case 55: 46830b57cec5SDimitry Andric result.push_back(L'%'); 46840b57cec5SDimitry Andric result.push_back(L'M'); 46850b57cec5SDimitry Andric break; 46860b57cec5SDimitry Andric case 59: 46870b57cec5SDimitry Andric result.push_back(L'%'); 46880b57cec5SDimitry Andric result.push_back(L'S'); 46890b57cec5SDimitry Andric break; 46900b57cec5SDimitry Andric case 61: 46910b57cec5SDimitry Andric result.push_back(L'%'); 46920b57cec5SDimitry Andric result.push_back(L'y'); 46930b57cec5SDimitry Andric break; 46940b57cec5SDimitry Andric case 364: 46950b57cec5SDimitry Andric result.push_back(L'%'); 46960b57cec5SDimitry Andric result.push_back(L'j'); 46970b57cec5SDimitry Andric break; 46980b57cec5SDimitry Andric case 2061: 46990b57cec5SDimitry Andric result.push_back(L'%'); 47000b57cec5SDimitry Andric result.push_back(L'Y'); 47010b57cec5SDimitry Andric break; 47020b57cec5SDimitry Andric default: 47030b57cec5SDimitry Andric for (; w != wbb; ++w) 47040b57cec5SDimitry Andric result.push_back(*w); 47050b57cec5SDimitry Andric break; 47060b57cec5SDimitry Andric } 47070b57cec5SDimitry Andric continue; 47080b57cec5SDimitry Andric } 4709*cb14a3feSDimitry Andric if (ct.narrow(*wbb, 0) == '%') { 47100b57cec5SDimitry Andric result.push_back(L'%'); 47110b57cec5SDimitry Andric result.push_back(L'%'); 47120b57cec5SDimitry Andric ++wbb; 47130b57cec5SDimitry Andric continue; 47140b57cec5SDimitry Andric } 47150b57cec5SDimitry Andric result.push_back(*wbb); 47160b57cec5SDimitry Andric ++wbb; 47170b57cec5SDimitry Andric } 47180b57cec5SDimitry Andric return result; 47190b57cec5SDimitry Andric } 4720349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 47210b57cec5SDimitry Andric 47220b57cec5SDimitry Andric template <> 4723*cb14a3feSDimitry Andric void __time_get_storage<char>::init(const ctype<char>& ct) { 47240b57cec5SDimitry Andric tm t = {0}; 47250b57cec5SDimitry Andric char buf[100]; 47260b57cec5SDimitry Andric // __weeks_ 4727*cb14a3feSDimitry Andric for (int i = 0; i < 7; ++i) { 47280b57cec5SDimitry Andric t.tm_wday = i; 47290b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%A", &t, __loc_); 47300b57cec5SDimitry Andric __weeks_[i] = buf; 47310b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%a", &t, __loc_); 47320b57cec5SDimitry Andric __weeks_[i + 7] = buf; 47330b57cec5SDimitry Andric } 47340b57cec5SDimitry Andric // __months_ 4735*cb14a3feSDimitry Andric for (int i = 0; i < 12; ++i) { 47360b57cec5SDimitry Andric t.tm_mon = i; 47370b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%B", &t, __loc_); 47380b57cec5SDimitry Andric __months_[i] = buf; 47390b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%b", &t, __loc_); 47400b57cec5SDimitry Andric __months_[i + 12] = buf; 47410b57cec5SDimitry Andric } 47420b57cec5SDimitry Andric // __am_pm_ 47430b57cec5SDimitry Andric t.tm_hour = 1; 47440b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%p", &t, __loc_); 47450b57cec5SDimitry Andric __am_pm_[0] = buf; 47460b57cec5SDimitry Andric t.tm_hour = 13; 47470b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%p", &t, __loc_); 47480b57cec5SDimitry Andric __am_pm_[1] = buf; 47490b57cec5SDimitry Andric __c_ = __analyze('c', ct); 47500b57cec5SDimitry Andric __r_ = __analyze('r', ct); 47510b57cec5SDimitry Andric __x_ = __analyze('x', ct); 47520b57cec5SDimitry Andric __X_ = __analyze('X', ct); 47530b57cec5SDimitry Andric } 47540b57cec5SDimitry Andric 4755349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 47560b57cec5SDimitry Andric template <> 4757*cb14a3feSDimitry Andric void __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) { 47580b57cec5SDimitry Andric tm t = {0}; 47590b57cec5SDimitry Andric char buf[100]; 47600b57cec5SDimitry Andric wchar_t wbuf[100]; 47610b57cec5SDimitry Andric wchar_t* wbe; 47620b57cec5SDimitry Andric mbstate_t mb = {0}; 47630b57cec5SDimitry Andric // __weeks_ 4764*cb14a3feSDimitry Andric for (int i = 0; i < 7; ++i) { 47650b57cec5SDimitry Andric t.tm_wday = i; 47660b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%A", &t, __loc_); 47670b57cec5SDimitry Andric mb = mbstate_t(); 47680b57cec5SDimitry Andric const char* bb = buf; 47690b57cec5SDimitry Andric size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 4770e8d8bef9SDimitry Andric if (j == size_t(-1) || j == 0) 47710b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 47720b57cec5SDimitry Andric wbe = wbuf + j; 47730b57cec5SDimitry Andric __weeks_[i].assign(wbuf, wbe); 47740b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%a", &t, __loc_); 47750b57cec5SDimitry Andric mb = mbstate_t(); 47760b57cec5SDimitry Andric bb = buf; 47770b57cec5SDimitry Andric j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 4778e8d8bef9SDimitry Andric if (j == size_t(-1) || j == 0) 47790b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 47800b57cec5SDimitry Andric wbe = wbuf + j; 47810b57cec5SDimitry Andric __weeks_[i + 7].assign(wbuf, wbe); 47820b57cec5SDimitry Andric } 47830b57cec5SDimitry Andric // __months_ 4784*cb14a3feSDimitry Andric for (int i = 0; i < 12; ++i) { 47850b57cec5SDimitry Andric t.tm_mon = i; 47860b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%B", &t, __loc_); 47870b57cec5SDimitry Andric mb = mbstate_t(); 47880b57cec5SDimitry Andric const char* bb = buf; 47890b57cec5SDimitry Andric size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 4790e8d8bef9SDimitry Andric if (j == size_t(-1) || j == 0) 47910b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 47920b57cec5SDimitry Andric wbe = wbuf + j; 47930b57cec5SDimitry Andric __months_[i].assign(wbuf, wbe); 47940b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%b", &t, __loc_); 47950b57cec5SDimitry Andric mb = mbstate_t(); 47960b57cec5SDimitry Andric bb = buf; 47970b57cec5SDimitry Andric j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 4798e8d8bef9SDimitry Andric if (j == size_t(-1) || j == 0) 47990b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 48000b57cec5SDimitry Andric wbe = wbuf + j; 48010b57cec5SDimitry Andric __months_[i + 12].assign(wbuf, wbe); 48020b57cec5SDimitry Andric } 48030b57cec5SDimitry Andric // __am_pm_ 48040b57cec5SDimitry Andric t.tm_hour = 1; 48050b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%p", &t, __loc_); 48060b57cec5SDimitry Andric mb = mbstate_t(); 48070b57cec5SDimitry Andric const char* bb = buf; 48080b57cec5SDimitry Andric size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 48090b57cec5SDimitry Andric if (j == size_t(-1)) 48100b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 48110b57cec5SDimitry Andric wbe = wbuf + j; 48120b57cec5SDimitry Andric __am_pm_[0].assign(wbuf, wbe); 48130b57cec5SDimitry Andric t.tm_hour = 13; 48140b57cec5SDimitry Andric strftime_l(buf, countof(buf), "%p", &t, __loc_); 48150b57cec5SDimitry Andric mb = mbstate_t(); 48160b57cec5SDimitry Andric bb = buf; 48170b57cec5SDimitry Andric j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); 48180b57cec5SDimitry Andric if (j == size_t(-1)) 48190b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 48200b57cec5SDimitry Andric wbe = wbuf + j; 48210b57cec5SDimitry Andric __am_pm_[1].assign(wbuf, wbe); 48220b57cec5SDimitry Andric __c_ = __analyze('c', ct); 48230b57cec5SDimitry Andric __r_ = __analyze('r', ct); 48240b57cec5SDimitry Andric __x_ = __analyze('x', ct); 48250b57cec5SDimitry Andric __X_ = __analyze('X', ct); 48260b57cec5SDimitry Andric } 4827349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 48280b57cec5SDimitry Andric 48290b57cec5SDimitry Andric template <class CharT> 4830*cb14a3feSDimitry Andric struct _LIBCPP_HIDDEN __time_get_temp : public ctype_byname<CharT> { 4831*cb14a3feSDimitry Andric explicit __time_get_temp(const char* nm) : ctype_byname<CharT>(nm, 1) {} 4832*cb14a3feSDimitry Andric explicit __time_get_temp(const string& nm) : ctype_byname<CharT>(nm, 1) {} 48330b57cec5SDimitry Andric }; 48340b57cec5SDimitry Andric 48350b57cec5SDimitry Andric template <> 4836*cb14a3feSDimitry Andric __time_get_storage<char>::__time_get_storage(const char* __nm) : __time_get(__nm) { 48370b57cec5SDimitry Andric const __time_get_temp<char> ct(__nm); 48380b57cec5SDimitry Andric init(ct); 48390b57cec5SDimitry Andric } 48400b57cec5SDimitry Andric 48410b57cec5SDimitry Andric template <> 4842*cb14a3feSDimitry Andric __time_get_storage<char>::__time_get_storage(const string& __nm) : __time_get(__nm) { 48430b57cec5SDimitry Andric const __time_get_temp<char> ct(__nm); 48440b57cec5SDimitry Andric init(ct); 48450b57cec5SDimitry Andric } 48460b57cec5SDimitry Andric 4847349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 48480b57cec5SDimitry Andric template <> 4849*cb14a3feSDimitry Andric __time_get_storage<wchar_t>::__time_get_storage(const char* __nm) : __time_get(__nm) { 48500b57cec5SDimitry Andric const __time_get_temp<wchar_t> ct(__nm); 48510b57cec5SDimitry Andric init(ct); 48520b57cec5SDimitry Andric } 48530b57cec5SDimitry Andric 48540b57cec5SDimitry Andric template <> 4855*cb14a3feSDimitry Andric __time_get_storage<wchar_t>::__time_get_storage(const string& __nm) : __time_get(__nm) { 48560b57cec5SDimitry Andric const __time_get_temp<wchar_t> ct(__nm); 48570b57cec5SDimitry Andric init(ct); 48580b57cec5SDimitry Andric } 4859349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 48600b57cec5SDimitry Andric 48610b57cec5SDimitry Andric template <> 4862*cb14a3feSDimitry Andric time_base::dateorder __time_get_storage<char>::__do_date_order() const { 48630b57cec5SDimitry Andric unsigned i; 48640b57cec5SDimitry Andric for (i = 0; i < __x_.size(); ++i) 48650b57cec5SDimitry Andric if (__x_[i] == '%') 48660b57cec5SDimitry Andric break; 48670b57cec5SDimitry Andric ++i; 4868*cb14a3feSDimitry Andric switch (__x_[i]) { 48690b57cec5SDimitry Andric case 'y': 48700b57cec5SDimitry Andric case 'Y': 48710b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 48720b57cec5SDimitry Andric if (__x_[i] == '%') 48730b57cec5SDimitry Andric break; 48740b57cec5SDimitry Andric if (i == __x_.size()) 48750b57cec5SDimitry Andric break; 48760b57cec5SDimitry Andric ++i; 4877*cb14a3feSDimitry Andric switch (__x_[i]) { 48780b57cec5SDimitry Andric case 'm': 48790b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 48800b57cec5SDimitry Andric if (__x_[i] == '%') 48810b57cec5SDimitry Andric break; 48820b57cec5SDimitry Andric if (i == __x_.size()) 48830b57cec5SDimitry Andric break; 48840b57cec5SDimitry Andric ++i; 48850b57cec5SDimitry Andric if (__x_[i] == 'd') 48860b57cec5SDimitry Andric return time_base::ymd; 48870b57cec5SDimitry Andric break; 48880b57cec5SDimitry Andric case 'd': 48890b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 48900b57cec5SDimitry Andric if (__x_[i] == '%') 48910b57cec5SDimitry Andric break; 48920b57cec5SDimitry Andric if (i == __x_.size()) 48930b57cec5SDimitry Andric break; 48940b57cec5SDimitry Andric ++i; 48950b57cec5SDimitry Andric if (__x_[i] == 'm') 48960b57cec5SDimitry Andric return time_base::ydm; 48970b57cec5SDimitry Andric break; 48980b57cec5SDimitry Andric } 48990b57cec5SDimitry Andric break; 49000b57cec5SDimitry Andric case 'm': 49010b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49020b57cec5SDimitry Andric if (__x_[i] == '%') 49030b57cec5SDimitry Andric break; 49040b57cec5SDimitry Andric if (i == __x_.size()) 49050b57cec5SDimitry Andric break; 49060b57cec5SDimitry Andric ++i; 4907*cb14a3feSDimitry Andric if (__x_[i] == 'd') { 49080b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49090b57cec5SDimitry Andric if (__x_[i] == '%') 49100b57cec5SDimitry Andric break; 49110b57cec5SDimitry Andric if (i == __x_.size()) 49120b57cec5SDimitry Andric break; 49130b57cec5SDimitry Andric ++i; 49140b57cec5SDimitry Andric if (__x_[i] == 'y' || __x_[i] == 'Y') 49150b57cec5SDimitry Andric return time_base::mdy; 49160b57cec5SDimitry Andric break; 49170b57cec5SDimitry Andric } 49180b57cec5SDimitry Andric break; 49190b57cec5SDimitry Andric case 'd': 49200b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49210b57cec5SDimitry Andric if (__x_[i] == '%') 49220b57cec5SDimitry Andric break; 49230b57cec5SDimitry Andric if (i == __x_.size()) 49240b57cec5SDimitry Andric break; 49250b57cec5SDimitry Andric ++i; 4926*cb14a3feSDimitry Andric if (__x_[i] == 'm') { 49270b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49280b57cec5SDimitry Andric if (__x_[i] == '%') 49290b57cec5SDimitry Andric break; 49300b57cec5SDimitry Andric if (i == __x_.size()) 49310b57cec5SDimitry Andric break; 49320b57cec5SDimitry Andric ++i; 49330b57cec5SDimitry Andric if (__x_[i] == 'y' || __x_[i] == 'Y') 49340b57cec5SDimitry Andric return time_base::dmy; 49350b57cec5SDimitry Andric break; 49360b57cec5SDimitry Andric } 49370b57cec5SDimitry Andric break; 49380b57cec5SDimitry Andric } 49390b57cec5SDimitry Andric return time_base::no_order; 49400b57cec5SDimitry Andric } 49410b57cec5SDimitry Andric 4942349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 49430b57cec5SDimitry Andric template <> 4944*cb14a3feSDimitry Andric time_base::dateorder __time_get_storage<wchar_t>::__do_date_order() const { 49450b57cec5SDimitry Andric unsigned i; 49460b57cec5SDimitry Andric for (i = 0; i < __x_.size(); ++i) 49470b57cec5SDimitry Andric if (__x_[i] == L'%') 49480b57cec5SDimitry Andric break; 49490b57cec5SDimitry Andric ++i; 4950*cb14a3feSDimitry Andric switch (__x_[i]) { 49510b57cec5SDimitry Andric case L'y': 49520b57cec5SDimitry Andric case L'Y': 49530b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49540b57cec5SDimitry Andric if (__x_[i] == L'%') 49550b57cec5SDimitry Andric break; 49560b57cec5SDimitry Andric if (i == __x_.size()) 49570b57cec5SDimitry Andric break; 49580b57cec5SDimitry Andric ++i; 4959*cb14a3feSDimitry Andric switch (__x_[i]) { 49600b57cec5SDimitry Andric case L'm': 49610b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49620b57cec5SDimitry Andric if (__x_[i] == L'%') 49630b57cec5SDimitry Andric break; 49640b57cec5SDimitry Andric if (i == __x_.size()) 49650b57cec5SDimitry Andric break; 49660b57cec5SDimitry Andric ++i; 49670b57cec5SDimitry Andric if (__x_[i] == L'd') 49680b57cec5SDimitry Andric return time_base::ymd; 49690b57cec5SDimitry Andric break; 49700b57cec5SDimitry Andric case L'd': 49710b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49720b57cec5SDimitry Andric if (__x_[i] == L'%') 49730b57cec5SDimitry Andric break; 49740b57cec5SDimitry Andric if (i == __x_.size()) 49750b57cec5SDimitry Andric break; 49760b57cec5SDimitry Andric ++i; 49770b57cec5SDimitry Andric if (__x_[i] == L'm') 49780b57cec5SDimitry Andric return time_base::ydm; 49790b57cec5SDimitry Andric break; 49800b57cec5SDimitry Andric } 49810b57cec5SDimitry Andric break; 49820b57cec5SDimitry Andric case L'm': 49830b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49840b57cec5SDimitry Andric if (__x_[i] == L'%') 49850b57cec5SDimitry Andric break; 49860b57cec5SDimitry Andric if (i == __x_.size()) 49870b57cec5SDimitry Andric break; 49880b57cec5SDimitry Andric ++i; 4989*cb14a3feSDimitry Andric if (__x_[i] == L'd') { 49900b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 49910b57cec5SDimitry Andric if (__x_[i] == L'%') 49920b57cec5SDimitry Andric break; 49930b57cec5SDimitry Andric if (i == __x_.size()) 49940b57cec5SDimitry Andric break; 49950b57cec5SDimitry Andric ++i; 49960b57cec5SDimitry Andric if (__x_[i] == L'y' || __x_[i] == L'Y') 49970b57cec5SDimitry Andric return time_base::mdy; 49980b57cec5SDimitry Andric break; 49990b57cec5SDimitry Andric } 50000b57cec5SDimitry Andric break; 50010b57cec5SDimitry Andric case L'd': 50020b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 50030b57cec5SDimitry Andric if (__x_[i] == L'%') 50040b57cec5SDimitry Andric break; 50050b57cec5SDimitry Andric if (i == __x_.size()) 50060b57cec5SDimitry Andric break; 50070b57cec5SDimitry Andric ++i; 5008*cb14a3feSDimitry Andric if (__x_[i] == L'm') { 50090b57cec5SDimitry Andric for (++i; i < __x_.size(); ++i) 50100b57cec5SDimitry Andric if (__x_[i] == L'%') 50110b57cec5SDimitry Andric break; 50120b57cec5SDimitry Andric if (i == __x_.size()) 50130b57cec5SDimitry Andric break; 50140b57cec5SDimitry Andric ++i; 50150b57cec5SDimitry Andric if (__x_[i] == L'y' || __x_[i] == L'Y') 50160b57cec5SDimitry Andric return time_base::dmy; 50170b57cec5SDimitry Andric break; 50180b57cec5SDimitry Andric } 50190b57cec5SDimitry Andric break; 50200b57cec5SDimitry Andric } 50210b57cec5SDimitry Andric return time_base::no_order; 50220b57cec5SDimitry Andric } 5023349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 50240b57cec5SDimitry Andric 50250b57cec5SDimitry Andric // time_put 50260b57cec5SDimitry Andric 5027*cb14a3feSDimitry Andric __time_put::__time_put(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) { 50280b57cec5SDimitry Andric if (__loc_ == 0) 50295f757f3fSDimitry Andric __throw_runtime_error(("time_put_byname failed to construct for " + string(nm)).c_str()); 50300b57cec5SDimitry Andric } 50310b57cec5SDimitry Andric 5032*cb14a3feSDimitry Andric __time_put::__time_put(const string& nm) : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) { 50330b57cec5SDimitry Andric if (__loc_ == 0) 50345f757f3fSDimitry Andric __throw_runtime_error(("time_put_byname failed to construct for " + nm).c_str()); 50350b57cec5SDimitry Andric } 50360b57cec5SDimitry Andric 5037*cb14a3feSDimitry Andric __time_put::~__time_put() { 50380b57cec5SDimitry Andric if (__loc_ != _LIBCPP_GET_C_LOCALE) 50390b57cec5SDimitry Andric freelocale(__loc_); 50400b57cec5SDimitry Andric } 50410b57cec5SDimitry Andric 5042*cb14a3feSDimitry Andric void __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const { 50430b57cec5SDimitry Andric char fmt[] = {'%', __fmt, __mod, 0}; 50440b57cec5SDimitry Andric if (__mod != 0) 50450b57cec5SDimitry Andric swap(fmt[1], fmt[2]); 50460b57cec5SDimitry Andric size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_); 50470b57cec5SDimitry Andric __ne = __nb + n; 50480b57cec5SDimitry Andric } 50490b57cec5SDimitry Andric 5050349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 5051*cb14a3feSDimitry Andric void __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const { 50520b57cec5SDimitry Andric char __nar[100]; 50530b57cec5SDimitry Andric char* __ne = __nar + 100; 50540b57cec5SDimitry Andric __do_put(__nar, __ne, __tm, __fmt, __mod); 50550b57cec5SDimitry Andric mbstate_t mb = {0}; 50560b57cec5SDimitry Andric const char* __nb = __nar; 50570b57cec5SDimitry Andric size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); 50580b57cec5SDimitry Andric if (j == size_t(-1)) 50590b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 50600b57cec5SDimitry Andric __we = __wb + j; 50610b57cec5SDimitry Andric } 5062349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 50630b57cec5SDimitry Andric 50640b57cec5SDimitry Andric // moneypunct_byname 50650b57cec5SDimitry Andric 50660b57cec5SDimitry Andric template <class charT> 5067*cb14a3feSDimitry Andric static void __init_pat( 5068*cb14a3feSDimitry Andric money_base::pattern& pat, 5069*cb14a3feSDimitry Andric basic_string<charT>& __curr_symbol_, 5070*cb14a3feSDimitry Andric bool intl, 5071*cb14a3feSDimitry Andric char cs_precedes, 5072*cb14a3feSDimitry Andric char sep_by_space, 5073*cb14a3feSDimitry Andric char sign_posn, 5074*cb14a3feSDimitry Andric charT space_char) { 50750b57cec5SDimitry Andric const char sign = static_cast<char>(money_base::sign); 50760b57cec5SDimitry Andric const char space = static_cast<char>(money_base::space); 50770b57cec5SDimitry Andric const char none = static_cast<char>(money_base::none); 50780b57cec5SDimitry Andric const char symbol = static_cast<char>(money_base::symbol); 50790b57cec5SDimitry Andric const char value = static_cast<char>(money_base::value); 50800b57cec5SDimitry Andric const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4; 50810b57cec5SDimitry Andric 50820b57cec5SDimitry Andric // Comments on case branches reflect 'C11 7.11.2.1 The localeconv 50830b57cec5SDimitry Andric // function'. "Space between sign and symbol or value" means that 50840b57cec5SDimitry Andric // if the sign is adjacent to the symbol, there's a space between 50850b57cec5SDimitry Andric // them, and otherwise there's a space between the sign and value. 50860b57cec5SDimitry Andric // 50870b57cec5SDimitry Andric // C11's localeconv specifies that the fourth character of an 50880b57cec5SDimitry Andric // international curr_symbol is used to separate the sign and 50890b57cec5SDimitry Andric // value when sep_by_space says to do so. C++ can't represent 50900b57cec5SDimitry Andric // that, so we just use a space. When sep_by_space says to 50910b57cec5SDimitry Andric // separate the symbol and value-or-sign with a space, we rearrange the 50920b57cec5SDimitry Andric // curr_symbol to put its spacing character on the correct side of 50930b57cec5SDimitry Andric // the symbol. 50940b57cec5SDimitry Andric // 50950b57cec5SDimitry Andric // We also need to avoid adding an extra space between the sign 50960b57cec5SDimitry Andric // and value when the currency symbol is suppressed (by not 50970b57cec5SDimitry Andric // setting showbase). We match glibc's strfmon by interpreting 50980b57cec5SDimitry Andric // sep_by_space==1 as "omit the space when the currency symbol is 50990b57cec5SDimitry Andric // absent". 51000b57cec5SDimitry Andric // 51010b57cec5SDimitry Andric // Users who want to get this right should use ICU instead. 51020b57cec5SDimitry Andric 5103*cb14a3feSDimitry Andric switch (cs_precedes) { 51040b57cec5SDimitry Andric case 0: // value before curr_symbol 51050b57cec5SDimitry Andric if (symbol_contains_sep) { 51060b57cec5SDimitry Andric // Move the separator to before the symbol, to place it 51070b57cec5SDimitry Andric // between the value and symbol. 5108*cb14a3feSDimitry Andric rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3, __curr_symbol_.end()); 51090b57cec5SDimitry Andric } 5110*cb14a3feSDimitry Andric switch (sign_posn) { 51110b57cec5SDimitry Andric case 0: // Parentheses surround the quantity and currency symbol. 51120b57cec5SDimitry Andric pat.field[0] = sign; 51130b57cec5SDimitry Andric pat.field[1] = value; 51140b57cec5SDimitry Andric pat.field[2] = none; // Any space appears in the symbol. 51150b57cec5SDimitry Andric pat.field[3] = symbol; 5116*cb14a3feSDimitry Andric switch (sep_by_space) { 51170b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 51180b57cec5SDimitry Andric // This case may have changed between C99 and C11; 51190b57cec5SDimitry Andric // assume the currency symbol matches the intention. 51200b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 51210b57cec5SDimitry Andric // The "sign" is two parentheses, so no space here either. 51220b57cec5SDimitry Andric return; 51230b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 51240b57cec5SDimitry Andric if (!symbol_contains_sep) { 51250b57cec5SDimitry Andric // We insert the space into the symbol instead of 51260b57cec5SDimitry Andric // setting pat.field[2]=space so that when 51270b57cec5SDimitry Andric // showbase is not set, the space goes away too. 51280b57cec5SDimitry Andric __curr_symbol_.insert(0, 1, space_char); 51290b57cec5SDimitry Andric } 51300b57cec5SDimitry Andric return; 51310b57cec5SDimitry Andric default: 51320b57cec5SDimitry Andric break; 51330b57cec5SDimitry Andric } 51340b57cec5SDimitry Andric break; 51350b57cec5SDimitry Andric case 1: // The sign string precedes the quantity and currency symbol. 51360b57cec5SDimitry Andric pat.field[0] = sign; 51370b57cec5SDimitry Andric pat.field[3] = symbol; 5138*cb14a3feSDimitry Andric switch (sep_by_space) { 51390b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 51400b57cec5SDimitry Andric pat.field[1] = value; 51410b57cec5SDimitry Andric pat.field[2] = none; 51420b57cec5SDimitry Andric return; 51430b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 51440b57cec5SDimitry Andric pat.field[1] = value; 51450b57cec5SDimitry Andric pat.field[2] = none; 51460b57cec5SDimitry Andric if (!symbol_contains_sep) { 51470b57cec5SDimitry Andric // We insert the space into the symbol instead of 51480b57cec5SDimitry Andric // setting pat.field[2]=space so that when 51490b57cec5SDimitry Andric // showbase is not set, the space goes away too. 51500b57cec5SDimitry Andric __curr_symbol_.insert(0, 1, space_char); 51510b57cec5SDimitry Andric } 51520b57cec5SDimitry Andric return; 51530b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 51540b57cec5SDimitry Andric pat.field[1] = space; 51550b57cec5SDimitry Andric pat.field[2] = value; 51560b57cec5SDimitry Andric if (symbol_contains_sep) { 51570b57cec5SDimitry Andric // Remove the separator from the symbol, since it 51580b57cec5SDimitry Andric // has already appeared after the sign. 51590b57cec5SDimitry Andric __curr_symbol_.erase(__curr_symbol_.begin()); 51600b57cec5SDimitry Andric } 51610b57cec5SDimitry Andric return; 51620b57cec5SDimitry Andric default: 51630b57cec5SDimitry Andric break; 51640b57cec5SDimitry Andric } 51650b57cec5SDimitry Andric break; 51660b57cec5SDimitry Andric case 2: // The sign string succeeds the quantity and currency symbol. 51670b57cec5SDimitry Andric pat.field[0] = value; 51680b57cec5SDimitry Andric pat.field[3] = sign; 5169*cb14a3feSDimitry Andric switch (sep_by_space) { 51700b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 51710b57cec5SDimitry Andric pat.field[1] = none; 51720b57cec5SDimitry Andric pat.field[2] = symbol; 51730b57cec5SDimitry Andric return; 51740b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 51750b57cec5SDimitry Andric if (!symbol_contains_sep) { 51760b57cec5SDimitry Andric // We insert the space into the symbol instead of 51770b57cec5SDimitry Andric // setting pat.field[1]=space so that when 51780b57cec5SDimitry Andric // showbase is not set, the space goes away too. 51790b57cec5SDimitry Andric __curr_symbol_.insert(0, 1, space_char); 51800b57cec5SDimitry Andric } 51810b57cec5SDimitry Andric pat.field[1] = none; 51820b57cec5SDimitry Andric pat.field[2] = symbol; 51830b57cec5SDimitry Andric return; 51840b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 51850b57cec5SDimitry Andric pat.field[1] = symbol; 51860b57cec5SDimitry Andric pat.field[2] = space; 51870b57cec5SDimitry Andric if (symbol_contains_sep) { 51880b57cec5SDimitry Andric // Remove the separator from the symbol, since it 51890b57cec5SDimitry Andric // should not be removed if showbase is absent. 51900b57cec5SDimitry Andric __curr_symbol_.erase(__curr_symbol_.begin()); 51910b57cec5SDimitry Andric } 51920b57cec5SDimitry Andric return; 51930b57cec5SDimitry Andric default: 51940b57cec5SDimitry Andric break; 51950b57cec5SDimitry Andric } 51960b57cec5SDimitry Andric break; 51970b57cec5SDimitry Andric case 3: // The sign string immediately precedes the currency symbol. 51980b57cec5SDimitry Andric pat.field[0] = value; 51990b57cec5SDimitry Andric pat.field[3] = symbol; 5200*cb14a3feSDimitry Andric switch (sep_by_space) { 52010b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 52020b57cec5SDimitry Andric pat.field[1] = none; 52030b57cec5SDimitry Andric pat.field[2] = sign; 52040b57cec5SDimitry Andric return; 52050b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 52060b57cec5SDimitry Andric pat.field[1] = space; 52070b57cec5SDimitry Andric pat.field[2] = sign; 52080b57cec5SDimitry Andric if (symbol_contains_sep) { 52090b57cec5SDimitry Andric // Remove the separator from the symbol, since it 52100b57cec5SDimitry Andric // has already appeared before the sign. 52110b57cec5SDimitry Andric __curr_symbol_.erase(__curr_symbol_.begin()); 52120b57cec5SDimitry Andric } 52130b57cec5SDimitry Andric return; 52140b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 52150b57cec5SDimitry Andric pat.field[1] = sign; 52160b57cec5SDimitry Andric pat.field[2] = none; 52170b57cec5SDimitry Andric if (!symbol_contains_sep) { 52180b57cec5SDimitry Andric // We insert the space into the symbol instead of 52190b57cec5SDimitry Andric // setting pat.field[2]=space so that when 52200b57cec5SDimitry Andric // showbase is not set, the space goes away too. 52210b57cec5SDimitry Andric __curr_symbol_.insert(0, 1, space_char); 52220b57cec5SDimitry Andric } 52230b57cec5SDimitry Andric return; 52240b57cec5SDimitry Andric default: 52250b57cec5SDimitry Andric break; 52260b57cec5SDimitry Andric } 52270b57cec5SDimitry Andric break; 52280b57cec5SDimitry Andric case 4: // The sign string immediately succeeds the currency symbol. 52290b57cec5SDimitry Andric pat.field[0] = value; 52300b57cec5SDimitry Andric pat.field[3] = sign; 5231*cb14a3feSDimitry Andric switch (sep_by_space) { 52320b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 52330b57cec5SDimitry Andric pat.field[1] = none; 52340b57cec5SDimitry Andric pat.field[2] = symbol; 52350b57cec5SDimitry Andric return; 52360b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 52370b57cec5SDimitry Andric pat.field[1] = none; 52380b57cec5SDimitry Andric pat.field[2] = symbol; 52390b57cec5SDimitry Andric if (!symbol_contains_sep) { 52400b57cec5SDimitry Andric // We insert the space into the symbol instead of 52410b57cec5SDimitry Andric // setting pat.field[1]=space so that when 52420b57cec5SDimitry Andric // showbase is not set, the space goes away too. 52430b57cec5SDimitry Andric __curr_symbol_.insert(0, 1, space_char); 52440b57cec5SDimitry Andric } 52450b57cec5SDimitry Andric return; 52460b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 52470b57cec5SDimitry Andric pat.field[1] = symbol; 52480b57cec5SDimitry Andric pat.field[2] = space; 52490b57cec5SDimitry Andric if (symbol_contains_sep) { 52500b57cec5SDimitry Andric // Remove the separator from the symbol, since it 52510b57cec5SDimitry Andric // should not disappear when showbase is absent. 52520b57cec5SDimitry Andric __curr_symbol_.erase(__curr_symbol_.begin()); 52530b57cec5SDimitry Andric } 52540b57cec5SDimitry Andric return; 52550b57cec5SDimitry Andric default: 52560b57cec5SDimitry Andric break; 52570b57cec5SDimitry Andric } 52580b57cec5SDimitry Andric break; 52590b57cec5SDimitry Andric default: 52600b57cec5SDimitry Andric break; 52610b57cec5SDimitry Andric } 52620b57cec5SDimitry Andric break; 52630b57cec5SDimitry Andric case 1: // curr_symbol before value 5264*cb14a3feSDimitry Andric switch (sign_posn) { 52650b57cec5SDimitry Andric case 0: // Parentheses surround the quantity and currency symbol. 52660b57cec5SDimitry Andric pat.field[0] = sign; 52670b57cec5SDimitry Andric pat.field[1] = symbol; 52680b57cec5SDimitry Andric pat.field[2] = none; // Any space appears in the symbol. 52690b57cec5SDimitry Andric pat.field[3] = value; 5270*cb14a3feSDimitry Andric switch (sep_by_space) { 52710b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 52720b57cec5SDimitry Andric // This case may have changed between C99 and C11; 52730b57cec5SDimitry Andric // assume the currency symbol matches the intention. 52740b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 52750b57cec5SDimitry Andric // The "sign" is two parentheses, so no space here either. 52760b57cec5SDimitry Andric return; 52770b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 52780b57cec5SDimitry Andric if (!symbol_contains_sep) { 52790b57cec5SDimitry Andric // We insert the space into the symbol instead of 52800b57cec5SDimitry Andric // setting pat.field[2]=space so that when 52810b57cec5SDimitry Andric // showbase is not set, the space goes away too. 52820b57cec5SDimitry Andric __curr_symbol_.insert(0, 1, space_char); 52830b57cec5SDimitry Andric } 52840b57cec5SDimitry Andric return; 52850b57cec5SDimitry Andric default: 52860b57cec5SDimitry Andric break; 52870b57cec5SDimitry Andric } 52880b57cec5SDimitry Andric break; 52890b57cec5SDimitry Andric case 1: // The sign string precedes the quantity and currency symbol. 52900b57cec5SDimitry Andric pat.field[0] = sign; 52910b57cec5SDimitry Andric pat.field[3] = value; 5292*cb14a3feSDimitry Andric switch (sep_by_space) { 52930b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 52940b57cec5SDimitry Andric pat.field[1] = symbol; 52950b57cec5SDimitry Andric pat.field[2] = none; 52960b57cec5SDimitry Andric return; 52970b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 52980b57cec5SDimitry Andric pat.field[1] = symbol; 52990b57cec5SDimitry Andric pat.field[2] = none; 53000b57cec5SDimitry Andric if (!symbol_contains_sep) { 53010b57cec5SDimitry Andric // We insert the space into the symbol instead of 53020b57cec5SDimitry Andric // setting pat.field[2]=space so that when 53030b57cec5SDimitry Andric // showbase is not set, the space goes away too. 53040b57cec5SDimitry Andric __curr_symbol_.push_back(space_char); 53050b57cec5SDimitry Andric } 53060b57cec5SDimitry Andric return; 53070b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 53080b57cec5SDimitry Andric pat.field[1] = space; 53090b57cec5SDimitry Andric pat.field[2] = symbol; 53100b57cec5SDimitry Andric if (symbol_contains_sep) { 53110b57cec5SDimitry Andric // Remove the separator from the symbol, since it 53120b57cec5SDimitry Andric // has already appeared after the sign. 53130b57cec5SDimitry Andric __curr_symbol_.pop_back(); 53140b57cec5SDimitry Andric } 53150b57cec5SDimitry Andric return; 53160b57cec5SDimitry Andric default: 53170b57cec5SDimitry Andric break; 53180b57cec5SDimitry Andric } 53190b57cec5SDimitry Andric break; 53200b57cec5SDimitry Andric case 2: // The sign string succeeds the quantity and currency symbol. 53210b57cec5SDimitry Andric pat.field[0] = symbol; 53220b57cec5SDimitry Andric pat.field[3] = sign; 5323*cb14a3feSDimitry Andric switch (sep_by_space) { 53240b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 53250b57cec5SDimitry Andric pat.field[1] = none; 53260b57cec5SDimitry Andric pat.field[2] = value; 53270b57cec5SDimitry Andric return; 53280b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 53290b57cec5SDimitry Andric pat.field[1] = none; 53300b57cec5SDimitry Andric pat.field[2] = value; 53310b57cec5SDimitry Andric if (!symbol_contains_sep) { 53320b57cec5SDimitry Andric // We insert the space into the symbol instead of 53330b57cec5SDimitry Andric // setting pat.field[1]=space so that when 53340b57cec5SDimitry Andric // showbase is not set, the space goes away too. 53350b57cec5SDimitry Andric __curr_symbol_.push_back(space_char); 53360b57cec5SDimitry Andric } 53370b57cec5SDimitry Andric return; 53380b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 53390b57cec5SDimitry Andric pat.field[1] = value; 53400b57cec5SDimitry Andric pat.field[2] = space; 53410b57cec5SDimitry Andric if (symbol_contains_sep) { 53420b57cec5SDimitry Andric // Remove the separator from the symbol, since it 53430b57cec5SDimitry Andric // will appear before the sign. 53440b57cec5SDimitry Andric __curr_symbol_.pop_back(); 53450b57cec5SDimitry Andric } 53460b57cec5SDimitry Andric return; 53470b57cec5SDimitry Andric default: 53480b57cec5SDimitry Andric break; 53490b57cec5SDimitry Andric } 53500b57cec5SDimitry Andric break; 53510b57cec5SDimitry Andric case 3: // The sign string immediately precedes the currency symbol. 53520b57cec5SDimitry Andric pat.field[0] = sign; 53530b57cec5SDimitry Andric pat.field[3] = value; 5354*cb14a3feSDimitry Andric switch (sep_by_space) { 53550b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 53560b57cec5SDimitry Andric pat.field[1] = symbol; 53570b57cec5SDimitry Andric pat.field[2] = none; 53580b57cec5SDimitry Andric return; 53590b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 53600b57cec5SDimitry Andric pat.field[1] = symbol; 53610b57cec5SDimitry Andric pat.field[2] = none; 53620b57cec5SDimitry Andric if (!symbol_contains_sep) { 53630b57cec5SDimitry Andric // We insert the space into the symbol instead of 53640b57cec5SDimitry Andric // setting pat.field[2]=space so that when 53650b57cec5SDimitry Andric // showbase is not set, the space goes away too. 53660b57cec5SDimitry Andric __curr_symbol_.push_back(space_char); 53670b57cec5SDimitry Andric } 53680b57cec5SDimitry Andric return; 53690b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 53700b57cec5SDimitry Andric pat.field[1] = space; 53710b57cec5SDimitry Andric pat.field[2] = symbol; 53720b57cec5SDimitry Andric if (symbol_contains_sep) { 53730b57cec5SDimitry Andric // Remove the separator from the symbol, since it 53740b57cec5SDimitry Andric // has already appeared after the sign. 53750b57cec5SDimitry Andric __curr_symbol_.pop_back(); 53760b57cec5SDimitry Andric } 53770b57cec5SDimitry Andric return; 53780b57cec5SDimitry Andric default: 53790b57cec5SDimitry Andric break; 53800b57cec5SDimitry Andric } 53810b57cec5SDimitry Andric break; 53820b57cec5SDimitry Andric case 4: // The sign string immediately succeeds the currency symbol. 53830b57cec5SDimitry Andric pat.field[0] = symbol; 53840b57cec5SDimitry Andric pat.field[3] = value; 5385*cb14a3feSDimitry Andric switch (sep_by_space) { 53860b57cec5SDimitry Andric case 0: // No space separates the currency symbol and value. 53870b57cec5SDimitry Andric pat.field[1] = sign; 53880b57cec5SDimitry Andric pat.field[2] = none; 53890b57cec5SDimitry Andric return; 53900b57cec5SDimitry Andric case 1: // Space between currency-and-sign or currency and value. 53910b57cec5SDimitry Andric pat.field[1] = sign; 53920b57cec5SDimitry Andric pat.field[2] = space; 53930b57cec5SDimitry Andric if (symbol_contains_sep) { 53940b57cec5SDimitry Andric // Remove the separator from the symbol, since it 53950b57cec5SDimitry Andric // should not disappear when showbase is absent. 53960b57cec5SDimitry Andric __curr_symbol_.pop_back(); 53970b57cec5SDimitry Andric } 53980b57cec5SDimitry Andric return; 53990b57cec5SDimitry Andric case 2: // Space between sign and currency or value. 54000b57cec5SDimitry Andric pat.field[1] = none; 54010b57cec5SDimitry Andric pat.field[2] = sign; 54020b57cec5SDimitry Andric if (!symbol_contains_sep) { 54030b57cec5SDimitry Andric // We insert the space into the symbol instead of 54040b57cec5SDimitry Andric // setting pat.field[1]=space so that when 54050b57cec5SDimitry Andric // showbase is not set, the space goes away too. 54060b57cec5SDimitry Andric __curr_symbol_.push_back(space_char); 54070b57cec5SDimitry Andric } 54080b57cec5SDimitry Andric return; 54090b57cec5SDimitry Andric default: 54100b57cec5SDimitry Andric break; 54110b57cec5SDimitry Andric } 54120b57cec5SDimitry Andric break; 54130b57cec5SDimitry Andric default: 54140b57cec5SDimitry Andric break; 54150b57cec5SDimitry Andric } 54160b57cec5SDimitry Andric break; 54170b57cec5SDimitry Andric default: 54180b57cec5SDimitry Andric break; 54190b57cec5SDimitry Andric } 54200b57cec5SDimitry Andric pat.field[0] = symbol; 54210b57cec5SDimitry Andric pat.field[1] = sign; 54220b57cec5SDimitry Andric pat.field[2] = none; 54230b57cec5SDimitry Andric pat.field[3] = value; 54240b57cec5SDimitry Andric } 54250b57cec5SDimitry Andric 54260b57cec5SDimitry Andric template <> 5427*cb14a3feSDimitry Andric void moneypunct_byname<char, false>::init(const char* nm) { 54280b57cec5SDimitry Andric typedef moneypunct<char, false> base; 54290b57cec5SDimitry Andric __libcpp_unique_locale loc(nm); 54300b57cec5SDimitry Andric if (!loc) 54315f757f3fSDimitry Andric __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str()); 54320b57cec5SDimitry Andric 54330b57cec5SDimitry Andric lconv* lc = __libcpp_localeconv_l(loc.get()); 5434*cb14a3feSDimitry Andric if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get())) 54350b57cec5SDimitry Andric __decimal_point_ = base::do_decimal_point(); 5436*cb14a3feSDimitry Andric if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get())) 54370b57cec5SDimitry Andric __thousands_sep_ = base::do_thousands_sep(); 54380b57cec5SDimitry Andric 54390b57cec5SDimitry Andric __grouping_ = lc->mon_grouping; 54400b57cec5SDimitry Andric __curr_symbol_ = lc->currency_symbol; 54410b57cec5SDimitry Andric if (lc->frac_digits != CHAR_MAX) 54420b57cec5SDimitry Andric __frac_digits_ = lc->frac_digits; 54430b57cec5SDimitry Andric else 54440b57cec5SDimitry Andric __frac_digits_ = base::do_frac_digits(); 54450b57cec5SDimitry Andric if (lc->p_sign_posn == 0) 54460b57cec5SDimitry Andric __positive_sign_ = "()"; 54470b57cec5SDimitry Andric else 54480b57cec5SDimitry Andric __positive_sign_ = lc->positive_sign; 54490b57cec5SDimitry Andric if (lc->n_sign_posn == 0) 54500b57cec5SDimitry Andric __negative_sign_ = "()"; 54510b57cec5SDimitry Andric else 54520b57cec5SDimitry Andric __negative_sign_ = lc->negative_sign; 54530b57cec5SDimitry Andric // Assume the positive and negative formats will want spaces in 54540b57cec5SDimitry Andric // the same places in curr_symbol since there's no way to 54550b57cec5SDimitry Andric // represent anything else. 54560b57cec5SDimitry Andric string_type __dummy_curr_symbol = __curr_symbol_; 5457*cb14a3feSDimitry Andric __init_pat(__pos_format_, __dummy_curr_symbol, false, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); 5458*cb14a3feSDimitry Andric __init_pat(__neg_format_, __curr_symbol_, false, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); 54590b57cec5SDimitry Andric } 54600b57cec5SDimitry Andric 54610b57cec5SDimitry Andric template <> 5462*cb14a3feSDimitry Andric void moneypunct_byname<char, true>::init(const char* nm) { 54630b57cec5SDimitry Andric typedef moneypunct<char, true> base; 54640b57cec5SDimitry Andric __libcpp_unique_locale loc(nm); 54650b57cec5SDimitry Andric if (!loc) 54665f757f3fSDimitry Andric __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str()); 54670b57cec5SDimitry Andric 54680b57cec5SDimitry Andric lconv* lc = __libcpp_localeconv_l(loc.get()); 5469*cb14a3feSDimitry Andric if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get())) 54700b57cec5SDimitry Andric __decimal_point_ = base::do_decimal_point(); 5471*cb14a3feSDimitry Andric if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get())) 54720b57cec5SDimitry Andric __thousands_sep_ = base::do_thousands_sep(); 54730b57cec5SDimitry Andric __grouping_ = lc->mon_grouping; 54740b57cec5SDimitry Andric __curr_symbol_ = lc->int_curr_symbol; 54750b57cec5SDimitry Andric if (lc->int_frac_digits != CHAR_MAX) 54760b57cec5SDimitry Andric __frac_digits_ = lc->int_frac_digits; 54770b57cec5SDimitry Andric else 54780b57cec5SDimitry Andric __frac_digits_ = base::do_frac_digits(); 54790b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 54800b57cec5SDimitry Andric if (lc->p_sign_posn == 0) 54810b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT 54820b57cec5SDimitry Andric if (lc->int_p_sign_posn == 0) 54830b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT 54840b57cec5SDimitry Andric __positive_sign_ = "()"; 54850b57cec5SDimitry Andric else 54860b57cec5SDimitry Andric __positive_sign_ = lc->positive_sign; 54870b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 54880b57cec5SDimitry Andric if (lc->n_sign_posn == 0) 54890b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT 54900b57cec5SDimitry Andric if (lc->int_n_sign_posn == 0) 54910b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT 54920b57cec5SDimitry Andric __negative_sign_ = "()"; 54930b57cec5SDimitry Andric else 54940b57cec5SDimitry Andric __negative_sign_ = lc->negative_sign; 54950b57cec5SDimitry Andric // Assume the positive and negative formats will want spaces in 54960b57cec5SDimitry Andric // the same places in curr_symbol since there's no way to 54970b57cec5SDimitry Andric // represent anything else. 54980b57cec5SDimitry Andric string_type __dummy_curr_symbol = __curr_symbol_; 54990b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 5500*cb14a3feSDimitry Andric __init_pat(__pos_format_, __dummy_curr_symbol, true, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); 5501*cb14a3feSDimitry Andric __init_pat(__neg_format_, __curr_symbol_, true, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); 55020b57cec5SDimitry Andric #else // _LIBCPP_MSVCRT 5503*cb14a3feSDimitry Andric __init_pat( 5504*cb14a3feSDimitry Andric __pos_format_, 5505*cb14a3feSDimitry Andric __dummy_curr_symbol, 5506*cb14a3feSDimitry Andric true, 5507*cb14a3feSDimitry Andric lc->int_p_cs_precedes, 5508*cb14a3feSDimitry Andric lc->int_p_sep_by_space, 5509*cb14a3feSDimitry Andric lc->int_p_sign_posn, 5510*cb14a3feSDimitry Andric ' '); 5511*cb14a3feSDimitry Andric __init_pat( 5512*cb14a3feSDimitry Andric __neg_format_, __curr_symbol_, true, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn, ' '); 55130b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT 55140b57cec5SDimitry Andric } 55150b57cec5SDimitry Andric 5516349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 55170b57cec5SDimitry Andric template <> 5518*cb14a3feSDimitry Andric void moneypunct_byname<wchar_t, false>::init(const char* nm) { 55190b57cec5SDimitry Andric typedef moneypunct<wchar_t, false> base; 55200b57cec5SDimitry Andric __libcpp_unique_locale loc(nm); 55210b57cec5SDimitry Andric if (!loc) 55225f757f3fSDimitry Andric __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str()); 55230b57cec5SDimitry Andric lconv* lc = __libcpp_localeconv_l(loc.get()); 5524*cb14a3feSDimitry Andric if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get())) 55250b57cec5SDimitry Andric __decimal_point_ = base::do_decimal_point(); 5526*cb14a3feSDimitry Andric if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get())) 55270b57cec5SDimitry Andric __thousands_sep_ = base::do_thousands_sep(); 55280b57cec5SDimitry Andric __grouping_ = lc->mon_grouping; 55290b57cec5SDimitry Andric wchar_t wbuf[100]; 55300b57cec5SDimitry Andric mbstate_t mb = {0}; 55310b57cec5SDimitry Andric const char* bb = lc->currency_symbol; 55320b57cec5SDimitry Andric size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 55330b57cec5SDimitry Andric if (j == size_t(-1)) 55340b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 55350b57cec5SDimitry Andric wchar_t* wbe = wbuf + j; 55360b57cec5SDimitry Andric __curr_symbol_.assign(wbuf, wbe); 55370b57cec5SDimitry Andric if (lc->frac_digits != CHAR_MAX) 55380b57cec5SDimitry Andric __frac_digits_ = lc->frac_digits; 55390b57cec5SDimitry Andric else 55400b57cec5SDimitry Andric __frac_digits_ = base::do_frac_digits(); 55410b57cec5SDimitry Andric if (lc->p_sign_posn == 0) 55420b57cec5SDimitry Andric __positive_sign_ = L"()"; 5543*cb14a3feSDimitry Andric else { 55440b57cec5SDimitry Andric mb = mbstate_t(); 55450b57cec5SDimitry Andric bb = lc->positive_sign; 55460b57cec5SDimitry Andric j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 55470b57cec5SDimitry Andric if (j == size_t(-1)) 55480b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 55490b57cec5SDimitry Andric wbe = wbuf + j; 55500b57cec5SDimitry Andric __positive_sign_.assign(wbuf, wbe); 55510b57cec5SDimitry Andric } 55520b57cec5SDimitry Andric if (lc->n_sign_posn == 0) 55530b57cec5SDimitry Andric __negative_sign_ = L"()"; 5554*cb14a3feSDimitry Andric else { 55550b57cec5SDimitry Andric mb = mbstate_t(); 55560b57cec5SDimitry Andric bb = lc->negative_sign; 55570b57cec5SDimitry Andric j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 55580b57cec5SDimitry Andric if (j == size_t(-1)) 55590b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 55600b57cec5SDimitry Andric wbe = wbuf + j; 55610b57cec5SDimitry Andric __negative_sign_.assign(wbuf, wbe); 55620b57cec5SDimitry Andric } 55630b57cec5SDimitry Andric // Assume the positive and negative formats will want spaces in 55640b57cec5SDimitry Andric // the same places in curr_symbol since there's no way to 55650b57cec5SDimitry Andric // represent anything else. 55660b57cec5SDimitry Andric string_type __dummy_curr_symbol = __curr_symbol_; 5567*cb14a3feSDimitry Andric __init_pat(__pos_format_, __dummy_curr_symbol, false, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); 5568*cb14a3feSDimitry Andric __init_pat(__neg_format_, __curr_symbol_, false, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); 55690b57cec5SDimitry Andric } 55700b57cec5SDimitry Andric 55710b57cec5SDimitry Andric template <> 5572*cb14a3feSDimitry Andric void moneypunct_byname<wchar_t, true>::init(const char* nm) { 55730b57cec5SDimitry Andric typedef moneypunct<wchar_t, true> base; 55740b57cec5SDimitry Andric __libcpp_unique_locale loc(nm); 55750b57cec5SDimitry Andric if (!loc) 55765f757f3fSDimitry Andric __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str()); 55770b57cec5SDimitry Andric 55780b57cec5SDimitry Andric lconv* lc = __libcpp_localeconv_l(loc.get()); 5579*cb14a3feSDimitry Andric if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get())) 55800b57cec5SDimitry Andric __decimal_point_ = base::do_decimal_point(); 5581*cb14a3feSDimitry Andric if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get())) 55820b57cec5SDimitry Andric __thousands_sep_ = base::do_thousands_sep(); 55830b57cec5SDimitry Andric __grouping_ = lc->mon_grouping; 55840b57cec5SDimitry Andric wchar_t wbuf[100]; 55850b57cec5SDimitry Andric mbstate_t mb = {0}; 55860b57cec5SDimitry Andric const char* bb = lc->int_curr_symbol; 55870b57cec5SDimitry Andric size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 55880b57cec5SDimitry Andric if (j == size_t(-1)) 55890b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 55900b57cec5SDimitry Andric wchar_t* wbe = wbuf + j; 55910b57cec5SDimitry Andric __curr_symbol_.assign(wbuf, wbe); 55920b57cec5SDimitry Andric if (lc->int_frac_digits != CHAR_MAX) 55930b57cec5SDimitry Andric __frac_digits_ = lc->int_frac_digits; 55940b57cec5SDimitry Andric else 55950b57cec5SDimitry Andric __frac_digits_ = base::do_frac_digits(); 55960b57cec5SDimitry Andric # if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 55970b57cec5SDimitry Andric if (lc->p_sign_posn == 0) 55980b57cec5SDimitry Andric # else // _LIBCPP_MSVCRT 55990b57cec5SDimitry Andric if (lc->int_p_sign_posn == 0) 56000b57cec5SDimitry Andric # endif // !_LIBCPP_MSVCRT 56010b57cec5SDimitry Andric __positive_sign_ = L"()"; 5602*cb14a3feSDimitry Andric else { 56030b57cec5SDimitry Andric mb = mbstate_t(); 56040b57cec5SDimitry Andric bb = lc->positive_sign; 56050b57cec5SDimitry Andric j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 56060b57cec5SDimitry Andric if (j == size_t(-1)) 56070b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 56080b57cec5SDimitry Andric wbe = wbuf + j; 56090b57cec5SDimitry Andric __positive_sign_.assign(wbuf, wbe); 56100b57cec5SDimitry Andric } 56110b57cec5SDimitry Andric # if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 56120b57cec5SDimitry Andric if (lc->n_sign_posn == 0) 56130b57cec5SDimitry Andric # else // _LIBCPP_MSVCRT 56140b57cec5SDimitry Andric if (lc->int_n_sign_posn == 0) 56150b57cec5SDimitry Andric # endif // !_LIBCPP_MSVCRT 56160b57cec5SDimitry Andric __negative_sign_ = L"()"; 5617*cb14a3feSDimitry Andric else { 56180b57cec5SDimitry Andric mb = mbstate_t(); 56190b57cec5SDimitry Andric bb = lc->negative_sign; 56200b57cec5SDimitry Andric j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); 56210b57cec5SDimitry Andric if (j == size_t(-1)) 56220b57cec5SDimitry Andric __throw_runtime_error("locale not supported"); 56230b57cec5SDimitry Andric wbe = wbuf + j; 56240b57cec5SDimitry Andric __negative_sign_.assign(wbuf, wbe); 56250b57cec5SDimitry Andric } 56260b57cec5SDimitry Andric // Assume the positive and negative formats will want spaces in 56270b57cec5SDimitry Andric // the same places in curr_symbol since there's no way to 56280b57cec5SDimitry Andric // represent anything else. 56290b57cec5SDimitry Andric string_type __dummy_curr_symbol = __curr_symbol_; 56300b57cec5SDimitry Andric # if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) 5631*cb14a3feSDimitry Andric __init_pat(__pos_format_, __dummy_curr_symbol, true, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); 5632*cb14a3feSDimitry Andric __init_pat(__neg_format_, __curr_symbol_, true, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); 56330b57cec5SDimitry Andric # else // _LIBCPP_MSVCRT 5634*cb14a3feSDimitry Andric __init_pat( 5635*cb14a3feSDimitry Andric __pos_format_, 5636*cb14a3feSDimitry Andric __dummy_curr_symbol, 5637*cb14a3feSDimitry Andric true, 5638*cb14a3feSDimitry Andric lc->int_p_cs_precedes, 5639*cb14a3feSDimitry Andric lc->int_p_sep_by_space, 5640*cb14a3feSDimitry Andric lc->int_p_sign_posn, 5641*cb14a3feSDimitry Andric L' '); 5642*cb14a3feSDimitry Andric __init_pat( 5643*cb14a3feSDimitry Andric __neg_format_, __curr_symbol_, true, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn, L' '); 56440b57cec5SDimitry Andric # endif // !_LIBCPP_MSVCRT 56450b57cec5SDimitry Andric } 5646349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 56470b57cec5SDimitry Andric 56480b57cec5SDimitry Andric void __do_nothing(void*) {} 56490b57cec5SDimitry Andric 56500b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>; 5651349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;) 56520b57cec5SDimitry Andric 56530b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>; 5654349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;) 56550b57cec5SDimitry Andric 56560b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>; 5657349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;) 56580b57cec5SDimitry Andric 56590b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>; 5660349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;) 56610b57cec5SDimitry Andric 56620b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>; 5663349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;) 56640b57cec5SDimitry Andric 56650b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>; 5666349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;) 56670b57cec5SDimitry Andric 56680b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>; 5669349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;) 56700b57cec5SDimitry Andric 56710b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>; 5672349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;) 56730b57cec5SDimitry Andric 56740b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>; 5675349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;) 56760b57cec5SDimitry Andric 56770b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>; 56780b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>; 5679349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;) 5680349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;) 56810b57cec5SDimitry Andric 56820b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>; 56830b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>; 5684349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;) 5685349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;) 56860b57cec5SDimitry Andric 56870b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>; 5688349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;) 56890b57cec5SDimitry Andric 56900b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>; 5691349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;) 56920b57cec5SDimitry Andric 56930b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>; 5694349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;) 56950b57cec5SDimitry Andric 56960b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>; 5697349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;) 56980b57cec5SDimitry Andric 56990b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>; 5700349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;) 57010b57cec5SDimitry Andric 57020b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>; 5703349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;) 57040b57cec5SDimitry Andric 57050b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>; 5706*cb14a3feSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS( 5707*cb14a3feSDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;) 5708*cb14a3feSDimitry Andric template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS 5709*cb14a3feSDimitry Andric codecvt_byname<char16_t, char, mbstate_t>; 5710*cb14a3feSDimitry Andric template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS 5711*cb14a3feSDimitry Andric codecvt_byname<char32_t, char, mbstate_t>; 5712fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 5713e8d8bef9SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>; 5714e8d8bef9SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>; 5715e8d8bef9SDimitry Andric #endif 57160b57cec5SDimitry Andric 57170b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 571881ad6265SDimitry Andric 571981ad6265SDimitry Andric _LIBCPP_POP_MACROS 5720