xref: /freebsd/contrib/llvm-project/libcxx/src/locale.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
37*0fca6ea1SDimitry Andric #if !defined(_LIBCPP_MSVCRT) && !defined(__MINGW32__) && !defined(__BIONIC__) && !defined(__NuttX__)
380b57cec5SDimitry Andric #  include <langinfo.h>
390b57cec5SDimitry Andric #endif
40349cc55cSDimitry Andric 
410b57cec5SDimitry Andric #include "include/atomic_support.h"
42fe6060f1SDimitry Andric #include "include/sso_allocator.h"
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric // On Linux, wint_t and wchar_t have different signed-ness, and this causes
450b57cec5SDimitry Andric // lots of noise in the build log, but no bugs that I know of.
4681ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion")
4781ad6265SDimitry Andric 
4881ad6265SDimitry Andric _LIBCPP_PUSH_MACROS
4981ad6265SDimitry Andric #include <__undef_macros>
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric struct __libcpp_unique_locale {
__libcpp_unique_locale__libcpp_unique_locale540b57cec5SDimitry Andric   __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
550b57cec5SDimitry Andric 
~__libcpp_unique_locale__libcpp_unique_locale560b57cec5SDimitry Andric   ~__libcpp_unique_locale() {
570b57cec5SDimitry Andric     if (__loc_)
580b57cec5SDimitry Andric       freelocale(__loc_);
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric 
operator bool__libcpp_unique_locale610b57cec5SDimitry Andric   explicit operator bool() const { return __loc_; }
620b57cec5SDimitry Andric 
get__libcpp_unique_locale630b57cec5SDimitry Andric   locale_t& get() { return __loc_; }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   locale_t __loc_;
66cb14a3feSDimitry Andric 
670b57cec5SDimitry Andric private:
680b57cec5SDimitry Andric   __libcpp_unique_locale(__libcpp_unique_locale const&);
690b57cec5SDimitry Andric   __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
700b57cec5SDimitry Andric };
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric #ifdef __cloc_defined
__cloc()730b57cec5SDimitry Andric locale_t __cloc() {
740b57cec5SDimitry Andric   // In theory this could create a race condition. In practice
750b57cec5SDimitry Andric   // the race condition is non-fatal since it will just create
760b57cec5SDimitry Andric   // a little resource leak. Better approach would be appreciated.
770b57cec5SDimitry Andric   static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
780b57cec5SDimitry Andric   return result;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric #endif // __cloc_defined
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric namespace {
830b57cec5SDimitry Andric 
845f757f3fSDimitry Andric struct releaser {
operator ()__anonba3b9cc00111::releaser850b57cec5SDimitry Andric   void operator()(locale::facet* p) { p->__release_shared(); }
860b57cec5SDimitry Andric };
870b57cec5SDimitry Andric 
88349cc55cSDimitry Andric template <class T, class... Args>
make(Args...args)89cb14a3feSDimitry Andric T& make(Args... args) {
905f757f3fSDimitry Andric   alignas(T) static std::byte buf[sizeof(T)];
91349cc55cSDimitry Andric   auto* obj = ::new (&buf) T(args...);
920b57cec5SDimitry Andric   return *obj;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric template <typename T, size_t N>
countof(const T (&)[N])96cb14a3feSDimitry Andric inline constexpr size_t countof(const T (&)[N]) {
970b57cec5SDimitry Andric   return N;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric template <typename T>
countof(const T * const begin,const T * const end)101cb14a3feSDimitry Andric inline constexpr size_t countof(const T* const begin, const T* const end) {
1020b57cec5SDimitry Andric   return static_cast<size_t>(end - begin);
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
build_name(const string & other,const string & one,locale::category c)105cb14a3feSDimitry Andric string build_name(const string& other, const string& one, locale::category c) {
10606c3fb27SDimitry Andric   if (other == "*" || one == "*")
10706c3fb27SDimitry Andric     return "*";
10806c3fb27SDimitry Andric   if (c == locale::none || other == one)
10906c3fb27SDimitry Andric     return other;
11006c3fb27SDimitry Andric 
11106c3fb27SDimitry Andric   // FIXME: Handle the more complicated cases, such as when the locale has
11206c3fb27SDimitry Andric   // different names for different categories.
11306c3fb27SDimitry Andric   return "*";
11406c3fb27SDimitry Andric }
11506c3fb27SDimitry Andric 
116*0fca6ea1SDimitry Andric } // namespace
117*0fca6ea1SDimitry Andric 
1180b57cec5SDimitry Andric const locale::category locale::none;
1190b57cec5SDimitry Andric const locale::category locale::collate;
1200b57cec5SDimitry Andric const locale::category locale::ctype;
1210b57cec5SDimitry Andric const locale::category locale::monetary;
1220b57cec5SDimitry Andric const locale::category locale::numeric;
1230b57cec5SDimitry Andric const locale::category locale::time;
1240b57cec5SDimitry Andric const locale::category locale::messages;
1250b57cec5SDimitry Andric const locale::category locale::all;
1260b57cec5SDimitry Andric 
127cb14a3feSDimitry Andric class _LIBCPP_HIDDEN locale::__imp : public facet {
128e8d8bef9SDimitry Andric   enum { N = 30 };
1290b57cec5SDimitry Andric   vector<facet*, __sso_allocator<facet*, N> > facets_;
1300b57cec5SDimitry Andric   string name_;
131cb14a3feSDimitry Andric 
1320b57cec5SDimitry Andric public:
1330b57cec5SDimitry Andric   explicit __imp(size_t refs = 0);
1340b57cec5SDimitry Andric   explicit __imp(const string& name, size_t refs = 0);
1350b57cec5SDimitry Andric   __imp(const __imp&);
1360b57cec5SDimitry Andric   __imp(const __imp&, const string&, locale::category c);
1370b57cec5SDimitry Andric   __imp(const __imp& other, const __imp& one, locale::category c);
1380b57cec5SDimitry Andric   __imp(const __imp&, facet* f, long id);
1390b57cec5SDimitry Andric   ~__imp();
1400b57cec5SDimitry Andric 
name() const1410b57cec5SDimitry Andric   const string& name() const { return name_; }
has_facet(long id) const142cb14a3feSDimitry Andric   bool has_facet(long id) const { return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)]; }
1430b57cec5SDimitry Andric   const locale::facet* use_facet(long id) const;
1440b57cec5SDimitry Andric 
1455f757f3fSDimitry Andric   void acquire();
1465f757f3fSDimitry Andric   void release();
1475f757f3fSDimitry Andric   static __no_destroy<__imp> classic_locale_imp_;
1485f757f3fSDimitry Andric 
1490b57cec5SDimitry Andric private:
1500b57cec5SDimitry Andric   void install(facet* f, long id);
151cb14a3feSDimitry Andric   template <class F>
install(F * f)152cb14a3feSDimitry Andric   void install(F* f) {
153cb14a3feSDimitry Andric     install(f, f->id.__get());
154cb14a3feSDimitry Andric   }
155cb14a3feSDimitry Andric   template <class F>
156cb14a3feSDimitry Andric   void install_from(const __imp& other);
1570b57cec5SDimitry Andric };
1580b57cec5SDimitry Andric 
__imp(size_t refs)159cb14a3feSDimitry Andric locale::__imp::__imp(size_t refs) : facet(refs), facets_(N), name_("C") {
1600b57cec5SDimitry Andric   facets_.clear();
1615f757f3fSDimitry Andric   install(&make<std::collate<char> >(1u));
162349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1635f757f3fSDimitry Andric   install(&make<std::collate<wchar_t> >(1u));
164349cc55cSDimitry Andric #endif
1655f757f3fSDimitry Andric   install(&make<std::ctype<char> >(nullptr, false, 1u));
166349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1675f757f3fSDimitry Andric   install(&make<std::ctype<wchar_t> >(1u));
168349cc55cSDimitry Andric #endif
1690b57cec5SDimitry Andric   install(&make<codecvt<char, char, mbstate_t> >(1u));
170349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1710b57cec5SDimitry Andric   install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
172349cc55cSDimitry Andric #endif
173e8d8bef9SDimitry Andric   _LIBCPP_SUPPRESS_DEPRECATED_PUSH
1740b57cec5SDimitry Andric   install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
1750b57cec5SDimitry Andric   install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
176e8d8bef9SDimitry Andric   _LIBCPP_SUPPRESS_DEPRECATED_POP
177fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
178e8d8bef9SDimitry Andric   install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
179e8d8bef9SDimitry Andric   install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
180e8d8bef9SDimitry Andric #endif
1810b57cec5SDimitry Andric   install(&make<numpunct<char> >(1u));
182349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1830b57cec5SDimitry Andric   install(&make<numpunct<wchar_t> >(1u));
184349cc55cSDimitry Andric #endif
1850b57cec5SDimitry Andric   install(&make<num_get<char> >(1u));
186349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1870b57cec5SDimitry Andric   install(&make<num_get<wchar_t> >(1u));
188349cc55cSDimitry Andric #endif
1890b57cec5SDimitry Andric   install(&make<num_put<char> >(1u));
190349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1910b57cec5SDimitry Andric   install(&make<num_put<wchar_t> >(1u));
192349cc55cSDimitry Andric #endif
1930b57cec5SDimitry Andric   install(&make<moneypunct<char, false> >(1u));
1940b57cec5SDimitry Andric   install(&make<moneypunct<char, true> >(1u));
195349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1960b57cec5SDimitry Andric   install(&make<moneypunct<wchar_t, false> >(1u));
1970b57cec5SDimitry Andric   install(&make<moneypunct<wchar_t, true> >(1u));
198349cc55cSDimitry Andric #endif
1990b57cec5SDimitry Andric   install(&make<money_get<char> >(1u));
200349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2010b57cec5SDimitry Andric   install(&make<money_get<wchar_t> >(1u));
202349cc55cSDimitry Andric #endif
2030b57cec5SDimitry Andric   install(&make<money_put<char> >(1u));
204349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2050b57cec5SDimitry Andric   install(&make<money_put<wchar_t> >(1u));
206349cc55cSDimitry Andric #endif
2070b57cec5SDimitry Andric   install(&make<time_get<char> >(1u));
208349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2090b57cec5SDimitry Andric   install(&make<time_get<wchar_t> >(1u));
210349cc55cSDimitry Andric #endif
2110b57cec5SDimitry Andric   install(&make<time_put<char> >(1u));
212349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2130b57cec5SDimitry Andric   install(&make<time_put<wchar_t> >(1u));
214349cc55cSDimitry Andric #endif
2155f757f3fSDimitry Andric   install(&make<std::messages<char> >(1u));
216349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2175f757f3fSDimitry Andric   install(&make<std::messages<wchar_t> >(1u));
218349cc55cSDimitry Andric #endif
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
__imp(const string & name,size_t refs)221cb14a3feSDimitry Andric locale::__imp::__imp(const string& name, size_t refs) : facet(refs), facets_(N), name_(name) {
22206c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
223cb14a3feSDimitry Andric   try {
22406c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS
2250b57cec5SDimitry Andric     facets_ = locale::classic().__locale_->facets_;
2260b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
2270b57cec5SDimitry Andric       if (facets_[i])
2280b57cec5SDimitry Andric         facets_[i]->__add_shared();
2290b57cec5SDimitry Andric     install(new collate_byname<char>(name_));
230349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2310b57cec5SDimitry Andric     install(new collate_byname<wchar_t>(name_));
232349cc55cSDimitry Andric #endif
2330b57cec5SDimitry Andric     install(new ctype_byname<char>(name_));
234349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2350b57cec5SDimitry Andric     install(new ctype_byname<wchar_t>(name_));
236349cc55cSDimitry Andric #endif
2370b57cec5SDimitry Andric     install(new codecvt_byname<char, char, mbstate_t>(name_));
238349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2390b57cec5SDimitry Andric     install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
240349cc55cSDimitry Andric #endif
241e8d8bef9SDimitry Andric     _LIBCPP_SUPPRESS_DEPRECATED_PUSH
2420b57cec5SDimitry Andric     install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
2430b57cec5SDimitry Andric     install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
244e8d8bef9SDimitry Andric     _LIBCPP_SUPPRESS_DEPRECATED_POP
245fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
246e8d8bef9SDimitry Andric     install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
247e8d8bef9SDimitry Andric     install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
248e8d8bef9SDimitry Andric #endif
2490b57cec5SDimitry Andric     install(new numpunct_byname<char>(name_));
250349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2510b57cec5SDimitry Andric     install(new numpunct_byname<wchar_t>(name_));
252349cc55cSDimitry Andric #endif
2530b57cec5SDimitry Andric     install(new moneypunct_byname<char, false>(name_));
2540b57cec5SDimitry Andric     install(new moneypunct_byname<char, true>(name_));
255349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2560b57cec5SDimitry Andric     install(new moneypunct_byname<wchar_t, false>(name_));
2570b57cec5SDimitry Andric     install(new moneypunct_byname<wchar_t, true>(name_));
258349cc55cSDimitry Andric #endif
2590b57cec5SDimitry Andric     install(new time_get_byname<char>(name_));
260349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2610b57cec5SDimitry Andric     install(new time_get_byname<wchar_t>(name_));
262349cc55cSDimitry Andric #endif
2630b57cec5SDimitry Andric     install(new time_put_byname<char>(name_));
264349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2650b57cec5SDimitry Andric     install(new time_put_byname<wchar_t>(name_));
266349cc55cSDimitry Andric #endif
2670b57cec5SDimitry Andric     install(new messages_byname<char>(name_));
268349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2690b57cec5SDimitry Andric     install(new messages_byname<wchar_t>(name_));
270349cc55cSDimitry Andric #endif
27106c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
272cb14a3feSDimitry Andric   } catch (...) {
2730b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
2740b57cec5SDimitry Andric       if (facets_[i])
2750b57cec5SDimitry Andric         facets_[i]->__release_shared();
2760b57cec5SDimitry Andric     throw;
2770b57cec5SDimitry Andric   }
27806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
__imp(const __imp & other)281cb14a3feSDimitry Andric locale::__imp::__imp(const __imp& other) : facets_(max<size_t>(N, other.facets_.size())), name_(other.name_) {
2820b57cec5SDimitry Andric   facets_ = other.facets_;
2830b57cec5SDimitry Andric   for (unsigned i = 0; i < facets_.size(); ++i)
2840b57cec5SDimitry Andric     if (facets_[i])
2850b57cec5SDimitry Andric       facets_[i]->__add_shared();
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
__imp(const __imp & other,const string & name,locale::category c)2880b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
289cb14a3feSDimitry Andric     : facets_(N), name_(build_name(other.name_, name, c)) {
2900b57cec5SDimitry Andric   facets_ = other.facets_;
2910b57cec5SDimitry Andric   for (unsigned i = 0; i < facets_.size(); ++i)
2920b57cec5SDimitry Andric     if (facets_[i])
2930b57cec5SDimitry Andric       facets_[i]->__add_shared();
29406c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
295cb14a3feSDimitry Andric   try {
29606c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS
297cb14a3feSDimitry Andric     if (c & locale::collate) {
2980b57cec5SDimitry Andric       install(new collate_byname<char>(name));
299349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3000b57cec5SDimitry Andric       install(new collate_byname<wchar_t>(name));
301349cc55cSDimitry Andric #endif
3020b57cec5SDimitry Andric     }
303cb14a3feSDimitry Andric     if (c & locale::ctype) {
3040b57cec5SDimitry Andric       install(new ctype_byname<char>(name));
305349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3060b57cec5SDimitry Andric       install(new ctype_byname<wchar_t>(name));
307349cc55cSDimitry Andric #endif
3080b57cec5SDimitry Andric       install(new codecvt_byname<char, char, mbstate_t>(name));
309349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3100b57cec5SDimitry Andric       install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
311349cc55cSDimitry Andric #endif
312e8d8bef9SDimitry Andric       _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3130b57cec5SDimitry Andric       install(new codecvt_byname<char16_t, char, mbstate_t>(name));
3140b57cec5SDimitry Andric       install(new codecvt_byname<char32_t, char, mbstate_t>(name));
315e8d8bef9SDimitry Andric       _LIBCPP_SUPPRESS_DEPRECATED_POP
316fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
317e8d8bef9SDimitry Andric       install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
318e8d8bef9SDimitry Andric       install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
319e8d8bef9SDimitry Andric #endif
3200b57cec5SDimitry Andric     }
321cb14a3feSDimitry Andric     if (c & locale::monetary) {
3220b57cec5SDimitry Andric       install(new moneypunct_byname<char, false>(name));
3230b57cec5SDimitry Andric       install(new moneypunct_byname<char, true>(name));
324349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3250b57cec5SDimitry Andric       install(new moneypunct_byname<wchar_t, false>(name));
3260b57cec5SDimitry Andric       install(new moneypunct_byname<wchar_t, true>(name));
327349cc55cSDimitry Andric #endif
3280b57cec5SDimitry Andric     }
329cb14a3feSDimitry Andric     if (c & locale::numeric) {
3300b57cec5SDimitry Andric       install(new numpunct_byname<char>(name));
331349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3320b57cec5SDimitry Andric       install(new numpunct_byname<wchar_t>(name));
333349cc55cSDimitry Andric #endif
3340b57cec5SDimitry Andric     }
335cb14a3feSDimitry Andric     if (c & locale::time) {
3360b57cec5SDimitry Andric       install(new time_get_byname<char>(name));
337349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3380b57cec5SDimitry Andric       install(new time_get_byname<wchar_t>(name));
339349cc55cSDimitry Andric #endif
3400b57cec5SDimitry Andric       install(new time_put_byname<char>(name));
341349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3420b57cec5SDimitry Andric       install(new time_put_byname<wchar_t>(name));
343349cc55cSDimitry Andric #endif
3440b57cec5SDimitry Andric     }
345cb14a3feSDimitry Andric     if (c & locale::messages) {
3460b57cec5SDimitry Andric       install(new messages_byname<char>(name));
347349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3480b57cec5SDimitry Andric       install(new messages_byname<wchar_t>(name));
349349cc55cSDimitry Andric #endif
3500b57cec5SDimitry Andric     }
35106c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
352cb14a3feSDimitry Andric   } catch (...) {
3530b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
3540b57cec5SDimitry Andric       if (facets_[i])
3550b57cec5SDimitry Andric         facets_[i]->__release_shared();
3560b57cec5SDimitry Andric     throw;
3570b57cec5SDimitry Andric   }
35806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric template <class F>
install_from(const locale::__imp & one)362cb14a3feSDimitry Andric inline void locale::__imp::install_from(const locale::__imp& one) {
3630b57cec5SDimitry Andric   long id = F::id.__get();
3640b57cec5SDimitry Andric   install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric 
__imp(const __imp & other,const __imp & one,locale::category c)3670b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
368cb14a3feSDimitry Andric     : facets_(N), name_(build_name(other.name_, one.name_, c)) {
3690b57cec5SDimitry Andric   facets_ = other.facets_;
3700b57cec5SDimitry Andric   for (unsigned i = 0; i < facets_.size(); ++i)
3710b57cec5SDimitry Andric     if (facets_[i])
3720b57cec5SDimitry Andric       facets_[i]->__add_shared();
37306c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
374cb14a3feSDimitry Andric   try {
37506c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS
376cb14a3feSDimitry Andric     if (c & locale::collate) {
3775f757f3fSDimitry Andric       install_from<std::collate<char> >(one);
378349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3795f757f3fSDimitry Andric       install_from<std::collate<wchar_t> >(one);
380349cc55cSDimitry Andric #endif
3810b57cec5SDimitry Andric     }
382cb14a3feSDimitry Andric     if (c & locale::ctype) {
3835f757f3fSDimitry Andric       install_from<std::ctype<char> >(one);
384349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3855f757f3fSDimitry Andric       install_from<std::ctype<wchar_t> >(one);
386349cc55cSDimitry Andric #endif
3875f757f3fSDimitry Andric       install_from<std::codecvt<char, char, mbstate_t> >(one);
388e8d8bef9SDimitry Andric       _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3895f757f3fSDimitry Andric       install_from<std::codecvt<char16_t, char, mbstate_t> >(one);
3905f757f3fSDimitry Andric       install_from<std::codecvt<char32_t, char, mbstate_t> >(one);
391e8d8bef9SDimitry Andric       _LIBCPP_SUPPRESS_DEPRECATED_POP
392fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
3935f757f3fSDimitry Andric       install_from<std::codecvt<char16_t, char8_t, mbstate_t> >(one);
3945f757f3fSDimitry Andric       install_from<std::codecvt<char32_t, char8_t, mbstate_t> >(one);
395e8d8bef9SDimitry Andric #endif
396349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3975f757f3fSDimitry Andric       install_from<std::codecvt<wchar_t, char, mbstate_t> >(one);
398349cc55cSDimitry Andric #endif
3990b57cec5SDimitry Andric     }
400cb14a3feSDimitry Andric     if (c & locale::monetary) {
4010b57cec5SDimitry Andric       install_from<moneypunct<char, false> >(one);
4020b57cec5SDimitry Andric       install_from<moneypunct<char, true> >(one);
403349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4040b57cec5SDimitry Andric       install_from<moneypunct<wchar_t, false> >(one);
4050b57cec5SDimitry Andric       install_from<moneypunct<wchar_t, true> >(one);
406349cc55cSDimitry Andric #endif
4070b57cec5SDimitry Andric       install_from<money_get<char> >(one);
408349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4090b57cec5SDimitry Andric       install_from<money_get<wchar_t> >(one);
410349cc55cSDimitry Andric #endif
4110b57cec5SDimitry Andric       install_from<money_put<char> >(one);
412349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4130b57cec5SDimitry Andric       install_from<money_put<wchar_t> >(one);
414349cc55cSDimitry Andric #endif
4150b57cec5SDimitry Andric     }
416cb14a3feSDimitry Andric     if (c & locale::numeric) {
4170b57cec5SDimitry Andric       install_from<numpunct<char> >(one);
418349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4190b57cec5SDimitry Andric       install_from<numpunct<wchar_t> >(one);
420349cc55cSDimitry Andric #endif
4210b57cec5SDimitry Andric       install_from<num_get<char> >(one);
422349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4230b57cec5SDimitry Andric       install_from<num_get<wchar_t> >(one);
424349cc55cSDimitry Andric #endif
4250b57cec5SDimitry Andric       install_from<num_put<char> >(one);
426349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4270b57cec5SDimitry Andric       install_from<num_put<wchar_t> >(one);
428349cc55cSDimitry Andric #endif
4290b57cec5SDimitry Andric     }
430cb14a3feSDimitry Andric     if (c & locale::time) {
4310b57cec5SDimitry Andric       install_from<time_get<char> >(one);
432349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4330b57cec5SDimitry Andric       install_from<time_get<wchar_t> >(one);
434349cc55cSDimitry Andric #endif
4350b57cec5SDimitry Andric       install_from<time_put<char> >(one);
436349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4370b57cec5SDimitry Andric       install_from<time_put<wchar_t> >(one);
438349cc55cSDimitry Andric #endif
4390b57cec5SDimitry Andric     }
440cb14a3feSDimitry Andric     if (c & locale::messages) {
4415f757f3fSDimitry Andric       install_from<std::messages<char> >(one);
442349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4435f757f3fSDimitry Andric       install_from<std::messages<wchar_t> >(one);
444349cc55cSDimitry Andric #endif
4450b57cec5SDimitry Andric     }
44606c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
447cb14a3feSDimitry Andric   } catch (...) {
4480b57cec5SDimitry Andric     for (unsigned i = 0; i < facets_.size(); ++i)
4490b57cec5SDimitry Andric       if (facets_[i])
4500b57cec5SDimitry Andric         facets_[i]->__release_shared();
4510b57cec5SDimitry Andric     throw;
4520b57cec5SDimitry Andric   }
45306c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
__imp(const __imp & other,facet * f,long id)4560b57cec5SDimitry Andric locale::__imp::__imp(const __imp& other, facet* f, long id)
457cb14a3feSDimitry Andric     : facets_(max<size_t>(N, other.facets_.size() + 1)), name_("*") {
4580b57cec5SDimitry Andric   f->__add_shared();
4595f757f3fSDimitry Andric   unique_ptr<facet, releaser> hold(f);
4600b57cec5SDimitry Andric   facets_ = other.facets_;
4610b57cec5SDimitry Andric   for (unsigned i = 0; i < other.facets_.size(); ++i)
4620b57cec5SDimitry Andric     if (facets_[i])
4630b57cec5SDimitry Andric       facets_[i]->__add_shared();
4640b57cec5SDimitry Andric   install(hold.get(), id);
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
~__imp()467cb14a3feSDimitry Andric locale::__imp::~__imp() {
4680b57cec5SDimitry Andric   for (unsigned i = 0; i < facets_.size(); ++i)
4690b57cec5SDimitry Andric     if (facets_[i])
4700b57cec5SDimitry Andric       facets_[i]->__release_shared();
4710b57cec5SDimitry Andric }
4720b57cec5SDimitry Andric 
install(facet * f,long id)473cb14a3feSDimitry Andric void locale::__imp::install(facet* f, long id) {
4740b57cec5SDimitry Andric   f->__add_shared();
4755f757f3fSDimitry Andric   unique_ptr<facet, releaser> hold(f);
4760b57cec5SDimitry Andric   if (static_cast<size_t>(id) >= facets_.size())
4770b57cec5SDimitry Andric     facets_.resize(static_cast<size_t>(id + 1));
4780b57cec5SDimitry Andric   if (facets_[static_cast<size_t>(id)])
4790b57cec5SDimitry Andric     facets_[static_cast<size_t>(id)]->__release_shared();
4800b57cec5SDimitry Andric   facets_[static_cast<size_t>(id)] = hold.release();
4810b57cec5SDimitry Andric }
4820b57cec5SDimitry Andric 
use_facet(long id) const483cb14a3feSDimitry Andric const locale::facet* locale::__imp::use_facet(long id) const {
4840b57cec5SDimitry Andric   if (!has_facet(id))
4850b57cec5SDimitry Andric     __throw_bad_cast();
4860b57cec5SDimitry Andric   return facets_[static_cast<size_t>(id)];
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric // locale
4900b57cec5SDimitry Andric 
4915f757f3fSDimitry Andric // We don't do reference counting on the classic locale.
4925f757f3fSDimitry Andric // It's never destroyed anyway, but atomic reference counting may be very
4935f757f3fSDimitry Andric // expensive in parallel applications. The classic locale is used by default
4945f757f3fSDimitry Andric // in all streams. Note: if a new global locale is installed, then we lose
4955f757f3fSDimitry Andric // the benefit of no reference counting.
4965f757f3fSDimitry Andric constinit __no_destroy<locale::__imp>
4975f757f3fSDimitry Andric     locale::__imp::classic_locale_imp_(__uninitialized_tag{}); // initialized below in classic()
4985f757f3fSDimitry Andric 
classic()4995f757f3fSDimitry Andric const locale& locale::classic() {
500*0fca6ea1SDimitry Andric   static const __no_destroy<locale> classic_locale(__private_constructor_tag{}, [] {
5015f757f3fSDimitry Andric     // executed exactly once on first initialization of `classic_locale`
5025f757f3fSDimitry Andric     locale::__imp::classic_locale_imp_.__emplace(1u);
5035f757f3fSDimitry Andric     return &locale::__imp::classic_locale_imp_.__get();
5045f757f3fSDimitry Andric   }());
5055f757f3fSDimitry Andric   return classic_locale.__get();
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric 
__global()5085f757f3fSDimitry Andric locale& locale::__global() {
5095f757f3fSDimitry Andric   static __no_destroy<locale> g(locale::classic());
5105f757f3fSDimitry Andric   return g.__get();
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric 
acquire()5135f757f3fSDimitry Andric void locale::__imp::acquire() {
5145f757f3fSDimitry Andric   if (this != &locale::__imp::classic_locale_imp_.__get())
5155f757f3fSDimitry Andric     __add_shared();
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric 
release()5185f757f3fSDimitry Andric void locale::__imp::release() {
5195f757f3fSDimitry Andric   if (this != &locale::__imp::classic_locale_imp_.__get())
5205f757f3fSDimitry Andric     __release_shared();
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
locale()5235f757f3fSDimitry Andric locale::locale() noexcept : __locale_(__global().__locale_) { __locale_->acquire(); }
5240b57cec5SDimitry Andric 
locale(const locale & l)5255f757f3fSDimitry Andric locale::locale(const locale& l) noexcept : __locale_(l.__locale_) { __locale_->acquire(); }
5260b57cec5SDimitry Andric 
~locale()5275f757f3fSDimitry Andric locale::~locale() { __locale_->release(); }
5280b57cec5SDimitry Andric 
operator =(const locale & other)529cb14a3feSDimitry Andric const locale& locale::operator=(const locale& other) noexcept {
5305f757f3fSDimitry Andric   other.__locale_->acquire();
5315f757f3fSDimitry Andric   __locale_->release();
5320b57cec5SDimitry Andric   __locale_ = other.__locale_;
5330b57cec5SDimitry Andric   return *this;
5340b57cec5SDimitry Andric }
5350b57cec5SDimitry Andric 
locale(const char * name)5360b57cec5SDimitry Andric locale::locale(const char* name)
537cb14a3feSDimitry Andric     : __locale_(name ? new __imp(name) : (__throw_runtime_error("locale constructed with null"), nullptr)) {
5385f757f3fSDimitry Andric   __locale_->acquire();
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric 
locale(const string & name)5415f757f3fSDimitry Andric locale::locale(const string& name) : __locale_(new __imp(name)) { __locale_->acquire(); }
5420b57cec5SDimitry Andric 
locale(const locale & other,const char * name,category c)5430b57cec5SDimitry Andric locale::locale(const locale& other, const char* name, category c)
5440b57cec5SDimitry Andric     : __locale_(name ? new __imp(*other.__locale_, name, c)
545cb14a3feSDimitry Andric                      : (__throw_runtime_error("locale constructed with null"), nullptr)) {
5465f757f3fSDimitry Andric   __locale_->acquire();
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric 
locale(const locale & other,const string & name,category c)549cb14a3feSDimitry Andric locale::locale(const locale& other, const string& name, category c) : __locale_(new __imp(*other.__locale_, name, c)) {
5505f757f3fSDimitry Andric   __locale_->acquire();
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric 
locale(const locale & other,const locale & one,category c)5530b57cec5SDimitry Andric locale::locale(const locale& other, const locale& one, category c)
554cb14a3feSDimitry Andric     : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) {
5555f757f3fSDimitry Andric   __locale_->acquire();
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
name() const558cb14a3feSDimitry Andric string locale::name() const { return __locale_->name(); }
5590b57cec5SDimitry Andric 
__install_ctor(const locale & other,facet * f,long facet_id)560*0fca6ea1SDimitry Andric void locale::__install_ctor(const locale& other, facet* f, long facet_id) {
5610b57cec5SDimitry Andric   if (f)
562*0fca6ea1SDimitry Andric     __locale_ = new __imp(*other.__locale_, f, facet_id);
5630b57cec5SDimitry Andric   else
5640b57cec5SDimitry Andric     __locale_ = other.__locale_;
5655f757f3fSDimitry Andric   __locale_->acquire();
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric 
global(const locale & loc)568cb14a3feSDimitry Andric locale locale::global(const locale& loc) {
5690b57cec5SDimitry Andric   locale& g = __global();
5700b57cec5SDimitry Andric   locale r  = g;
5710b57cec5SDimitry Andric   g         = loc;
5720b57cec5SDimitry Andric   if (g.name() != "*")
5730b57cec5SDimitry Andric     setlocale(LC_ALL, g.name().c_str());
5740b57cec5SDimitry Andric   return r;
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
has_facet(id & x) const577cb14a3feSDimitry Andric bool locale::has_facet(id& x) const { return __locale_->has_facet(x.__get()); }
5780b57cec5SDimitry Andric 
use_facet(id & x) const579cb14a3feSDimitry Andric const locale::facet* locale::use_facet(id& x) const { return __locale_->use_facet(x.__get()); }
5800b57cec5SDimitry Andric 
operator ==(const locale & y) const581cb14a3feSDimitry Andric bool locale::operator==(const locale& y) const {
582cb14a3feSDimitry Andric   return (__locale_ == y.__locale_) || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric // locale::facet
5860b57cec5SDimitry Andric 
~facet()587cb14a3feSDimitry Andric locale::facet::~facet() {}
5880b57cec5SDimitry Andric 
__on_zero_shared()589cb14a3feSDimitry Andric void locale::facet::__on_zero_shared() noexcept { delete this; }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric // locale::id
5920b57cec5SDimitry Andric 
5935f757f3fSDimitry Andric constinit int32_t locale::id::__next_id = 0;
5940b57cec5SDimitry Andric 
__get()5955f757f3fSDimitry Andric long locale::id::__get() {
5965f757f3fSDimitry Andric   call_once(__flag_, [&] { __id_ = __libcpp_atomic_add(&__next_id, 1); });
5970b57cec5SDimitry Andric   return __id_ - 1;
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric // template <> class collate_byname<char>
6010b57cec5SDimitry Andric 
collate_byname(const char * n,size_t refs)6020b57cec5SDimitry Andric collate_byname<char>::collate_byname(const char* n, size_t refs)
603cb14a3feSDimitry Andric     : collate<char>(refs), __l_(newlocale(LC_ALL_MASK, n, 0)) {
604bdd1243dSDimitry Andric   if (__l_ == 0)
605cb14a3feSDimitry Andric     __throw_runtime_error(
606cb14a3feSDimitry Andric         ("collate_byname<char>::collate_byname"
607cb14a3feSDimitry Andric          " failed to construct for " +
608cb14a3feSDimitry Andric          string(n))
609cb14a3feSDimitry Andric             .c_str());
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
collate_byname(const string & name,size_t refs)6120b57cec5SDimitry Andric collate_byname<char>::collate_byname(const string& name, size_t refs)
613cb14a3feSDimitry Andric     : collate<char>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
614bdd1243dSDimitry Andric   if (__l_ == 0)
615cb14a3feSDimitry Andric     __throw_runtime_error(
616cb14a3feSDimitry Andric         ("collate_byname<char>::collate_byname"
617cb14a3feSDimitry Andric          " failed to construct for " +
618cb14a3feSDimitry Andric          name)
619cb14a3feSDimitry Andric             .c_str());
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric 
~collate_byname()622cb14a3feSDimitry Andric collate_byname<char>::~collate_byname() { freelocale(__l_); }
6230b57cec5SDimitry Andric 
do_compare(const char_type * __lo1,const char_type * __hi1,const char_type * __lo2,const char_type * __hi2) const624cb14a3feSDimitry Andric int collate_byname<char>::do_compare(
625cb14a3feSDimitry Andric     const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const {
6260b57cec5SDimitry Andric   string_type lhs(__lo1, __hi1);
6270b57cec5SDimitry Andric   string_type rhs(__lo2, __hi2);
628bdd1243dSDimitry Andric   int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l_);
6290b57cec5SDimitry Andric   if (r < 0)
6300b57cec5SDimitry Andric     return -1;
6310b57cec5SDimitry Andric   if (r > 0)
6320b57cec5SDimitry Andric     return 1;
6330b57cec5SDimitry Andric   return r;
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric 
do_transform(const char_type * lo,const char_type * hi) const636cb14a3feSDimitry Andric collate_byname<char>::string_type collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const {
6370b57cec5SDimitry Andric   const string_type in(lo, hi);
638bdd1243dSDimitry Andric   string_type out(strxfrm_l(0, in.c_str(), 0, __l_), char());
639bdd1243dSDimitry Andric   strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size() + 1, __l_);
6400b57cec5SDimitry Andric   return out;
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric // template <> class collate_byname<wchar_t>
6440b57cec5SDimitry Andric 
645349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
collate_byname(const char * n,size_t refs)6460b57cec5SDimitry Andric collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
647cb14a3feSDimitry Andric     : collate<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, n, 0)) {
648bdd1243dSDimitry Andric   if (__l_ == 0)
649cb14a3feSDimitry Andric     __throw_runtime_error(
650cb14a3feSDimitry Andric         ("collate_byname<wchar_t>::collate_byname(size_t refs)"
651cb14a3feSDimitry Andric          " failed to construct for " +
652cb14a3feSDimitry Andric          string(n))
653cb14a3feSDimitry Andric             .c_str());
6540b57cec5SDimitry Andric }
6550b57cec5SDimitry Andric 
collate_byname(const string & name,size_t refs)6560b57cec5SDimitry Andric collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
657cb14a3feSDimitry Andric     : collate<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
658bdd1243dSDimitry Andric   if (__l_ == 0)
659cb14a3feSDimitry Andric     __throw_runtime_error(
660cb14a3feSDimitry Andric         ("collate_byname<wchar_t>::collate_byname(size_t refs)"
661cb14a3feSDimitry Andric          " failed to construct for " +
662cb14a3feSDimitry Andric          name)
663cb14a3feSDimitry Andric             .c_str());
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
~collate_byname()666cb14a3feSDimitry Andric collate_byname<wchar_t>::~collate_byname() { freelocale(__l_); }
6670b57cec5SDimitry Andric 
do_compare(const char_type * __lo1,const char_type * __hi1,const char_type * __lo2,const char_type * __hi2) const668cb14a3feSDimitry Andric int collate_byname<wchar_t>::do_compare(
669cb14a3feSDimitry Andric     const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const {
6700b57cec5SDimitry Andric   string_type lhs(__lo1, __hi1);
6710b57cec5SDimitry Andric   string_type rhs(__lo2, __hi2);
672bdd1243dSDimitry Andric   int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l_);
6730b57cec5SDimitry Andric   if (r < 0)
6740b57cec5SDimitry Andric     return -1;
6750b57cec5SDimitry Andric   if (r > 0)
6760b57cec5SDimitry Andric     return 1;
6770b57cec5SDimitry Andric   return r;
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric collate_byname<wchar_t>::string_type
do_transform(const char_type * lo,const char_type * hi) const681cb14a3feSDimitry Andric collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const {
6820b57cec5SDimitry Andric   const string_type in(lo, hi);
683bdd1243dSDimitry Andric   string_type out(wcsxfrm_l(0, in.c_str(), 0, __l_), wchar_t());
684bdd1243dSDimitry Andric   wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size() + 1, __l_);
6850b57cec5SDimitry Andric   return out;
6860b57cec5SDimitry Andric }
687349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric const ctype_base::mask ctype_base::space;
6900b57cec5SDimitry Andric const ctype_base::mask ctype_base::print;
6910b57cec5SDimitry Andric const ctype_base::mask ctype_base::cntrl;
6920b57cec5SDimitry Andric const ctype_base::mask ctype_base::upper;
6930b57cec5SDimitry Andric const ctype_base::mask ctype_base::lower;
6940b57cec5SDimitry Andric const ctype_base::mask ctype_base::alpha;
6950b57cec5SDimitry Andric const ctype_base::mask ctype_base::digit;
6960b57cec5SDimitry Andric const ctype_base::mask ctype_base::punct;
6970b57cec5SDimitry Andric const ctype_base::mask ctype_base::xdigit;
6980b57cec5SDimitry Andric const ctype_base::mask ctype_base::blank;
6990b57cec5SDimitry Andric const ctype_base::mask ctype_base::alnum;
7000b57cec5SDimitry Andric const ctype_base::mask ctype_base::graph;
7010b57cec5SDimitry Andric 
702349cc55cSDimitry Andric // template <> class ctype<wchar_t>;
703349cc55cSDimitry Andric 
704349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
7055f757f3fSDimitry Andric constinit locale::id ctype<wchar_t>::id;
7060b57cec5SDimitry Andric 
~ctype()707cb14a3feSDimitry Andric ctype<wchar_t>::~ctype() {}
7080b57cec5SDimitry Andric 
do_is(mask m,char_type c) const709cb14a3feSDimitry Andric bool ctype<wchar_t>::do_is(mask m, char_type c) const {
7100b57cec5SDimitry Andric   return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
7110b57cec5SDimitry Andric }
7120b57cec5SDimitry Andric 
do_is(const char_type * low,const char_type * high,mask * vec) const713cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const {
7140b57cec5SDimitry Andric   for (; low != high; ++low, ++vec)
715cb14a3feSDimitry Andric     *vec = static_cast<mask>(isascii(*low) ? ctype<char>::classic_table()[*low] : 0);
7160b57cec5SDimitry Andric   return low;
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
do_scan_is(mask m,const char_type * low,const char_type * high) const719cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const {
7200b57cec5SDimitry Andric   for (; low != high; ++low)
7210b57cec5SDimitry Andric     if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
7220b57cec5SDimitry Andric       break;
7230b57cec5SDimitry Andric   return low;
7240b57cec5SDimitry Andric }
7250b57cec5SDimitry Andric 
do_scan_not(mask m,const char_type * low,const char_type * high) const726cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const {
7270b57cec5SDimitry Andric   for (; low != high; ++low)
7280b57cec5SDimitry Andric     if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
7290b57cec5SDimitry Andric       break;
7300b57cec5SDimitry Andric   return low;
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric 
do_toupper(char_type c) const733cb14a3feSDimitry Andric wchar_t ctype<wchar_t>::do_toupper(char_type c) const {
7340b57cec5SDimitry Andric #  ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
7350b57cec5SDimitry Andric   return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
736cb14a3feSDimitry Andric #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
7370b57cec5SDimitry Andric   return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
7380b57cec5SDimitry Andric #  else
7390b57cec5SDimitry Andric   return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c - L'a' + L'A' : c;
7400b57cec5SDimitry Andric #  endif
7410b57cec5SDimitry Andric }
7420b57cec5SDimitry Andric 
do_toupper(char_type * low,const char_type * high) const743cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const {
7440b57cec5SDimitry Andric   for (; low != high; ++low)
7450b57cec5SDimitry Andric #  ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
7460b57cec5SDimitry Andric     *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
747cb14a3feSDimitry Andric #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
748cb14a3feSDimitry Andric     *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] : *low;
7490b57cec5SDimitry Andric #  else
7500b57cec5SDimitry Andric     *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low - L'a' + L'A') : *low;
7510b57cec5SDimitry Andric #  endif
7520b57cec5SDimitry Andric   return low;
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric 
do_tolower(char_type c) const755cb14a3feSDimitry Andric wchar_t ctype<wchar_t>::do_tolower(char_type c) const {
7560b57cec5SDimitry Andric #  ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
7570b57cec5SDimitry Andric   return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
758cb14a3feSDimitry Andric #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
7590b57cec5SDimitry Andric   return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
7600b57cec5SDimitry Andric #  else
7610b57cec5SDimitry Andric   return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c - L'A' + 'a' : c;
7620b57cec5SDimitry Andric #  endif
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric 
do_tolower(char_type * low,const char_type * high) const765cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const {
7660b57cec5SDimitry Andric   for (; low != high; ++low)
7670b57cec5SDimitry Andric #  ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
7680b57cec5SDimitry Andric     *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
769cb14a3feSDimitry Andric #  elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || defined(__MVS__)
770cb14a3feSDimitry Andric     *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] : *low;
7710b57cec5SDimitry Andric #  else
7720b57cec5SDimitry Andric     *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - L'A' + L'a' : *low;
7730b57cec5SDimitry Andric #  endif
7740b57cec5SDimitry Andric   return low;
7750b57cec5SDimitry Andric }
7760b57cec5SDimitry Andric 
do_widen(char c) const777cb14a3feSDimitry Andric wchar_t ctype<wchar_t>::do_widen(char c) const { return c; }
7780b57cec5SDimitry Andric 
do_widen(const char * low,const char * high,char_type * dest) const779cb14a3feSDimitry Andric const char* ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const {
7800b57cec5SDimitry Andric   for (; low != high; ++low, ++dest)
7810b57cec5SDimitry Andric     *dest = *low;
7820b57cec5SDimitry Andric   return low;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
do_narrow(char_type c,char dfault) const785cb14a3feSDimitry Andric char ctype<wchar_t>::do_narrow(char_type c, char dfault) const {
7860b57cec5SDimitry Andric   if (isascii(c))
7870b57cec5SDimitry Andric     return static_cast<char>(c);
7880b57cec5SDimitry Andric   return dfault;
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric 
do_narrow(const char_type * low,const char_type * high,char dfault,char * dest) const791cb14a3feSDimitry Andric const wchar_t* ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const {
7920b57cec5SDimitry Andric   for (; low != high; ++low, ++dest)
7930b57cec5SDimitry Andric     if (isascii(*low))
7940b57cec5SDimitry Andric       *dest = static_cast<char>(*low);
7950b57cec5SDimitry Andric     else
7960b57cec5SDimitry Andric       *dest = dfault;
7970b57cec5SDimitry Andric   return low;
7980b57cec5SDimitry Andric }
799349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric // template <> class ctype<char>;
8020b57cec5SDimitry Andric 
8035f757f3fSDimitry Andric constinit locale::id ctype<char>::id;
8040b57cec5SDimitry Andric 
805349cc55cSDimitry Andric const size_t ctype<char>::table_size;
806349cc55cSDimitry Andric 
ctype(const mask * tab,bool del,size_t refs)807cb14a3feSDimitry Andric ctype<char>::ctype(const mask* tab, bool del, size_t refs) : locale::facet(refs), __tab_(tab), __del_(del) {
8080b57cec5SDimitry Andric   if (__tab_ == 0)
8090b57cec5SDimitry Andric     __tab_ = classic_table();
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric 
~ctype()812cb14a3feSDimitry Andric ctype<char>::~ctype() {
8130b57cec5SDimitry Andric   if (__tab_ && __del_)
8140b57cec5SDimitry Andric     delete[] __tab_;
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric 
do_toupper(char_type c) const817cb14a3feSDimitry Andric char ctype<char>::do_toupper(char_type c) const {
8180b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
819cb14a3feSDimitry Andric   return isascii(c) ? static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
8200b57cec5SDimitry Andric #elif defined(__NetBSD__)
8210b57cec5SDimitry Andric   return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
82204eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
823cb14a3feSDimitry Andric   return isascii(c) ? static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
8240b57cec5SDimitry Andric #else
8250b57cec5SDimitry Andric   return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c - 'a' + 'A' : c;
8260b57cec5SDimitry Andric #endif
8270b57cec5SDimitry Andric }
8280b57cec5SDimitry Andric 
do_toupper(char_type * low,const char_type * high) const829cb14a3feSDimitry Andric const char* ctype<char>::do_toupper(char_type* low, const char_type* high) const {
8300b57cec5SDimitry Andric   for (; low != high; ++low)
8310b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
832cb14a3feSDimitry Andric     *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
8330b57cec5SDimitry Andric #elif defined(__NetBSD__)
8340b57cec5SDimitry Andric     *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
83504eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
836cb14a3feSDimitry Andric     *low = isascii(*low) ? static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
8370b57cec5SDimitry Andric #else
8380b57cec5SDimitry Andric     *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'a' + 'A' : *low;
8390b57cec5SDimitry Andric #endif
8400b57cec5SDimitry Andric   return low;
8410b57cec5SDimitry Andric }
8420b57cec5SDimitry Andric 
do_tolower(char_type c) const843cb14a3feSDimitry Andric char ctype<char>::do_tolower(char_type c) const {
8440b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
845cb14a3feSDimitry Andric   return isascii(c) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
8460b57cec5SDimitry Andric #elif defined(__NetBSD__)
8470b57cec5SDimitry Andric   return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
84804eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
849cb14a3feSDimitry Andric   return isascii(c) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
8500b57cec5SDimitry Andric #else
8510b57cec5SDimitry Andric   return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c - 'A' + 'a' : c;
8520b57cec5SDimitry Andric #endif
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric 
do_tolower(char_type * low,const char_type * high) const855cb14a3feSDimitry Andric const char* ctype<char>::do_tolower(char_type* low, const char_type* high) const {
8560b57cec5SDimitry Andric   for (; low != high; ++low)
8570b57cec5SDimitry Andric #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
8580b57cec5SDimitry Andric     *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
8590b57cec5SDimitry Andric #elif defined(__NetBSD__)
8600b57cec5SDimitry Andric     *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
86104eeddc0SDimitry Andric #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
8620b57cec5SDimitry Andric     *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
8630b57cec5SDimitry Andric #else
8640b57cec5SDimitry Andric     *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low - 'A' + 'a' : *low;
8650b57cec5SDimitry Andric #endif
8660b57cec5SDimitry Andric   return low;
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric 
do_widen(char c) const869cb14a3feSDimitry Andric char ctype<char>::do_widen(char c) const { return c; }
8700b57cec5SDimitry Andric 
do_widen(const char * low,const char * high,char_type * dest) const871cb14a3feSDimitry Andric const char* ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const {
8720b57cec5SDimitry Andric   for (; low != high; ++low, ++dest)
8730b57cec5SDimitry Andric     *dest = *low;
8740b57cec5SDimitry Andric   return low;
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
do_narrow(char_type c,char dfault) const877cb14a3feSDimitry Andric char ctype<char>::do_narrow(char_type c, char dfault) const {
8780b57cec5SDimitry Andric   if (isascii(c))
8790b57cec5SDimitry Andric     return static_cast<char>(c);
8800b57cec5SDimitry Andric   return dfault;
8810b57cec5SDimitry Andric }
8820b57cec5SDimitry Andric 
do_narrow(const char_type * low,const char_type * high,char dfault,char * dest) const883cb14a3feSDimitry Andric const char* ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const {
8840b57cec5SDimitry Andric   for (; low != high; ++low, ++dest)
8850b57cec5SDimitry Andric     if (isascii(*low))
8860b57cec5SDimitry Andric       *dest = *low;
8870b57cec5SDimitry Andric     else
8880b57cec5SDimitry Andric       *dest = dfault;
8890b57cec5SDimitry Andric   return low;
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric #if defined(__EMSCRIPTEN__)
8930b57cec5SDimitry Andric extern "C" const unsigned short** __ctype_b_loc();
8940b57cec5SDimitry Andric extern "C" const int** __ctype_tolower_loc();
8950b57cec5SDimitry Andric extern "C" const int** __ctype_toupper_loc();
8960b57cec5SDimitry Andric #endif
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
classic_table()899cb14a3feSDimitry Andric const ctype<char>::mask* ctype<char>::classic_table() noexcept {
9005f757f3fSDimitry Andric   // clang-format off
9015f757f3fSDimitry Andric     static constexpr const ctype<char>::mask builtin_table[table_size] = {
9020b57cec5SDimitry Andric         cntrl,                          cntrl,
9030b57cec5SDimitry Andric         cntrl,                          cntrl,
9040b57cec5SDimitry Andric         cntrl,                          cntrl,
9050b57cec5SDimitry Andric         cntrl,                          cntrl,
9060b57cec5SDimitry Andric         cntrl,                          cntrl | space | blank,
9070b57cec5SDimitry Andric         cntrl | space,                  cntrl | space,
9080b57cec5SDimitry Andric         cntrl | space,                  cntrl | space,
9090b57cec5SDimitry Andric         cntrl,                          cntrl,
9100b57cec5SDimitry Andric         cntrl,                          cntrl,
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         space | blank | print,          punct | print,
9190b57cec5SDimitry Andric         punct | print,                  punct | print,
9200b57cec5SDimitry Andric         punct | 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         digit | print | xdigit,         digit | print | xdigit,
9270b57cec5SDimitry Andric         digit | print | xdigit,         digit | print | xdigit,
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         punct | print,                  punct | print,
9320b57cec5SDimitry Andric         punct | print,                  punct | print,
9330b57cec5SDimitry Andric         punct | print,                  punct | print,
9340b57cec5SDimitry Andric         punct | print,                  upper | xdigit | print | alpha,
9350b57cec5SDimitry Andric         upper | xdigit | print | alpha, upper | xdigit | print | alpha,
9360b57cec5SDimitry Andric         upper | xdigit | print | alpha, upper | xdigit | print | alpha,
9370b57cec5SDimitry Andric         upper | xdigit | print | alpha, upper | print | alpha,
9380b57cec5SDimitry Andric         upper | print | alpha,          upper | print | alpha,
9390b57cec5SDimitry Andric         upper | 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,          punct | print,
9480b57cec5SDimitry Andric         punct | print,                  punct | print,
9490b57cec5SDimitry Andric         punct | print,                  punct | print,
9500b57cec5SDimitry Andric         punct | print,                  lower | xdigit | print | alpha,
9510b57cec5SDimitry Andric         lower | xdigit | print | alpha, lower | xdigit | print | alpha,
9520b57cec5SDimitry Andric         lower | xdigit | print | alpha, lower | xdigit | print | alpha,
9530b57cec5SDimitry Andric         lower | xdigit | print | alpha, lower | print | alpha,
9540b57cec5SDimitry Andric         lower | print | alpha,          lower | print | alpha,
9550b57cec5SDimitry Andric         lower | 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,          punct | print,
9640b57cec5SDimitry Andric         punct | print,                  punct | print,
9650b57cec5SDimitry Andric         punct | print,                  cntrl,
9660b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9670b57cec5SDimitry Andric         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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     };
9755f757f3fSDimitry Andric   // clang-format on
9760b57cec5SDimitry Andric   return builtin_table;
9770b57cec5SDimitry Andric }
9780b57cec5SDimitry Andric #else
classic_table()979cb14a3feSDimitry Andric const ctype<char>::mask* ctype<char>::classic_table() noexcept {
9800b57cec5SDimitry Andric #  if defined(__APPLE__) || defined(__FreeBSD__)
9810b57cec5SDimitry Andric   return _DefaultRuneLocale.__runetype;
9820b57cec5SDimitry Andric #  elif defined(__NetBSD__)
9830b57cec5SDimitry Andric   return _C_ctype_tab_ + 1;
9840b57cec5SDimitry Andric #  elif defined(__GLIBC__)
9850b57cec5SDimitry Andric   return _LIBCPP_GET_C_LOCALE->__ctype_b;
9860b57cec5SDimitry Andric #  elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
9870b57cec5SDimitry Andric   return __pctype_func();
9880b57cec5SDimitry Andric #  elif defined(__EMSCRIPTEN__)
9890b57cec5SDimitry Andric   return *__ctype_b_loc();
9900b57cec5SDimitry Andric #  elif defined(_NEWLIB_VERSION)
9910b57cec5SDimitry Andric   // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
9920b57cec5SDimitry Andric   return _ctype_ + 1;
9930b57cec5SDimitry Andric #  elif defined(_AIX)
9940b57cec5SDimitry Andric   return (const unsigned int*)__lc_ctype_ptr->obj->mask;
99504eeddc0SDimitry Andric #  elif defined(__MVS__)
99604eeddc0SDimitry Andric #    if defined(__NATIVE_ASCII_F)
99704eeddc0SDimitry Andric   return const_cast<const ctype<char>::mask*>(__OBJ_DATA(__lc_ctype_a)->mask);
99804eeddc0SDimitry Andric #    else
99904eeddc0SDimitry Andric   return const_cast<const ctype<char>::mask*>(__ctypec);
100004eeddc0SDimitry Andric #    endif
10010b57cec5SDimitry Andric #  else
10020b57cec5SDimitry Andric   // Platform not supported: abort so the person doing the port knows what to
10030b57cec5SDimitry Andric   // fix
10040b57cec5SDimitry Andric #    warning ctype<char>::classic_table() is not implemented
10050b57cec5SDimitry Andric   printf("ctype<char>::classic_table() is not implemented\n");
10060b57cec5SDimitry Andric   abort();
10070b57cec5SDimitry Andric   return NULL;
10080b57cec5SDimitry Andric #  endif
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric #endif
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric #if defined(__GLIBC__)
__classic_lower_table()1013cb14a3feSDimitry Andric const int* ctype<char>::__classic_lower_table() noexcept { return _LIBCPP_GET_C_LOCALE->__ctype_tolower; }
10140b57cec5SDimitry Andric 
__classic_upper_table()1015cb14a3feSDimitry Andric const int* ctype<char>::__classic_upper_table() noexcept { return _LIBCPP_GET_C_LOCALE->__ctype_toupper; }
1016e8d8bef9SDimitry Andric #elif defined(__NetBSD__)
__classic_lower_table()1017cb14a3feSDimitry Andric const short* ctype<char>::__classic_lower_table() noexcept { return _C_tolower_tab_ + 1; }
10180b57cec5SDimitry Andric 
__classic_upper_table()1019cb14a3feSDimitry Andric const short* ctype<char>::__classic_upper_table() noexcept { return _C_toupper_tab_ + 1; }
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric #elif defined(__EMSCRIPTEN__)
__classic_lower_table()1022cb14a3feSDimitry Andric const int* ctype<char>::__classic_lower_table() noexcept { return *__ctype_tolower_loc(); }
10230b57cec5SDimitry Andric 
__classic_upper_table()1024cb14a3feSDimitry Andric const int* ctype<char>::__classic_upper_table() noexcept { return *__ctype_toupper_loc(); }
102504eeddc0SDimitry Andric #elif defined(__MVS__)
__classic_lower_table()1026cb14a3feSDimitry Andric const unsigned short* ctype<char>::__classic_lower_table() _NOEXCEPT {
102704eeddc0SDimitry Andric #  if defined(__NATIVE_ASCII_F)
102804eeddc0SDimitry Andric   return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
102904eeddc0SDimitry Andric #  else
103004eeddc0SDimitry Andric   return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
103104eeddc0SDimitry Andric #  endif
103204eeddc0SDimitry Andric }
__classic_upper_table()1033cb14a3feSDimitry Andric const unsigned short* ctype<char>::__classic_upper_table() _NOEXCEPT {
103404eeddc0SDimitry Andric #  if defined(__NATIVE_ASCII_F)
103504eeddc0SDimitry Andric   return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
103604eeddc0SDimitry Andric #  else
103704eeddc0SDimitry Andric   return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
103804eeddc0SDimitry Andric #  endif
103904eeddc0SDimitry Andric }
104004eeddc0SDimitry Andric #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric // template <> class ctype_byname<char>
10430b57cec5SDimitry Andric 
ctype_byname(const char * name,size_t refs)10440b57cec5SDimitry Andric ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1045cb14a3feSDimitry Andric     : ctype<char>(0, false, refs), __l_(newlocale(LC_ALL_MASK, name, 0)) {
1046bdd1243dSDimitry Andric   if (__l_ == 0)
1047cb14a3feSDimitry Andric     __throw_runtime_error(
1048cb14a3feSDimitry Andric         ("ctype_byname<char>::ctype_byname"
1049cb14a3feSDimitry Andric          " failed to construct for " +
1050cb14a3feSDimitry Andric          string(name))
1051cb14a3feSDimitry Andric             .c_str());
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric 
ctype_byname(const string & name,size_t refs)10540b57cec5SDimitry Andric ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1055cb14a3feSDimitry Andric     : ctype<char>(0, false, refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
1056bdd1243dSDimitry Andric   if (__l_ == 0)
1057cb14a3feSDimitry Andric     __throw_runtime_error(
1058cb14a3feSDimitry Andric         ("ctype_byname<char>::ctype_byname"
1059cb14a3feSDimitry Andric          " failed to construct for " +
1060cb14a3feSDimitry Andric          name)
1061cb14a3feSDimitry Andric             .c_str());
10620b57cec5SDimitry Andric }
10630b57cec5SDimitry Andric 
~ctype_byname()1064cb14a3feSDimitry Andric ctype_byname<char>::~ctype_byname() { freelocale(__l_); }
10650b57cec5SDimitry Andric 
do_toupper(char_type c) const1066cb14a3feSDimitry Andric char ctype_byname<char>::do_toupper(char_type c) const {
1067bdd1243dSDimitry Andric   return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l_));
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
do_toupper(char_type * low,const char_type * high) const1070cb14a3feSDimitry Andric const char* ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const {
10710b57cec5SDimitry Andric   for (; low != high; ++low)
1072bdd1243dSDimitry Andric     *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l_));
10730b57cec5SDimitry Andric   return low;
10740b57cec5SDimitry Andric }
10750b57cec5SDimitry Andric 
do_tolower(char_type c) const1076cb14a3feSDimitry Andric char ctype_byname<char>::do_tolower(char_type c) const {
1077bdd1243dSDimitry Andric   return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l_));
10780b57cec5SDimitry Andric }
10790b57cec5SDimitry Andric 
do_tolower(char_type * low,const char_type * high) const1080cb14a3feSDimitry Andric const char* ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const {
10810b57cec5SDimitry Andric   for (; low != high; ++low)
1082bdd1243dSDimitry Andric     *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l_));
10830b57cec5SDimitry Andric   return low;
10840b57cec5SDimitry Andric }
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric // template <> class ctype_byname<wchar_t>
10870b57cec5SDimitry Andric 
1088349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
ctype_byname(const char * name,size_t refs)10890b57cec5SDimitry Andric ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1090cb14a3feSDimitry Andric     : ctype<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name, 0)) {
1091bdd1243dSDimitry Andric   if (__l_ == 0)
1092cb14a3feSDimitry Andric     __throw_runtime_error(
1093cb14a3feSDimitry Andric         ("ctype_byname<wchar_t>::ctype_byname"
1094cb14a3feSDimitry Andric          " failed to construct for " +
1095cb14a3feSDimitry Andric          string(name))
1096cb14a3feSDimitry Andric             .c_str());
10970b57cec5SDimitry Andric }
10980b57cec5SDimitry Andric 
ctype_byname(const string & name,size_t refs)10990b57cec5SDimitry Andric ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1100cb14a3feSDimitry Andric     : ctype<wchar_t>(refs), __l_(newlocale(LC_ALL_MASK, name.c_str(), 0)) {
1101bdd1243dSDimitry Andric   if (__l_ == 0)
1102cb14a3feSDimitry Andric     __throw_runtime_error(
1103cb14a3feSDimitry Andric         ("ctype_byname<wchar_t>::ctype_byname"
1104cb14a3feSDimitry Andric          " failed to construct for " +
1105cb14a3feSDimitry Andric          name)
1106cb14a3feSDimitry Andric             .c_str());
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric 
~ctype_byname()1109cb14a3feSDimitry Andric ctype_byname<wchar_t>::~ctype_byname() { freelocale(__l_); }
11100b57cec5SDimitry Andric 
do_is(mask m,char_type c) const1111cb14a3feSDimitry Andric bool ctype_byname<wchar_t>::do_is(mask m, char_type c) const {
11120b57cec5SDimitry Andric #  ifdef _LIBCPP_WCTYPE_IS_MASK
1113bdd1243dSDimitry Andric   return static_cast<bool>(iswctype_l(c, m, __l_));
11140b57cec5SDimitry Andric #  else
11150b57cec5SDimitry Andric   bool result = false;
11160b57cec5SDimitry Andric   wint_t ch   = static_cast<wint_t>(c);
1117cb14a3feSDimitry Andric   if ((m & space) == space)
1118cb14a3feSDimitry Andric     result |= (iswspace_l(ch, __l_) != 0);
1119cb14a3feSDimitry Andric   if ((m & print) == print)
1120cb14a3feSDimitry Andric     result |= (iswprint_l(ch, __l_) != 0);
1121cb14a3feSDimitry Andric   if ((m & cntrl) == cntrl)
1122cb14a3feSDimitry Andric     result |= (iswcntrl_l(ch, __l_) != 0);
1123cb14a3feSDimitry Andric   if ((m & upper) == upper)
1124cb14a3feSDimitry Andric     result |= (iswupper_l(ch, __l_) != 0);
1125cb14a3feSDimitry Andric   if ((m & lower) == lower)
1126cb14a3feSDimitry Andric     result |= (iswlower_l(ch, __l_) != 0);
1127cb14a3feSDimitry Andric   if ((m & alpha) == alpha)
1128cb14a3feSDimitry Andric     result |= (iswalpha_l(ch, __l_) != 0);
1129cb14a3feSDimitry Andric   if ((m & digit) == digit)
1130cb14a3feSDimitry Andric     result |= (iswdigit_l(ch, __l_) != 0);
1131cb14a3feSDimitry Andric   if ((m & punct) == punct)
1132cb14a3feSDimitry Andric     result |= (iswpunct_l(ch, __l_) != 0);
1133cb14a3feSDimitry Andric   if ((m & xdigit) == xdigit)
1134cb14a3feSDimitry Andric     result |= (iswxdigit_l(ch, __l_) != 0);
1135cb14a3feSDimitry Andric   if ((m & blank) == blank)
1136cb14a3feSDimitry Andric     result |= (iswblank_l(ch, __l_) != 0);
11370b57cec5SDimitry Andric   return result;
11380b57cec5SDimitry Andric #  endif
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric 
do_is(const char_type * low,const char_type * high,mask * vec) const1141cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const {
1142cb14a3feSDimitry Andric   for (; low != high; ++low, ++vec) {
11430b57cec5SDimitry Andric     if (isascii(*low))
11440b57cec5SDimitry Andric       *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
1145cb14a3feSDimitry Andric     else {
11460b57cec5SDimitry Andric       *vec      = 0;
11470b57cec5SDimitry Andric       wint_t ch = static_cast<wint_t>(*low);
1148bdd1243dSDimitry Andric       if (iswspace_l(ch, __l_))
11490b57cec5SDimitry Andric         *vec |= space;
11500b57cec5SDimitry Andric #  ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
1151bdd1243dSDimitry Andric       if (iswprint_l(ch, __l_))
11520b57cec5SDimitry Andric         *vec |= print;
11530b57cec5SDimitry Andric #  endif
1154bdd1243dSDimitry Andric       if (iswcntrl_l(ch, __l_))
11550b57cec5SDimitry Andric         *vec |= cntrl;
1156bdd1243dSDimitry Andric       if (iswupper_l(ch, __l_))
11570b57cec5SDimitry Andric         *vec |= upper;
1158bdd1243dSDimitry Andric       if (iswlower_l(ch, __l_))
11590b57cec5SDimitry Andric         *vec |= lower;
11600b57cec5SDimitry Andric #  ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
1161bdd1243dSDimitry Andric       if (iswalpha_l(ch, __l_))
11620b57cec5SDimitry Andric         *vec |= alpha;
11630b57cec5SDimitry Andric #  endif
1164bdd1243dSDimitry Andric       if (iswdigit_l(ch, __l_))
11650b57cec5SDimitry Andric         *vec |= digit;
1166bdd1243dSDimitry Andric       if (iswpunct_l(ch, __l_))
11670b57cec5SDimitry Andric         *vec |= punct;
11680b57cec5SDimitry Andric #  ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
1169bdd1243dSDimitry Andric       if (iswxdigit_l(ch, __l_))
11700b57cec5SDimitry Andric         *vec |= xdigit;
11710b57cec5SDimitry Andric #  endif
1172bdd1243dSDimitry Andric       if (iswblank_l(ch, __l_))
11730b57cec5SDimitry Andric         *vec |= blank;
11740b57cec5SDimitry Andric     }
11750b57cec5SDimitry Andric   }
11760b57cec5SDimitry Andric   return low;
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric 
do_scan_is(mask m,const char_type * low,const char_type * high) const1179cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const {
1180cb14a3feSDimitry Andric   for (; low != high; ++low) {
11810b57cec5SDimitry Andric #  ifdef _LIBCPP_WCTYPE_IS_MASK
1182bdd1243dSDimitry Andric     if (iswctype_l(*low, m, __l_))
11830b57cec5SDimitry Andric       break;
11840b57cec5SDimitry Andric #  else
11850b57cec5SDimitry Andric     wint_t ch = static_cast<wint_t>(*low);
1186cb14a3feSDimitry Andric     if ((m & space) == space && iswspace_l(ch, __l_))
1187cb14a3feSDimitry Andric       break;
1188cb14a3feSDimitry Andric     if ((m & print) == print && iswprint_l(ch, __l_))
1189cb14a3feSDimitry Andric       break;
1190cb14a3feSDimitry Andric     if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_))
1191cb14a3feSDimitry Andric       break;
1192cb14a3feSDimitry Andric     if ((m & upper) == upper && iswupper_l(ch, __l_))
1193cb14a3feSDimitry Andric       break;
1194cb14a3feSDimitry Andric     if ((m & lower) == lower && iswlower_l(ch, __l_))
1195cb14a3feSDimitry Andric       break;
1196cb14a3feSDimitry Andric     if ((m & alpha) == alpha && iswalpha_l(ch, __l_))
1197cb14a3feSDimitry Andric       break;
1198cb14a3feSDimitry Andric     if ((m & digit) == digit && iswdigit_l(ch, __l_))
1199cb14a3feSDimitry Andric       break;
1200cb14a3feSDimitry Andric     if ((m & punct) == punct && iswpunct_l(ch, __l_))
1201cb14a3feSDimitry Andric       break;
1202cb14a3feSDimitry Andric     if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_))
1203cb14a3feSDimitry Andric       break;
1204cb14a3feSDimitry Andric     if ((m & blank) == blank && iswblank_l(ch, __l_))
1205cb14a3feSDimitry Andric       break;
12060b57cec5SDimitry Andric #  endif
12070b57cec5SDimitry Andric   }
12080b57cec5SDimitry Andric   return low;
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric 
do_scan_not(mask m,const char_type * low,const char_type * high) const1211cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const {
1212cb14a3feSDimitry Andric   for (; low != high; ++low) {
12130b57cec5SDimitry Andric #  ifdef _LIBCPP_WCTYPE_IS_MASK
1214bdd1243dSDimitry Andric     if (!iswctype_l(*low, m, __l_))
12150b57cec5SDimitry Andric       break;
12160b57cec5SDimitry Andric #  else
12170b57cec5SDimitry Andric     wint_t ch = static_cast<wint_t>(*low);
1218cb14a3feSDimitry Andric     if ((m & space) == space && iswspace_l(ch, __l_))
1219cb14a3feSDimitry Andric       continue;
1220cb14a3feSDimitry Andric     if ((m & print) == print && iswprint_l(ch, __l_))
1221cb14a3feSDimitry Andric       continue;
1222cb14a3feSDimitry Andric     if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_))
1223cb14a3feSDimitry Andric       continue;
1224cb14a3feSDimitry Andric     if ((m & upper) == upper && iswupper_l(ch, __l_))
1225cb14a3feSDimitry Andric       continue;
1226cb14a3feSDimitry Andric     if ((m & lower) == lower && iswlower_l(ch, __l_))
1227cb14a3feSDimitry Andric       continue;
1228cb14a3feSDimitry Andric     if ((m & alpha) == alpha && iswalpha_l(ch, __l_))
1229cb14a3feSDimitry Andric       continue;
1230cb14a3feSDimitry Andric     if ((m & digit) == digit && iswdigit_l(ch, __l_))
1231cb14a3feSDimitry Andric       continue;
1232cb14a3feSDimitry Andric     if ((m & punct) == punct && iswpunct_l(ch, __l_))
1233cb14a3feSDimitry Andric       continue;
1234cb14a3feSDimitry Andric     if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_))
1235cb14a3feSDimitry Andric       continue;
1236cb14a3feSDimitry Andric     if ((m & blank) == blank && iswblank_l(ch, __l_))
1237cb14a3feSDimitry Andric       continue;
12380b57cec5SDimitry Andric     break;
12390b57cec5SDimitry Andric #  endif
12400b57cec5SDimitry Andric   }
12410b57cec5SDimitry Andric   return low;
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric 
do_toupper(char_type c) const1244cb14a3feSDimitry Andric wchar_t ctype_byname<wchar_t>::do_toupper(char_type c) const { return towupper_l(c, __l_); }
12450b57cec5SDimitry Andric 
do_toupper(char_type * low,const char_type * high) const1246cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const {
12470b57cec5SDimitry Andric   for (; low != high; ++low)
1248bdd1243dSDimitry Andric     *low = towupper_l(*low, __l_);
12490b57cec5SDimitry Andric   return low;
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric 
do_tolower(char_type c) const1252cb14a3feSDimitry Andric wchar_t ctype_byname<wchar_t>::do_tolower(char_type c) const { return towlower_l(c, __l_); }
12530b57cec5SDimitry Andric 
do_tolower(char_type * low,const char_type * high) const1254cb14a3feSDimitry Andric const wchar_t* ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const {
12550b57cec5SDimitry Andric   for (; low != high; ++low)
1256bdd1243dSDimitry Andric     *low = towlower_l(*low, __l_);
12570b57cec5SDimitry Andric   return low;
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
do_widen(char c) const1260cb14a3feSDimitry Andric wchar_t ctype_byname<wchar_t>::do_widen(char c) const { return __libcpp_btowc_l(c, __l_); }
12610b57cec5SDimitry Andric 
do_widen(const char * low,const char * high,char_type * dest) const1262cb14a3feSDimitry Andric const char* ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const {
12630b57cec5SDimitry Andric   for (; low != high; ++low, ++dest)
1264bdd1243dSDimitry Andric     *dest = __libcpp_btowc_l(*low, __l_);
12650b57cec5SDimitry Andric   return low;
12660b57cec5SDimitry Andric }
12670b57cec5SDimitry Andric 
do_narrow(char_type c,char dfault) const1268cb14a3feSDimitry Andric char ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const {
1269bdd1243dSDimitry Andric   int r = __libcpp_wctob_l(c, __l_);
127081ad6265SDimitry Andric   return (r != EOF) ? static_cast<char>(r) : dfault;
12710b57cec5SDimitry Andric }
12720b57cec5SDimitry Andric 
12730b57cec5SDimitry Andric const wchar_t*
do_narrow(const char_type * low,const char_type * high,char dfault,char * dest) const1274cb14a3feSDimitry Andric ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const {
1275cb14a3feSDimitry Andric   for (; low != high; ++low, ++dest) {
1276bdd1243dSDimitry Andric     int r = __libcpp_wctob_l(*low, __l_);
127781ad6265SDimitry Andric     *dest = (r != EOF) ? static_cast<char>(r) : dfault;
12780b57cec5SDimitry Andric   }
12790b57cec5SDimitry Andric   return low;
12800b57cec5SDimitry Andric }
1281349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric // template <> class codecvt<char, char, mbstate_t>
12840b57cec5SDimitry Andric 
12855f757f3fSDimitry Andric constinit locale::id codecvt<char, char, mbstate_t>::id;
12860b57cec5SDimitry Andric 
~codecvt()1287cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::~codecvt() {}
1288cb14a3feSDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type *,const intern_type * & frm_nxt,extern_type * to,extern_type *,extern_type * & to_nxt) const1289cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::result codecvt<char, char, mbstate_t>::do_out(
1290cb14a3feSDimitry Andric     state_type&,
1291cb14a3feSDimitry Andric     const intern_type* frm,
1292cb14a3feSDimitry Andric     const intern_type*,
1293cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
1294cb14a3feSDimitry Andric     extern_type* to,
1295cb14a3feSDimitry Andric     extern_type*,
1296cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
1297cb14a3feSDimitry Andric   frm_nxt = frm;
1298cb14a3feSDimitry Andric   to_nxt  = to;
1299cb14a3feSDimitry Andric   return noconv;
13000b57cec5SDimitry Andric }
13010b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type *,const extern_type * & frm_nxt,intern_type * to,intern_type *,intern_type * & to_nxt) const1302cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::result codecvt<char, char, mbstate_t>::do_in(
1303cb14a3feSDimitry Andric     state_type&,
1304cb14a3feSDimitry Andric     const extern_type* frm,
1305cb14a3feSDimitry Andric     const extern_type*,
1306cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
1307cb14a3feSDimitry Andric     intern_type* to,
1308cb14a3feSDimitry Andric     intern_type*,
1309cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
13100b57cec5SDimitry Andric   frm_nxt = frm;
13110b57cec5SDimitry Andric   to_nxt  = to;
13120b57cec5SDimitry Andric   return noconv;
13130b57cec5SDimitry Andric }
13140b57cec5SDimitry Andric 
13150b57cec5SDimitry Andric codecvt<char, char, mbstate_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const1316cb14a3feSDimitry Andric codecvt<char, char, mbstate_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
13170b57cec5SDimitry Andric   to_nxt = to;
13180b57cec5SDimitry Andric   return noconv;
13190b57cec5SDimitry Andric }
13200b57cec5SDimitry Andric 
do_encoding() const1321cb14a3feSDimitry Andric int codecvt<char, char, mbstate_t>::do_encoding() const noexcept { return 1; }
13220b57cec5SDimitry Andric 
do_always_noconv() const1323cb14a3feSDimitry Andric bool codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept { return true; }
13240b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * end,size_t mx) const1325cb14a3feSDimitry Andric int codecvt<char, char, mbstate_t>::do_length(
1326cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* end, size_t mx) const {
13270b57cec5SDimitry Andric   return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end - frm)));
13280b57cec5SDimitry Andric }
13290b57cec5SDimitry Andric 
do_max_length() const1330cb14a3feSDimitry Andric int codecvt<char, char, mbstate_t>::do_max_length() const noexcept { return 1; }
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric // template <> class codecvt<wchar_t, char, mbstate_t>
13330b57cec5SDimitry Andric 
1334349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
13355f757f3fSDimitry Andric constinit locale::id codecvt<wchar_t, char, mbstate_t>::id;
13360b57cec5SDimitry Andric 
codecvt(size_t refs)1337cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) : locale::facet(refs), __l_(_LIBCPP_GET_C_LOCALE) {}
13380b57cec5SDimitry Andric 
codecvt(const char * nm,size_t refs)13390b57cec5SDimitry Andric codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1340cb14a3feSDimitry Andric     : locale::facet(refs), __l_(newlocale(LC_ALL_MASK, nm, 0)) {
1341bdd1243dSDimitry Andric   if (__l_ == 0)
1342cb14a3feSDimitry Andric     __throw_runtime_error(
1343cb14a3feSDimitry Andric         ("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1344cb14a3feSDimitry Andric          " failed to construct for " +
1345cb14a3feSDimitry Andric          string(nm))
1346cb14a3feSDimitry Andric             .c_str());
13470b57cec5SDimitry Andric }
13480b57cec5SDimitry Andric 
~codecvt()1349cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::~codecvt() {
1350bdd1243dSDimitry Andric   if (__l_ != _LIBCPP_GET_C_LOCALE)
1351bdd1243dSDimitry Andric     freelocale(__l_);
13520b57cec5SDimitry Andric }
13530b57cec5SDimitry Andric 
do_out(state_type & st,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const1354cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_out(
1355cb14a3feSDimitry Andric     state_type& st,
1356cb14a3feSDimitry Andric     const intern_type* frm,
1357cb14a3feSDimitry Andric     const intern_type* frm_end,
1358cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
1359cb14a3feSDimitry Andric     extern_type* to,
1360cb14a3feSDimitry Andric     extern_type* to_end,
1361cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
13620b57cec5SDimitry Andric   // look for first internal null in frm
13630b57cec5SDimitry Andric   const intern_type* fend = frm;
13640b57cec5SDimitry Andric   for (; fend != frm_end; ++fend)
13650b57cec5SDimitry Andric     if (*fend == 0)
13660b57cec5SDimitry Andric       break;
13670b57cec5SDimitry Andric   // loop over all null-terminated sequences in frm
13680b57cec5SDimitry Andric   to_nxt = to;
1369cb14a3feSDimitry Andric   for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) {
13700b57cec5SDimitry Andric     // save state in case it is needed to recover to_nxt on error
13710b57cec5SDimitry Andric     mbstate_t save_state = st;
1372cb14a3feSDimitry Andric     size_t n             = __libcpp_wcsnrtombs_l(
1373cb14a3feSDimitry Andric         to, &frm_nxt, static_cast<size_t>(fend - frm), static_cast<size_t>(to_end - to), &st, __l_);
1374cb14a3feSDimitry Andric     if (n == size_t(-1)) {
13750b57cec5SDimitry Andric       // need to recover to_nxt
1376cb14a3feSDimitry Andric       for (to_nxt = to; frm != frm_nxt; ++frm) {
1377bdd1243dSDimitry Andric         n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l_);
13780b57cec5SDimitry Andric         if (n == size_t(-1))
13790b57cec5SDimitry Andric           break;
13800b57cec5SDimitry Andric         to_nxt += n;
13810b57cec5SDimitry Andric       }
13820b57cec5SDimitry Andric       frm_nxt = frm;
13830b57cec5SDimitry Andric       return error;
13840b57cec5SDimitry Andric     }
13850b57cec5SDimitry Andric     if (n == 0)
13860b57cec5SDimitry Andric       return partial;
13870b57cec5SDimitry Andric     to_nxt += n;
13880b57cec5SDimitry Andric     if (to_nxt == to_end)
13890b57cec5SDimitry Andric       break;
13900b57cec5SDimitry Andric     if (fend != frm_end) // set up next null terminated sequence
13910b57cec5SDimitry Andric     {
13920b57cec5SDimitry Andric       // Try to write the terminating null
13930b57cec5SDimitry Andric       extern_type tmp[MB_LEN_MAX];
1394bdd1243dSDimitry Andric       n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
13950b57cec5SDimitry Andric       if (n == size_t(-1)) // on error
13960b57cec5SDimitry Andric         return error;
13970b57cec5SDimitry Andric       if (n > static_cast<size_t>(to_end - to_nxt)) // is there room?
13980b57cec5SDimitry Andric         return partial;
13990b57cec5SDimitry Andric       for (extern_type* p = tmp; n; --n) // write it
14000b57cec5SDimitry Andric         *to_nxt++ = *p++;
14010b57cec5SDimitry Andric       ++frm_nxt;
14020b57cec5SDimitry Andric       // look for next null in frm
14030b57cec5SDimitry Andric       for (fend = frm_nxt; fend != frm_end; ++fend)
14040b57cec5SDimitry Andric         if (*fend == 0)
14050b57cec5SDimitry Andric           break;
14060b57cec5SDimitry Andric     }
14070b57cec5SDimitry Andric   }
14080b57cec5SDimitry Andric   return frm_nxt == frm_end ? ok : partial;
14090b57cec5SDimitry Andric }
14100b57cec5SDimitry Andric 
do_in(state_type & st,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const1411cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_in(
1412cb14a3feSDimitry Andric     state_type& st,
1413cb14a3feSDimitry Andric     const extern_type* frm,
1414cb14a3feSDimitry Andric     const extern_type* frm_end,
1415cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
1416cb14a3feSDimitry Andric     intern_type* to,
1417cb14a3feSDimitry Andric     intern_type* to_end,
1418cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
14190b57cec5SDimitry Andric   // look for first internal null in frm
14200b57cec5SDimitry Andric   const extern_type* fend = frm;
14210b57cec5SDimitry Andric   for (; fend != frm_end; ++fend)
14220b57cec5SDimitry Andric     if (*fend == 0)
14230b57cec5SDimitry Andric       break;
14240b57cec5SDimitry Andric   // loop over all null-terminated sequences in frm
14250b57cec5SDimitry Andric   to_nxt = to;
1426cb14a3feSDimitry Andric   for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) {
14270b57cec5SDimitry Andric     // save state in case it is needed to recover to_nxt on error
14280b57cec5SDimitry Andric     mbstate_t save_state = st;
1429cb14a3feSDimitry Andric     size_t n             = __libcpp_mbsnrtowcs_l(
1430cb14a3feSDimitry Andric         to, &frm_nxt, static_cast<size_t>(fend - frm), static_cast<size_t>(to_end - to), &st, __l_);
1431cb14a3feSDimitry Andric     if (n == size_t(-1)) {
14320b57cec5SDimitry Andric       // need to recover to_nxt
1433cb14a3feSDimitry Andric       for (to_nxt = to; frm != frm_nxt; ++to_nxt) {
1434cb14a3feSDimitry Andric         n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend - frm), &save_state, __l_);
1435cb14a3feSDimitry Andric         switch (n) {
14360b57cec5SDimitry Andric         case 0:
14370b57cec5SDimitry Andric           ++frm;
14380b57cec5SDimitry Andric           break;
14390b57cec5SDimitry Andric         case size_t(-1):
14400b57cec5SDimitry Andric           frm_nxt = frm;
14410b57cec5SDimitry Andric           return error;
14420b57cec5SDimitry Andric         case size_t(-2):
14430b57cec5SDimitry Andric           frm_nxt = frm;
14440b57cec5SDimitry Andric           return partial;
14450b57cec5SDimitry Andric         default:
14460b57cec5SDimitry Andric           frm += n;
14470b57cec5SDimitry Andric           break;
14480b57cec5SDimitry Andric         }
14490b57cec5SDimitry Andric       }
14500b57cec5SDimitry Andric       frm_nxt = frm;
14510b57cec5SDimitry Andric       return frm_nxt == frm_end ? ok : partial;
14520b57cec5SDimitry Andric     }
14530b57cec5SDimitry Andric     if (n == size_t(-1))
14540b57cec5SDimitry Andric       return error;
14550b57cec5SDimitry Andric     to_nxt += n;
14560b57cec5SDimitry Andric     if (to_nxt == to_end)
14570b57cec5SDimitry Andric       break;
14580b57cec5SDimitry Andric     if (fend != frm_end) // set up next null terminated sequence
14590b57cec5SDimitry Andric     {
14600b57cec5SDimitry Andric       // Try to write the terminating null
1461bdd1243dSDimitry Andric       n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l_);
14620b57cec5SDimitry Andric       if (n != 0) // on error
14630b57cec5SDimitry Andric         return error;
14640b57cec5SDimitry Andric       ++to_nxt;
14650b57cec5SDimitry Andric       ++frm_nxt;
14660b57cec5SDimitry Andric       // look for next null in frm
14670b57cec5SDimitry Andric       for (fend = frm_nxt; fend != frm_end; ++fend)
14680b57cec5SDimitry Andric         if (*fend == 0)
14690b57cec5SDimitry Andric           break;
14700b57cec5SDimitry Andric     }
14710b57cec5SDimitry Andric   }
14720b57cec5SDimitry Andric   return frm_nxt == frm_end ? ok : partial;
14730b57cec5SDimitry Andric }
14740b57cec5SDimitry Andric 
do_unshift(state_type & st,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const1475cb14a3feSDimitry Andric codecvt<wchar_t, char, mbstate_t>::result codecvt<wchar_t, char, mbstate_t>::do_unshift(
1476cb14a3feSDimitry Andric     state_type& st, extern_type* to, extern_type* to_end, extern_type*& to_nxt) const {
14770b57cec5SDimitry Andric   to_nxt = to;
14780b57cec5SDimitry Andric   extern_type tmp[MB_LEN_MAX];
1479bdd1243dSDimitry Andric   size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
14800b57cec5SDimitry Andric   if (n == size_t(-1) || n == 0) // on error
14810b57cec5SDimitry Andric     return error;
14820b57cec5SDimitry Andric   --n;
14830b57cec5SDimitry Andric   if (n > static_cast<size_t>(to_end - to_nxt)) // is there room?
14840b57cec5SDimitry Andric     return partial;
14850b57cec5SDimitry Andric   for (extern_type* p = tmp; n; --n) // write it
14860b57cec5SDimitry Andric     *to_nxt++ = *p++;
14870b57cec5SDimitry Andric   return ok;
14880b57cec5SDimitry Andric }
14890b57cec5SDimitry Andric 
do_encoding() const1490cb14a3feSDimitry Andric int codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept {
1491bdd1243dSDimitry Andric   if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l_) != 0)
14920b57cec5SDimitry Andric     return -1;
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric   // stateless encoding
1495bdd1243dSDimitry Andric   if (__l_ == 0 || __libcpp_mb_cur_max_l(__l_) == 1) // there are no known constant length encodings
14960b57cec5SDimitry Andric     return 1;                                        // which take more than 1 char to form a wchar_t
14970b57cec5SDimitry Andric   return 0;
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric 
do_always_noconv() const1500cb14a3feSDimitry Andric bool codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; }
15010b57cec5SDimitry Andric 
do_length(state_type & st,const extern_type * frm,const extern_type * frm_end,size_t mx) const1502cb14a3feSDimitry Andric int codecvt<wchar_t, char, mbstate_t>::do_length(
1503cb14a3feSDimitry Andric     state_type& st, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
15040b57cec5SDimitry Andric   int nbytes = 0;
1505cb14a3feSDimitry Andric   for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) {
1506bdd1243dSDimitry Andric     size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end - frm), &st, __l_);
1507cb14a3feSDimitry Andric     switch (n) {
15080b57cec5SDimitry Andric     case 0:
15090b57cec5SDimitry Andric       ++nbytes;
15100b57cec5SDimitry Andric       ++frm;
15110b57cec5SDimitry Andric       break;
15120b57cec5SDimitry Andric     case size_t(-1):
15130b57cec5SDimitry Andric     case size_t(-2):
15140b57cec5SDimitry Andric       return nbytes;
15150b57cec5SDimitry Andric     default:
15160b57cec5SDimitry Andric       nbytes += n;
15170b57cec5SDimitry Andric       frm += n;
15180b57cec5SDimitry Andric       break;
15190b57cec5SDimitry Andric     }
15200b57cec5SDimitry Andric   }
15210b57cec5SDimitry Andric   return nbytes;
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric 
do_max_length() const1524cb14a3feSDimitry Andric int codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept {
1525bdd1243dSDimitry Andric   return __l_ == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l_));
15260b57cec5SDimitry Andric }
1527349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric //                                     Valid UTF ranges
15300b57cec5SDimitry Andric //     UTF-32               UTF-16                          UTF-8               # of code points
15310b57cec5SDimitry Andric //                     first      second       first   second    third   fourth
15320b57cec5SDimitry Andric // 000000 - 00007F  0000 - 007F               00 - 7F                                 127
15330b57cec5SDimitry Andric // 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920
15340b57cec5SDimitry Andric // 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048
15350b57cec5SDimitry Andric // 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152
15360b57cec5SDimitry Andric // 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048
15370b57cec5SDimitry Andric // 00D800 - 00DFFF                invalid
15380b57cec5SDimitry Andric // 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192
15390b57cec5SDimitry Andric // 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608
15400b57cec5SDimitry Andric // 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432
15410b57cec5SDimitry Andric // 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536
15420b57cec5SDimitry Andric 
154381ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
utf16_to_utf8(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))1544cb14a3feSDimitry Andric static codecvt_base::result utf16_to_utf8(
1545cb14a3feSDimitry Andric     const uint16_t* frm,
1546cb14a3feSDimitry Andric     const uint16_t* frm_end,
1547cb14a3feSDimitry Andric     const uint16_t*& frm_nxt,
1548cb14a3feSDimitry Andric     uint8_t* to,
1549cb14a3feSDimitry Andric     uint8_t* to_end,
1550cb14a3feSDimitry Andric     uint8_t*& to_nxt,
1551cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
1552cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
15530b57cec5SDimitry Andric   frm_nxt = frm;
15540b57cec5SDimitry Andric   to_nxt  = to;
1555cb14a3feSDimitry Andric   if (mode & generate_header) {
15560b57cec5SDimitry Andric     if (to_end - to_nxt < 3)
15570b57cec5SDimitry Andric       return codecvt_base::partial;
15580b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xEF);
15590b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBB);
15600b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBF);
15610b57cec5SDimitry Andric   }
1562cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
15630b57cec5SDimitry Andric     uint16_t wc1 = *frm_nxt;
15640b57cec5SDimitry Andric     if (wc1 > Maxcode)
15650b57cec5SDimitry Andric       return codecvt_base::error;
1566cb14a3feSDimitry Andric     if (wc1 < 0x0080) {
15670b57cec5SDimitry Andric       if (to_end - to_nxt < 1)
15680b57cec5SDimitry Andric         return codecvt_base::partial;
15690b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc1);
1570cb14a3feSDimitry Andric     } else if (wc1 < 0x0800) {
15710b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
15720b57cec5SDimitry Andric         return codecvt_base::partial;
15730b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
15740b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1575cb14a3feSDimitry Andric     } else if (wc1 < 0xD800) {
15760b57cec5SDimitry Andric       if (to_end - to_nxt < 3)
15770b57cec5SDimitry Andric         return codecvt_base::partial;
15780b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
15790b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
15800b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1581cb14a3feSDimitry Andric     } else if (wc1 < 0xDC00) {
15820b57cec5SDimitry Andric       if (frm_end - frm_nxt < 2)
15830b57cec5SDimitry Andric         return codecvt_base::partial;
15840b57cec5SDimitry Andric       uint16_t wc2 = frm_nxt[1];
15850b57cec5SDimitry Andric       if ((wc2 & 0xFC00) != 0xDC00)
15860b57cec5SDimitry Andric         return codecvt_base::error;
15870b57cec5SDimitry Andric       if (to_end - to_nxt < 4)
15880b57cec5SDimitry Andric         return codecvt_base::partial;
1589cb14a3feSDimitry Andric       if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
15900b57cec5SDimitry Andric         return codecvt_base::error;
15910b57cec5SDimitry Andric       ++frm_nxt;
15920b57cec5SDimitry Andric       uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
15930b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
15940b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
15950b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
15960b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1597cb14a3feSDimitry Andric     } else if (wc1 < 0xE000) {
15980b57cec5SDimitry Andric       return codecvt_base::error;
1599cb14a3feSDimitry Andric     } else {
16000b57cec5SDimitry Andric       if (to_end - to_nxt < 3)
16010b57cec5SDimitry Andric         return codecvt_base::partial;
16020b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
16030b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
16040b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
16050b57cec5SDimitry Andric     }
16060b57cec5SDimitry Andric   }
16070b57cec5SDimitry Andric   return codecvt_base::ok;
16080b57cec5SDimitry Andric }
16090b57cec5SDimitry Andric 
utf16_to_utf8(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))1610cb14a3feSDimitry Andric static codecvt_base::result utf16_to_utf8(
1611cb14a3feSDimitry Andric     const uint32_t* frm,
1612cb14a3feSDimitry Andric     const uint32_t* frm_end,
1613cb14a3feSDimitry Andric     const uint32_t*& frm_nxt,
1614cb14a3feSDimitry Andric     uint8_t* to,
1615cb14a3feSDimitry Andric     uint8_t* to_end,
1616cb14a3feSDimitry Andric     uint8_t*& to_nxt,
1617cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
1618cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
16190b57cec5SDimitry Andric   frm_nxt = frm;
16200b57cec5SDimitry Andric   to_nxt  = to;
1621cb14a3feSDimitry Andric   if (mode & generate_header) {
16220b57cec5SDimitry Andric     if (to_end - to_nxt < 3)
16230b57cec5SDimitry Andric       return codecvt_base::partial;
16240b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xEF);
16250b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBB);
16260b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBF);
16270b57cec5SDimitry Andric   }
1628cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
16290b57cec5SDimitry Andric     uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
16300b57cec5SDimitry Andric     if (wc1 > Maxcode)
16310b57cec5SDimitry Andric       return codecvt_base::error;
1632cb14a3feSDimitry Andric     if (wc1 < 0x0080) {
16330b57cec5SDimitry Andric       if (to_end - to_nxt < 1)
16340b57cec5SDimitry Andric         return codecvt_base::partial;
16350b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc1);
1636cb14a3feSDimitry Andric     } else if (wc1 < 0x0800) {
16370b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
16380b57cec5SDimitry Andric         return codecvt_base::partial;
16390b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
16400b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1641cb14a3feSDimitry Andric     } else if (wc1 < 0xD800) {
16420b57cec5SDimitry Andric       if (to_end - to_nxt < 3)
16430b57cec5SDimitry Andric         return codecvt_base::partial;
16440b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
16450b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
16460b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1647cb14a3feSDimitry Andric     } else if (wc1 < 0xDC00) {
16480b57cec5SDimitry Andric       if (frm_end - frm_nxt < 2)
16490b57cec5SDimitry Andric         return codecvt_base::partial;
16500b57cec5SDimitry Andric       uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
16510b57cec5SDimitry Andric       if ((wc2 & 0xFC00) != 0xDC00)
16520b57cec5SDimitry Andric         return codecvt_base::error;
16530b57cec5SDimitry Andric       if (to_end - to_nxt < 4)
16540b57cec5SDimitry Andric         return codecvt_base::partial;
1655cb14a3feSDimitry Andric       if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
16560b57cec5SDimitry Andric         return codecvt_base::error;
16570b57cec5SDimitry Andric       ++frm_nxt;
16580b57cec5SDimitry Andric       uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
16590b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
16600b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
16610b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
16620b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1663cb14a3feSDimitry Andric     } else if (wc1 < 0xE000) {
16640b57cec5SDimitry Andric       return codecvt_base::error;
1665cb14a3feSDimitry Andric     } else {
16660b57cec5SDimitry Andric       if (to_end - to_nxt < 3)
16670b57cec5SDimitry Andric         return codecvt_base::partial;
16680b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
16690b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
16700b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
16710b57cec5SDimitry Andric     }
16720b57cec5SDimitry Andric   }
16730b57cec5SDimitry Andric   return codecvt_base::ok;
16740b57cec5SDimitry Andric }
16750b57cec5SDimitry Andric 
utf8_to_utf16(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))1676cb14a3feSDimitry Andric static codecvt_base::result utf8_to_utf16(
1677cb14a3feSDimitry Andric     const uint8_t* frm,
1678cb14a3feSDimitry Andric     const uint8_t* frm_end,
1679cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
1680cb14a3feSDimitry Andric     uint16_t* to,
1681cb14a3feSDimitry Andric     uint16_t* to_end,
1682cb14a3feSDimitry Andric     uint16_t*& to_nxt,
1683cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
1684cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
16850b57cec5SDimitry Andric   frm_nxt = frm;
16860b57cec5SDimitry Andric   to_nxt  = to;
1687cb14a3feSDimitry Andric   if (mode & consume_header) {
1688cb14a3feSDimitry Andric     if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
16890b57cec5SDimitry Andric       frm_nxt += 3;
16900b57cec5SDimitry Andric   }
1691cb14a3feSDimitry Andric   for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) {
16920b57cec5SDimitry Andric     uint8_t c1 = *frm_nxt;
16930b57cec5SDimitry Andric     if (c1 > Maxcode)
16940b57cec5SDimitry Andric       return codecvt_base::error;
1695cb14a3feSDimitry Andric     if (c1 < 0x80) {
16960b57cec5SDimitry Andric       *to_nxt = static_cast<uint16_t>(c1);
16970b57cec5SDimitry Andric       ++frm_nxt;
1698cb14a3feSDimitry Andric     } else if (c1 < 0xC2) {
16990b57cec5SDimitry Andric       return codecvt_base::error;
1700cb14a3feSDimitry Andric     } else if (c1 < 0xE0) {
17010b57cec5SDimitry Andric       if (frm_end - frm_nxt < 2)
17020b57cec5SDimitry Andric         return codecvt_base::partial;
17030b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
17040b57cec5SDimitry Andric       if ((c2 & 0xC0) != 0x80)
17050b57cec5SDimitry Andric         return codecvt_base::error;
17060b57cec5SDimitry Andric       uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
17070b57cec5SDimitry Andric       if (t > Maxcode)
17080b57cec5SDimitry Andric         return codecvt_base::error;
17090b57cec5SDimitry Andric       *to_nxt = t;
17100b57cec5SDimitry Andric       frm_nxt += 2;
1711cb14a3feSDimitry Andric     } else if (c1 < 0xF0) {
17125f757f3fSDimitry Andric       if (frm_end - frm_nxt < 2)
17130b57cec5SDimitry Andric         return codecvt_base::partial;
17140b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
1715cb14a3feSDimitry Andric       switch (c1) {
17160b57cec5SDimitry Andric       case 0xE0:
17170b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0xA0)
17180b57cec5SDimitry Andric           return codecvt_base::error;
17190b57cec5SDimitry Andric         break;
17200b57cec5SDimitry Andric       case 0xED:
17210b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0x80)
17220b57cec5SDimitry Andric           return codecvt_base::error;
17230b57cec5SDimitry Andric         break;
17240b57cec5SDimitry Andric       default:
17250b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
17260b57cec5SDimitry Andric           return codecvt_base::error;
17270b57cec5SDimitry Andric         break;
17280b57cec5SDimitry Andric       }
17295f757f3fSDimitry Andric       if (frm_end - frm_nxt < 3)
17305f757f3fSDimitry Andric         return codecvt_base::partial;
17315f757f3fSDimitry Andric       uint8_t c3 = frm_nxt[2];
17320b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80)
17330b57cec5SDimitry Andric         return codecvt_base::error;
1734cb14a3feSDimitry Andric       uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
17350b57cec5SDimitry Andric       if (t > Maxcode)
17360b57cec5SDimitry Andric         return codecvt_base::error;
17370b57cec5SDimitry Andric       *to_nxt = t;
17380b57cec5SDimitry Andric       frm_nxt += 3;
1739cb14a3feSDimitry Andric     } else if (c1 < 0xF5) {
17405f757f3fSDimitry Andric       if (frm_end - frm_nxt < 2)
17410b57cec5SDimitry Andric         return codecvt_base::partial;
17420b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
1743cb14a3feSDimitry Andric       switch (c1) {
17440b57cec5SDimitry Andric       case 0xF0:
17450b57cec5SDimitry Andric         if (!(0x90 <= c2 && c2 <= 0xBF))
17460b57cec5SDimitry Andric           return codecvt_base::error;
17470b57cec5SDimitry Andric         break;
17480b57cec5SDimitry Andric       case 0xF4:
17490b57cec5SDimitry Andric         if ((c2 & 0xF0) != 0x80)
17500b57cec5SDimitry Andric           return codecvt_base::error;
17510b57cec5SDimitry Andric         break;
17520b57cec5SDimitry Andric       default:
17530b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
17540b57cec5SDimitry Andric           return codecvt_base::error;
17550b57cec5SDimitry Andric         break;
17560b57cec5SDimitry Andric       }
17575f757f3fSDimitry Andric       if (frm_end - frm_nxt < 3)
17585f757f3fSDimitry Andric         return codecvt_base::partial;
17595f757f3fSDimitry Andric       uint8_t c3 = frm_nxt[2];
17605f757f3fSDimitry Andric       if ((c3 & 0xC0) != 0x80)
17615f757f3fSDimitry Andric         return codecvt_base::error;
17625f757f3fSDimitry Andric       if (frm_end - frm_nxt < 4)
17635f757f3fSDimitry Andric         return codecvt_base::partial;
17645f757f3fSDimitry Andric       uint8_t c4 = frm_nxt[3];
17655f757f3fSDimitry Andric       if ((c4 & 0xC0) != 0x80)
17660b57cec5SDimitry Andric         return codecvt_base::error;
17670b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
17680b57cec5SDimitry Andric         return codecvt_base::partial;
1769cb14a3feSDimitry Andric       if ((((c1 & 7UL) << 18) + ((c2 & 0x3FUL) << 12) + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
17700b57cec5SDimitry Andric         return codecvt_base::error;
17710b57cec5SDimitry Andric       *to_nxt = static_cast<uint16_t>(
1772cb14a3feSDimitry Andric           0xD800 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) | ((c2 & 0x0F) << 2) | ((c3 & 0x30) >> 4));
1773cb14a3feSDimitry Andric       *++to_nxt = static_cast<uint16_t>(0xDC00 | ((c3 & 0x0F) << 6) | (c4 & 0x3F));
17740b57cec5SDimitry Andric       frm_nxt += 4;
1775cb14a3feSDimitry Andric     } else {
17760b57cec5SDimitry Andric       return codecvt_base::error;
17770b57cec5SDimitry Andric     }
17780b57cec5SDimitry Andric   }
17790b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
17800b57cec5SDimitry Andric }
17810b57cec5SDimitry Andric 
utf8_to_utf16(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))1782cb14a3feSDimitry Andric static codecvt_base::result utf8_to_utf16(
1783cb14a3feSDimitry Andric     const uint8_t* frm,
1784cb14a3feSDimitry Andric     const uint8_t* frm_end,
1785cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
1786cb14a3feSDimitry Andric     uint32_t* to,
1787cb14a3feSDimitry Andric     uint32_t* to_end,
1788cb14a3feSDimitry Andric     uint32_t*& to_nxt,
1789cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
1790cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
17910b57cec5SDimitry Andric   frm_nxt = frm;
17920b57cec5SDimitry Andric   to_nxt  = to;
1793cb14a3feSDimitry Andric   if (mode & consume_header) {
1794cb14a3feSDimitry Andric     if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
17950b57cec5SDimitry Andric       frm_nxt += 3;
17960b57cec5SDimitry Andric   }
1797cb14a3feSDimitry Andric   for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) {
17980b57cec5SDimitry Andric     uint8_t c1 = *frm_nxt;
17990b57cec5SDimitry Andric     if (c1 > Maxcode)
18000b57cec5SDimitry Andric       return codecvt_base::error;
1801cb14a3feSDimitry Andric     if (c1 < 0x80) {
18020b57cec5SDimitry Andric       *to_nxt = static_cast<uint32_t>(c1);
18030b57cec5SDimitry Andric       ++frm_nxt;
1804cb14a3feSDimitry Andric     } else if (c1 < 0xC2) {
18050b57cec5SDimitry Andric       return codecvt_base::error;
1806cb14a3feSDimitry Andric     } else if (c1 < 0xE0) {
18070b57cec5SDimitry Andric       if (frm_end - frm_nxt < 2)
18080b57cec5SDimitry Andric         return codecvt_base::partial;
18090b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
18100b57cec5SDimitry Andric       if ((c2 & 0xC0) != 0x80)
18110b57cec5SDimitry Andric         return codecvt_base::error;
18120b57cec5SDimitry Andric       uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
18130b57cec5SDimitry Andric       if (t > Maxcode)
18140b57cec5SDimitry Andric         return codecvt_base::error;
18150b57cec5SDimitry Andric       *to_nxt = static_cast<uint32_t>(t);
18160b57cec5SDimitry Andric       frm_nxt += 2;
1817cb14a3feSDimitry Andric     } else if (c1 < 0xF0) {
18185f757f3fSDimitry Andric       if (frm_end - frm_nxt < 2)
18190b57cec5SDimitry Andric         return codecvt_base::partial;
18200b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
1821cb14a3feSDimitry Andric       switch (c1) {
18220b57cec5SDimitry Andric       case 0xE0:
18230b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0xA0)
18240b57cec5SDimitry Andric           return codecvt_base::error;
18250b57cec5SDimitry Andric         break;
18260b57cec5SDimitry Andric       case 0xED:
18270b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0x80)
18280b57cec5SDimitry Andric           return codecvt_base::error;
18290b57cec5SDimitry Andric         break;
18300b57cec5SDimitry Andric       default:
18310b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
18320b57cec5SDimitry Andric           return codecvt_base::error;
18330b57cec5SDimitry Andric         break;
18340b57cec5SDimitry Andric       }
18355f757f3fSDimitry Andric       if (frm_end - frm_nxt < 3)
18365f757f3fSDimitry Andric         return codecvt_base::partial;
18375f757f3fSDimitry Andric       uint8_t c3 = frm_nxt[2];
18380b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80)
18390b57cec5SDimitry Andric         return codecvt_base::error;
1840cb14a3feSDimitry Andric       uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
18410b57cec5SDimitry Andric       if (t > Maxcode)
18420b57cec5SDimitry Andric         return codecvt_base::error;
18430b57cec5SDimitry Andric       *to_nxt = static_cast<uint32_t>(t);
18440b57cec5SDimitry Andric       frm_nxt += 3;
1845cb14a3feSDimitry Andric     } else if (c1 < 0xF5) {
18465f757f3fSDimitry Andric       if (frm_end - frm_nxt < 2)
18470b57cec5SDimitry Andric         return codecvt_base::partial;
18480b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
1849cb14a3feSDimitry Andric       switch (c1) {
18500b57cec5SDimitry Andric       case 0xF0:
18510b57cec5SDimitry Andric         if (!(0x90 <= c2 && c2 <= 0xBF))
18520b57cec5SDimitry Andric           return codecvt_base::error;
18530b57cec5SDimitry Andric         break;
18540b57cec5SDimitry Andric       case 0xF4:
18550b57cec5SDimitry Andric         if ((c2 & 0xF0) != 0x80)
18560b57cec5SDimitry Andric           return codecvt_base::error;
18570b57cec5SDimitry Andric         break;
18580b57cec5SDimitry Andric       default:
18590b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
18600b57cec5SDimitry Andric           return codecvt_base::error;
18610b57cec5SDimitry Andric         break;
18620b57cec5SDimitry Andric       }
18635f757f3fSDimitry Andric       if (frm_end - frm_nxt < 3)
18645f757f3fSDimitry Andric         return codecvt_base::partial;
18655f757f3fSDimitry Andric       uint8_t c3 = frm_nxt[2];
18665f757f3fSDimitry Andric       if ((c3 & 0xC0) != 0x80)
18675f757f3fSDimitry Andric         return codecvt_base::error;
18685f757f3fSDimitry Andric       if (frm_end - frm_nxt < 4)
18695f757f3fSDimitry Andric         return codecvt_base::partial;
18705f757f3fSDimitry Andric       uint8_t c4 = frm_nxt[3];
18715f757f3fSDimitry Andric       if ((c4 & 0xC0) != 0x80)
18720b57cec5SDimitry Andric         return codecvt_base::error;
18730b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
18740b57cec5SDimitry Andric         return codecvt_base::partial;
1875cb14a3feSDimitry Andric       if ((((c1 & 7UL) << 18) + ((c2 & 0x3FUL) << 12) + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
18760b57cec5SDimitry Andric         return codecvt_base::error;
18770b57cec5SDimitry Andric       *to_nxt = static_cast<uint32_t>(
1878cb14a3feSDimitry Andric           0xD800 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) | ((c2 & 0x0F) << 2) | ((c3 & 0x30) >> 4));
1879cb14a3feSDimitry Andric       *++to_nxt = static_cast<uint32_t>(0xDC00 | ((c3 & 0x0F) << 6) | (c4 & 0x3F));
18800b57cec5SDimitry Andric       frm_nxt += 4;
1881cb14a3feSDimitry Andric     } else {
18820b57cec5SDimitry Andric       return codecvt_base::error;
18830b57cec5SDimitry Andric     }
18840b57cec5SDimitry Andric   }
18850b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
18860b57cec5SDimitry Andric }
18870b57cec5SDimitry Andric 
utf8_to_utf16_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))1888cb14a3feSDimitry Andric static int utf8_to_utf16_length(
1889cb14a3feSDimitry Andric     const uint8_t* frm,
1890cb14a3feSDimitry Andric     const uint8_t* frm_end,
1891cb14a3feSDimitry Andric     size_t mx,
1892cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
1893cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
18940b57cec5SDimitry Andric   const uint8_t* frm_nxt = frm;
1895cb14a3feSDimitry Andric   if (mode & consume_header) {
1896cb14a3feSDimitry Andric     if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
18970b57cec5SDimitry Andric       frm_nxt += 3;
18980b57cec5SDimitry Andric   }
1899cb14a3feSDimitry Andric   for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) {
19000b57cec5SDimitry Andric     uint8_t c1 = *frm_nxt;
19010b57cec5SDimitry Andric     if (c1 > Maxcode)
19020b57cec5SDimitry Andric       break;
1903cb14a3feSDimitry Andric     if (c1 < 0x80) {
19040b57cec5SDimitry Andric       ++frm_nxt;
1905cb14a3feSDimitry Andric     } else if (c1 < 0xC2) {
19060b57cec5SDimitry Andric       break;
1907cb14a3feSDimitry Andric     } else if (c1 < 0xE0) {
19080b57cec5SDimitry Andric       if ((frm_end - frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
19090b57cec5SDimitry Andric         break;
19100b57cec5SDimitry Andric       uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
19110b57cec5SDimitry Andric       if (t > Maxcode)
19120b57cec5SDimitry Andric         break;
19130b57cec5SDimitry Andric       frm_nxt += 2;
1914cb14a3feSDimitry Andric     } else if (c1 < 0xF0) {
19150b57cec5SDimitry Andric       if (frm_end - frm_nxt < 3)
19160b57cec5SDimitry Andric         break;
19170b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
19180b57cec5SDimitry Andric       uint8_t c3 = frm_nxt[2];
1919cb14a3feSDimitry Andric       switch (c1) {
19200b57cec5SDimitry Andric       case 0xE0:
19210b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0xA0)
19220b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
19230b57cec5SDimitry Andric         break;
19240b57cec5SDimitry Andric       case 0xED:
19250b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0x80)
19260b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
19270b57cec5SDimitry Andric         break;
19280b57cec5SDimitry Andric       default:
19290b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
19300b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
19310b57cec5SDimitry Andric         break;
19320b57cec5SDimitry Andric       }
19330b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80)
19340b57cec5SDimitry Andric         break;
19350b57cec5SDimitry Andric       if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
19360b57cec5SDimitry Andric         break;
19370b57cec5SDimitry Andric       frm_nxt += 3;
1938cb14a3feSDimitry Andric     } else if (c1 < 0xF5) {
19390b57cec5SDimitry Andric       if (frm_end - frm_nxt < 4 || mx - nchar16_t < 2)
19400b57cec5SDimitry Andric         break;
19410b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
19420b57cec5SDimitry Andric       uint8_t c3 = frm_nxt[2];
19430b57cec5SDimitry Andric       uint8_t c4 = frm_nxt[3];
1944cb14a3feSDimitry Andric       switch (c1) {
19450b57cec5SDimitry Andric       case 0xF0:
19460b57cec5SDimitry Andric         if (!(0x90 <= c2 && c2 <= 0xBF))
19470b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
19480b57cec5SDimitry Andric         break;
19490b57cec5SDimitry Andric       case 0xF4:
19500b57cec5SDimitry Andric         if ((c2 & 0xF0) != 0x80)
19510b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
19520b57cec5SDimitry Andric         break;
19530b57cec5SDimitry Andric       default:
19540b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
19550b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
19560b57cec5SDimitry Andric         break;
19570b57cec5SDimitry Andric       }
19580b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
19590b57cec5SDimitry Andric         break;
1960cb14a3feSDimitry Andric       if ((((c1 & 7UL) << 18) + ((c2 & 0x3FUL) << 12) + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
19610b57cec5SDimitry Andric         break;
19620b57cec5SDimitry Andric       ++nchar16_t;
19630b57cec5SDimitry Andric       frm_nxt += 4;
1964cb14a3feSDimitry Andric     } else {
19650b57cec5SDimitry Andric       break;
19660b57cec5SDimitry Andric     }
19670b57cec5SDimitry Andric   }
19680b57cec5SDimitry Andric   return static_cast<int>(frm_nxt - frm);
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric 
ucs4_to_utf8(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))1971cb14a3feSDimitry Andric static codecvt_base::result ucs4_to_utf8(
1972cb14a3feSDimitry Andric     const uint32_t* frm,
1973cb14a3feSDimitry Andric     const uint32_t* frm_end,
1974cb14a3feSDimitry Andric     const uint32_t*& frm_nxt,
1975cb14a3feSDimitry Andric     uint8_t* to,
1976cb14a3feSDimitry Andric     uint8_t* to_end,
1977cb14a3feSDimitry Andric     uint8_t*& to_nxt,
1978cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
1979cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
19800b57cec5SDimitry Andric   frm_nxt = frm;
19810b57cec5SDimitry Andric   to_nxt  = to;
1982cb14a3feSDimitry Andric   if (mode & generate_header) {
19830b57cec5SDimitry Andric     if (to_end - to_nxt < 3)
19840b57cec5SDimitry Andric       return codecvt_base::partial;
19850b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xEF);
19860b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBB);
19870b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBF);
19880b57cec5SDimitry Andric   }
1989cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
19900b57cec5SDimitry Andric     uint32_t wc = *frm_nxt;
19910b57cec5SDimitry Andric     if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
19920b57cec5SDimitry Andric       return codecvt_base::error;
1993cb14a3feSDimitry Andric     if (wc < 0x000080) {
19940b57cec5SDimitry Andric       if (to_end - to_nxt < 1)
19950b57cec5SDimitry Andric         return codecvt_base::partial;
19960b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc);
1997cb14a3feSDimitry Andric     } else if (wc < 0x000800) {
19980b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
19990b57cec5SDimitry Andric         return codecvt_base::partial;
20000b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
20010b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2002cb14a3feSDimitry Andric     } else if (wc < 0x010000) {
20030b57cec5SDimitry Andric       if (to_end - to_nxt < 3)
20040b57cec5SDimitry Andric         return codecvt_base::partial;
20050b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
20060b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
20070b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2008cb14a3feSDimitry Andric     } else // if (wc < 0x110000)
20090b57cec5SDimitry Andric     {
20100b57cec5SDimitry Andric       if (to_end - to_nxt < 4)
20110b57cec5SDimitry Andric         return codecvt_base::partial;
20120b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
20130b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
20140b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
20150b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
20160b57cec5SDimitry Andric     }
20170b57cec5SDimitry Andric   }
20180b57cec5SDimitry Andric   return codecvt_base::ok;
20190b57cec5SDimitry Andric }
20200b57cec5SDimitry Andric 
utf8_to_ucs4(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2021cb14a3feSDimitry Andric static codecvt_base::result utf8_to_ucs4(
2022cb14a3feSDimitry Andric     const uint8_t* frm,
2023cb14a3feSDimitry Andric     const uint8_t* frm_end,
2024cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
2025cb14a3feSDimitry Andric     uint32_t* to,
2026cb14a3feSDimitry Andric     uint32_t* to_end,
2027cb14a3feSDimitry Andric     uint32_t*& to_nxt,
2028cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2029cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
20300b57cec5SDimitry Andric   frm_nxt = frm;
20310b57cec5SDimitry Andric   to_nxt  = to;
2032cb14a3feSDimitry Andric   if (mode & consume_header) {
2033cb14a3feSDimitry Andric     if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
20340b57cec5SDimitry Andric       frm_nxt += 3;
20350b57cec5SDimitry Andric   }
2036cb14a3feSDimitry Andric   for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) {
20370b57cec5SDimitry Andric     uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2038cb14a3feSDimitry Andric     if (c1 < 0x80) {
20390b57cec5SDimitry Andric       if (c1 > Maxcode)
20400b57cec5SDimitry Andric         return codecvt_base::error;
20410b57cec5SDimitry Andric       *to_nxt = static_cast<uint32_t>(c1);
20420b57cec5SDimitry Andric       ++frm_nxt;
2043cb14a3feSDimitry Andric     } else if (c1 < 0xC2) {
20440b57cec5SDimitry Andric       return codecvt_base::error;
2045cb14a3feSDimitry Andric     } else if (c1 < 0xE0) {
20460b57cec5SDimitry Andric       if (frm_end - frm_nxt < 2)
20470b57cec5SDimitry Andric         return codecvt_base::partial;
20480b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
20490b57cec5SDimitry Andric       if ((c2 & 0xC0) != 0x80)
20500b57cec5SDimitry Andric         return codecvt_base::error;
2051cb14a3feSDimitry Andric       uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
20520b57cec5SDimitry Andric       if (t > Maxcode)
20530b57cec5SDimitry Andric         return codecvt_base::error;
20540b57cec5SDimitry Andric       *to_nxt = t;
20550b57cec5SDimitry Andric       frm_nxt += 2;
2056cb14a3feSDimitry Andric     } else if (c1 < 0xF0) {
20575f757f3fSDimitry Andric       if (frm_end - frm_nxt < 2)
20580b57cec5SDimitry Andric         return codecvt_base::partial;
20590b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
2060cb14a3feSDimitry Andric       switch (c1) {
20610b57cec5SDimitry Andric       case 0xE0:
20620b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0xA0)
20630b57cec5SDimitry Andric           return codecvt_base::error;
20640b57cec5SDimitry Andric         break;
20650b57cec5SDimitry Andric       case 0xED:
20660b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0x80)
20670b57cec5SDimitry Andric           return codecvt_base::error;
20680b57cec5SDimitry Andric         break;
20690b57cec5SDimitry Andric       default:
20700b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
20710b57cec5SDimitry Andric           return codecvt_base::error;
20720b57cec5SDimitry Andric         break;
20730b57cec5SDimitry Andric       }
20745f757f3fSDimitry Andric       if (frm_end - frm_nxt < 3)
20755f757f3fSDimitry Andric         return codecvt_base::partial;
20765f757f3fSDimitry Andric       uint8_t c3 = frm_nxt[2];
20770b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80)
20780b57cec5SDimitry Andric         return codecvt_base::error;
2079cb14a3feSDimitry Andric       uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
20800b57cec5SDimitry Andric       if (t > Maxcode)
20810b57cec5SDimitry Andric         return codecvt_base::error;
20820b57cec5SDimitry Andric       *to_nxt = t;
20830b57cec5SDimitry Andric       frm_nxt += 3;
2084cb14a3feSDimitry Andric     } else if (c1 < 0xF5) {
20855f757f3fSDimitry Andric       if (frm_end - frm_nxt < 2)
20860b57cec5SDimitry Andric         return codecvt_base::partial;
20870b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
2088cb14a3feSDimitry Andric       switch (c1) {
20890b57cec5SDimitry Andric       case 0xF0:
20900b57cec5SDimitry Andric         if (!(0x90 <= c2 && c2 <= 0xBF))
20910b57cec5SDimitry Andric           return codecvt_base::error;
20920b57cec5SDimitry Andric         break;
20930b57cec5SDimitry Andric       case 0xF4:
20940b57cec5SDimitry Andric         if ((c2 & 0xF0) != 0x80)
20950b57cec5SDimitry Andric           return codecvt_base::error;
20960b57cec5SDimitry Andric         break;
20970b57cec5SDimitry Andric       default:
20980b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
20990b57cec5SDimitry Andric           return codecvt_base::error;
21000b57cec5SDimitry Andric         break;
21010b57cec5SDimitry Andric       }
21025f757f3fSDimitry Andric       if (frm_end - frm_nxt < 3)
21035f757f3fSDimitry Andric         return codecvt_base::partial;
21045f757f3fSDimitry Andric       uint8_t c3 = frm_nxt[2];
21055f757f3fSDimitry Andric       if ((c3 & 0xC0) != 0x80)
21065f757f3fSDimitry Andric         return codecvt_base::error;
21075f757f3fSDimitry Andric       if (frm_end - frm_nxt < 4)
21085f757f3fSDimitry Andric         return codecvt_base::partial;
21095f757f3fSDimitry Andric       uint8_t c4 = frm_nxt[3];
21105f757f3fSDimitry Andric       if ((c4 & 0xC0) != 0x80)
21110b57cec5SDimitry Andric         return codecvt_base::error;
2112cb14a3feSDimitry Andric       uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) | (c4 & 0x3F));
21130b57cec5SDimitry Andric       if (t > Maxcode)
21140b57cec5SDimitry Andric         return codecvt_base::error;
21150b57cec5SDimitry Andric       *to_nxt = t;
21160b57cec5SDimitry Andric       frm_nxt += 4;
2117cb14a3feSDimitry Andric     } else {
21180b57cec5SDimitry Andric       return codecvt_base::error;
21190b57cec5SDimitry Andric     }
21200b57cec5SDimitry Andric   }
21210b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
21220b57cec5SDimitry Andric }
21230b57cec5SDimitry Andric 
utf8_to_ucs4_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2124cb14a3feSDimitry Andric static int utf8_to_ucs4_length(
2125cb14a3feSDimitry Andric     const uint8_t* frm,
2126cb14a3feSDimitry Andric     const uint8_t* frm_end,
2127cb14a3feSDimitry Andric     size_t mx,
2128cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2129cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
21300b57cec5SDimitry Andric   const uint8_t* frm_nxt = frm;
2131cb14a3feSDimitry Andric   if (mode & consume_header) {
2132cb14a3feSDimitry Andric     if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
21330b57cec5SDimitry Andric       frm_nxt += 3;
21340b57cec5SDimitry Andric   }
2135cb14a3feSDimitry Andric   for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) {
21360b57cec5SDimitry Andric     uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2137cb14a3feSDimitry Andric     if (c1 < 0x80) {
21380b57cec5SDimitry Andric       if (c1 > Maxcode)
21390b57cec5SDimitry Andric         break;
21400b57cec5SDimitry Andric       ++frm_nxt;
2141cb14a3feSDimitry Andric     } else if (c1 < 0xC2) {
21420b57cec5SDimitry Andric       break;
2143cb14a3feSDimitry Andric     } else if (c1 < 0xE0) {
21440b57cec5SDimitry Andric       if ((frm_end - frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
21450b57cec5SDimitry Andric         break;
21460b57cec5SDimitry Andric       if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
21470b57cec5SDimitry Andric         break;
21480b57cec5SDimitry Andric       frm_nxt += 2;
2149cb14a3feSDimitry Andric     } else if (c1 < 0xF0) {
21500b57cec5SDimitry Andric       if (frm_end - frm_nxt < 3)
21510b57cec5SDimitry Andric         break;
21520b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
21530b57cec5SDimitry Andric       uint8_t c3 = frm_nxt[2];
2154cb14a3feSDimitry Andric       switch (c1) {
21550b57cec5SDimitry Andric       case 0xE0:
21560b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0xA0)
21570b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
21580b57cec5SDimitry Andric         break;
21590b57cec5SDimitry Andric       case 0xED:
21600b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0x80)
21610b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
21620b57cec5SDimitry Andric         break;
21630b57cec5SDimitry Andric       default:
21640b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
21650b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
21660b57cec5SDimitry Andric         break;
21670b57cec5SDimitry Andric       }
21680b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80)
21690b57cec5SDimitry Andric         break;
21700b57cec5SDimitry Andric       if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
21710b57cec5SDimitry Andric         break;
21720b57cec5SDimitry Andric       frm_nxt += 3;
2173cb14a3feSDimitry Andric     } else if (c1 < 0xF5) {
21740b57cec5SDimitry Andric       if (frm_end - frm_nxt < 4)
21750b57cec5SDimitry Andric         break;
21760b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
21770b57cec5SDimitry Andric       uint8_t c3 = frm_nxt[2];
21780b57cec5SDimitry Andric       uint8_t c4 = frm_nxt[3];
2179cb14a3feSDimitry Andric       switch (c1) {
21800b57cec5SDimitry Andric       case 0xF0:
21810b57cec5SDimitry Andric         if (!(0x90 <= c2 && c2 <= 0xBF))
21820b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
21830b57cec5SDimitry Andric         break;
21840b57cec5SDimitry Andric       case 0xF4:
21850b57cec5SDimitry Andric         if ((c2 & 0xF0) != 0x80)
21860b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
21870b57cec5SDimitry Andric         break;
21880b57cec5SDimitry Andric       default:
21890b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
21900b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
21910b57cec5SDimitry Andric         break;
21920b57cec5SDimitry Andric       }
21930b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
21940b57cec5SDimitry Andric         break;
2195cb14a3feSDimitry Andric       if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
21960b57cec5SDimitry Andric         break;
21970b57cec5SDimitry Andric       frm_nxt += 4;
2198cb14a3feSDimitry Andric     } else {
21990b57cec5SDimitry Andric       break;
22000b57cec5SDimitry Andric     }
22010b57cec5SDimitry Andric   }
22020b57cec5SDimitry Andric   return static_cast<int>(frm_nxt - frm);
22030b57cec5SDimitry Andric }
22040b57cec5SDimitry Andric 
ucs2_to_utf8(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2205cb14a3feSDimitry Andric static codecvt_base::result ucs2_to_utf8(
2206cb14a3feSDimitry Andric     const uint16_t* frm,
2207cb14a3feSDimitry Andric     const uint16_t* frm_end,
2208cb14a3feSDimitry Andric     const uint16_t*& frm_nxt,
2209cb14a3feSDimitry Andric     uint8_t* to,
2210cb14a3feSDimitry Andric     uint8_t* to_end,
2211cb14a3feSDimitry Andric     uint8_t*& to_nxt,
2212cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2213cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
22140b57cec5SDimitry Andric   frm_nxt = frm;
22150b57cec5SDimitry Andric   to_nxt  = to;
2216cb14a3feSDimitry Andric   if (mode & generate_header) {
22170b57cec5SDimitry Andric     if (to_end - to_nxt < 3)
22180b57cec5SDimitry Andric       return codecvt_base::partial;
22190b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xEF);
22200b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBB);
22210b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xBF);
22220b57cec5SDimitry Andric   }
2223cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
22240b57cec5SDimitry Andric     uint16_t wc = *frm_nxt;
22250b57cec5SDimitry Andric     if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
22260b57cec5SDimitry Andric       return codecvt_base::error;
2227cb14a3feSDimitry Andric     if (wc < 0x0080) {
22280b57cec5SDimitry Andric       if (to_end - to_nxt < 1)
22290b57cec5SDimitry Andric         return codecvt_base::partial;
22300b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc);
2231cb14a3feSDimitry Andric     } else if (wc < 0x0800) {
22320b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
22330b57cec5SDimitry Andric         return codecvt_base::partial;
22340b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
22350b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2236cb14a3feSDimitry Andric     } else // if (wc <= 0xFFFF)
22370b57cec5SDimitry Andric     {
22380b57cec5SDimitry Andric       if (to_end - to_nxt < 3)
22390b57cec5SDimitry Andric         return codecvt_base::partial;
22400b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
22410b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
22420b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
22430b57cec5SDimitry Andric     }
22440b57cec5SDimitry Andric   }
22450b57cec5SDimitry Andric   return codecvt_base::ok;
22460b57cec5SDimitry Andric }
22470b57cec5SDimitry Andric 
utf8_to_ucs2(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2248cb14a3feSDimitry Andric static codecvt_base::result utf8_to_ucs2(
2249cb14a3feSDimitry Andric     const uint8_t* frm,
2250cb14a3feSDimitry Andric     const uint8_t* frm_end,
2251cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
2252cb14a3feSDimitry Andric     uint16_t* to,
2253cb14a3feSDimitry Andric     uint16_t* to_end,
2254cb14a3feSDimitry Andric     uint16_t*& to_nxt,
2255cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2256cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
22570b57cec5SDimitry Andric   frm_nxt = frm;
22580b57cec5SDimitry Andric   to_nxt  = to;
2259cb14a3feSDimitry Andric   if (mode & consume_header) {
2260cb14a3feSDimitry Andric     if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
22610b57cec5SDimitry Andric       frm_nxt += 3;
22620b57cec5SDimitry Andric   }
2263cb14a3feSDimitry Andric   for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) {
22640b57cec5SDimitry Andric     uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2265cb14a3feSDimitry Andric     if (c1 < 0x80) {
22660b57cec5SDimitry Andric       if (c1 > Maxcode)
22670b57cec5SDimitry Andric         return codecvt_base::error;
22680b57cec5SDimitry Andric       *to_nxt = static_cast<uint16_t>(c1);
22690b57cec5SDimitry Andric       ++frm_nxt;
2270cb14a3feSDimitry Andric     } else if (c1 < 0xC2) {
22710b57cec5SDimitry Andric       return codecvt_base::error;
2272cb14a3feSDimitry Andric     } else if (c1 < 0xE0) {
22730b57cec5SDimitry Andric       if (frm_end - frm_nxt < 2)
22740b57cec5SDimitry Andric         return codecvt_base::partial;
22750b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
22760b57cec5SDimitry Andric       if ((c2 & 0xC0) != 0x80)
22770b57cec5SDimitry Andric         return codecvt_base::error;
2278cb14a3feSDimitry Andric       uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
22790b57cec5SDimitry Andric       if (t > Maxcode)
22800b57cec5SDimitry Andric         return codecvt_base::error;
22810b57cec5SDimitry Andric       *to_nxt = t;
22820b57cec5SDimitry Andric       frm_nxt += 2;
2283cb14a3feSDimitry Andric     } else if (c1 < 0xF0) {
22845f757f3fSDimitry Andric       if (frm_end - frm_nxt < 2)
22850b57cec5SDimitry Andric         return codecvt_base::partial;
22860b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
2287cb14a3feSDimitry Andric       switch (c1) {
22880b57cec5SDimitry Andric       case 0xE0:
22890b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0xA0)
22900b57cec5SDimitry Andric           return codecvt_base::error;
22910b57cec5SDimitry Andric         break;
22920b57cec5SDimitry Andric       case 0xED:
22930b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0x80)
22940b57cec5SDimitry Andric           return codecvt_base::error;
22950b57cec5SDimitry Andric         break;
22960b57cec5SDimitry Andric       default:
22970b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
22980b57cec5SDimitry Andric           return codecvt_base::error;
22990b57cec5SDimitry Andric         break;
23000b57cec5SDimitry Andric       }
23015f757f3fSDimitry Andric       if (frm_end - frm_nxt < 3)
23025f757f3fSDimitry Andric         return codecvt_base::partial;
23035f757f3fSDimitry Andric       uint8_t c3 = frm_nxt[2];
23040b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80)
23050b57cec5SDimitry Andric         return codecvt_base::error;
2306cb14a3feSDimitry Andric       uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
23070b57cec5SDimitry Andric       if (t > Maxcode)
23080b57cec5SDimitry Andric         return codecvt_base::error;
23090b57cec5SDimitry Andric       *to_nxt = t;
23100b57cec5SDimitry Andric       frm_nxt += 3;
2311cb14a3feSDimitry Andric     } else {
23120b57cec5SDimitry Andric       return codecvt_base::error;
23130b57cec5SDimitry Andric     }
23140b57cec5SDimitry Andric   }
23150b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
23160b57cec5SDimitry Andric }
23170b57cec5SDimitry Andric 
utf8_to_ucs2_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2318cb14a3feSDimitry Andric static int utf8_to_ucs2_length(
2319cb14a3feSDimitry Andric     const uint8_t* frm,
2320cb14a3feSDimitry Andric     const uint8_t* frm_end,
2321cb14a3feSDimitry Andric     size_t mx,
2322cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2323cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
23240b57cec5SDimitry Andric   const uint8_t* frm_nxt = frm;
2325cb14a3feSDimitry Andric   if (mode & consume_header) {
2326cb14a3feSDimitry Andric     if (frm_end - frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && frm_nxt[2] == 0xBF)
23270b57cec5SDimitry Andric       frm_nxt += 3;
23280b57cec5SDimitry Andric   }
2329cb14a3feSDimitry Andric   for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) {
23300b57cec5SDimitry Andric     uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2331cb14a3feSDimitry Andric     if (c1 < 0x80) {
23320b57cec5SDimitry Andric       if (c1 > Maxcode)
23330b57cec5SDimitry Andric         break;
23340b57cec5SDimitry Andric       ++frm_nxt;
2335cb14a3feSDimitry Andric     } else if (c1 < 0xC2) {
23360b57cec5SDimitry Andric       break;
2337cb14a3feSDimitry Andric     } else if (c1 < 0xE0) {
23380b57cec5SDimitry Andric       if ((frm_end - frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
23390b57cec5SDimitry Andric         break;
23400b57cec5SDimitry Andric       if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
23410b57cec5SDimitry Andric         break;
23420b57cec5SDimitry Andric       frm_nxt += 2;
2343cb14a3feSDimitry Andric     } else if (c1 < 0xF0) {
23440b57cec5SDimitry Andric       if (frm_end - frm_nxt < 3)
23450b57cec5SDimitry Andric         break;
23460b57cec5SDimitry Andric       uint8_t c2 = frm_nxt[1];
23470b57cec5SDimitry Andric       uint8_t c3 = frm_nxt[2];
2348cb14a3feSDimitry Andric       switch (c1) {
23490b57cec5SDimitry Andric       case 0xE0:
23500b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0xA0)
23510b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
23520b57cec5SDimitry Andric         break;
23530b57cec5SDimitry Andric       case 0xED:
23540b57cec5SDimitry Andric         if ((c2 & 0xE0) != 0x80)
23550b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
23560b57cec5SDimitry Andric         break;
23570b57cec5SDimitry Andric       default:
23580b57cec5SDimitry Andric         if ((c2 & 0xC0) != 0x80)
23590b57cec5SDimitry Andric           return static_cast<int>(frm_nxt - frm);
23600b57cec5SDimitry Andric         break;
23610b57cec5SDimitry Andric       }
23620b57cec5SDimitry Andric       if ((c3 & 0xC0) != 0x80)
23630b57cec5SDimitry Andric         break;
23640b57cec5SDimitry Andric       if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
23650b57cec5SDimitry Andric         break;
23660b57cec5SDimitry Andric       frm_nxt += 3;
2367cb14a3feSDimitry Andric     } else {
23680b57cec5SDimitry Andric       break;
23690b57cec5SDimitry Andric     }
23700b57cec5SDimitry Andric   }
23710b57cec5SDimitry Andric   return static_cast<int>(frm_nxt - frm);
23720b57cec5SDimitry Andric }
23730b57cec5SDimitry Andric 
ucs4_to_utf16be(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2374cb14a3feSDimitry Andric static codecvt_base::result ucs4_to_utf16be(
2375cb14a3feSDimitry Andric     const uint32_t* frm,
2376cb14a3feSDimitry Andric     const uint32_t* frm_end,
2377cb14a3feSDimitry Andric     const uint32_t*& frm_nxt,
2378cb14a3feSDimitry Andric     uint8_t* to,
2379cb14a3feSDimitry Andric     uint8_t* to_end,
2380cb14a3feSDimitry Andric     uint8_t*& to_nxt,
2381cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2382cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
23830b57cec5SDimitry Andric   frm_nxt = frm;
23840b57cec5SDimitry Andric   to_nxt  = to;
2385cb14a3feSDimitry Andric   if (mode & generate_header) {
23860b57cec5SDimitry Andric     if (to_end - to_nxt < 2)
23870b57cec5SDimitry Andric       return codecvt_base::partial;
23880b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFE);
23890b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFF);
23900b57cec5SDimitry Andric   }
2391cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
23920b57cec5SDimitry Andric     uint32_t wc = *frm_nxt;
23930b57cec5SDimitry Andric     if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
23940b57cec5SDimitry Andric       return codecvt_base::error;
2395cb14a3feSDimitry Andric     if (wc < 0x010000) {
23960b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
23970b57cec5SDimitry Andric         return codecvt_base::partial;
23980b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc >> 8);
23990b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc);
2400cb14a3feSDimitry Andric     } else {
24010b57cec5SDimitry Andric       if (to_end - to_nxt < 4)
24020b57cec5SDimitry Andric         return codecvt_base::partial;
2403cb14a3feSDimitry Andric       uint16_t t = static_cast<uint16_t>(0xD800 | ((((wc & 0x1F0000) >> 16) - 1) << 6) | ((wc & 0x00FC00) >> 10));
24040b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t >> 8);
24050b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t);
24060b57cec5SDimitry Andric       t          = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
24070b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t >> 8);
24080b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t);
24090b57cec5SDimitry Andric     }
24100b57cec5SDimitry Andric   }
24110b57cec5SDimitry Andric   return codecvt_base::ok;
24120b57cec5SDimitry Andric }
24130b57cec5SDimitry Andric 
utf16be_to_ucs4(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2414cb14a3feSDimitry Andric static codecvt_base::result utf16be_to_ucs4(
2415cb14a3feSDimitry Andric     const uint8_t* frm,
2416cb14a3feSDimitry Andric     const uint8_t* frm_end,
2417cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
2418cb14a3feSDimitry Andric     uint32_t* to,
2419cb14a3feSDimitry Andric     uint32_t* to_end,
2420cb14a3feSDimitry Andric     uint32_t*& to_nxt,
2421cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2422cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
24230b57cec5SDimitry Andric   frm_nxt = frm;
24240b57cec5SDimitry Andric   to_nxt  = to;
2425cb14a3feSDimitry Andric   if (mode & consume_header) {
24260b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
24270b57cec5SDimitry Andric       frm_nxt += 2;
24280b57cec5SDimitry Andric   }
2429cb14a3feSDimitry Andric   for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) {
24300b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
24310b57cec5SDimitry Andric     if ((c1 & 0xFC00) == 0xDC00)
24320b57cec5SDimitry Andric       return codecvt_base::error;
2433cb14a3feSDimitry Andric     if ((c1 & 0xFC00) != 0xD800) {
24340b57cec5SDimitry Andric       if (c1 > Maxcode)
24350b57cec5SDimitry Andric         return codecvt_base::error;
24360b57cec5SDimitry Andric       *to_nxt = static_cast<uint32_t>(c1);
24370b57cec5SDimitry Andric       frm_nxt += 2;
2438cb14a3feSDimitry Andric     } else {
24390b57cec5SDimitry Andric       if (frm_end - frm_nxt < 4)
24400b57cec5SDimitry Andric         return codecvt_base::partial;
24410b57cec5SDimitry Andric       uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
24420b57cec5SDimitry Andric       if ((c2 & 0xFC00) != 0xDC00)
24430b57cec5SDimitry Andric         return codecvt_base::error;
2444cb14a3feSDimitry Andric       uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
24450b57cec5SDimitry Andric       if (t > Maxcode)
24460b57cec5SDimitry Andric         return codecvt_base::error;
24470b57cec5SDimitry Andric       *to_nxt = t;
24480b57cec5SDimitry Andric       frm_nxt += 4;
24490b57cec5SDimitry Andric     }
24500b57cec5SDimitry Andric   }
24510b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
24520b57cec5SDimitry Andric }
24530b57cec5SDimitry Andric 
utf16be_to_ucs4_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2454cb14a3feSDimitry Andric static int utf16be_to_ucs4_length(
2455cb14a3feSDimitry Andric     const uint8_t* frm,
2456cb14a3feSDimitry Andric     const uint8_t* frm_end,
2457cb14a3feSDimitry Andric     size_t mx,
2458cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2459cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
24600b57cec5SDimitry Andric   const uint8_t* frm_nxt = frm;
2461cb14a3feSDimitry Andric   if (mode & consume_header) {
24620b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
24630b57cec5SDimitry Andric       frm_nxt += 2;
24640b57cec5SDimitry Andric   }
2465cb14a3feSDimitry Andric   for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) {
24660b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
24670b57cec5SDimitry Andric     if ((c1 & 0xFC00) == 0xDC00)
24680b57cec5SDimitry Andric       break;
2469cb14a3feSDimitry Andric     if ((c1 & 0xFC00) != 0xD800) {
24700b57cec5SDimitry Andric       if (c1 > Maxcode)
24710b57cec5SDimitry Andric         break;
24720b57cec5SDimitry Andric       frm_nxt += 2;
2473cb14a3feSDimitry Andric     } else {
24740b57cec5SDimitry Andric       if (frm_end - frm_nxt < 4)
24750b57cec5SDimitry Andric         break;
24760b57cec5SDimitry Andric       uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
24770b57cec5SDimitry Andric       if ((c2 & 0xFC00) != 0xDC00)
24780b57cec5SDimitry Andric         break;
2479cb14a3feSDimitry Andric       uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
24800b57cec5SDimitry Andric       if (t > Maxcode)
24810b57cec5SDimitry Andric         break;
24820b57cec5SDimitry Andric       frm_nxt += 4;
24830b57cec5SDimitry Andric     }
24840b57cec5SDimitry Andric   }
24850b57cec5SDimitry Andric   return static_cast<int>(frm_nxt - frm);
24860b57cec5SDimitry Andric }
24870b57cec5SDimitry Andric 
ucs4_to_utf16le(const uint32_t * frm,const uint32_t * frm_end,const uint32_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2488cb14a3feSDimitry Andric static codecvt_base::result ucs4_to_utf16le(
2489cb14a3feSDimitry Andric     const uint32_t* frm,
2490cb14a3feSDimitry Andric     const uint32_t* frm_end,
2491cb14a3feSDimitry Andric     const uint32_t*& frm_nxt,
2492cb14a3feSDimitry Andric     uint8_t* to,
2493cb14a3feSDimitry Andric     uint8_t* to_end,
2494cb14a3feSDimitry Andric     uint8_t*& to_nxt,
2495cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2496cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
24970b57cec5SDimitry Andric   frm_nxt = frm;
24980b57cec5SDimitry Andric   to_nxt  = to;
2499cb14a3feSDimitry Andric   if (mode & generate_header) {
25000b57cec5SDimitry Andric     if (to_end - to_nxt < 2)
25010b57cec5SDimitry Andric       return codecvt_base::partial;
25020b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFF);
25030b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFE);
25040b57cec5SDimitry Andric   }
2505cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
25060b57cec5SDimitry Andric     uint32_t wc = *frm_nxt;
25070b57cec5SDimitry Andric     if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
25080b57cec5SDimitry Andric       return codecvt_base::error;
2509cb14a3feSDimitry Andric     if (wc < 0x010000) {
25100b57cec5SDimitry Andric       if (to_end - to_nxt < 2)
25110b57cec5SDimitry Andric         return codecvt_base::partial;
25120b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc);
25130b57cec5SDimitry Andric       *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2514cb14a3feSDimitry Andric     } else {
25150b57cec5SDimitry Andric       if (to_end - to_nxt < 4)
25160b57cec5SDimitry Andric         return codecvt_base::partial;
2517cb14a3feSDimitry Andric       uint16_t t = static_cast<uint16_t>(0xD800 | ((((wc & 0x1F0000) >> 16) - 1) << 6) | ((wc & 0x00FC00) >> 10));
25180b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t);
25190b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t >> 8);
25200b57cec5SDimitry Andric       t          = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
25210b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t);
25220b57cec5SDimitry Andric       *to_nxt++  = static_cast<uint8_t>(t >> 8);
25230b57cec5SDimitry Andric     }
25240b57cec5SDimitry Andric   }
25250b57cec5SDimitry Andric   return codecvt_base::ok;
25260b57cec5SDimitry Andric }
25270b57cec5SDimitry Andric 
utf16le_to_ucs4(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint32_t * to,uint32_t * to_end,uint32_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2528cb14a3feSDimitry Andric static codecvt_base::result utf16le_to_ucs4(
2529cb14a3feSDimitry Andric     const uint8_t* frm,
2530cb14a3feSDimitry Andric     const uint8_t* frm_end,
2531cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
2532cb14a3feSDimitry Andric     uint32_t* to,
2533cb14a3feSDimitry Andric     uint32_t* to_end,
2534cb14a3feSDimitry Andric     uint32_t*& to_nxt,
2535cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2536cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
25370b57cec5SDimitry Andric   frm_nxt = frm;
25380b57cec5SDimitry Andric   to_nxt  = to;
2539cb14a3feSDimitry Andric   if (mode & consume_header) {
25400b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
25410b57cec5SDimitry Andric       frm_nxt += 2;
25420b57cec5SDimitry Andric   }
2543cb14a3feSDimitry Andric   for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) {
25440b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
25450b57cec5SDimitry Andric     if ((c1 & 0xFC00) == 0xDC00)
25460b57cec5SDimitry Andric       return codecvt_base::error;
2547cb14a3feSDimitry Andric     if ((c1 & 0xFC00) != 0xD800) {
25480b57cec5SDimitry Andric       if (c1 > Maxcode)
25490b57cec5SDimitry Andric         return codecvt_base::error;
25500b57cec5SDimitry Andric       *to_nxt = static_cast<uint32_t>(c1);
25510b57cec5SDimitry Andric       frm_nxt += 2;
2552cb14a3feSDimitry Andric     } else {
25530b57cec5SDimitry Andric       if (frm_end - frm_nxt < 4)
25540b57cec5SDimitry Andric         return codecvt_base::partial;
25550b57cec5SDimitry Andric       uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
25560b57cec5SDimitry Andric       if ((c2 & 0xFC00) != 0xDC00)
25570b57cec5SDimitry Andric         return codecvt_base::error;
2558cb14a3feSDimitry Andric       uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
25590b57cec5SDimitry Andric       if (t > Maxcode)
25600b57cec5SDimitry Andric         return codecvt_base::error;
25610b57cec5SDimitry Andric       *to_nxt = t;
25620b57cec5SDimitry Andric       frm_nxt += 4;
25630b57cec5SDimitry Andric     }
25640b57cec5SDimitry Andric   }
25650b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
25660b57cec5SDimitry Andric }
25670b57cec5SDimitry Andric 
utf16le_to_ucs4_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2568cb14a3feSDimitry Andric static int utf16le_to_ucs4_length(
2569cb14a3feSDimitry Andric     const uint8_t* frm,
2570cb14a3feSDimitry Andric     const uint8_t* frm_end,
2571cb14a3feSDimitry Andric     size_t mx,
2572cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2573cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
25740b57cec5SDimitry Andric   const uint8_t* frm_nxt = frm;
2575cb14a3feSDimitry Andric   if (mode & consume_header) {
25760b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
25770b57cec5SDimitry Andric       frm_nxt += 2;
25780b57cec5SDimitry Andric   }
2579cb14a3feSDimitry Andric   for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) {
25800b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
25810b57cec5SDimitry Andric     if ((c1 & 0xFC00) == 0xDC00)
25820b57cec5SDimitry Andric       break;
2583cb14a3feSDimitry Andric     if ((c1 & 0xFC00) != 0xD800) {
25840b57cec5SDimitry Andric       if (c1 > Maxcode)
25850b57cec5SDimitry Andric         break;
25860b57cec5SDimitry Andric       frm_nxt += 2;
2587cb14a3feSDimitry Andric     } else {
25880b57cec5SDimitry Andric       if (frm_end - frm_nxt < 4)
25890b57cec5SDimitry Andric         break;
25900b57cec5SDimitry Andric       uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
25910b57cec5SDimitry Andric       if ((c2 & 0xFC00) != 0xDC00)
25920b57cec5SDimitry Andric         break;
2593cb14a3feSDimitry Andric       uint32_t t = static_cast<uint32_t>(((((c1 & 0x03C0) >> 6) + 1) << 16) | ((c1 & 0x003F) << 10) | (c2 & 0x03FF));
25940b57cec5SDimitry Andric       if (t > Maxcode)
25950b57cec5SDimitry Andric         break;
25960b57cec5SDimitry Andric       frm_nxt += 4;
25970b57cec5SDimitry Andric     }
25980b57cec5SDimitry Andric   }
25990b57cec5SDimitry Andric   return static_cast<int>(frm_nxt - frm);
26000b57cec5SDimitry Andric }
26010b57cec5SDimitry Andric 
ucs2_to_utf16be(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2602cb14a3feSDimitry Andric static codecvt_base::result ucs2_to_utf16be(
2603cb14a3feSDimitry Andric     const uint16_t* frm,
2604cb14a3feSDimitry Andric     const uint16_t* frm_end,
2605cb14a3feSDimitry Andric     const uint16_t*& frm_nxt,
2606cb14a3feSDimitry Andric     uint8_t* to,
2607cb14a3feSDimitry Andric     uint8_t* to_end,
2608cb14a3feSDimitry Andric     uint8_t*& to_nxt,
2609cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2610cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
26110b57cec5SDimitry Andric   frm_nxt = frm;
26120b57cec5SDimitry Andric   to_nxt  = to;
2613cb14a3feSDimitry Andric   if (mode & generate_header) {
26140b57cec5SDimitry Andric     if (to_end - to_nxt < 2)
26150b57cec5SDimitry Andric       return codecvt_base::partial;
26160b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFE);
26170b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFF);
26180b57cec5SDimitry Andric   }
2619cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
26200b57cec5SDimitry Andric     uint16_t wc = *frm_nxt;
26210b57cec5SDimitry Andric     if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
26220b57cec5SDimitry Andric       return codecvt_base::error;
26230b57cec5SDimitry Andric     if (to_end - to_nxt < 2)
26240b57cec5SDimitry Andric       return codecvt_base::partial;
26250b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(wc >> 8);
26260b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(wc);
26270b57cec5SDimitry Andric   }
26280b57cec5SDimitry Andric   return codecvt_base::ok;
26290b57cec5SDimitry Andric }
26300b57cec5SDimitry Andric 
utf16be_to_ucs2(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2631cb14a3feSDimitry Andric static codecvt_base::result utf16be_to_ucs2(
2632cb14a3feSDimitry Andric     const uint8_t* frm,
2633cb14a3feSDimitry Andric     const uint8_t* frm_end,
2634cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
2635cb14a3feSDimitry Andric     uint16_t* to,
2636cb14a3feSDimitry Andric     uint16_t* to_end,
2637cb14a3feSDimitry Andric     uint16_t*& to_nxt,
2638cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2639cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
26400b57cec5SDimitry Andric   frm_nxt = frm;
26410b57cec5SDimitry Andric   to_nxt  = to;
2642cb14a3feSDimitry Andric   if (mode & consume_header) {
26430b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
26440b57cec5SDimitry Andric       frm_nxt += 2;
26450b57cec5SDimitry Andric   }
2646cb14a3feSDimitry Andric   for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) {
26470b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
26480b57cec5SDimitry Andric     if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
26490b57cec5SDimitry Andric       return codecvt_base::error;
26500b57cec5SDimitry Andric     *to_nxt = c1;
26510b57cec5SDimitry Andric     frm_nxt += 2;
26520b57cec5SDimitry Andric   }
26530b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
26540b57cec5SDimitry Andric }
26550b57cec5SDimitry Andric 
utf16be_to_ucs2_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2656cb14a3feSDimitry Andric static int utf16be_to_ucs2_length(
2657cb14a3feSDimitry Andric     const uint8_t* frm,
2658cb14a3feSDimitry Andric     const uint8_t* frm_end,
2659cb14a3feSDimitry Andric     size_t mx,
2660cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2661cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
26620b57cec5SDimitry Andric   const uint8_t* frm_nxt = frm;
2663cb14a3feSDimitry Andric   if (mode & consume_header) {
26640b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
26650b57cec5SDimitry Andric       frm_nxt += 2;
26660b57cec5SDimitry Andric   }
2667cb14a3feSDimitry Andric   for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) {
26680b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
26690b57cec5SDimitry Andric     if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
26700b57cec5SDimitry Andric       break;
26710b57cec5SDimitry Andric     frm_nxt += 2;
26720b57cec5SDimitry Andric   }
26730b57cec5SDimitry Andric   return static_cast<int>(frm_nxt - frm);
26740b57cec5SDimitry Andric }
26750b57cec5SDimitry Andric 
ucs2_to_utf16le(const uint16_t * frm,const uint16_t * frm_end,const uint16_t * & frm_nxt,uint8_t * to,uint8_t * to_end,uint8_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2676cb14a3feSDimitry Andric static codecvt_base::result ucs2_to_utf16le(
2677cb14a3feSDimitry Andric     const uint16_t* frm,
2678cb14a3feSDimitry Andric     const uint16_t* frm_end,
2679cb14a3feSDimitry Andric     const uint16_t*& frm_nxt,
2680cb14a3feSDimitry Andric     uint8_t* to,
2681cb14a3feSDimitry Andric     uint8_t* to_end,
2682cb14a3feSDimitry Andric     uint8_t*& to_nxt,
2683cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2684cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
26850b57cec5SDimitry Andric   frm_nxt = frm;
26860b57cec5SDimitry Andric   to_nxt  = to;
2687cb14a3feSDimitry Andric   if (mode & generate_header) {
26880b57cec5SDimitry Andric     if (to_end - to_nxt < 2)
26890b57cec5SDimitry Andric       return codecvt_base::partial;
26900b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFF);
26910b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(0xFE);
26920b57cec5SDimitry Andric   }
2693cb14a3feSDimitry Andric   for (; frm_nxt < frm_end; ++frm_nxt) {
26940b57cec5SDimitry Andric     uint16_t wc = *frm_nxt;
26950b57cec5SDimitry Andric     if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
26960b57cec5SDimitry Andric       return codecvt_base::error;
26970b57cec5SDimitry Andric     if (to_end - to_nxt < 2)
26980b57cec5SDimitry Andric       return codecvt_base::partial;
26990b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(wc);
27000b57cec5SDimitry Andric     *to_nxt++ = static_cast<uint8_t>(wc >> 8);
27010b57cec5SDimitry Andric   }
27020b57cec5SDimitry Andric   return codecvt_base::ok;
27030b57cec5SDimitry Andric }
27040b57cec5SDimitry Andric 
utf16le_to_ucs2(const uint8_t * frm,const uint8_t * frm_end,const uint8_t * & frm_nxt,uint16_t * to,uint16_t * to_end,uint16_t * & to_nxt,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2705cb14a3feSDimitry Andric static codecvt_base::result utf16le_to_ucs2(
2706cb14a3feSDimitry Andric     const uint8_t* frm,
2707cb14a3feSDimitry Andric     const uint8_t* frm_end,
2708cb14a3feSDimitry Andric     const uint8_t*& frm_nxt,
2709cb14a3feSDimitry Andric     uint16_t* to,
2710cb14a3feSDimitry Andric     uint16_t* to_end,
2711cb14a3feSDimitry Andric     uint16_t*& to_nxt,
2712cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2713cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
27140b57cec5SDimitry Andric   frm_nxt = frm;
27150b57cec5SDimitry Andric   to_nxt  = to;
2716cb14a3feSDimitry Andric   if (mode & consume_header) {
27170b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
27180b57cec5SDimitry Andric       frm_nxt += 2;
27190b57cec5SDimitry Andric   }
2720cb14a3feSDimitry Andric   for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) {
27210b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
27220b57cec5SDimitry Andric     if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
27230b57cec5SDimitry Andric       return codecvt_base::error;
27240b57cec5SDimitry Andric     *to_nxt = c1;
27250b57cec5SDimitry Andric     frm_nxt += 2;
27260b57cec5SDimitry Andric   }
27270b57cec5SDimitry Andric   return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
27280b57cec5SDimitry Andric }
27290b57cec5SDimitry Andric 
utf16le_to_ucs2_length(const uint8_t * frm,const uint8_t * frm_end,size_t mx,unsigned long Maxcode=0x10FFFF,codecvt_mode mode=codecvt_mode (0))2730cb14a3feSDimitry Andric static int utf16le_to_ucs2_length(
2731cb14a3feSDimitry Andric     const uint8_t* frm,
2732cb14a3feSDimitry Andric     const uint8_t* frm_end,
2733cb14a3feSDimitry Andric     size_t mx,
2734cb14a3feSDimitry Andric     unsigned long Maxcode = 0x10FFFF,
2735cb14a3feSDimitry Andric     codecvt_mode mode     = codecvt_mode(0)) {
27360b57cec5SDimitry Andric   const uint8_t* frm_nxt = frm;
27370b57cec5SDimitry Andric   frm_nxt                = frm;
2738cb14a3feSDimitry Andric   if (mode & consume_header) {
27390b57cec5SDimitry Andric     if (frm_end - frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
27400b57cec5SDimitry Andric       frm_nxt += 2;
27410b57cec5SDimitry Andric   }
2742cb14a3feSDimitry Andric   for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) {
27430b57cec5SDimitry Andric     uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
27440b57cec5SDimitry Andric     if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
27450b57cec5SDimitry Andric       break;
27460b57cec5SDimitry Andric     frm_nxt += 2;
27470b57cec5SDimitry Andric   }
27480b57cec5SDimitry Andric   return static_cast<int>(frm_nxt - frm);
27490b57cec5SDimitry Andric }
27500b57cec5SDimitry Andric 
275181ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
275281ad6265SDimitry Andric 
27530b57cec5SDimitry Andric // template <> class codecvt<char16_t, char, mbstate_t>
27540b57cec5SDimitry Andric 
27555f757f3fSDimitry Andric constinit locale::id codecvt<char16_t, char, mbstate_t>::id;
27560b57cec5SDimitry Andric 
~codecvt()2757cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::~codecvt() {}
27580b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const2759cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::result codecvt<char16_t, char, mbstate_t>::do_out(
2760cb14a3feSDimitry Andric     state_type&,
2761cb14a3feSDimitry Andric     const intern_type* frm,
2762cb14a3feSDimitry Andric     const intern_type* frm_end,
2763cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
2764cb14a3feSDimitry Andric     extern_type* to,
2765cb14a3feSDimitry Andric     extern_type* to_end,
2766cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
27670b57cec5SDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
27680b57cec5SDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
27690b57cec5SDimitry Andric   const uint16_t* _frm_nxt = _frm;
27700b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
27710b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
27720b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
27730b57cec5SDimitry Andric   result r                 = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
27740b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
27750b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
27760b57cec5SDimitry Andric   return r;
27770b57cec5SDimitry Andric }
27780b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const2779cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::result codecvt<char16_t, char, mbstate_t>::do_in(
2780cb14a3feSDimitry Andric     state_type&,
2781cb14a3feSDimitry Andric     const extern_type* frm,
2782cb14a3feSDimitry Andric     const extern_type* frm_end,
2783cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
2784cb14a3feSDimitry Andric     intern_type* to,
2785cb14a3feSDimitry Andric     intern_type* to_end,
2786cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
27870b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
27880b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
27890b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
27900b57cec5SDimitry Andric   uint16_t* _to           = reinterpret_cast<uint16_t*>(to);
27910b57cec5SDimitry Andric   uint16_t* _to_end       = reinterpret_cast<uint16_t*>(to_end);
27920b57cec5SDimitry Andric   uint16_t* _to_nxt       = _to;
27930b57cec5SDimitry Andric   result r                = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
27940b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
27950b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
27960b57cec5SDimitry Andric   return r;
27970b57cec5SDimitry Andric }
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric codecvt<char16_t, char, mbstate_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const2800cb14a3feSDimitry Andric codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
28010b57cec5SDimitry Andric   to_nxt = to;
28020b57cec5SDimitry Andric   return noconv;
28030b57cec5SDimitry Andric }
28040b57cec5SDimitry Andric 
do_encoding() const2805cb14a3feSDimitry Andric int codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept { return 0; }
28060b57cec5SDimitry Andric 
do_always_noconv() const2807cb14a3feSDimitry Andric bool codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; }
28080b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const2809cb14a3feSDimitry Andric int codecvt<char16_t, char, mbstate_t>::do_length(
2810cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
28110b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
28120b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
28130b57cec5SDimitry Andric   return utf8_to_utf16_length(_frm, _frm_end, mx);
28140b57cec5SDimitry Andric }
28150b57cec5SDimitry Andric 
do_max_length() const2816cb14a3feSDimitry Andric int codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept { return 4; }
28170b57cec5SDimitry Andric 
2818fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
2819e8d8bef9SDimitry Andric 
2820e8d8bef9SDimitry Andric // template <> class codecvt<char16_t, char8_t, mbstate_t>
2821e8d8bef9SDimitry Andric 
28225f757f3fSDimitry Andric constinit locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
2823e8d8bef9SDimitry Andric 
~codecvt()2824cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::~codecvt() {}
2825e8d8bef9SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const2826cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result codecvt<char16_t, char8_t, mbstate_t>::do_out(
2827cb14a3feSDimitry Andric     state_type&,
2828cb14a3feSDimitry Andric     const intern_type* frm,
2829cb14a3feSDimitry Andric     const intern_type* frm_end,
2830cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
2831cb14a3feSDimitry Andric     extern_type* to,
2832cb14a3feSDimitry Andric     extern_type* to_end,
2833cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
2834e8d8bef9SDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
2835e8d8bef9SDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2836e8d8bef9SDimitry Andric   const uint16_t* _frm_nxt = _frm;
2837e8d8bef9SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
2838e8d8bef9SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
2839e8d8bef9SDimitry Andric   uint8_t* _to_nxt         = _to;
2840e8d8bef9SDimitry Andric   result r                 = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2841e8d8bef9SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
2842e8d8bef9SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
2843e8d8bef9SDimitry Andric   return r;
2844e8d8bef9SDimitry Andric }
2845e8d8bef9SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const2846cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result codecvt<char16_t, char8_t, mbstate_t>::do_in(
2847cb14a3feSDimitry Andric     state_type&,
2848cb14a3feSDimitry Andric     const extern_type* frm,
2849cb14a3feSDimitry Andric     const extern_type* frm_end,
2850cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
2851cb14a3feSDimitry Andric     intern_type* to,
2852cb14a3feSDimitry Andric     intern_type* to_end,
2853cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
2854e8d8bef9SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
2855e8d8bef9SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2856e8d8bef9SDimitry Andric   const uint8_t* _frm_nxt = _frm;
2857e8d8bef9SDimitry Andric   uint16_t* _to           = reinterpret_cast<uint16_t*>(to);
2858e8d8bef9SDimitry Andric   uint16_t* _to_end       = reinterpret_cast<uint16_t*>(to_end);
2859e8d8bef9SDimitry Andric   uint16_t* _to_nxt       = _to;
2860e8d8bef9SDimitry Andric   result r                = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2861e8d8bef9SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
2862e8d8bef9SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
2863e8d8bef9SDimitry Andric   return r;
2864e8d8bef9SDimitry Andric }
2865e8d8bef9SDimitry Andric 
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const2866cb14a3feSDimitry Andric codecvt<char16_t, char8_t, mbstate_t>::result codecvt<char16_t, char8_t, mbstate_t>::do_unshift(
2867cb14a3feSDimitry Andric     state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
2868e8d8bef9SDimitry Andric   to_nxt = to;
2869e8d8bef9SDimitry Andric   return noconv;
2870e8d8bef9SDimitry Andric }
2871e8d8bef9SDimitry Andric 
do_encoding() const2872cb14a3feSDimitry Andric int codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept { return 0; }
2873e8d8bef9SDimitry Andric 
do_always_noconv() const2874cb14a3feSDimitry Andric bool codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept { return false; }
2875e8d8bef9SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const2876cb14a3feSDimitry Andric int codecvt<char16_t, char8_t, mbstate_t>::do_length(
2877cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
2878e8d8bef9SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
2879e8d8bef9SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2880e8d8bef9SDimitry Andric   return utf8_to_utf16_length(_frm, _frm_end, mx);
2881e8d8bef9SDimitry Andric }
2882e8d8bef9SDimitry Andric 
do_max_length() const2883cb14a3feSDimitry Andric int codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept { return 4; }
2884e8d8bef9SDimitry Andric 
2885e8d8bef9SDimitry Andric #endif
2886e8d8bef9SDimitry Andric 
28870b57cec5SDimitry Andric // template <> class codecvt<char32_t, char, mbstate_t>
28880b57cec5SDimitry Andric 
28895f757f3fSDimitry Andric constinit locale::id codecvt<char32_t, char, mbstate_t>::id;
28900b57cec5SDimitry Andric 
~codecvt()2891cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::~codecvt() {}
28920b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const2893cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::result codecvt<char32_t, char, mbstate_t>::do_out(
2894cb14a3feSDimitry Andric     state_type&,
2895cb14a3feSDimitry Andric     const intern_type* frm,
2896cb14a3feSDimitry Andric     const intern_type* frm_end,
2897cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
2898cb14a3feSDimitry Andric     extern_type* to,
2899cb14a3feSDimitry Andric     extern_type* to_end,
2900cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
29010b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
29020b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
29030b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
29040b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
29050b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
29060b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
29070b57cec5SDimitry Andric   result r                 = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
29080b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
29090b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
29100b57cec5SDimitry Andric   return r;
29110b57cec5SDimitry Andric }
29120b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const2913cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::result codecvt<char32_t, char, mbstate_t>::do_in(
2914cb14a3feSDimitry Andric     state_type&,
2915cb14a3feSDimitry Andric     const extern_type* frm,
2916cb14a3feSDimitry Andric     const extern_type* frm_end,
2917cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
2918cb14a3feSDimitry Andric     intern_type* to,
2919cb14a3feSDimitry Andric     intern_type* to_end,
2920cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
29210b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
29220b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
29230b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
29240b57cec5SDimitry Andric   uint32_t* _to           = reinterpret_cast<uint32_t*>(to);
29250b57cec5SDimitry Andric   uint32_t* _to_end       = reinterpret_cast<uint32_t*>(to_end);
29260b57cec5SDimitry Andric   uint32_t* _to_nxt       = _to;
29270b57cec5SDimitry Andric   result r                = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
29280b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
29290b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
29300b57cec5SDimitry Andric   return r;
29310b57cec5SDimitry Andric }
29320b57cec5SDimitry Andric 
29330b57cec5SDimitry Andric codecvt<char32_t, char, mbstate_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const2934cb14a3feSDimitry Andric codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
29350b57cec5SDimitry Andric   to_nxt = to;
29360b57cec5SDimitry Andric   return noconv;
29370b57cec5SDimitry Andric }
29380b57cec5SDimitry Andric 
do_encoding() const2939cb14a3feSDimitry Andric int codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept { return 0; }
29400b57cec5SDimitry Andric 
do_always_noconv() const2941cb14a3feSDimitry Andric bool codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept { return false; }
29420b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const2943cb14a3feSDimitry Andric int codecvt<char32_t, char, mbstate_t>::do_length(
2944cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
29450b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
29460b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
29470b57cec5SDimitry Andric   return utf8_to_ucs4_length(_frm, _frm_end, mx);
29480b57cec5SDimitry Andric }
29490b57cec5SDimitry Andric 
do_max_length() const2950cb14a3feSDimitry Andric int codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept { return 4; }
29510b57cec5SDimitry Andric 
2952fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
2953e8d8bef9SDimitry Andric 
2954e8d8bef9SDimitry Andric // template <> class codecvt<char32_t, char8_t, mbstate_t>
2955e8d8bef9SDimitry Andric 
29565f757f3fSDimitry Andric constinit locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
2957e8d8bef9SDimitry Andric 
~codecvt()2958cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::~codecvt() {}
2959e8d8bef9SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const2960cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result codecvt<char32_t, char8_t, mbstate_t>::do_out(
2961cb14a3feSDimitry Andric     state_type&,
2962cb14a3feSDimitry Andric     const intern_type* frm,
2963cb14a3feSDimitry Andric     const intern_type* frm_end,
2964cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
2965cb14a3feSDimitry Andric     extern_type* to,
2966cb14a3feSDimitry Andric     extern_type* to_end,
2967cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
2968e8d8bef9SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
2969e8d8bef9SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
2970e8d8bef9SDimitry Andric   const uint32_t* _frm_nxt = _frm;
2971e8d8bef9SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
2972e8d8bef9SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
2973e8d8bef9SDimitry Andric   uint8_t* _to_nxt         = _to;
2974e8d8bef9SDimitry Andric   result r                 = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2975e8d8bef9SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
2976e8d8bef9SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
2977e8d8bef9SDimitry Andric   return r;
2978e8d8bef9SDimitry Andric }
2979e8d8bef9SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const2980cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result codecvt<char32_t, char8_t, mbstate_t>::do_in(
2981cb14a3feSDimitry Andric     state_type&,
2982cb14a3feSDimitry Andric     const extern_type* frm,
2983cb14a3feSDimitry Andric     const extern_type* frm_end,
2984cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
2985cb14a3feSDimitry Andric     intern_type* to,
2986cb14a3feSDimitry Andric     intern_type* to_end,
2987cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
2988e8d8bef9SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
2989e8d8bef9SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2990e8d8bef9SDimitry Andric   const uint8_t* _frm_nxt = _frm;
2991e8d8bef9SDimitry Andric   uint32_t* _to           = reinterpret_cast<uint32_t*>(to);
2992e8d8bef9SDimitry Andric   uint32_t* _to_end       = reinterpret_cast<uint32_t*>(to_end);
2993e8d8bef9SDimitry Andric   uint32_t* _to_nxt       = _to;
2994e8d8bef9SDimitry Andric   result r                = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2995e8d8bef9SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
2996e8d8bef9SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
2997e8d8bef9SDimitry Andric   return r;
2998e8d8bef9SDimitry Andric }
2999e8d8bef9SDimitry Andric 
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3000cb14a3feSDimitry Andric codecvt<char32_t, char8_t, mbstate_t>::result codecvt<char32_t, char8_t, mbstate_t>::do_unshift(
3001cb14a3feSDimitry Andric     state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
3002e8d8bef9SDimitry Andric   to_nxt = to;
3003e8d8bef9SDimitry Andric   return noconv;
3004e8d8bef9SDimitry Andric }
3005e8d8bef9SDimitry Andric 
do_encoding() const3006cb14a3feSDimitry Andric int codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept { return 0; }
3007e8d8bef9SDimitry Andric 
do_always_noconv() const3008cb14a3feSDimitry Andric bool codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept { return false; }
3009e8d8bef9SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3010cb14a3feSDimitry Andric int codecvt<char32_t, char8_t, mbstate_t>::do_length(
3011cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
3012e8d8bef9SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
3013e8d8bef9SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3014e8d8bef9SDimitry Andric   return utf8_to_ucs4_length(_frm, _frm_end, mx);
3015e8d8bef9SDimitry Andric }
3016e8d8bef9SDimitry Andric 
do_max_length() const3017cb14a3feSDimitry Andric int codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept { return 4; }
3018e8d8bef9SDimitry Andric 
3019e8d8bef9SDimitry Andric #endif
3020e8d8bef9SDimitry Andric 
30210b57cec5SDimitry Andric // __codecvt_utf8<wchar_t>
30220b57cec5SDimitry Andric 
3023349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3024cb14a3feSDimitry Andric __codecvt_utf8<wchar_t>::result __codecvt_utf8<wchar_t>::do_out(
3025cb14a3feSDimitry Andric     state_type&,
3026cb14a3feSDimitry Andric     const intern_type* frm,
3027cb14a3feSDimitry Andric     const intern_type* frm_end,
3028cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3029cb14a3feSDimitry Andric     extern_type* to,
3030cb14a3feSDimitry Andric     extern_type* to_end,
3031cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
30320b57cec5SDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
30330b57cec5SDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
30340b57cec5SDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
30350b57cec5SDimitry Andric   const uint16_t* _frm_nxt = _frm;
30360b57cec5SDimitry Andric #  else
30370b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
30380b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
30390b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
30400b57cec5SDimitry Andric #  endif
30410b57cec5SDimitry Andric   uint8_t* _to     = reinterpret_cast<uint8_t*>(to);
30420b57cec5SDimitry Andric   uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
30430b57cec5SDimitry Andric   uint8_t* _to_nxt = _to;
30440b57cec5SDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3045cb14a3feSDimitry Andric   result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
30460b57cec5SDimitry Andric #  else
3047cb14a3feSDimitry Andric   result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
30480b57cec5SDimitry Andric #  endif
30490b57cec5SDimitry Andric   frm_nxt = frm + (_frm_nxt - _frm);
30500b57cec5SDimitry Andric   to_nxt  = to + (_to_nxt - _to);
30510b57cec5SDimitry Andric   return r;
30520b57cec5SDimitry Andric }
30530b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3054cb14a3feSDimitry Andric __codecvt_utf8<wchar_t>::result __codecvt_utf8<wchar_t>::do_in(
3055cb14a3feSDimitry Andric     state_type&,
3056cb14a3feSDimitry Andric     const extern_type* frm,
3057cb14a3feSDimitry Andric     const extern_type* frm_end,
3058cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3059cb14a3feSDimitry Andric     intern_type* to,
3060cb14a3feSDimitry Andric     intern_type* to_end,
3061cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
30620b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
30630b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
30640b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
30650b57cec5SDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
30660b57cec5SDimitry Andric   uint16_t* _to     = reinterpret_cast<uint16_t*>(to);
30670b57cec5SDimitry Andric   uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
30680b57cec5SDimitry Andric   uint16_t* _to_nxt = _to;
3069cb14a3feSDimitry Andric   result r          = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
30700b57cec5SDimitry Andric #  else
30710b57cec5SDimitry Andric   uint32_t* _to     = reinterpret_cast<uint32_t*>(to);
30720b57cec5SDimitry Andric   uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
30730b57cec5SDimitry Andric   uint32_t* _to_nxt = _to;
3074cb14a3feSDimitry Andric   result r          = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
30750b57cec5SDimitry Andric #  endif
30760b57cec5SDimitry Andric   frm_nxt = frm + (_frm_nxt - _frm);
30770b57cec5SDimitry Andric   to_nxt  = to + (_to_nxt - _to);
30780b57cec5SDimitry Andric   return r;
30790b57cec5SDimitry Andric }
30800b57cec5SDimitry Andric 
30810b57cec5SDimitry Andric __codecvt_utf8<wchar_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3082cb14a3feSDimitry Andric __codecvt_utf8<wchar_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
30830b57cec5SDimitry Andric   to_nxt = to;
30840b57cec5SDimitry Andric   return noconv;
30850b57cec5SDimitry Andric }
30860b57cec5SDimitry Andric 
do_encoding() const3087cb14a3feSDimitry Andric int __codecvt_utf8<wchar_t>::do_encoding() const noexcept { return 0; }
30880b57cec5SDimitry Andric 
do_always_noconv() const3089cb14a3feSDimitry Andric bool __codecvt_utf8<wchar_t>::do_always_noconv() const noexcept { return false; }
30900b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3091cb14a3feSDimitry Andric int __codecvt_utf8<wchar_t>::do_length(
3092cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
30930b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
30940b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3095349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3096bdd1243dSDimitry Andric   return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3097349cc55cSDimitry Andric #  else
3098bdd1243dSDimitry Andric   return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3099349cc55cSDimitry Andric #  endif
31000b57cec5SDimitry Andric }
31010b57cec5SDimitry Andric 
310281ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3103cb14a3feSDimitry Andric int __codecvt_utf8<wchar_t>::do_max_length() const noexcept {
3104349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3105bdd1243dSDimitry Andric   if (__mode_ & consume_header)
3106349cc55cSDimitry Andric     return 6;
3107349cc55cSDimitry Andric   return 3;
3108349cc55cSDimitry Andric #  else
3109bdd1243dSDimitry Andric   if (__mode_ & consume_header)
31100b57cec5SDimitry Andric     return 7;
31110b57cec5SDimitry Andric   return 4;
3112349cc55cSDimitry Andric #  endif
31130b57cec5SDimitry Andric }
3114349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
31150b57cec5SDimitry Andric 
31160b57cec5SDimitry Andric // __codecvt_utf8<char16_t>
31170b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3118cb14a3feSDimitry Andric __codecvt_utf8<char16_t>::result __codecvt_utf8<char16_t>::do_out(
3119cb14a3feSDimitry Andric     state_type&,
3120cb14a3feSDimitry Andric     const intern_type* frm,
3121cb14a3feSDimitry Andric     const intern_type* frm_end,
3122cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3123cb14a3feSDimitry Andric     extern_type* to,
3124cb14a3feSDimitry Andric     extern_type* to_end,
3125cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
31260b57cec5SDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
31270b57cec5SDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
31280b57cec5SDimitry Andric   const uint16_t* _frm_nxt = _frm;
31290b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
31300b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
31310b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3132cb14a3feSDimitry Andric   result r                 = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
31330b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
31340b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
31350b57cec5SDimitry Andric   return r;
31360b57cec5SDimitry Andric }
31370b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3138cb14a3feSDimitry Andric __codecvt_utf8<char16_t>::result __codecvt_utf8<char16_t>::do_in(
3139cb14a3feSDimitry Andric     state_type&,
3140cb14a3feSDimitry Andric     const extern_type* frm,
3141cb14a3feSDimitry Andric     const extern_type* frm_end,
3142cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3143cb14a3feSDimitry Andric     intern_type* to,
3144cb14a3feSDimitry Andric     intern_type* to_end,
3145cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
31460b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
31470b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
31480b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
31490b57cec5SDimitry Andric   uint16_t* _to           = reinterpret_cast<uint16_t*>(to);
31500b57cec5SDimitry Andric   uint16_t* _to_end       = reinterpret_cast<uint16_t*>(to_end);
31510b57cec5SDimitry Andric   uint16_t* _to_nxt       = _to;
3152cb14a3feSDimitry Andric   result r                = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
31530b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
31540b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
31550b57cec5SDimitry Andric   return r;
31560b57cec5SDimitry Andric }
31570b57cec5SDimitry Andric 
31580b57cec5SDimitry Andric __codecvt_utf8<char16_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3159cb14a3feSDimitry Andric __codecvt_utf8<char16_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
31600b57cec5SDimitry Andric   to_nxt = to;
31610b57cec5SDimitry Andric   return noconv;
31620b57cec5SDimitry Andric }
31630b57cec5SDimitry Andric 
do_encoding() const3164cb14a3feSDimitry Andric int __codecvt_utf8<char16_t>::do_encoding() const noexcept { return 0; }
31650b57cec5SDimitry Andric 
do_always_noconv() const3166cb14a3feSDimitry Andric bool __codecvt_utf8<char16_t>::do_always_noconv() const noexcept { return false; }
31670b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3168cb14a3feSDimitry Andric int __codecvt_utf8<char16_t>::do_length(
3169cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
31700b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
31710b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3172bdd1243dSDimitry Andric   return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
31730b57cec5SDimitry Andric }
31740b57cec5SDimitry Andric 
317581ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3176cb14a3feSDimitry Andric int __codecvt_utf8<char16_t>::do_max_length() const noexcept {
3177bdd1243dSDimitry Andric   if (__mode_ & consume_header)
31780b57cec5SDimitry Andric     return 6;
31790b57cec5SDimitry Andric   return 3;
31800b57cec5SDimitry Andric }
318181ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
31820b57cec5SDimitry Andric 
31830b57cec5SDimitry Andric // __codecvt_utf8<char32_t>
31840b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3185cb14a3feSDimitry Andric __codecvt_utf8<char32_t>::result __codecvt_utf8<char32_t>::do_out(
3186cb14a3feSDimitry Andric     state_type&,
3187cb14a3feSDimitry Andric     const intern_type* frm,
3188cb14a3feSDimitry Andric     const intern_type* frm_end,
3189cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3190cb14a3feSDimitry Andric     extern_type* to,
3191cb14a3feSDimitry Andric     extern_type* to_end,
3192cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
31930b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
31940b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
31950b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
31960b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
31970b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
31980b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3199cb14a3feSDimitry Andric   result r                 = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
32000b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
32010b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
32020b57cec5SDimitry Andric   return r;
32030b57cec5SDimitry Andric }
32040b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3205cb14a3feSDimitry Andric __codecvt_utf8<char32_t>::result __codecvt_utf8<char32_t>::do_in(
3206cb14a3feSDimitry Andric     state_type&,
3207cb14a3feSDimitry Andric     const extern_type* frm,
3208cb14a3feSDimitry Andric     const extern_type* frm_end,
3209cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3210cb14a3feSDimitry Andric     intern_type* to,
3211cb14a3feSDimitry Andric     intern_type* to_end,
3212cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
32130b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
32140b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
32150b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
32160b57cec5SDimitry Andric   uint32_t* _to           = reinterpret_cast<uint32_t*>(to);
32170b57cec5SDimitry Andric   uint32_t* _to_end       = reinterpret_cast<uint32_t*>(to_end);
32180b57cec5SDimitry Andric   uint32_t* _to_nxt       = _to;
3219cb14a3feSDimitry Andric   result r                = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
32200b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
32210b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
32220b57cec5SDimitry Andric   return r;
32230b57cec5SDimitry Andric }
32240b57cec5SDimitry Andric 
32250b57cec5SDimitry Andric __codecvt_utf8<char32_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3226cb14a3feSDimitry Andric __codecvt_utf8<char32_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
32270b57cec5SDimitry Andric   to_nxt = to;
32280b57cec5SDimitry Andric   return noconv;
32290b57cec5SDimitry Andric }
32300b57cec5SDimitry Andric 
do_encoding() const3231cb14a3feSDimitry Andric int __codecvt_utf8<char32_t>::do_encoding() const noexcept { return 0; }
32320b57cec5SDimitry Andric 
do_always_noconv() const3233cb14a3feSDimitry Andric bool __codecvt_utf8<char32_t>::do_always_noconv() const noexcept { return false; }
32340b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3235cb14a3feSDimitry Andric int __codecvt_utf8<char32_t>::do_length(
3236cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
32370b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
32380b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3239bdd1243dSDimitry Andric   return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
32400b57cec5SDimitry Andric }
32410b57cec5SDimitry Andric 
324281ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3243cb14a3feSDimitry Andric int __codecvt_utf8<char32_t>::do_max_length() const noexcept {
3244bdd1243dSDimitry Andric   if (__mode_ & consume_header)
32450b57cec5SDimitry Andric     return 7;
32460b57cec5SDimitry Andric   return 4;
32470b57cec5SDimitry Andric }
324881ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
32490b57cec5SDimitry Andric 
32500b57cec5SDimitry Andric // __codecvt_utf16<wchar_t, false>
32510b57cec5SDimitry Andric 
3252349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3253cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, false>::result __codecvt_utf16<wchar_t, false>::do_out(
3254cb14a3feSDimitry Andric     state_type&,
3255cb14a3feSDimitry Andric     const intern_type* frm,
3256cb14a3feSDimitry Andric     const intern_type* frm_end,
3257cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3258cb14a3feSDimitry Andric     extern_type* to,
3259cb14a3feSDimitry Andric     extern_type* to_end,
3260cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
3261349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3262349cc55cSDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
3263349cc55cSDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3264349cc55cSDimitry Andric   const uint16_t* _frm_nxt = _frm;
3265349cc55cSDimitry Andric #  else
32660b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
32670b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
32680b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
3269349cc55cSDimitry Andric #  endif
32700b57cec5SDimitry Andric   uint8_t* _to     = reinterpret_cast<uint8_t*>(to);
32710b57cec5SDimitry Andric   uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
32720b57cec5SDimitry Andric   uint8_t* _to_nxt = _to;
3273349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3274cb14a3feSDimitry Andric   result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3275349cc55cSDimitry Andric #  else
3276cb14a3feSDimitry Andric   result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3277349cc55cSDimitry Andric #  endif
32780b57cec5SDimitry Andric   frm_nxt = frm + (_frm_nxt - _frm);
32790b57cec5SDimitry Andric   to_nxt  = to + (_to_nxt - _to);
32800b57cec5SDimitry Andric   return r;
32810b57cec5SDimitry Andric }
32820b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3283cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, false>::result __codecvt_utf16<wchar_t, false>::do_in(
3284cb14a3feSDimitry Andric     state_type&,
3285cb14a3feSDimitry Andric     const extern_type* frm,
3286cb14a3feSDimitry Andric     const extern_type* frm_end,
3287cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3288cb14a3feSDimitry Andric     intern_type* to,
3289cb14a3feSDimitry Andric     intern_type* to_end,
3290cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
32910b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
32920b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
32930b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
3294349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3295349cc55cSDimitry Andric   uint16_t* _to     = reinterpret_cast<uint16_t*>(to);
3296349cc55cSDimitry Andric   uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3297349cc55cSDimitry Andric   uint16_t* _to_nxt = _to;
3298cb14a3feSDimitry Andric   result r          = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3299349cc55cSDimitry Andric #  else
33000b57cec5SDimitry Andric   uint32_t* _to     = reinterpret_cast<uint32_t*>(to);
33010b57cec5SDimitry Andric   uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
33020b57cec5SDimitry Andric   uint32_t* _to_nxt = _to;
3303cb14a3feSDimitry Andric   result r          = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3304349cc55cSDimitry Andric #  endif
33050b57cec5SDimitry Andric   frm_nxt = frm + (_frm_nxt - _frm);
33060b57cec5SDimitry Andric   to_nxt  = to + (_to_nxt - _to);
33070b57cec5SDimitry Andric   return r;
33080b57cec5SDimitry Andric }
33090b57cec5SDimitry Andric 
33100b57cec5SDimitry Andric __codecvt_utf16<wchar_t, false>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3311cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, false>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
33120b57cec5SDimitry Andric   to_nxt = to;
33130b57cec5SDimitry Andric   return noconv;
33140b57cec5SDimitry Andric }
33150b57cec5SDimitry Andric 
do_encoding() const3316cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, false>::do_encoding() const noexcept { return 0; }
33170b57cec5SDimitry Andric 
do_always_noconv() const3318cb14a3feSDimitry Andric bool __codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept { return false; }
33190b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3320cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, false>::do_length(
3321cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
33220b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
33230b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3324349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3325bdd1243dSDimitry Andric   return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3326349cc55cSDimitry Andric #  else
3327bdd1243dSDimitry Andric   return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3328349cc55cSDimitry Andric #  endif
33290b57cec5SDimitry Andric }
33300b57cec5SDimitry Andric 
do_max_length() const3331cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, false>::do_max_length() const noexcept {
3332349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3333bdd1243dSDimitry Andric   if (__mode_ & consume_header)
3334349cc55cSDimitry Andric     return 4;
3335349cc55cSDimitry Andric   return 2;
3336349cc55cSDimitry Andric #  else
3337bdd1243dSDimitry Andric   if (__mode_ & consume_header)
33380b57cec5SDimitry Andric     return 6;
33390b57cec5SDimitry Andric   return 4;
3340349cc55cSDimitry Andric #  endif
33410b57cec5SDimitry Andric }
33420b57cec5SDimitry Andric 
33430b57cec5SDimitry Andric // __codecvt_utf16<wchar_t, true>
33440b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3345cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, true>::result __codecvt_utf16<wchar_t, true>::do_out(
3346cb14a3feSDimitry Andric     state_type&,
3347cb14a3feSDimitry Andric     const intern_type* frm,
3348cb14a3feSDimitry Andric     const intern_type* frm_end,
3349cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3350cb14a3feSDimitry Andric     extern_type* to,
3351cb14a3feSDimitry Andric     extern_type* to_end,
3352cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
3353349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3354349cc55cSDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
3355349cc55cSDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3356349cc55cSDimitry Andric   const uint16_t* _frm_nxt = _frm;
3357349cc55cSDimitry Andric #  else
33580b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
33590b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
33600b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
3361349cc55cSDimitry Andric #  endif
33620b57cec5SDimitry Andric   uint8_t* _to     = reinterpret_cast<uint8_t*>(to);
33630b57cec5SDimitry Andric   uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
33640b57cec5SDimitry Andric   uint8_t* _to_nxt = _to;
3365349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3366cb14a3feSDimitry Andric   result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3367349cc55cSDimitry Andric #  else
3368cb14a3feSDimitry Andric   result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3369349cc55cSDimitry Andric #  endif
33700b57cec5SDimitry Andric   frm_nxt = frm + (_frm_nxt - _frm);
33710b57cec5SDimitry Andric   to_nxt  = to + (_to_nxt - _to);
33720b57cec5SDimitry Andric   return r;
33730b57cec5SDimitry Andric }
33740b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3375cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, true>::result __codecvt_utf16<wchar_t, true>::do_in(
3376cb14a3feSDimitry Andric     state_type&,
3377cb14a3feSDimitry Andric     const extern_type* frm,
3378cb14a3feSDimitry Andric     const extern_type* frm_end,
3379cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3380cb14a3feSDimitry Andric     intern_type* to,
3381cb14a3feSDimitry Andric     intern_type* to_end,
3382cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
33830b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
33840b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
33850b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
3386349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3387349cc55cSDimitry Andric   uint16_t* _to     = reinterpret_cast<uint16_t*>(to);
3388349cc55cSDimitry Andric   uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3389349cc55cSDimitry Andric   uint16_t* _to_nxt = _to;
3390cb14a3feSDimitry Andric   result r          = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3391349cc55cSDimitry Andric #  else
33920b57cec5SDimitry Andric   uint32_t* _to     = reinterpret_cast<uint32_t*>(to);
33930b57cec5SDimitry Andric   uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
33940b57cec5SDimitry Andric   uint32_t* _to_nxt = _to;
3395cb14a3feSDimitry Andric   result r          = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
3396349cc55cSDimitry Andric #  endif
33970b57cec5SDimitry Andric   frm_nxt = frm + (_frm_nxt - _frm);
33980b57cec5SDimitry Andric   to_nxt  = to + (_to_nxt - _to);
33990b57cec5SDimitry Andric   return r;
34000b57cec5SDimitry Andric }
34010b57cec5SDimitry Andric 
34020b57cec5SDimitry Andric __codecvt_utf16<wchar_t, true>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3403cb14a3feSDimitry Andric __codecvt_utf16<wchar_t, true>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
34040b57cec5SDimitry Andric   to_nxt = to;
34050b57cec5SDimitry Andric   return noconv;
34060b57cec5SDimitry Andric }
34070b57cec5SDimitry Andric 
do_encoding() const3408cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, true>::do_encoding() const noexcept { return 0; }
34090b57cec5SDimitry Andric 
do_always_noconv() const3410cb14a3feSDimitry Andric bool __codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept { return false; }
34110b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3412cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, true>::do_length(
3413cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
34140b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
34150b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3416349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3417bdd1243dSDimitry Andric   return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3418349cc55cSDimitry Andric #  else
3419bdd1243dSDimitry Andric   return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3420349cc55cSDimitry Andric #  endif
34210b57cec5SDimitry Andric }
34220b57cec5SDimitry Andric 
do_max_length() const3423cb14a3feSDimitry Andric int __codecvt_utf16<wchar_t, true>::do_max_length() const noexcept {
3424349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3425bdd1243dSDimitry Andric   if (__mode_ & consume_header)
3426349cc55cSDimitry Andric     return 4;
3427349cc55cSDimitry Andric   return 2;
3428349cc55cSDimitry Andric #  else
3429bdd1243dSDimitry Andric   if (__mode_ & consume_header)
34300b57cec5SDimitry Andric     return 6;
34310b57cec5SDimitry Andric   return 4;
3432349cc55cSDimitry Andric #  endif
34330b57cec5SDimitry Andric }
3434349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
34350b57cec5SDimitry Andric 
34360b57cec5SDimitry Andric // __codecvt_utf16<char16_t, false>
34370b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3438cb14a3feSDimitry Andric __codecvt_utf16<char16_t, false>::result __codecvt_utf16<char16_t, false>::do_out(
3439cb14a3feSDimitry Andric     state_type&,
3440cb14a3feSDimitry Andric     const intern_type* frm,
3441cb14a3feSDimitry Andric     const intern_type* frm_end,
3442cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3443cb14a3feSDimitry Andric     extern_type* to,
3444cb14a3feSDimitry Andric     extern_type* to_end,
3445cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
34460b57cec5SDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
34470b57cec5SDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
34480b57cec5SDimitry Andric   const uint16_t* _frm_nxt = _frm;
34490b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
34500b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
34510b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3452cb14a3feSDimitry Andric   result r                 = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
34530b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
34540b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
34550b57cec5SDimitry Andric   return r;
34560b57cec5SDimitry Andric }
34570b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3458cb14a3feSDimitry Andric __codecvt_utf16<char16_t, false>::result __codecvt_utf16<char16_t, false>::do_in(
3459cb14a3feSDimitry Andric     state_type&,
3460cb14a3feSDimitry Andric     const extern_type* frm,
3461cb14a3feSDimitry Andric     const extern_type* frm_end,
3462cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3463cb14a3feSDimitry Andric     intern_type* to,
3464cb14a3feSDimitry Andric     intern_type* to_end,
3465cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
34660b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
34670b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
34680b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
34690b57cec5SDimitry Andric   uint16_t* _to           = reinterpret_cast<uint16_t*>(to);
34700b57cec5SDimitry Andric   uint16_t* _to_end       = reinterpret_cast<uint16_t*>(to_end);
34710b57cec5SDimitry Andric   uint16_t* _to_nxt       = _to;
3472cb14a3feSDimitry Andric   result r                = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
34730b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
34740b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
34750b57cec5SDimitry Andric   return r;
34760b57cec5SDimitry Andric }
34770b57cec5SDimitry Andric 
34780b57cec5SDimitry Andric __codecvt_utf16<char16_t, false>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3479cb14a3feSDimitry Andric __codecvt_utf16<char16_t, false>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
34800b57cec5SDimitry Andric   to_nxt = to;
34810b57cec5SDimitry Andric   return noconv;
34820b57cec5SDimitry Andric }
34830b57cec5SDimitry Andric 
do_encoding() const3484cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, false>::do_encoding() const noexcept { return 0; }
34850b57cec5SDimitry Andric 
do_always_noconv() const3486cb14a3feSDimitry Andric bool __codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept { return false; }
34870b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3488cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, false>::do_length(
3489cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
34900b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
34910b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3492bdd1243dSDimitry Andric   return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
34930b57cec5SDimitry Andric }
34940b57cec5SDimitry Andric 
349581ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3496cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, false>::do_max_length() const noexcept {
3497bdd1243dSDimitry Andric   if (__mode_ & consume_header)
34980b57cec5SDimitry Andric     return 4;
34990b57cec5SDimitry Andric   return 2;
35000b57cec5SDimitry Andric }
350181ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
35020b57cec5SDimitry Andric 
35030b57cec5SDimitry Andric // __codecvt_utf16<char16_t, true>
35040b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3505cb14a3feSDimitry Andric __codecvt_utf16<char16_t, true>::result __codecvt_utf16<char16_t, true>::do_out(
3506cb14a3feSDimitry Andric     state_type&,
3507cb14a3feSDimitry Andric     const intern_type* frm,
3508cb14a3feSDimitry Andric     const intern_type* frm_end,
3509cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3510cb14a3feSDimitry Andric     extern_type* to,
3511cb14a3feSDimitry Andric     extern_type* to_end,
3512cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
35130b57cec5SDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
35140b57cec5SDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
35150b57cec5SDimitry Andric   const uint16_t* _frm_nxt = _frm;
35160b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
35170b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
35180b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3519cb14a3feSDimitry Andric   result r                 = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
35200b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
35210b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
35220b57cec5SDimitry Andric   return r;
35230b57cec5SDimitry Andric }
35240b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3525cb14a3feSDimitry Andric __codecvt_utf16<char16_t, true>::result __codecvt_utf16<char16_t, true>::do_in(
3526cb14a3feSDimitry Andric     state_type&,
3527cb14a3feSDimitry Andric     const extern_type* frm,
3528cb14a3feSDimitry Andric     const extern_type* frm_end,
3529cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3530cb14a3feSDimitry Andric     intern_type* to,
3531cb14a3feSDimitry Andric     intern_type* to_end,
3532cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
35330b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
35340b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
35350b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
35360b57cec5SDimitry Andric   uint16_t* _to           = reinterpret_cast<uint16_t*>(to);
35370b57cec5SDimitry Andric   uint16_t* _to_end       = reinterpret_cast<uint16_t*>(to_end);
35380b57cec5SDimitry Andric   uint16_t* _to_nxt       = _to;
3539cb14a3feSDimitry Andric   result r                = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
35400b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
35410b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
35420b57cec5SDimitry Andric   return r;
35430b57cec5SDimitry Andric }
35440b57cec5SDimitry Andric 
35450b57cec5SDimitry Andric __codecvt_utf16<char16_t, true>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3546cb14a3feSDimitry Andric __codecvt_utf16<char16_t, true>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
35470b57cec5SDimitry Andric   to_nxt = to;
35480b57cec5SDimitry Andric   return noconv;
35490b57cec5SDimitry Andric }
35500b57cec5SDimitry Andric 
do_encoding() const3551cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, true>::do_encoding() const noexcept { return 0; }
35520b57cec5SDimitry Andric 
do_always_noconv() const3553cb14a3feSDimitry Andric bool __codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept { return false; }
35540b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3555cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, true>::do_length(
3556cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
35570b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
35580b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3559bdd1243dSDimitry Andric   return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
35600b57cec5SDimitry Andric }
35610b57cec5SDimitry Andric 
356281ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3563cb14a3feSDimitry Andric int __codecvt_utf16<char16_t, true>::do_max_length() const noexcept {
3564bdd1243dSDimitry Andric   if (__mode_ & consume_header)
35650b57cec5SDimitry Andric     return 4;
35660b57cec5SDimitry Andric   return 2;
35670b57cec5SDimitry Andric }
356881ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
35690b57cec5SDimitry Andric 
35700b57cec5SDimitry Andric // __codecvt_utf16<char32_t, false>
35710b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3572cb14a3feSDimitry Andric __codecvt_utf16<char32_t, false>::result __codecvt_utf16<char32_t, false>::do_out(
3573cb14a3feSDimitry Andric     state_type&,
3574cb14a3feSDimitry Andric     const intern_type* frm,
3575cb14a3feSDimitry Andric     const intern_type* frm_end,
3576cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3577cb14a3feSDimitry Andric     extern_type* to,
3578cb14a3feSDimitry Andric     extern_type* to_end,
3579cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
35800b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
35810b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
35820b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
35830b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
35840b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
35850b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3586cb14a3feSDimitry Andric   result r                 = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
35870b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
35880b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
35890b57cec5SDimitry Andric   return r;
35900b57cec5SDimitry Andric }
35910b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3592cb14a3feSDimitry Andric __codecvt_utf16<char32_t, false>::result __codecvt_utf16<char32_t, false>::do_in(
3593cb14a3feSDimitry Andric     state_type&,
3594cb14a3feSDimitry Andric     const extern_type* frm,
3595cb14a3feSDimitry Andric     const extern_type* frm_end,
3596cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3597cb14a3feSDimitry Andric     intern_type* to,
3598cb14a3feSDimitry Andric     intern_type* to_end,
3599cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
36000b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
36010b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
36020b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
36030b57cec5SDimitry Andric   uint32_t* _to           = reinterpret_cast<uint32_t*>(to);
36040b57cec5SDimitry Andric   uint32_t* _to_end       = reinterpret_cast<uint32_t*>(to_end);
36050b57cec5SDimitry Andric   uint32_t* _to_nxt       = _to;
3606cb14a3feSDimitry Andric   result r                = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
36070b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
36080b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
36090b57cec5SDimitry Andric   return r;
36100b57cec5SDimitry Andric }
36110b57cec5SDimitry Andric 
36120b57cec5SDimitry Andric __codecvt_utf16<char32_t, false>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3613cb14a3feSDimitry Andric __codecvt_utf16<char32_t, false>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
36140b57cec5SDimitry Andric   to_nxt = to;
36150b57cec5SDimitry Andric   return noconv;
36160b57cec5SDimitry Andric }
36170b57cec5SDimitry Andric 
do_encoding() const3618cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, false>::do_encoding() const noexcept { return 0; }
36190b57cec5SDimitry Andric 
do_always_noconv() const3620cb14a3feSDimitry Andric bool __codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept { return false; }
36210b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3622cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, false>::do_length(
3623cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
36240b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
36250b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3626bdd1243dSDimitry Andric   return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
36270b57cec5SDimitry Andric }
36280b57cec5SDimitry Andric 
362981ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3630cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, false>::do_max_length() const noexcept {
3631bdd1243dSDimitry Andric   if (__mode_ & consume_header)
36320b57cec5SDimitry Andric     return 6;
36330b57cec5SDimitry Andric   return 4;
36340b57cec5SDimitry Andric }
363581ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
36360b57cec5SDimitry Andric 
36370b57cec5SDimitry Andric // __codecvt_utf16<char32_t, true>
36380b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3639cb14a3feSDimitry Andric __codecvt_utf16<char32_t, true>::result __codecvt_utf16<char32_t, true>::do_out(
3640cb14a3feSDimitry Andric     state_type&,
3641cb14a3feSDimitry Andric     const intern_type* frm,
3642cb14a3feSDimitry Andric     const intern_type* frm_end,
3643cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3644cb14a3feSDimitry Andric     extern_type* to,
3645cb14a3feSDimitry Andric     extern_type* to_end,
3646cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
36470b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
36480b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
36490b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
36500b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
36510b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
36520b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3653cb14a3feSDimitry Andric   result r                 = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
36540b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
36550b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
36560b57cec5SDimitry Andric   return r;
36570b57cec5SDimitry Andric }
36580b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3659cb14a3feSDimitry Andric __codecvt_utf16<char32_t, true>::result __codecvt_utf16<char32_t, true>::do_in(
3660cb14a3feSDimitry Andric     state_type&,
3661cb14a3feSDimitry Andric     const extern_type* frm,
3662cb14a3feSDimitry Andric     const extern_type* frm_end,
3663cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3664cb14a3feSDimitry Andric     intern_type* to,
3665cb14a3feSDimitry Andric     intern_type* to_end,
3666cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
36670b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
36680b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
36690b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
36700b57cec5SDimitry Andric   uint32_t* _to           = reinterpret_cast<uint32_t*>(to);
36710b57cec5SDimitry Andric   uint32_t* _to_end       = reinterpret_cast<uint32_t*>(to_end);
36720b57cec5SDimitry Andric   uint32_t* _to_nxt       = _to;
3673cb14a3feSDimitry Andric   result r                = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
36740b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
36750b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
36760b57cec5SDimitry Andric   return r;
36770b57cec5SDimitry Andric }
36780b57cec5SDimitry Andric 
36790b57cec5SDimitry Andric __codecvt_utf16<char32_t, true>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3680cb14a3feSDimitry Andric __codecvt_utf16<char32_t, true>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
36810b57cec5SDimitry Andric   to_nxt = to;
36820b57cec5SDimitry Andric   return noconv;
36830b57cec5SDimitry Andric }
36840b57cec5SDimitry Andric 
do_encoding() const3685cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, true>::do_encoding() const noexcept { return 0; }
36860b57cec5SDimitry Andric 
do_always_noconv() const3687cb14a3feSDimitry Andric bool __codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept { return false; }
36880b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3689cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, true>::do_length(
3690cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
36910b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
36920b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3693bdd1243dSDimitry Andric   return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
36940b57cec5SDimitry Andric }
36950b57cec5SDimitry Andric 
369681ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3697cb14a3feSDimitry Andric int __codecvt_utf16<char32_t, true>::do_max_length() const noexcept {
3698bdd1243dSDimitry Andric   if (__mode_ & consume_header)
36990b57cec5SDimitry Andric     return 6;
37000b57cec5SDimitry Andric   return 4;
37010b57cec5SDimitry Andric }
370281ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
37030b57cec5SDimitry Andric 
37040b57cec5SDimitry Andric // __codecvt_utf8_utf16<wchar_t>
37050b57cec5SDimitry Andric 
3706349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3707cb14a3feSDimitry Andric __codecvt_utf8_utf16<wchar_t>::result __codecvt_utf8_utf16<wchar_t>::do_out(
3708cb14a3feSDimitry Andric     state_type&,
3709cb14a3feSDimitry Andric     const intern_type* frm,
3710cb14a3feSDimitry Andric     const intern_type* frm_end,
3711cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3712cb14a3feSDimitry Andric     extern_type* to,
3713cb14a3feSDimitry Andric     extern_type* to_end,
3714cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
3715349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3716349cc55cSDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
3717349cc55cSDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3718349cc55cSDimitry Andric   const uint16_t* _frm_nxt = _frm;
3719349cc55cSDimitry Andric #  else
37200b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
37210b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
37220b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
3723349cc55cSDimitry Andric #  endif
37240b57cec5SDimitry Andric   uint8_t* _to     = reinterpret_cast<uint8_t*>(to);
37250b57cec5SDimitry Andric   uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
37260b57cec5SDimitry Andric   uint8_t* _to_nxt = _to;
3727cb14a3feSDimitry Andric   result r         = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
37280b57cec5SDimitry Andric   frm_nxt          = frm + (_frm_nxt - _frm);
37290b57cec5SDimitry Andric   to_nxt           = to + (_to_nxt - _to);
37300b57cec5SDimitry Andric   return r;
37310b57cec5SDimitry Andric }
37320b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3733cb14a3feSDimitry Andric __codecvt_utf8_utf16<wchar_t>::result __codecvt_utf8_utf16<wchar_t>::do_in(
3734cb14a3feSDimitry Andric     state_type&,
3735cb14a3feSDimitry Andric     const extern_type* frm,
3736cb14a3feSDimitry Andric     const extern_type* frm_end,
3737cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3738cb14a3feSDimitry Andric     intern_type* to,
3739cb14a3feSDimitry Andric     intern_type* to_end,
3740cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
37410b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
37420b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
37430b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
3744349cc55cSDimitry Andric #  if defined(_LIBCPP_SHORT_WCHAR)
3745349cc55cSDimitry Andric   uint16_t* _to     = reinterpret_cast<uint16_t*>(to);
3746349cc55cSDimitry Andric   uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3747349cc55cSDimitry Andric   uint16_t* _to_nxt = _to;
3748349cc55cSDimitry Andric #  else
37490b57cec5SDimitry Andric   uint32_t* _to     = reinterpret_cast<uint32_t*>(to);
37500b57cec5SDimitry Andric   uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
37510b57cec5SDimitry Andric   uint32_t* _to_nxt = _to;
3752349cc55cSDimitry Andric #  endif
3753cb14a3feSDimitry Andric   result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
37540b57cec5SDimitry Andric   frm_nxt  = frm + (_frm_nxt - _frm);
37550b57cec5SDimitry Andric   to_nxt   = to + (_to_nxt - _to);
37560b57cec5SDimitry Andric   return r;
37570b57cec5SDimitry Andric }
37580b57cec5SDimitry Andric 
37590b57cec5SDimitry Andric __codecvt_utf8_utf16<wchar_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3760cb14a3feSDimitry Andric __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
37610b57cec5SDimitry Andric   to_nxt = to;
37620b57cec5SDimitry Andric   return noconv;
37630b57cec5SDimitry Andric }
37640b57cec5SDimitry Andric 
do_encoding() const3765cb14a3feSDimitry Andric int __codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept { return 0; }
37660b57cec5SDimitry Andric 
do_always_noconv() const3767cb14a3feSDimitry Andric bool __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept { return false; }
37680b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3769cb14a3feSDimitry Andric int __codecvt_utf8_utf16<wchar_t>::do_length(
3770cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
37710b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
37720b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3773bdd1243dSDimitry Andric   return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
37740b57cec5SDimitry Andric }
37750b57cec5SDimitry Andric 
do_max_length() const3776cb14a3feSDimitry Andric int __codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept {
3777bdd1243dSDimitry Andric   if (__mode_ & consume_header)
37780b57cec5SDimitry Andric     return 7;
37790b57cec5SDimitry Andric   return 4;
37800b57cec5SDimitry Andric }
3781349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
37820b57cec5SDimitry Andric 
37830b57cec5SDimitry Andric // __codecvt_utf8_utf16<char16_t>
37840b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3785cb14a3feSDimitry Andric __codecvt_utf8_utf16<char16_t>::result __codecvt_utf8_utf16<char16_t>::do_out(
3786cb14a3feSDimitry Andric     state_type&,
3787cb14a3feSDimitry Andric     const intern_type* frm,
3788cb14a3feSDimitry Andric     const intern_type* frm_end,
3789cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3790cb14a3feSDimitry Andric     extern_type* to,
3791cb14a3feSDimitry Andric     extern_type* to_end,
3792cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
37930b57cec5SDimitry Andric   const uint16_t* _frm     = reinterpret_cast<const uint16_t*>(frm);
37940b57cec5SDimitry Andric   const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
37950b57cec5SDimitry Andric   const uint16_t* _frm_nxt = _frm;
37960b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
37970b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
37980b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3799cb14a3feSDimitry Andric   result r                 = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
38000b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
38010b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
38020b57cec5SDimitry Andric   return r;
38030b57cec5SDimitry Andric }
38040b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3805cb14a3feSDimitry Andric __codecvt_utf8_utf16<char16_t>::result __codecvt_utf8_utf16<char16_t>::do_in(
3806cb14a3feSDimitry Andric     state_type&,
3807cb14a3feSDimitry Andric     const extern_type* frm,
3808cb14a3feSDimitry Andric     const extern_type* frm_end,
3809cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3810cb14a3feSDimitry Andric     intern_type* to,
3811cb14a3feSDimitry Andric     intern_type* to_end,
3812cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
38130b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
38140b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
38150b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
38160b57cec5SDimitry Andric   uint16_t* _to           = reinterpret_cast<uint16_t*>(to);
38170b57cec5SDimitry Andric   uint16_t* _to_end       = reinterpret_cast<uint16_t*>(to_end);
38180b57cec5SDimitry Andric   uint16_t* _to_nxt       = _to;
3819cb14a3feSDimitry Andric   result r                = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
38200b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
38210b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
38220b57cec5SDimitry Andric   return r;
38230b57cec5SDimitry Andric }
38240b57cec5SDimitry Andric 
38250b57cec5SDimitry Andric __codecvt_utf8_utf16<char16_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3826cb14a3feSDimitry Andric __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
38270b57cec5SDimitry Andric   to_nxt = to;
38280b57cec5SDimitry Andric   return noconv;
38290b57cec5SDimitry Andric }
38300b57cec5SDimitry Andric 
do_encoding() const3831cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept { return 0; }
38320b57cec5SDimitry Andric 
do_always_noconv() const3833cb14a3feSDimitry Andric bool __codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept { return false; }
38340b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3835cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char16_t>::do_length(
3836cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
38370b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
38380b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3839bdd1243dSDimitry Andric   return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
38400b57cec5SDimitry Andric }
38410b57cec5SDimitry Andric 
384281ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3843cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept {
3844bdd1243dSDimitry Andric   if (__mode_ & consume_header)
38450b57cec5SDimitry Andric     return 7;
38460b57cec5SDimitry Andric   return 4;
38470b57cec5SDimitry Andric }
384881ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
38490b57cec5SDimitry Andric 
38500b57cec5SDimitry Andric // __codecvt_utf8_utf16<char32_t>
38510b57cec5SDimitry Andric 
do_out(state_type &,const intern_type * frm,const intern_type * frm_end,const intern_type * & frm_nxt,extern_type * to,extern_type * to_end,extern_type * & to_nxt) const3852cb14a3feSDimitry Andric __codecvt_utf8_utf16<char32_t>::result __codecvt_utf8_utf16<char32_t>::do_out(
3853cb14a3feSDimitry Andric     state_type&,
3854cb14a3feSDimitry Andric     const intern_type* frm,
3855cb14a3feSDimitry Andric     const intern_type* frm_end,
3856cb14a3feSDimitry Andric     const intern_type*& frm_nxt,
3857cb14a3feSDimitry Andric     extern_type* to,
3858cb14a3feSDimitry Andric     extern_type* to_end,
3859cb14a3feSDimitry Andric     extern_type*& to_nxt) const {
38600b57cec5SDimitry Andric   const uint32_t* _frm     = reinterpret_cast<const uint32_t*>(frm);
38610b57cec5SDimitry Andric   const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
38620b57cec5SDimitry Andric   const uint32_t* _frm_nxt = _frm;
38630b57cec5SDimitry Andric   uint8_t* _to             = reinterpret_cast<uint8_t*>(to);
38640b57cec5SDimitry Andric   uint8_t* _to_end         = reinterpret_cast<uint8_t*>(to_end);
38650b57cec5SDimitry Andric   uint8_t* _to_nxt         = _to;
3866cb14a3feSDimitry Andric   result r                 = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
38670b57cec5SDimitry Andric   frm_nxt                  = frm + (_frm_nxt - _frm);
38680b57cec5SDimitry Andric   to_nxt                   = to + (_to_nxt - _to);
38690b57cec5SDimitry Andric   return r;
38700b57cec5SDimitry Andric }
38710b57cec5SDimitry Andric 
do_in(state_type &,const extern_type * frm,const extern_type * frm_end,const extern_type * & frm_nxt,intern_type * to,intern_type * to_end,intern_type * & to_nxt) const3872cb14a3feSDimitry Andric __codecvt_utf8_utf16<char32_t>::result __codecvt_utf8_utf16<char32_t>::do_in(
3873cb14a3feSDimitry Andric     state_type&,
3874cb14a3feSDimitry Andric     const extern_type* frm,
3875cb14a3feSDimitry Andric     const extern_type* frm_end,
3876cb14a3feSDimitry Andric     const extern_type*& frm_nxt,
3877cb14a3feSDimitry Andric     intern_type* to,
3878cb14a3feSDimitry Andric     intern_type* to_end,
3879cb14a3feSDimitry Andric     intern_type*& to_nxt) const {
38800b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
38810b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
38820b57cec5SDimitry Andric   const uint8_t* _frm_nxt = _frm;
38830b57cec5SDimitry Andric   uint32_t* _to           = reinterpret_cast<uint32_t*>(to);
38840b57cec5SDimitry Andric   uint32_t* _to_end       = reinterpret_cast<uint32_t*>(to_end);
38850b57cec5SDimitry Andric   uint32_t* _to_nxt       = _to;
3886cb14a3feSDimitry Andric   result r                = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, __maxcode_, __mode_);
38870b57cec5SDimitry Andric   frm_nxt                 = frm + (_frm_nxt - _frm);
38880b57cec5SDimitry Andric   to_nxt                  = to + (_to_nxt - _to);
38890b57cec5SDimitry Andric   return r;
38900b57cec5SDimitry Andric }
38910b57cec5SDimitry Andric 
38920b57cec5SDimitry Andric __codecvt_utf8_utf16<char32_t>::result
do_unshift(state_type &,extern_type * to,extern_type *,extern_type * & to_nxt) const3893cb14a3feSDimitry Andric __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, extern_type* to, extern_type*, extern_type*& to_nxt) const {
38940b57cec5SDimitry Andric   to_nxt = to;
38950b57cec5SDimitry Andric   return noconv;
38960b57cec5SDimitry Andric }
38970b57cec5SDimitry Andric 
do_encoding() const3898cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept { return 0; }
38990b57cec5SDimitry Andric 
do_always_noconv() const3900cb14a3feSDimitry Andric bool __codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept { return false; }
39010b57cec5SDimitry Andric 
do_length(state_type &,const extern_type * frm,const extern_type * frm_end,size_t mx) const3902cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char32_t>::do_length(
3903cb14a3feSDimitry Andric     state_type&, const extern_type* frm, const extern_type* frm_end, size_t mx) const {
39040b57cec5SDimitry Andric   const uint8_t* _frm     = reinterpret_cast<const uint8_t*>(frm);
39050b57cec5SDimitry Andric   const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3906bdd1243dSDimitry Andric   return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
39070b57cec5SDimitry Andric }
39080b57cec5SDimitry Andric 
390981ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
do_max_length() const3910cb14a3feSDimitry Andric int __codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept {
3911bdd1243dSDimitry Andric   if (__mode_ & consume_header)
39120b57cec5SDimitry Andric     return 7;
39130b57cec5SDimitry Andric   return 4;
39140b57cec5SDimitry Andric }
391581ad6265SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
39160b57cec5SDimitry Andric 
39170b57cec5SDimitry Andric // __narrow_to_utf8<16>
39180b57cec5SDimitry Andric 
~__narrow_to_utf8()3919cb14a3feSDimitry Andric __narrow_to_utf8<16>::~__narrow_to_utf8() {}
39200b57cec5SDimitry Andric 
39210b57cec5SDimitry Andric // __narrow_to_utf8<32>
39220b57cec5SDimitry Andric 
~__narrow_to_utf8()3923cb14a3feSDimitry Andric __narrow_to_utf8<32>::~__narrow_to_utf8() {}
39240b57cec5SDimitry Andric 
39250b57cec5SDimitry Andric // __widen_from_utf8<16>
39260b57cec5SDimitry Andric 
~__widen_from_utf8()3927cb14a3feSDimitry Andric __widen_from_utf8<16>::~__widen_from_utf8() {}
39280b57cec5SDimitry Andric 
39290b57cec5SDimitry Andric // __widen_from_utf8<32>
39300b57cec5SDimitry Andric 
~__widen_from_utf8()3931cb14a3feSDimitry Andric __widen_from_utf8<32>::~__widen_from_utf8() {}
39320b57cec5SDimitry Andric 
3933349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
checked_string_to_wchar_convert(wchar_t & dest,const char * ptr,locale_t loc)3934cb14a3feSDimitry Andric static bool checked_string_to_wchar_convert(wchar_t& dest, const char* ptr, locale_t loc) {
39350b57cec5SDimitry Andric   if (*ptr == '\0')
39360b57cec5SDimitry Andric     return false;
39370b57cec5SDimitry Andric   mbstate_t mb = {};
39380b57cec5SDimitry Andric   wchar_t out;
39390b57cec5SDimitry Andric   size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
39400b57cec5SDimitry Andric   if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
39410b57cec5SDimitry Andric     return false;
39420b57cec5SDimitry Andric   }
39430b57cec5SDimitry Andric   dest = out;
39440b57cec5SDimitry Andric   return true;
39450b57cec5SDimitry Andric }
3946349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3947349cc55cSDimitry Andric 
3948349cc55cSDimitry Andric #ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
is_narrow_non_breaking_space(const char * ptr)3949349cc55cSDimitry Andric static bool is_narrow_non_breaking_space(const char* ptr) {
3950349cc55cSDimitry Andric   // https://www.fileformat.info/info/unicode/char/202f/index.htm
3951349cc55cSDimitry Andric   return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
3952349cc55cSDimitry Andric }
3953349cc55cSDimitry Andric 
is_non_breaking_space(const char * ptr)3954349cc55cSDimitry Andric static bool is_non_breaking_space(const char* ptr) {
3955349cc55cSDimitry Andric   // https://www.fileformat.info/info/unicode/char/0a/index.htm
3956349cc55cSDimitry Andric   return ptr[0] == '\xc2' && ptr[1] == '\xa0';
3957349cc55cSDimitry Andric }
3958349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
39590b57cec5SDimitry Andric 
checked_string_to_char_convert(char & dest,const char * ptr,locale_t __loc)3960cb14a3feSDimitry Andric static bool checked_string_to_char_convert(char& dest, const char* ptr, locale_t __loc) {
39610b57cec5SDimitry Andric   if (*ptr == '\0')
39620b57cec5SDimitry Andric     return false;
39630b57cec5SDimitry Andric   if (!ptr[1]) {
39640b57cec5SDimitry Andric     dest = *ptr;
39650b57cec5SDimitry Andric     return true;
39660b57cec5SDimitry Andric   }
3967349cc55cSDimitry Andric 
3968349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
39690b57cec5SDimitry Andric   // First convert the MBS into a wide char then attempt to narrow it using
39700b57cec5SDimitry Andric   // wctob_l.
39710b57cec5SDimitry Andric   wchar_t wout;
39720b57cec5SDimitry Andric   if (!checked_string_to_wchar_convert(wout, ptr, __loc))
39730b57cec5SDimitry Andric     return false;
39740b57cec5SDimitry Andric   int res;
39750b57cec5SDimitry Andric   if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
39760b57cec5SDimitry Andric     dest = res;
39770b57cec5SDimitry Andric     return true;
39780b57cec5SDimitry Andric   }
3979349cc55cSDimitry Andric   // FIXME: Work around specific multibyte sequences that we can reasonably
39800b57cec5SDimitry Andric   // translate into a different single byte.
39810b57cec5SDimitry Andric   switch (wout) {
39820b57cec5SDimitry Andric   case L'\u202F': // narrow non-breaking space
39830b57cec5SDimitry Andric   case L'\u00A0': // non-breaking space
39840b57cec5SDimitry Andric     dest = ' ';
39850b57cec5SDimitry Andric     return true;
39860b57cec5SDimitry Andric   default:
39870b57cec5SDimitry Andric     return false;
39880b57cec5SDimitry Andric   }
3989349cc55cSDimitry Andric #else  // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3990349cc55cSDimitry Andric   // FIXME: Work around specific multibyte sequences that we can reasonably
3991349cc55cSDimitry Andric   // translate into a different single byte.
3992349cc55cSDimitry Andric   if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
3993349cc55cSDimitry Andric     dest = ' ';
3994349cc55cSDimitry Andric     return true;
3995349cc55cSDimitry Andric   }
3996349cc55cSDimitry Andric 
3997349cc55cSDimitry Andric   return false;
3998349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
399981ad6265SDimitry Andric   __libcpp_unreachable();
40000b57cec5SDimitry Andric }
40010b57cec5SDimitry Andric 
40020b57cec5SDimitry Andric // numpunct<char> && numpunct<wchar_t>
40030b57cec5SDimitry Andric 
40045f757f3fSDimitry Andric constinit locale::id numpunct<char>::id;
4005349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
40065f757f3fSDimitry Andric constinit locale::id numpunct<wchar_t>::id;
4007349cc55cSDimitry Andric #endif
40080b57cec5SDimitry Andric 
numpunct(size_t refs)4009cb14a3feSDimitry Andric numpunct<char>::numpunct(size_t refs) : locale::facet(refs), __decimal_point_('.'), __thousands_sep_(',') {}
40100b57cec5SDimitry Andric 
4011349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
numpunct(size_t refs)4012cb14a3feSDimitry Andric numpunct<wchar_t>::numpunct(size_t refs) : locale::facet(refs), __decimal_point_(L'.'), __thousands_sep_(L',') {}
4013349cc55cSDimitry Andric #endif
40140b57cec5SDimitry Andric 
~numpunct()4015cb14a3feSDimitry Andric numpunct<char>::~numpunct() {}
40160b57cec5SDimitry Andric 
4017349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
~numpunct()4018cb14a3feSDimitry Andric numpunct<wchar_t>::~numpunct() {}
4019349cc55cSDimitry Andric #endif
40200b57cec5SDimitry Andric 
do_decimal_point() const40210b57cec5SDimitry Andric char numpunct< char >::do_decimal_point() const { return __decimal_point_; }
4022349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_decimal_point() const40230b57cec5SDimitry Andric wchar_t numpunct<wchar_t>::do_decimal_point() const { return __decimal_point_; }
4024349cc55cSDimitry Andric #endif
40250b57cec5SDimitry Andric 
do_thousands_sep() const40260b57cec5SDimitry Andric char numpunct< char >::do_thousands_sep() const { return __thousands_sep_; }
4027349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_thousands_sep() const40280b57cec5SDimitry Andric wchar_t numpunct<wchar_t>::do_thousands_sep() const { return __thousands_sep_; }
4029349cc55cSDimitry Andric #endif
40300b57cec5SDimitry Andric 
do_grouping() const40310b57cec5SDimitry Andric string numpunct< char >::do_grouping() const { return __grouping_; }
4032349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_grouping() const40330b57cec5SDimitry Andric string numpunct<wchar_t>::do_grouping() const { return __grouping_; }
4034349cc55cSDimitry Andric #endif
40350b57cec5SDimitry Andric 
do_truename() const40360b57cec5SDimitry Andric string numpunct< char >::do_truename() const { return "true"; }
4037349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_truename() const40380b57cec5SDimitry Andric wstring numpunct<wchar_t>::do_truename() const { return L"true"; }
4039349cc55cSDimitry Andric #endif
40400b57cec5SDimitry Andric 
do_falsename() const40410b57cec5SDimitry Andric string numpunct< char >::do_falsename() const { return "false"; }
4042349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
do_falsename() const40430b57cec5SDimitry Andric wstring numpunct<wchar_t>::do_falsename() const { return L"false"; }
4044349cc55cSDimitry Andric #endif
40450b57cec5SDimitry Andric 
40460b57cec5SDimitry Andric // numpunct_byname<char>
40470b57cec5SDimitry Andric 
numpunct_byname(const char * nm,size_t refs)4048cb14a3feSDimitry Andric numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs) : numpunct<char>(refs) { __init(nm); }
40490b57cec5SDimitry Andric 
numpunct_byname(const string & nm,size_t refs)4050cb14a3feSDimitry Andric numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs) : numpunct<char>(refs) { __init(nm.c_str()); }
40510b57cec5SDimitry Andric 
~numpunct_byname()4052cb14a3feSDimitry Andric numpunct_byname<char>::~numpunct_byname() {}
40530b57cec5SDimitry Andric 
__init(const char * nm)4054cb14a3feSDimitry Andric void numpunct_byname<char>::__init(const char* nm) {
4055349cc55cSDimitry Andric   typedef numpunct<char> base;
4056cb14a3feSDimitry Andric   if (strcmp(nm, "C") != 0) {
40570b57cec5SDimitry Andric     __libcpp_unique_locale loc(nm);
40580b57cec5SDimitry Andric     if (!loc)
4059cb14a3feSDimitry Andric       __throw_runtime_error(
4060cb14a3feSDimitry Andric           ("numpunct_byname<char>::numpunct_byname"
4061cb14a3feSDimitry Andric            " failed to construct for " +
4062cb14a3feSDimitry Andric            string(nm))
4063cb14a3feSDimitry Andric               .c_str());
40640b57cec5SDimitry Andric 
40650b57cec5SDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
4066cb14a3feSDimitry Andric     if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point, loc.get()))
4067349cc55cSDimitry Andric       __decimal_point_ = base::do_decimal_point();
4068cb14a3feSDimitry Andric     if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, loc.get()))
4069349cc55cSDimitry Andric       __thousands_sep_ = base::do_thousands_sep();
40700b57cec5SDimitry Andric     __grouping_ = lc->grouping;
40710b57cec5SDimitry Andric     // localization for truename and falsename is not available
40720b57cec5SDimitry Andric   }
40730b57cec5SDimitry Andric }
40740b57cec5SDimitry Andric 
40750b57cec5SDimitry Andric // numpunct_byname<wchar_t>
40760b57cec5SDimitry Andric 
4077349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
numpunct_byname(const char * nm,size_t refs)4078cb14a3feSDimitry Andric numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs) : numpunct<wchar_t>(refs) { __init(nm); }
40790b57cec5SDimitry Andric 
numpunct_byname(const string & nm,size_t refs)4080cb14a3feSDimitry Andric numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs) : numpunct<wchar_t>(refs) {
40810b57cec5SDimitry Andric   __init(nm.c_str());
40820b57cec5SDimitry Andric }
40830b57cec5SDimitry Andric 
~numpunct_byname()4084cb14a3feSDimitry Andric numpunct_byname<wchar_t>::~numpunct_byname() {}
40850b57cec5SDimitry Andric 
__init(const char * nm)4086cb14a3feSDimitry Andric void numpunct_byname<wchar_t>::__init(const char* nm) {
4087cb14a3feSDimitry Andric   if (strcmp(nm, "C") != 0) {
40880b57cec5SDimitry Andric     __libcpp_unique_locale loc(nm);
40890b57cec5SDimitry Andric     if (!loc)
4090cb14a3feSDimitry Andric       __throw_runtime_error(
4091cb14a3feSDimitry Andric           ("numpunct_byname<wchar_t>::numpunct_byname"
4092cb14a3feSDimitry Andric            " failed to construct for " +
4093cb14a3feSDimitry Andric            string(nm))
4094cb14a3feSDimitry Andric               .c_str());
40950b57cec5SDimitry Andric 
40960b57cec5SDimitry Andric     lconv* lc = __libcpp_localeconv_l(loc.get());
4097cb14a3feSDimitry Andric     checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, loc.get());
4098cb14a3feSDimitry Andric     checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, loc.get());
40990b57cec5SDimitry Andric     __grouping_ = lc->grouping;
41000b57cec5SDimitry Andric     // localization for truename and falsename is not available
41010b57cec5SDimitry Andric   }
41020b57cec5SDimitry Andric }
4103349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
41040b57cec5SDimitry Andric 
41050b57cec5SDimitry Andric // num_get helpers
41060b57cec5SDimitry Andric 
__get_base(ios_base & iob)4107cb14a3feSDimitry Andric int __num_get_base::__get_base(ios_base& iob) {
41080b57cec5SDimitry Andric   ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
41090b57cec5SDimitry Andric   if (__basefield == ios_base::oct)
41100b57cec5SDimitry Andric     return 8;
41110b57cec5SDimitry Andric   else if (__basefield == ios_base::hex)
41120b57cec5SDimitry Andric     return 16;
41130b57cec5SDimitry Andric   else if (__basefield == 0)
41140b57cec5SDimitry Andric     return 0;
41150b57cec5SDimitry Andric   return 10;
41160b57cec5SDimitry Andric }
41170b57cec5SDimitry Andric 
41180b57cec5SDimitry Andric const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
41190b57cec5SDimitry Andric 
__check_grouping(const string & __grouping,unsigned * __g,unsigned * __g_end,ios_base::iostate & __err)4120cb14a3feSDimitry Andric void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err) {
41210b57cec5SDimitry Andric   //  if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
41220b57cec5SDimitry Andric   //  we always have at least a single entry in [__g, __g_end); the end of the input sequence
4123cb14a3feSDimitry Andric   if (__grouping.size() != 0 && __g_end - __g > 1) {
41240b57cec5SDimitry Andric     reverse(__g, __g_end);
41250b57cec5SDimitry Andric     const char* __ig = __grouping.data();
41260b57cec5SDimitry Andric     const char* __eg = __ig + __grouping.size();
4127cb14a3feSDimitry Andric     for (unsigned* __r = __g; __r < __g_end - 1; ++__r) {
4128cb14a3feSDimitry Andric       if (0 < *__ig && *__ig < numeric_limits<char>::max()) {
4129cb14a3feSDimitry Andric         if (static_cast<unsigned>(*__ig) != *__r) {
41300b57cec5SDimitry Andric           __err = ios_base::failbit;
41310b57cec5SDimitry Andric           return;
41320b57cec5SDimitry Andric         }
41330b57cec5SDimitry Andric       }
41340b57cec5SDimitry Andric       if (__eg - __ig > 1)
41350b57cec5SDimitry Andric         ++__ig;
41360b57cec5SDimitry Andric     }
4137cb14a3feSDimitry Andric     if (0 < *__ig && *__ig < numeric_limits<char>::max()) {
41380b57cec5SDimitry Andric       if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
41390b57cec5SDimitry Andric         __err = ios_base::failbit;
41400b57cec5SDimitry Andric     }
41410b57cec5SDimitry Andric   }
41420b57cec5SDimitry Andric }
41430b57cec5SDimitry Andric 
__format_int(char * __fmtp,const char * __len,bool __signd,ios_base::fmtflags __flags)4144cb14a3feSDimitry Andric void __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, ios_base::fmtflags __flags) {
4145cb14a3feSDimitry Andric   if ((__flags & ios_base::showpos) && (__flags & ios_base::basefield) != ios_base::oct &&
4146cb14a3feSDimitry Andric       (__flags & ios_base::basefield) != ios_base::hex && __signd)
41470b57cec5SDimitry Andric     *__fmtp++ = '+';
41480b57cec5SDimitry Andric   if (__flags & ios_base::showbase)
41490b57cec5SDimitry Andric     *__fmtp++ = '#';
41500b57cec5SDimitry Andric   while (*__len)
41510b57cec5SDimitry Andric     *__fmtp++ = *__len++;
41520b57cec5SDimitry Andric   if ((__flags & ios_base::basefield) == ios_base::oct)
41530b57cec5SDimitry Andric     *__fmtp = 'o';
4154cb14a3feSDimitry Andric   else if ((__flags & ios_base::basefield) == ios_base::hex) {
41550b57cec5SDimitry Andric     if (__flags & ios_base::uppercase)
41560b57cec5SDimitry Andric       *__fmtp = 'X';
41570b57cec5SDimitry Andric     else
41580b57cec5SDimitry Andric       *__fmtp = 'x';
4159cb14a3feSDimitry Andric   } else if (__signd)
41600b57cec5SDimitry Andric     *__fmtp = 'd';
41610b57cec5SDimitry Andric   else
41620b57cec5SDimitry Andric     *__fmtp = 'u';
41630b57cec5SDimitry Andric }
41640b57cec5SDimitry Andric 
__format_float(char * __fmtp,const char * __len,ios_base::fmtflags __flags)4165cb14a3feSDimitry Andric bool __num_put_base::__format_float(char* __fmtp, const char* __len, ios_base::fmtflags __flags) {
41660b57cec5SDimitry Andric   bool specify_precision = true;
41670b57cec5SDimitry Andric   if (__flags & ios_base::showpos)
41680b57cec5SDimitry Andric     *__fmtp++ = '+';
41690b57cec5SDimitry Andric   if (__flags & ios_base::showpoint)
41700b57cec5SDimitry Andric     *__fmtp++ = '#';
41710b57cec5SDimitry Andric   ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
41720b57cec5SDimitry Andric   bool uppercase                = (__flags & ios_base::uppercase) != 0;
41730b57cec5SDimitry Andric   if (floatfield == (ios_base::fixed | ios_base::scientific))
41740b57cec5SDimitry Andric     specify_precision = false;
4175cb14a3feSDimitry Andric   else {
41760b57cec5SDimitry Andric     *__fmtp++ = '.';
41770b57cec5SDimitry Andric     *__fmtp++ = '*';
41780b57cec5SDimitry Andric   }
41790b57cec5SDimitry Andric   while (*__len)
41800b57cec5SDimitry Andric     *__fmtp++ = *__len++;
4181cb14a3feSDimitry Andric   if (floatfield == ios_base::fixed) {
41820b57cec5SDimitry Andric     if (uppercase)
41830b57cec5SDimitry Andric       *__fmtp = 'F';
41840b57cec5SDimitry Andric     else
41850b57cec5SDimitry Andric       *__fmtp = 'f';
4186cb14a3feSDimitry Andric   } else if (floatfield == ios_base::scientific) {
41870b57cec5SDimitry Andric     if (uppercase)
41880b57cec5SDimitry Andric       *__fmtp = 'E';
41890b57cec5SDimitry Andric     else
41900b57cec5SDimitry Andric       *__fmtp = 'e';
4191cb14a3feSDimitry Andric   } else if (floatfield == (ios_base::fixed | ios_base::scientific)) {
41920b57cec5SDimitry Andric     if (uppercase)
41930b57cec5SDimitry Andric       *__fmtp = 'A';
41940b57cec5SDimitry Andric     else
41950b57cec5SDimitry Andric       *__fmtp = 'a';
4196cb14a3feSDimitry Andric   } else {
41970b57cec5SDimitry Andric     if (uppercase)
41980b57cec5SDimitry Andric       *__fmtp = 'G';
41990b57cec5SDimitry Andric     else
42000b57cec5SDimitry Andric       *__fmtp = 'g';
42010b57cec5SDimitry Andric   }
42020b57cec5SDimitry Andric   return specify_precision;
42030b57cec5SDimitry Andric }
42040b57cec5SDimitry Andric 
__identify_padding(char * __nb,char * __ne,const ios_base & __iob)4205cb14a3feSDimitry Andric char* __num_put_base::__identify_padding(char* __nb, char* __ne, const ios_base& __iob) {
4206cb14a3feSDimitry Andric   switch (__iob.flags() & ios_base::adjustfield) {
42070b57cec5SDimitry Andric   case ios_base::internal:
42080b57cec5SDimitry Andric     if (__nb[0] == '-' || __nb[0] == '+')
42090b57cec5SDimitry Andric       return __nb + 1;
4210cb14a3feSDimitry Andric     if (__ne - __nb >= 2 && __nb[0] == '0' && (__nb[1] == 'x' || __nb[1] == 'X'))
42110b57cec5SDimitry Andric       return __nb + 2;
42120b57cec5SDimitry Andric     break;
42130b57cec5SDimitry Andric   case ios_base::left:
42140b57cec5SDimitry Andric     return __ne;
42150b57cec5SDimitry Andric   case ios_base::right:
42160b57cec5SDimitry Andric   default:
42170b57cec5SDimitry Andric     break;
42180b57cec5SDimitry Andric   }
42190b57cec5SDimitry Andric   return __nb;
42200b57cec5SDimitry Andric }
42210b57cec5SDimitry Andric 
42220b57cec5SDimitry Andric // time_get
42230b57cec5SDimitry Andric 
init_weeks()4224cb14a3feSDimitry Andric static string* init_weeks() {
42250b57cec5SDimitry Andric   static string weeks[14];
42260b57cec5SDimitry Andric   weeks[0]  = "Sunday";
42270b57cec5SDimitry Andric   weeks[1]  = "Monday";
42280b57cec5SDimitry Andric   weeks[2]  = "Tuesday";
42290b57cec5SDimitry Andric   weeks[3]  = "Wednesday";
42300b57cec5SDimitry Andric   weeks[4]  = "Thursday";
42310b57cec5SDimitry Andric   weeks[5]  = "Friday";
42320b57cec5SDimitry Andric   weeks[6]  = "Saturday";
42330b57cec5SDimitry Andric   weeks[7]  = "Sun";
42340b57cec5SDimitry Andric   weeks[8]  = "Mon";
42350b57cec5SDimitry Andric   weeks[9]  = "Tue";
42360b57cec5SDimitry Andric   weeks[10] = "Wed";
42370b57cec5SDimitry Andric   weeks[11] = "Thu";
42380b57cec5SDimitry Andric   weeks[12] = "Fri";
42390b57cec5SDimitry Andric   weeks[13] = "Sat";
42400b57cec5SDimitry Andric   return weeks;
42410b57cec5SDimitry Andric }
42420b57cec5SDimitry Andric 
4243349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
init_wweeks()4244cb14a3feSDimitry Andric static wstring* init_wweeks() {
42450b57cec5SDimitry Andric   static wstring weeks[14];
42460b57cec5SDimitry Andric   weeks[0]  = L"Sunday";
42470b57cec5SDimitry Andric   weeks[1]  = L"Monday";
42480b57cec5SDimitry Andric   weeks[2]  = L"Tuesday";
42490b57cec5SDimitry Andric   weeks[3]  = L"Wednesday";
42500b57cec5SDimitry Andric   weeks[4]  = L"Thursday";
42510b57cec5SDimitry Andric   weeks[5]  = L"Friday";
42520b57cec5SDimitry Andric   weeks[6]  = L"Saturday";
42530b57cec5SDimitry Andric   weeks[7]  = L"Sun";
42540b57cec5SDimitry Andric   weeks[8]  = L"Mon";
42550b57cec5SDimitry Andric   weeks[9]  = L"Tue";
42560b57cec5SDimitry Andric   weeks[10] = L"Wed";
42570b57cec5SDimitry Andric   weeks[11] = L"Thu";
42580b57cec5SDimitry Andric   weeks[12] = L"Fri";
42590b57cec5SDimitry Andric   weeks[13] = L"Sat";
42600b57cec5SDimitry Andric   return weeks;
42610b57cec5SDimitry Andric }
4262349cc55cSDimitry Andric #endif
42630b57cec5SDimitry Andric 
42640b57cec5SDimitry Andric template <>
__weeks() const4265cb14a3feSDimitry Andric const string* __time_get_c_storage<char>::__weeks() const {
42660b57cec5SDimitry Andric   static const string* weeks = init_weeks();
42670b57cec5SDimitry Andric   return weeks;
42680b57cec5SDimitry Andric }
42690b57cec5SDimitry Andric 
4270349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
42710b57cec5SDimitry Andric template <>
__weeks() const4272cb14a3feSDimitry Andric const wstring* __time_get_c_storage<wchar_t>::__weeks() const {
42730b57cec5SDimitry Andric   static const wstring* weeks = init_wweeks();
42740b57cec5SDimitry Andric   return weeks;
42750b57cec5SDimitry Andric }
4276349cc55cSDimitry Andric #endif
42770b57cec5SDimitry Andric 
init_months()4278cb14a3feSDimitry Andric static string* init_months() {
42790b57cec5SDimitry Andric   static string months[24];
42800b57cec5SDimitry Andric   months[0]  = "January";
42810b57cec5SDimitry Andric   months[1]  = "February";
42820b57cec5SDimitry Andric   months[2]  = "March";
42830b57cec5SDimitry Andric   months[3]  = "April";
42840b57cec5SDimitry Andric   months[4]  = "May";
42850b57cec5SDimitry Andric   months[5]  = "June";
42860b57cec5SDimitry Andric   months[6]  = "July";
42870b57cec5SDimitry Andric   months[7]  = "August";
42880b57cec5SDimitry Andric   months[8]  = "September";
42890b57cec5SDimitry Andric   months[9]  = "October";
42900b57cec5SDimitry Andric   months[10] = "November";
42910b57cec5SDimitry Andric   months[11] = "December";
42920b57cec5SDimitry Andric   months[12] = "Jan";
42930b57cec5SDimitry Andric   months[13] = "Feb";
42940b57cec5SDimitry Andric   months[14] = "Mar";
42950b57cec5SDimitry Andric   months[15] = "Apr";
42960b57cec5SDimitry Andric   months[16] = "May";
42970b57cec5SDimitry Andric   months[17] = "Jun";
42980b57cec5SDimitry Andric   months[18] = "Jul";
42990b57cec5SDimitry Andric   months[19] = "Aug";
43000b57cec5SDimitry Andric   months[20] = "Sep";
43010b57cec5SDimitry Andric   months[21] = "Oct";
43020b57cec5SDimitry Andric   months[22] = "Nov";
43030b57cec5SDimitry Andric   months[23] = "Dec";
43040b57cec5SDimitry Andric   return months;
43050b57cec5SDimitry Andric }
43060b57cec5SDimitry Andric 
4307349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
init_wmonths()4308cb14a3feSDimitry Andric static wstring* init_wmonths() {
43090b57cec5SDimitry Andric   static wstring months[24];
43100b57cec5SDimitry Andric   months[0]  = L"January";
43110b57cec5SDimitry Andric   months[1]  = L"February";
43120b57cec5SDimitry Andric   months[2]  = L"March";
43130b57cec5SDimitry Andric   months[3]  = L"April";
43140b57cec5SDimitry Andric   months[4]  = L"May";
43150b57cec5SDimitry Andric   months[5]  = L"June";
43160b57cec5SDimitry Andric   months[6]  = L"July";
43170b57cec5SDimitry Andric   months[7]  = L"August";
43180b57cec5SDimitry Andric   months[8]  = L"September";
43190b57cec5SDimitry Andric   months[9]  = L"October";
43200b57cec5SDimitry Andric   months[10] = L"November";
43210b57cec5SDimitry Andric   months[11] = L"December";
43220b57cec5SDimitry Andric   months[12] = L"Jan";
43230b57cec5SDimitry Andric   months[13] = L"Feb";
43240b57cec5SDimitry Andric   months[14] = L"Mar";
43250b57cec5SDimitry Andric   months[15] = L"Apr";
43260b57cec5SDimitry Andric   months[16] = L"May";
43270b57cec5SDimitry Andric   months[17] = L"Jun";
43280b57cec5SDimitry Andric   months[18] = L"Jul";
43290b57cec5SDimitry Andric   months[19] = L"Aug";
43300b57cec5SDimitry Andric   months[20] = L"Sep";
43310b57cec5SDimitry Andric   months[21] = L"Oct";
43320b57cec5SDimitry Andric   months[22] = L"Nov";
43330b57cec5SDimitry Andric   months[23] = L"Dec";
43340b57cec5SDimitry Andric   return months;
43350b57cec5SDimitry Andric }
4336349cc55cSDimitry Andric #endif
43370b57cec5SDimitry Andric 
43380b57cec5SDimitry Andric template <>
__months() const4339cb14a3feSDimitry Andric const string* __time_get_c_storage<char>::__months() const {
43400b57cec5SDimitry Andric   static const string* months = init_months();
43410b57cec5SDimitry Andric   return months;
43420b57cec5SDimitry Andric }
43430b57cec5SDimitry Andric 
4344349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
43450b57cec5SDimitry Andric template <>
__months() const4346cb14a3feSDimitry Andric const wstring* __time_get_c_storage<wchar_t>::__months() const {
43470b57cec5SDimitry Andric   static const wstring* months = init_wmonths();
43480b57cec5SDimitry Andric   return months;
43490b57cec5SDimitry Andric }
4350349cc55cSDimitry Andric #endif
43510b57cec5SDimitry Andric 
init_am_pm()4352cb14a3feSDimitry Andric static string* init_am_pm() {
43530b57cec5SDimitry Andric   static string am_pm[2];
43540b57cec5SDimitry Andric   am_pm[0] = "AM";
43550b57cec5SDimitry Andric   am_pm[1] = "PM";
43560b57cec5SDimitry Andric   return am_pm;
43570b57cec5SDimitry Andric }
43580b57cec5SDimitry Andric 
4359349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
init_wam_pm()4360cb14a3feSDimitry Andric static wstring* init_wam_pm() {
43610b57cec5SDimitry Andric   static wstring am_pm[2];
43620b57cec5SDimitry Andric   am_pm[0] = L"AM";
43630b57cec5SDimitry Andric   am_pm[1] = L"PM";
43640b57cec5SDimitry Andric   return am_pm;
43650b57cec5SDimitry Andric }
4366349cc55cSDimitry Andric #endif
43670b57cec5SDimitry Andric 
43680b57cec5SDimitry Andric template <>
__am_pm() const4369cb14a3feSDimitry Andric const string* __time_get_c_storage<char>::__am_pm() const {
43700b57cec5SDimitry Andric   static const string* am_pm = init_am_pm();
43710b57cec5SDimitry Andric   return am_pm;
43720b57cec5SDimitry Andric }
43730b57cec5SDimitry Andric 
4374349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
43750b57cec5SDimitry Andric template <>
__am_pm() const4376cb14a3feSDimitry Andric const wstring* __time_get_c_storage<wchar_t>::__am_pm() const {
43770b57cec5SDimitry Andric   static const wstring* am_pm = init_wam_pm();
43780b57cec5SDimitry Andric   return am_pm;
43790b57cec5SDimitry Andric }
4380349cc55cSDimitry Andric #endif
43810b57cec5SDimitry Andric 
43820b57cec5SDimitry Andric template <>
__x() const4383cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__x() const {
43840b57cec5SDimitry Andric   static string s("%m/%d/%y");
43850b57cec5SDimitry Andric   return s;
43860b57cec5SDimitry Andric }
43870b57cec5SDimitry Andric 
4388349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
43890b57cec5SDimitry Andric template <>
__x() const4390cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__x() const {
43910b57cec5SDimitry Andric   static wstring s(L"%m/%d/%y");
43920b57cec5SDimitry Andric   return s;
43930b57cec5SDimitry Andric }
4394349cc55cSDimitry Andric #endif
43950b57cec5SDimitry Andric 
43960b57cec5SDimitry Andric template <>
__X() const4397cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__X() const {
43980b57cec5SDimitry Andric   static string s("%H:%M:%S");
43990b57cec5SDimitry Andric   return s;
44000b57cec5SDimitry Andric }
44010b57cec5SDimitry Andric 
4402349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
44030b57cec5SDimitry Andric template <>
__X() const4404cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__X() const {
44050b57cec5SDimitry Andric   static wstring s(L"%H:%M:%S");
44060b57cec5SDimitry Andric   return s;
44070b57cec5SDimitry Andric }
4408349cc55cSDimitry Andric #endif
44090b57cec5SDimitry Andric 
44100b57cec5SDimitry Andric template <>
__c() const4411cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__c() const {
44120b57cec5SDimitry Andric   static string s("%a %b %d %H:%M:%S %Y");
44130b57cec5SDimitry Andric   return s;
44140b57cec5SDimitry Andric }
44150b57cec5SDimitry Andric 
4416349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
44170b57cec5SDimitry Andric template <>
__c() const4418cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__c() const {
44190b57cec5SDimitry Andric   static wstring s(L"%a %b %d %H:%M:%S %Y");
44200b57cec5SDimitry Andric   return s;
44210b57cec5SDimitry Andric }
4422349cc55cSDimitry Andric #endif
44230b57cec5SDimitry Andric 
44240b57cec5SDimitry Andric template <>
__r() const4425cb14a3feSDimitry Andric const string& __time_get_c_storage<char>::__r() const {
44260b57cec5SDimitry Andric   static string s("%I:%M:%S %p");
44270b57cec5SDimitry Andric   return s;
44280b57cec5SDimitry Andric }
44290b57cec5SDimitry Andric 
4430349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
44310b57cec5SDimitry Andric template <>
__r() const4432cb14a3feSDimitry Andric const wstring& __time_get_c_storage<wchar_t>::__r() const {
44330b57cec5SDimitry Andric   static wstring s(L"%I:%M:%S %p");
44340b57cec5SDimitry Andric   return s;
44350b57cec5SDimitry Andric }
4436349cc55cSDimitry Andric #endif
44370b57cec5SDimitry Andric 
44380b57cec5SDimitry Andric // time_get_byname
44390b57cec5SDimitry Andric 
__time_get(const char * nm)4440cb14a3feSDimitry Andric __time_get::__time_get(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {
44410b57cec5SDimitry Andric   if (__loc_ == 0)
44425f757f3fSDimitry Andric     __throw_runtime_error(("time_get_byname failed to construct for " + string(nm)).c_str());
44430b57cec5SDimitry Andric }
44440b57cec5SDimitry Andric 
__time_get(const string & nm)4445cb14a3feSDimitry Andric __time_get::__time_get(const string& nm) : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
44460b57cec5SDimitry Andric   if (__loc_ == 0)
44475f757f3fSDimitry Andric     __throw_runtime_error(("time_get_byname failed to construct for " + nm).c_str());
44480b57cec5SDimitry Andric }
44490b57cec5SDimitry Andric 
~__time_get()4450cb14a3feSDimitry Andric __time_get::~__time_get() { freelocale(__loc_); }
445181ad6265SDimitry Andric 
445281ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
44530b57cec5SDimitry Andric 
44540b57cec5SDimitry Andric template <>
__analyze(char fmt,const ctype<char> & ct)4455cb14a3feSDimitry Andric string __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) {
44560b57cec5SDimitry Andric   tm t       = {0};
44570b57cec5SDimitry Andric   t.tm_sec   = 59;
44580b57cec5SDimitry Andric   t.tm_min   = 55;
44590b57cec5SDimitry Andric   t.tm_hour  = 23;
44600b57cec5SDimitry Andric   t.tm_mday  = 31;
44610b57cec5SDimitry Andric   t.tm_mon   = 11;
44620b57cec5SDimitry Andric   t.tm_year  = 161;
44630b57cec5SDimitry Andric   t.tm_wday  = 6;
44640b57cec5SDimitry Andric   t.tm_yday  = 364;
44650b57cec5SDimitry Andric   t.tm_isdst = -1;
44660b57cec5SDimitry Andric   char buf[100];
44670b57cec5SDimitry Andric   char f[3] = {0};
44680b57cec5SDimitry Andric   f[0]      = '%';
44690b57cec5SDimitry Andric   f[1]      = fmt;
44700b57cec5SDimitry Andric   size_t n  = strftime_l(buf, countof(buf), f, &t, __loc_);
44710b57cec5SDimitry Andric   char* bb  = buf;
44720b57cec5SDimitry Andric   char* be  = buf + n;
44730b57cec5SDimitry Andric   string result;
4474cb14a3feSDimitry Andric   while (bb != be) {
4475cb14a3feSDimitry Andric     if (ct.is(ctype_base::space, *bb)) {
44760b57cec5SDimitry Andric       result.push_back(' ');
44770b57cec5SDimitry Andric       for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
44780b57cec5SDimitry Andric         ;
44790b57cec5SDimitry Andric       continue;
44800b57cec5SDimitry Andric     }
44810b57cec5SDimitry Andric     char* w               = bb;
44820b57cec5SDimitry Andric     ios_base::iostate err = ios_base::goodbit;
4483cb14a3feSDimitry Andric     ptrdiff_t i           = __scan_keyword(w, be, this->__weeks_, this->__weeks_ + 14, ct, err, false) - this->__weeks_;
4484cb14a3feSDimitry Andric     if (i < 14) {
44850b57cec5SDimitry Andric       result.push_back('%');
44860b57cec5SDimitry Andric       if (i < 7)
44870b57cec5SDimitry Andric         result.push_back('A');
44880b57cec5SDimitry Andric       else
44890b57cec5SDimitry Andric         result.push_back('a');
44900b57cec5SDimitry Andric       bb = w;
44910b57cec5SDimitry Andric       continue;
44920b57cec5SDimitry Andric     }
44930b57cec5SDimitry Andric     w = bb;
4494cb14a3feSDimitry Andric     i = __scan_keyword(w, be, this->__months_, this->__months_ + 24, ct, err, false) - this->__months_;
4495cb14a3feSDimitry Andric     if (i < 24) {
44960b57cec5SDimitry Andric       result.push_back('%');
44970b57cec5SDimitry Andric       if (i < 12)
44980b57cec5SDimitry Andric         result.push_back('B');
44990b57cec5SDimitry Andric       else
45000b57cec5SDimitry Andric         result.push_back('b');
45010b57cec5SDimitry Andric       if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
45020b57cec5SDimitry Andric         result.back() = 'm';
45030b57cec5SDimitry Andric       bb = w;
45040b57cec5SDimitry Andric       continue;
45050b57cec5SDimitry Andric     }
4506cb14a3feSDimitry Andric     if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) {
45070b57cec5SDimitry Andric       w = bb;
4508cb14a3feSDimitry Andric       i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_ + 2, ct, err, false) - this->__am_pm_;
4509cb14a3feSDimitry Andric       if (i < 2) {
45100b57cec5SDimitry Andric         result.push_back('%');
45110b57cec5SDimitry Andric         result.push_back('p');
45120b57cec5SDimitry Andric         bb = w;
45130b57cec5SDimitry Andric         continue;
45140b57cec5SDimitry Andric       }
45150b57cec5SDimitry Andric     }
45160b57cec5SDimitry Andric     w = bb;
4517cb14a3feSDimitry Andric     if (ct.is(ctype_base::digit, *bb)) {
4518cb14a3feSDimitry Andric       switch (__get_up_to_n_digits(bb, be, err, ct, 4)) {
45190b57cec5SDimitry Andric       case 6:
45200b57cec5SDimitry Andric         result.push_back('%');
45210b57cec5SDimitry Andric         result.push_back('w');
45220b57cec5SDimitry Andric         break;
45230b57cec5SDimitry Andric       case 7:
45240b57cec5SDimitry Andric         result.push_back('%');
45250b57cec5SDimitry Andric         result.push_back('u');
45260b57cec5SDimitry Andric         break;
45270b57cec5SDimitry Andric       case 11:
45280b57cec5SDimitry Andric         result.push_back('%');
45290b57cec5SDimitry Andric         result.push_back('I');
45300b57cec5SDimitry Andric         break;
45310b57cec5SDimitry Andric       case 12:
45320b57cec5SDimitry Andric         result.push_back('%');
45330b57cec5SDimitry Andric         result.push_back('m');
45340b57cec5SDimitry Andric         break;
45350b57cec5SDimitry Andric       case 23:
45360b57cec5SDimitry Andric         result.push_back('%');
45370b57cec5SDimitry Andric         result.push_back('H');
45380b57cec5SDimitry Andric         break;
45390b57cec5SDimitry Andric       case 31:
45400b57cec5SDimitry Andric         result.push_back('%');
45410b57cec5SDimitry Andric         result.push_back('d');
45420b57cec5SDimitry Andric         break;
45430b57cec5SDimitry Andric       case 55:
45440b57cec5SDimitry Andric         result.push_back('%');
45450b57cec5SDimitry Andric         result.push_back('M');
45460b57cec5SDimitry Andric         break;
45470b57cec5SDimitry Andric       case 59:
45480b57cec5SDimitry Andric         result.push_back('%');
45490b57cec5SDimitry Andric         result.push_back('S');
45500b57cec5SDimitry Andric         break;
45510b57cec5SDimitry Andric       case 61:
45520b57cec5SDimitry Andric         result.push_back('%');
45530b57cec5SDimitry Andric         result.push_back('y');
45540b57cec5SDimitry Andric         break;
45550b57cec5SDimitry Andric       case 364:
45560b57cec5SDimitry Andric         result.push_back('%');
45570b57cec5SDimitry Andric         result.push_back('j');
45580b57cec5SDimitry Andric         break;
45590b57cec5SDimitry Andric       case 2061:
45600b57cec5SDimitry Andric         result.push_back('%');
45610b57cec5SDimitry Andric         result.push_back('Y');
45620b57cec5SDimitry Andric         break;
45630b57cec5SDimitry Andric       default:
45640b57cec5SDimitry Andric         for (; w != bb; ++w)
45650b57cec5SDimitry Andric           result.push_back(*w);
45660b57cec5SDimitry Andric         break;
45670b57cec5SDimitry Andric       }
45680b57cec5SDimitry Andric       continue;
45690b57cec5SDimitry Andric     }
4570cb14a3feSDimitry Andric     if (*bb == '%') {
45710b57cec5SDimitry Andric       result.push_back('%');
45720b57cec5SDimitry Andric       result.push_back('%');
45730b57cec5SDimitry Andric       ++bb;
45740b57cec5SDimitry Andric       continue;
45750b57cec5SDimitry Andric     }
45760b57cec5SDimitry Andric     result.push_back(*bb);
45770b57cec5SDimitry Andric     ++bb;
45780b57cec5SDimitry Andric   }
45790b57cec5SDimitry Andric   return result;
45800b57cec5SDimitry Andric }
45810b57cec5SDimitry Andric 
458281ad6265SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces")
45830b57cec5SDimitry Andric 
4584349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
45850b57cec5SDimitry Andric template <>
__analyze(char fmt,const ctype<wchar_t> & ct)4586cb14a3feSDimitry Andric wstring __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) {
45870b57cec5SDimitry Andric   tm t       = {0};
45880b57cec5SDimitry Andric   t.tm_sec   = 59;
45890b57cec5SDimitry Andric   t.tm_min   = 55;
45900b57cec5SDimitry Andric   t.tm_hour  = 23;
45910b57cec5SDimitry Andric   t.tm_mday  = 31;
45920b57cec5SDimitry Andric   t.tm_mon   = 11;
45930b57cec5SDimitry Andric   t.tm_year  = 161;
45940b57cec5SDimitry Andric   t.tm_wday  = 6;
45950b57cec5SDimitry Andric   t.tm_yday  = 364;
45960b57cec5SDimitry Andric   t.tm_isdst = -1;
45970b57cec5SDimitry Andric   char buf[100];
45980b57cec5SDimitry Andric   char f[3] = {0};
45990b57cec5SDimitry Andric   f[0]      = '%';
46000b57cec5SDimitry Andric   f[1]      = fmt;
46010b57cec5SDimitry Andric   strftime_l(buf, countof(buf), f, &t, __loc_);
46020b57cec5SDimitry Andric   wchar_t wbuf[100];
46030b57cec5SDimitry Andric   wchar_t* wbb   = wbuf;
46040b57cec5SDimitry Andric   mbstate_t mb   = {0};
46050b57cec5SDimitry Andric   const char* bb = buf;
46060b57cec5SDimitry Andric   size_t j       = __libcpp_mbsrtowcs_l(wbb, &bb, countof(wbuf), &mb, __loc_);
46070b57cec5SDimitry Andric   if (j == size_t(-1))
46080b57cec5SDimitry Andric     __throw_runtime_error("locale not supported");
46090b57cec5SDimitry Andric   wchar_t* wbe = wbb + j;
46100b57cec5SDimitry Andric   wstring result;
4611cb14a3feSDimitry Andric   while (wbb != wbe) {
4612cb14a3feSDimitry Andric     if (ct.is(ctype_base::space, *wbb)) {
46130b57cec5SDimitry Andric       result.push_back(L' ');
46140b57cec5SDimitry Andric       for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
46150b57cec5SDimitry Andric         ;
46160b57cec5SDimitry Andric       continue;
46170b57cec5SDimitry Andric     }
46180b57cec5SDimitry Andric     wchar_t* w            = wbb;
46190b57cec5SDimitry Andric     ios_base::iostate err = ios_base::goodbit;
4620cb14a3feSDimitry Andric     ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_ + 14, ct, err, false) - this->__weeks_;
4621cb14a3feSDimitry Andric     if (i < 14) {
46220b57cec5SDimitry Andric       result.push_back(L'%');
46230b57cec5SDimitry Andric       if (i < 7)
46240b57cec5SDimitry Andric         result.push_back(L'A');
46250b57cec5SDimitry Andric       else
46260b57cec5SDimitry Andric         result.push_back(L'a');
46270b57cec5SDimitry Andric       wbb = w;
46280b57cec5SDimitry Andric       continue;
46290b57cec5SDimitry Andric     }
46300b57cec5SDimitry Andric     w = wbb;
4631cb14a3feSDimitry Andric     i = __scan_keyword(w, wbe, this->__months_, this->__months_ + 24, ct, err, false) - this->__months_;
4632cb14a3feSDimitry Andric     if (i < 24) {
46330b57cec5SDimitry Andric       result.push_back(L'%');
46340b57cec5SDimitry Andric       if (i < 12)
46350b57cec5SDimitry Andric         result.push_back(L'B');
46360b57cec5SDimitry Andric       else
46370b57cec5SDimitry Andric         result.push_back(L'b');
46380b57cec5SDimitry Andric       if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
46390b57cec5SDimitry Andric         result.back() = L'm';
46400b57cec5SDimitry Andric       wbb = w;
46410b57cec5SDimitry Andric       continue;
46420b57cec5SDimitry Andric     }
4643cb14a3feSDimitry Andric     if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) {
46440b57cec5SDimitry Andric       w = wbb;
4645cb14a3feSDimitry Andric       i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_ + 2, ct, err, false) - this->__am_pm_;
4646cb14a3feSDimitry Andric       if (i < 2) {
46470b57cec5SDimitry Andric         result.push_back(L'%');
46480b57cec5SDimitry Andric         result.push_back(L'p');
46490b57cec5SDimitry Andric         wbb = w;
46500b57cec5SDimitry Andric         continue;
46510b57cec5SDimitry Andric       }
46520b57cec5SDimitry Andric     }
46530b57cec5SDimitry Andric     w = wbb;
4654cb14a3feSDimitry Andric     if (ct.is(ctype_base::digit, *wbb)) {
4655cb14a3feSDimitry Andric       switch (__get_up_to_n_digits(wbb, wbe, err, ct, 4)) {
46560b57cec5SDimitry Andric       case 6:
46570b57cec5SDimitry Andric         result.push_back(L'%');
46580b57cec5SDimitry Andric         result.push_back(L'w');
46590b57cec5SDimitry Andric         break;
46600b57cec5SDimitry Andric       case 7:
46610b57cec5SDimitry Andric         result.push_back(L'%');
46620b57cec5SDimitry Andric         result.push_back(L'u');
46630b57cec5SDimitry Andric         break;
46640b57cec5SDimitry Andric       case 11:
46650b57cec5SDimitry Andric         result.push_back(L'%');
46660b57cec5SDimitry Andric         result.push_back(L'I');
46670b57cec5SDimitry Andric         break;
46680b57cec5SDimitry Andric       case 12:
46690b57cec5SDimitry Andric         result.push_back(L'%');
46700b57cec5SDimitry Andric         result.push_back(L'm');
46710b57cec5SDimitry Andric         break;
46720b57cec5SDimitry Andric       case 23:
46730b57cec5SDimitry Andric         result.push_back(L'%');
46740b57cec5SDimitry Andric         result.push_back(L'H');
46750b57cec5SDimitry Andric         break;
46760b57cec5SDimitry Andric       case 31:
46770b57cec5SDimitry Andric         result.push_back(L'%');
46780b57cec5SDimitry Andric         result.push_back(L'd');
46790b57cec5SDimitry Andric         break;
46800b57cec5SDimitry Andric       case 55:
46810b57cec5SDimitry Andric         result.push_back(L'%');
46820b57cec5SDimitry Andric         result.push_back(L'M');
46830b57cec5SDimitry Andric         break;
46840b57cec5SDimitry Andric       case 59:
46850b57cec5SDimitry Andric         result.push_back(L'%');
46860b57cec5SDimitry Andric         result.push_back(L'S');
46870b57cec5SDimitry Andric         break;
46880b57cec5SDimitry Andric       case 61:
46890b57cec5SDimitry Andric         result.push_back(L'%');
46900b57cec5SDimitry Andric         result.push_back(L'y');
46910b57cec5SDimitry Andric         break;
46920b57cec5SDimitry Andric       case 364:
46930b57cec5SDimitry Andric         result.push_back(L'%');
46940b57cec5SDimitry Andric         result.push_back(L'j');
46950b57cec5SDimitry Andric         break;
46960b57cec5SDimitry Andric       case 2061:
46970b57cec5SDimitry Andric         result.push_back(L'%');
46980b57cec5SDimitry Andric         result.push_back(L'Y');
46990b57cec5SDimitry Andric         break;
47000b57cec5SDimitry Andric       default:
47010b57cec5SDimitry Andric         for (; w != wbb; ++w)
47020b57cec5SDimitry Andric           result.push_back(*w);
47030b57cec5SDimitry Andric         break;
47040b57cec5SDimitry Andric       }
47050b57cec5SDimitry Andric       continue;
47060b57cec5SDimitry Andric     }
4707cb14a3feSDimitry Andric     if (ct.narrow(*wbb, 0) == '%') {
47080b57cec5SDimitry Andric       result.push_back(L'%');
47090b57cec5SDimitry Andric       result.push_back(L'%');
47100b57cec5SDimitry Andric       ++wbb;
47110b57cec5SDimitry Andric       continue;
47120b57cec5SDimitry Andric     }
47130b57cec5SDimitry Andric     result.push_back(*wbb);
47140b57cec5SDimitry Andric     ++wbb;
47150b57cec5SDimitry Andric   }
47160b57cec5SDimitry Andric   return result;
47170b57cec5SDimitry Andric }
4718349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
47190b57cec5SDimitry Andric 
47200b57cec5SDimitry Andric template <>
init(const ctype<char> & ct)4721cb14a3feSDimitry Andric void __time_get_storage<char>::init(const ctype<char>& ct) {
47220b57cec5SDimitry Andric   tm t = {0};
47230b57cec5SDimitry Andric   char buf[100];
47240b57cec5SDimitry Andric   // __weeks_
4725cb14a3feSDimitry Andric   for (int i = 0; i < 7; ++i) {
47260b57cec5SDimitry Andric     t.tm_wday = i;
47270b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%A", &t, __loc_);
47280b57cec5SDimitry Andric     __weeks_[i] = buf;
47290b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%a", &t, __loc_);
47300b57cec5SDimitry Andric     __weeks_[i + 7] = buf;
47310b57cec5SDimitry Andric   }
47320b57cec5SDimitry Andric   // __months_
4733cb14a3feSDimitry Andric   for (int i = 0; i < 12; ++i) {
47340b57cec5SDimitry Andric     t.tm_mon = i;
47350b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%B", &t, __loc_);
47360b57cec5SDimitry Andric     __months_[i] = buf;
47370b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%b", &t, __loc_);
47380b57cec5SDimitry Andric     __months_[i + 12] = buf;
47390b57cec5SDimitry Andric   }
47400b57cec5SDimitry Andric   // __am_pm_
47410b57cec5SDimitry Andric   t.tm_hour = 1;
47420b57cec5SDimitry Andric   strftime_l(buf, countof(buf), "%p", &t, __loc_);
47430b57cec5SDimitry Andric   __am_pm_[0] = buf;
47440b57cec5SDimitry Andric   t.tm_hour   = 13;
47450b57cec5SDimitry Andric   strftime_l(buf, countof(buf), "%p", &t, __loc_);
47460b57cec5SDimitry Andric   __am_pm_[1] = buf;
47470b57cec5SDimitry Andric   __c_        = __analyze('c', ct);
47480b57cec5SDimitry Andric   __r_        = __analyze('r', ct);
47490b57cec5SDimitry Andric   __x_        = __analyze('x', ct);
47500b57cec5SDimitry Andric   __X_        = __analyze('X', ct);
47510b57cec5SDimitry Andric }
47520b57cec5SDimitry Andric 
4753349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
47540b57cec5SDimitry Andric template <>
init(const ctype<wchar_t> & ct)4755cb14a3feSDimitry Andric void __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) {
47560b57cec5SDimitry Andric   tm t = {0};
47570b57cec5SDimitry Andric   char buf[100];
47580b57cec5SDimitry Andric   wchar_t wbuf[100];
47590b57cec5SDimitry Andric   wchar_t* wbe;
47600b57cec5SDimitry Andric   mbstate_t mb = {0};
47610b57cec5SDimitry Andric   // __weeks_
4762cb14a3feSDimitry Andric   for (int i = 0; i < 7; ++i) {
47630b57cec5SDimitry Andric     t.tm_wday = i;
47640b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%A", &t, __loc_);
47650b57cec5SDimitry Andric     mb             = mbstate_t();
47660b57cec5SDimitry Andric     const char* bb = buf;
47670b57cec5SDimitry Andric     size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
4768e8d8bef9SDimitry Andric     if (j == size_t(-1) || j == 0)
47690b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
47700b57cec5SDimitry Andric     wbe = wbuf + j;
47710b57cec5SDimitry Andric     __weeks_[i].assign(wbuf, wbe);
47720b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%a", &t, __loc_);
47730b57cec5SDimitry Andric     mb = mbstate_t();
47740b57cec5SDimitry Andric     bb = buf;
47750b57cec5SDimitry Andric     j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
4776e8d8bef9SDimitry Andric     if (j == size_t(-1) || j == 0)
47770b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
47780b57cec5SDimitry Andric     wbe = wbuf + j;
47790b57cec5SDimitry Andric     __weeks_[i + 7].assign(wbuf, wbe);
47800b57cec5SDimitry Andric   }
47810b57cec5SDimitry Andric   // __months_
4782cb14a3feSDimitry Andric   for (int i = 0; i < 12; ++i) {
47830b57cec5SDimitry Andric     t.tm_mon = i;
47840b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%B", &t, __loc_);
47850b57cec5SDimitry Andric     mb             = mbstate_t();
47860b57cec5SDimitry Andric     const char* bb = buf;
47870b57cec5SDimitry Andric     size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
4788e8d8bef9SDimitry Andric     if (j == size_t(-1) || j == 0)
47890b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
47900b57cec5SDimitry Andric     wbe = wbuf + j;
47910b57cec5SDimitry Andric     __months_[i].assign(wbuf, wbe);
47920b57cec5SDimitry Andric     strftime_l(buf, countof(buf), "%b", &t, __loc_);
47930b57cec5SDimitry Andric     mb = mbstate_t();
47940b57cec5SDimitry Andric     bb = buf;
47950b57cec5SDimitry Andric     j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
4796e8d8bef9SDimitry Andric     if (j == size_t(-1) || j == 0)
47970b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
47980b57cec5SDimitry Andric     wbe = wbuf + j;
47990b57cec5SDimitry Andric     __months_[i + 12].assign(wbuf, wbe);
48000b57cec5SDimitry Andric   }
48010b57cec5SDimitry Andric   // __am_pm_
48020b57cec5SDimitry Andric   t.tm_hour = 1;
48030b57cec5SDimitry Andric   strftime_l(buf, countof(buf), "%p", &t, __loc_);
48040b57cec5SDimitry Andric   mb             = mbstate_t();
48050b57cec5SDimitry Andric   const char* bb = buf;
48060b57cec5SDimitry Andric   size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
48070b57cec5SDimitry Andric   if (j == size_t(-1))
48080b57cec5SDimitry Andric     __throw_runtime_error("locale not supported");
48090b57cec5SDimitry Andric   wbe = wbuf + j;
48100b57cec5SDimitry Andric   __am_pm_[0].assign(wbuf, wbe);
48110b57cec5SDimitry Andric   t.tm_hour = 13;
48120b57cec5SDimitry Andric   strftime_l(buf, countof(buf), "%p", &t, __loc_);
48130b57cec5SDimitry Andric   mb = mbstate_t();
48140b57cec5SDimitry Andric   bb = buf;
48150b57cec5SDimitry Andric   j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
48160b57cec5SDimitry Andric   if (j == size_t(-1))
48170b57cec5SDimitry Andric     __throw_runtime_error("locale not supported");
48180b57cec5SDimitry Andric   wbe = wbuf + j;
48190b57cec5SDimitry Andric   __am_pm_[1].assign(wbuf, wbe);
48200b57cec5SDimitry Andric   __c_ = __analyze('c', ct);
48210b57cec5SDimitry Andric   __r_ = __analyze('r', ct);
48220b57cec5SDimitry Andric   __x_ = __analyze('x', ct);
48230b57cec5SDimitry Andric   __X_ = __analyze('X', ct);
48240b57cec5SDimitry Andric }
4825349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
48260b57cec5SDimitry Andric 
48270b57cec5SDimitry Andric template <class CharT>
4828cb14a3feSDimitry Andric struct _LIBCPP_HIDDEN __time_get_temp : public ctype_byname<CharT> {
__time_get_temp__time_get_temp4829cb14a3feSDimitry Andric   explicit __time_get_temp(const char* nm) : ctype_byname<CharT>(nm, 1) {}
__time_get_temp__time_get_temp4830cb14a3feSDimitry Andric   explicit __time_get_temp(const string& nm) : ctype_byname<CharT>(nm, 1) {}
48310b57cec5SDimitry Andric };
48320b57cec5SDimitry Andric 
48330b57cec5SDimitry Andric template <>
__time_get_storage(const char * __nm)4834cb14a3feSDimitry Andric __time_get_storage<char>::__time_get_storage(const char* __nm) : __time_get(__nm) {
48350b57cec5SDimitry Andric   const __time_get_temp<char> ct(__nm);
48360b57cec5SDimitry Andric   init(ct);
48370b57cec5SDimitry Andric }
48380b57cec5SDimitry Andric 
48390b57cec5SDimitry Andric template <>
__time_get_storage(const string & __nm)4840cb14a3feSDimitry Andric __time_get_storage<char>::__time_get_storage(const string& __nm) : __time_get(__nm) {
48410b57cec5SDimitry Andric   const __time_get_temp<char> ct(__nm);
48420b57cec5SDimitry Andric   init(ct);
48430b57cec5SDimitry Andric }
48440b57cec5SDimitry Andric 
4845349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
48460b57cec5SDimitry Andric template <>
__time_get_storage(const char * __nm)4847cb14a3feSDimitry Andric __time_get_storage<wchar_t>::__time_get_storage(const char* __nm) : __time_get(__nm) {
48480b57cec5SDimitry Andric   const __time_get_temp<wchar_t> ct(__nm);
48490b57cec5SDimitry Andric   init(ct);
48500b57cec5SDimitry Andric }
48510b57cec5SDimitry Andric 
48520b57cec5SDimitry Andric template <>
__time_get_storage(const string & __nm)4853cb14a3feSDimitry Andric __time_get_storage<wchar_t>::__time_get_storage(const string& __nm) : __time_get(__nm) {
48540b57cec5SDimitry Andric   const __time_get_temp<wchar_t> ct(__nm);
48550b57cec5SDimitry Andric   init(ct);
48560b57cec5SDimitry Andric }
4857349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
48580b57cec5SDimitry Andric 
48590b57cec5SDimitry Andric template <>
__do_date_order() const4860cb14a3feSDimitry Andric time_base::dateorder __time_get_storage<char>::__do_date_order() const {
48610b57cec5SDimitry Andric   unsigned i;
48620b57cec5SDimitry Andric   for (i = 0; i < __x_.size(); ++i)
48630b57cec5SDimitry Andric     if (__x_[i] == '%')
48640b57cec5SDimitry Andric       break;
48650b57cec5SDimitry Andric   ++i;
4866cb14a3feSDimitry Andric   switch (__x_[i]) {
48670b57cec5SDimitry Andric   case 'y':
48680b57cec5SDimitry Andric   case 'Y':
48690b57cec5SDimitry Andric     for (++i; i < __x_.size(); ++i)
48700b57cec5SDimitry Andric       if (__x_[i] == '%')
48710b57cec5SDimitry Andric         break;
48720b57cec5SDimitry Andric     if (i == __x_.size())
48730b57cec5SDimitry Andric       break;
48740b57cec5SDimitry Andric     ++i;
4875cb14a3feSDimitry Andric     switch (__x_[i]) {
48760b57cec5SDimitry Andric     case 'm':
48770b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
48780b57cec5SDimitry Andric         if (__x_[i] == '%')
48790b57cec5SDimitry Andric           break;
48800b57cec5SDimitry Andric       if (i == __x_.size())
48810b57cec5SDimitry Andric         break;
48820b57cec5SDimitry Andric       ++i;
48830b57cec5SDimitry Andric       if (__x_[i] == 'd')
48840b57cec5SDimitry Andric         return time_base::ymd;
48850b57cec5SDimitry Andric       break;
48860b57cec5SDimitry Andric     case 'd':
48870b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
48880b57cec5SDimitry Andric         if (__x_[i] == '%')
48890b57cec5SDimitry Andric           break;
48900b57cec5SDimitry Andric       if (i == __x_.size())
48910b57cec5SDimitry Andric         break;
48920b57cec5SDimitry Andric       ++i;
48930b57cec5SDimitry Andric       if (__x_[i] == 'm')
48940b57cec5SDimitry Andric         return time_base::ydm;
48950b57cec5SDimitry Andric       break;
48960b57cec5SDimitry Andric     }
48970b57cec5SDimitry Andric     break;
48980b57cec5SDimitry Andric   case 'm':
48990b57cec5SDimitry Andric     for (++i; i < __x_.size(); ++i)
49000b57cec5SDimitry Andric       if (__x_[i] == '%')
49010b57cec5SDimitry Andric         break;
49020b57cec5SDimitry Andric     if (i == __x_.size())
49030b57cec5SDimitry Andric       break;
49040b57cec5SDimitry Andric     ++i;
4905cb14a3feSDimitry Andric     if (__x_[i] == 'd') {
49060b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
49070b57cec5SDimitry Andric         if (__x_[i] == '%')
49080b57cec5SDimitry Andric           break;
49090b57cec5SDimitry Andric       if (i == __x_.size())
49100b57cec5SDimitry Andric         break;
49110b57cec5SDimitry Andric       ++i;
49120b57cec5SDimitry Andric       if (__x_[i] == 'y' || __x_[i] == 'Y')
49130b57cec5SDimitry Andric         return time_base::mdy;
49140b57cec5SDimitry Andric       break;
49150b57cec5SDimitry Andric     }
49160b57cec5SDimitry Andric     break;
49170b57cec5SDimitry Andric   case 'd':
49180b57cec5SDimitry Andric     for (++i; i < __x_.size(); ++i)
49190b57cec5SDimitry Andric       if (__x_[i] == '%')
49200b57cec5SDimitry Andric         break;
49210b57cec5SDimitry Andric     if (i == __x_.size())
49220b57cec5SDimitry Andric       break;
49230b57cec5SDimitry Andric     ++i;
4924cb14a3feSDimitry Andric     if (__x_[i] == 'm') {
49250b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
49260b57cec5SDimitry Andric         if (__x_[i] == '%')
49270b57cec5SDimitry Andric           break;
49280b57cec5SDimitry Andric       if (i == __x_.size())
49290b57cec5SDimitry Andric         break;
49300b57cec5SDimitry Andric       ++i;
49310b57cec5SDimitry Andric       if (__x_[i] == 'y' || __x_[i] == 'Y')
49320b57cec5SDimitry Andric         return time_base::dmy;
49330b57cec5SDimitry Andric       break;
49340b57cec5SDimitry Andric     }
49350b57cec5SDimitry Andric     break;
49360b57cec5SDimitry Andric   }
49370b57cec5SDimitry Andric   return time_base::no_order;
49380b57cec5SDimitry Andric }
49390b57cec5SDimitry Andric 
4940349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
49410b57cec5SDimitry Andric template <>
__do_date_order() const4942cb14a3feSDimitry Andric time_base::dateorder __time_get_storage<wchar_t>::__do_date_order() const {
49430b57cec5SDimitry Andric   unsigned i;
49440b57cec5SDimitry Andric   for (i = 0; i < __x_.size(); ++i)
49450b57cec5SDimitry Andric     if (__x_[i] == L'%')
49460b57cec5SDimitry Andric       break;
49470b57cec5SDimitry Andric   ++i;
4948cb14a3feSDimitry Andric   switch (__x_[i]) {
49490b57cec5SDimitry Andric   case L'y':
49500b57cec5SDimitry Andric   case L'Y':
49510b57cec5SDimitry Andric     for (++i; i < __x_.size(); ++i)
49520b57cec5SDimitry Andric       if (__x_[i] == L'%')
49530b57cec5SDimitry Andric         break;
49540b57cec5SDimitry Andric     if (i == __x_.size())
49550b57cec5SDimitry Andric       break;
49560b57cec5SDimitry Andric     ++i;
4957cb14a3feSDimitry Andric     switch (__x_[i]) {
49580b57cec5SDimitry Andric     case L'm':
49590b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
49600b57cec5SDimitry Andric         if (__x_[i] == L'%')
49610b57cec5SDimitry Andric           break;
49620b57cec5SDimitry Andric       if (i == __x_.size())
49630b57cec5SDimitry Andric         break;
49640b57cec5SDimitry Andric       ++i;
49650b57cec5SDimitry Andric       if (__x_[i] == L'd')
49660b57cec5SDimitry Andric         return time_base::ymd;
49670b57cec5SDimitry Andric       break;
49680b57cec5SDimitry Andric     case L'd':
49690b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
49700b57cec5SDimitry Andric         if (__x_[i] == L'%')
49710b57cec5SDimitry Andric           break;
49720b57cec5SDimitry Andric       if (i == __x_.size())
49730b57cec5SDimitry Andric         break;
49740b57cec5SDimitry Andric       ++i;
49750b57cec5SDimitry Andric       if (__x_[i] == L'm')
49760b57cec5SDimitry Andric         return time_base::ydm;
49770b57cec5SDimitry Andric       break;
49780b57cec5SDimitry Andric     }
49790b57cec5SDimitry Andric     break;
49800b57cec5SDimitry Andric   case L'm':
49810b57cec5SDimitry Andric     for (++i; i < __x_.size(); ++i)
49820b57cec5SDimitry Andric       if (__x_[i] == L'%')
49830b57cec5SDimitry Andric         break;
49840b57cec5SDimitry Andric     if (i == __x_.size())
49850b57cec5SDimitry Andric       break;
49860b57cec5SDimitry Andric     ++i;
4987cb14a3feSDimitry Andric     if (__x_[i] == L'd') {
49880b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
49890b57cec5SDimitry Andric         if (__x_[i] == L'%')
49900b57cec5SDimitry Andric           break;
49910b57cec5SDimitry Andric       if (i == __x_.size())
49920b57cec5SDimitry Andric         break;
49930b57cec5SDimitry Andric       ++i;
49940b57cec5SDimitry Andric       if (__x_[i] == L'y' || __x_[i] == L'Y')
49950b57cec5SDimitry Andric         return time_base::mdy;
49960b57cec5SDimitry Andric       break;
49970b57cec5SDimitry Andric     }
49980b57cec5SDimitry Andric     break;
49990b57cec5SDimitry Andric   case L'd':
50000b57cec5SDimitry Andric     for (++i; i < __x_.size(); ++i)
50010b57cec5SDimitry Andric       if (__x_[i] == L'%')
50020b57cec5SDimitry Andric         break;
50030b57cec5SDimitry Andric     if (i == __x_.size())
50040b57cec5SDimitry Andric       break;
50050b57cec5SDimitry Andric     ++i;
5006cb14a3feSDimitry Andric     if (__x_[i] == L'm') {
50070b57cec5SDimitry Andric       for (++i; i < __x_.size(); ++i)
50080b57cec5SDimitry Andric         if (__x_[i] == L'%')
50090b57cec5SDimitry Andric           break;
50100b57cec5SDimitry Andric       if (i == __x_.size())
50110b57cec5SDimitry Andric         break;
50120b57cec5SDimitry Andric       ++i;
50130b57cec5SDimitry Andric       if (__x_[i] == L'y' || __x_[i] == L'Y')
50140b57cec5SDimitry Andric         return time_base::dmy;
50150b57cec5SDimitry Andric       break;
50160b57cec5SDimitry Andric     }
50170b57cec5SDimitry Andric     break;
50180b57cec5SDimitry Andric   }
50190b57cec5SDimitry Andric   return time_base::no_order;
50200b57cec5SDimitry Andric }
5021349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
50220b57cec5SDimitry Andric 
50230b57cec5SDimitry Andric // time_put
50240b57cec5SDimitry Andric 
__time_put(const char * nm)5025cb14a3feSDimitry Andric __time_put::__time_put(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {
50260b57cec5SDimitry Andric   if (__loc_ == 0)
50275f757f3fSDimitry Andric     __throw_runtime_error(("time_put_byname failed to construct for " + string(nm)).c_str());
50280b57cec5SDimitry Andric }
50290b57cec5SDimitry Andric 
__time_put(const string & nm)5030cb14a3feSDimitry Andric __time_put::__time_put(const string& nm) : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) {
50310b57cec5SDimitry Andric   if (__loc_ == 0)
50325f757f3fSDimitry Andric     __throw_runtime_error(("time_put_byname failed to construct for " + nm).c_str());
50330b57cec5SDimitry Andric }
50340b57cec5SDimitry Andric 
~__time_put()5035cb14a3feSDimitry Andric __time_put::~__time_put() {
50360b57cec5SDimitry Andric   if (__loc_ != _LIBCPP_GET_C_LOCALE)
50370b57cec5SDimitry Andric     freelocale(__loc_);
50380b57cec5SDimitry Andric }
50390b57cec5SDimitry Andric 
__do_put(char * __nb,char * & __ne,const tm * __tm,char __fmt,char __mod) const5040cb14a3feSDimitry Andric void __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const {
50410b57cec5SDimitry Andric   char fmt[] = {'%', __fmt, __mod, 0};
50420b57cec5SDimitry Andric   if (__mod != 0)
50430b57cec5SDimitry Andric     swap(fmt[1], fmt[2]);
50440b57cec5SDimitry Andric   size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
50450b57cec5SDimitry Andric   __ne     = __nb + n;
50460b57cec5SDimitry Andric }
50470b57cec5SDimitry Andric 
5048349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
__do_put(wchar_t * __wb,wchar_t * & __we,const tm * __tm,char __fmt,char __mod) const5049cb14a3feSDimitry Andric void __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const {
50500b57cec5SDimitry Andric   char __nar[100];
50510b57cec5SDimitry Andric   char* __ne = __nar + 100;
50520b57cec5SDimitry Andric   __do_put(__nar, __ne, __tm, __fmt, __mod);
50530b57cec5SDimitry Andric   mbstate_t mb     = {0};
50540b57cec5SDimitry Andric   const char* __nb = __nar;
50550b57cec5SDimitry Andric   size_t j         = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
50560b57cec5SDimitry Andric   if (j == size_t(-1))
50570b57cec5SDimitry Andric     __throw_runtime_error("locale not supported");
50580b57cec5SDimitry Andric   __we = __wb + j;
50590b57cec5SDimitry Andric }
5060349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
50610b57cec5SDimitry Andric 
50620b57cec5SDimitry Andric // moneypunct_byname
50630b57cec5SDimitry Andric 
50640b57cec5SDimitry Andric template <class charT>
__init_pat(money_base::pattern & pat,basic_string<charT> & __curr_symbol_,bool intl,char cs_precedes,char sep_by_space,char sign_posn,charT space_char)5065cb14a3feSDimitry Andric static void __init_pat(
5066cb14a3feSDimitry Andric     money_base::pattern& pat,
5067cb14a3feSDimitry Andric     basic_string<charT>& __curr_symbol_,
5068cb14a3feSDimitry Andric     bool intl,
5069cb14a3feSDimitry Andric     char cs_precedes,
5070cb14a3feSDimitry Andric     char sep_by_space,
5071cb14a3feSDimitry Andric     char sign_posn,
5072cb14a3feSDimitry Andric     charT space_char) {
50730b57cec5SDimitry Andric   const char sign                = static_cast<char>(money_base::sign);
50740b57cec5SDimitry Andric   const char space               = static_cast<char>(money_base::space);
50750b57cec5SDimitry Andric   const char none                = static_cast<char>(money_base::none);
50760b57cec5SDimitry Andric   const char symbol              = static_cast<char>(money_base::symbol);
50770b57cec5SDimitry Andric   const char value               = static_cast<char>(money_base::value);
50780b57cec5SDimitry Andric   const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
50790b57cec5SDimitry Andric 
50800b57cec5SDimitry Andric   // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
50810b57cec5SDimitry Andric   // function'. "Space between sign and symbol or value" means that
50820b57cec5SDimitry Andric   // if the sign is adjacent to the symbol, there's a space between
50830b57cec5SDimitry Andric   // them, and otherwise there's a space between the sign and value.
50840b57cec5SDimitry Andric   //
50850b57cec5SDimitry Andric   // C11's localeconv specifies that the fourth character of an
50860b57cec5SDimitry Andric   // international curr_symbol is used to separate the sign and
50870b57cec5SDimitry Andric   // value when sep_by_space says to do so. C++ can't represent
50880b57cec5SDimitry Andric   // that, so we just use a space.  When sep_by_space says to
50890b57cec5SDimitry Andric   // separate the symbol and value-or-sign with a space, we rearrange the
50900b57cec5SDimitry Andric   // curr_symbol to put its spacing character on the correct side of
50910b57cec5SDimitry Andric   // the symbol.
50920b57cec5SDimitry Andric   //
50930b57cec5SDimitry Andric   // We also need to avoid adding an extra space between the sign
50940b57cec5SDimitry Andric   // and value when the currency symbol is suppressed (by not
50950b57cec5SDimitry Andric   // setting showbase).  We match glibc's strfmon by interpreting
50960b57cec5SDimitry Andric   // sep_by_space==1 as "omit the space when the currency symbol is
50970b57cec5SDimitry Andric   // absent".
50980b57cec5SDimitry Andric   //
50990b57cec5SDimitry Andric   // Users who want to get this right should use ICU instead.
51000b57cec5SDimitry Andric 
5101cb14a3feSDimitry Andric   switch (cs_precedes) {
51020b57cec5SDimitry Andric   case 0: // value before curr_symbol
51030b57cec5SDimitry Andric     if (symbol_contains_sep) {
51040b57cec5SDimitry Andric       // Move the separator to before the symbol, to place it
51050b57cec5SDimitry Andric       // between the value and symbol.
5106cb14a3feSDimitry Andric       rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3, __curr_symbol_.end());
51070b57cec5SDimitry Andric     }
5108cb14a3feSDimitry Andric     switch (sign_posn) {
51090b57cec5SDimitry Andric     case 0: // Parentheses surround the quantity and currency symbol.
51100b57cec5SDimitry Andric       pat.field[0] = sign;
51110b57cec5SDimitry Andric       pat.field[1] = value;
51120b57cec5SDimitry Andric       pat.field[2] = none; // Any space appears in the symbol.
51130b57cec5SDimitry Andric       pat.field[3] = symbol;
5114cb14a3feSDimitry Andric       switch (sep_by_space) {
51150b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
51160b57cec5SDimitry Andric               // This case may have changed between C99 and C11;
51170b57cec5SDimitry Andric               // assume the currency symbol matches the intention.
51180b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
51190b57cec5SDimitry Andric         // The "sign" is two parentheses, so no space here either.
51200b57cec5SDimitry Andric         return;
51210b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
51220b57cec5SDimitry Andric         if (!symbol_contains_sep) {
51230b57cec5SDimitry Andric           // We insert the space into the symbol instead of
51240b57cec5SDimitry Andric           // setting pat.field[2]=space so that when
51250b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
51260b57cec5SDimitry Andric           __curr_symbol_.insert(0, 1, space_char);
51270b57cec5SDimitry Andric         }
51280b57cec5SDimitry Andric         return;
51290b57cec5SDimitry Andric       default:
51300b57cec5SDimitry Andric         break;
51310b57cec5SDimitry Andric       }
51320b57cec5SDimitry Andric       break;
51330b57cec5SDimitry Andric     case 1: // The sign string precedes the quantity and currency symbol.
51340b57cec5SDimitry Andric       pat.field[0] = sign;
51350b57cec5SDimitry Andric       pat.field[3] = symbol;
5136cb14a3feSDimitry Andric       switch (sep_by_space) {
51370b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
51380b57cec5SDimitry Andric         pat.field[1] = value;
51390b57cec5SDimitry Andric         pat.field[2] = none;
51400b57cec5SDimitry Andric         return;
51410b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
51420b57cec5SDimitry Andric         pat.field[1] = value;
51430b57cec5SDimitry Andric         pat.field[2] = none;
51440b57cec5SDimitry Andric         if (!symbol_contains_sep) {
51450b57cec5SDimitry Andric           // We insert the space into the symbol instead of
51460b57cec5SDimitry Andric           // setting pat.field[2]=space so that when
51470b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
51480b57cec5SDimitry Andric           __curr_symbol_.insert(0, 1, space_char);
51490b57cec5SDimitry Andric         }
51500b57cec5SDimitry Andric         return;
51510b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
51520b57cec5SDimitry Andric         pat.field[1] = space;
51530b57cec5SDimitry Andric         pat.field[2] = value;
51540b57cec5SDimitry Andric         if (symbol_contains_sep) {
51550b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
51560b57cec5SDimitry Andric           // has already appeared after the sign.
51570b57cec5SDimitry Andric           __curr_symbol_.erase(__curr_symbol_.begin());
51580b57cec5SDimitry Andric         }
51590b57cec5SDimitry Andric         return;
51600b57cec5SDimitry Andric       default:
51610b57cec5SDimitry Andric         break;
51620b57cec5SDimitry Andric       }
51630b57cec5SDimitry Andric       break;
51640b57cec5SDimitry Andric     case 2: // The sign string succeeds the quantity and currency symbol.
51650b57cec5SDimitry Andric       pat.field[0] = value;
51660b57cec5SDimitry Andric       pat.field[3] = sign;
5167cb14a3feSDimitry Andric       switch (sep_by_space) {
51680b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
51690b57cec5SDimitry Andric         pat.field[1] = none;
51700b57cec5SDimitry Andric         pat.field[2] = symbol;
51710b57cec5SDimitry Andric         return;
51720b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
51730b57cec5SDimitry Andric         if (!symbol_contains_sep) {
51740b57cec5SDimitry Andric           // We insert the space into the symbol instead of
51750b57cec5SDimitry Andric           // setting pat.field[1]=space so that when
51760b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
51770b57cec5SDimitry Andric           __curr_symbol_.insert(0, 1, space_char);
51780b57cec5SDimitry Andric         }
51790b57cec5SDimitry Andric         pat.field[1] = none;
51800b57cec5SDimitry Andric         pat.field[2] = symbol;
51810b57cec5SDimitry Andric         return;
51820b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
51830b57cec5SDimitry Andric         pat.field[1] = symbol;
51840b57cec5SDimitry Andric         pat.field[2] = space;
51850b57cec5SDimitry Andric         if (symbol_contains_sep) {
51860b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
51870b57cec5SDimitry Andric           // should not be removed if showbase is absent.
51880b57cec5SDimitry Andric           __curr_symbol_.erase(__curr_symbol_.begin());
51890b57cec5SDimitry Andric         }
51900b57cec5SDimitry Andric         return;
51910b57cec5SDimitry Andric       default:
51920b57cec5SDimitry Andric         break;
51930b57cec5SDimitry Andric       }
51940b57cec5SDimitry Andric       break;
51950b57cec5SDimitry Andric     case 3: // The sign string immediately precedes the currency symbol.
51960b57cec5SDimitry Andric       pat.field[0] = value;
51970b57cec5SDimitry Andric       pat.field[3] = symbol;
5198cb14a3feSDimitry Andric       switch (sep_by_space) {
51990b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
52000b57cec5SDimitry Andric         pat.field[1] = none;
52010b57cec5SDimitry Andric         pat.field[2] = sign;
52020b57cec5SDimitry Andric         return;
52030b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
52040b57cec5SDimitry Andric         pat.field[1] = space;
52050b57cec5SDimitry Andric         pat.field[2] = sign;
52060b57cec5SDimitry Andric         if (symbol_contains_sep) {
52070b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
52080b57cec5SDimitry Andric           // has already appeared before the sign.
52090b57cec5SDimitry Andric           __curr_symbol_.erase(__curr_symbol_.begin());
52100b57cec5SDimitry Andric         }
52110b57cec5SDimitry Andric         return;
52120b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
52130b57cec5SDimitry Andric         pat.field[1] = sign;
52140b57cec5SDimitry Andric         pat.field[2] = none;
52150b57cec5SDimitry Andric         if (!symbol_contains_sep) {
52160b57cec5SDimitry Andric           // We insert the space into the symbol instead of
52170b57cec5SDimitry Andric           // setting pat.field[2]=space so that when
52180b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
52190b57cec5SDimitry Andric           __curr_symbol_.insert(0, 1, space_char);
52200b57cec5SDimitry Andric         }
52210b57cec5SDimitry Andric         return;
52220b57cec5SDimitry Andric       default:
52230b57cec5SDimitry Andric         break;
52240b57cec5SDimitry Andric       }
52250b57cec5SDimitry Andric       break;
52260b57cec5SDimitry Andric     case 4: // The sign string immediately succeeds the currency symbol.
52270b57cec5SDimitry Andric       pat.field[0] = value;
52280b57cec5SDimitry Andric       pat.field[3] = sign;
5229cb14a3feSDimitry Andric       switch (sep_by_space) {
52300b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
52310b57cec5SDimitry Andric         pat.field[1] = none;
52320b57cec5SDimitry Andric         pat.field[2] = symbol;
52330b57cec5SDimitry Andric         return;
52340b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
52350b57cec5SDimitry Andric         pat.field[1] = none;
52360b57cec5SDimitry Andric         pat.field[2] = symbol;
52370b57cec5SDimitry Andric         if (!symbol_contains_sep) {
52380b57cec5SDimitry Andric           // We insert the space into the symbol instead of
52390b57cec5SDimitry Andric           // setting pat.field[1]=space so that when
52400b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
52410b57cec5SDimitry Andric           __curr_symbol_.insert(0, 1, space_char);
52420b57cec5SDimitry Andric         }
52430b57cec5SDimitry Andric         return;
52440b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
52450b57cec5SDimitry Andric         pat.field[1] = symbol;
52460b57cec5SDimitry Andric         pat.field[2] = space;
52470b57cec5SDimitry Andric         if (symbol_contains_sep) {
52480b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
52490b57cec5SDimitry Andric           // should not disappear when showbase is absent.
52500b57cec5SDimitry Andric           __curr_symbol_.erase(__curr_symbol_.begin());
52510b57cec5SDimitry Andric         }
52520b57cec5SDimitry Andric         return;
52530b57cec5SDimitry Andric       default:
52540b57cec5SDimitry Andric         break;
52550b57cec5SDimitry Andric       }
52560b57cec5SDimitry Andric       break;
52570b57cec5SDimitry Andric     default:
52580b57cec5SDimitry Andric       break;
52590b57cec5SDimitry Andric     }
52600b57cec5SDimitry Andric     break;
52610b57cec5SDimitry Andric   case 1: // curr_symbol before value
5262cb14a3feSDimitry Andric     switch (sign_posn) {
52630b57cec5SDimitry Andric     case 0: // Parentheses surround the quantity and currency symbol.
52640b57cec5SDimitry Andric       pat.field[0] = sign;
52650b57cec5SDimitry Andric       pat.field[1] = symbol;
52660b57cec5SDimitry Andric       pat.field[2] = none; // Any space appears in the symbol.
52670b57cec5SDimitry Andric       pat.field[3] = value;
5268cb14a3feSDimitry Andric       switch (sep_by_space) {
52690b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
52700b57cec5SDimitry Andric               // This case may have changed between C99 and C11;
52710b57cec5SDimitry Andric               // assume the currency symbol matches the intention.
52720b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
52730b57cec5SDimitry Andric         // The "sign" is two parentheses, so no space here either.
52740b57cec5SDimitry Andric         return;
52750b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
52760b57cec5SDimitry Andric         if (!symbol_contains_sep) {
52770b57cec5SDimitry Andric           // We insert the space into the symbol instead of
52780b57cec5SDimitry Andric           // setting pat.field[2]=space so that when
52790b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
52800b57cec5SDimitry Andric           __curr_symbol_.insert(0, 1, space_char);
52810b57cec5SDimitry Andric         }
52820b57cec5SDimitry Andric         return;
52830b57cec5SDimitry Andric       default:
52840b57cec5SDimitry Andric         break;
52850b57cec5SDimitry Andric       }
52860b57cec5SDimitry Andric       break;
52870b57cec5SDimitry Andric     case 1: // The sign string precedes the quantity and currency symbol.
52880b57cec5SDimitry Andric       pat.field[0] = sign;
52890b57cec5SDimitry Andric       pat.field[3] = value;
5290cb14a3feSDimitry Andric       switch (sep_by_space) {
52910b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
52920b57cec5SDimitry Andric         pat.field[1] = symbol;
52930b57cec5SDimitry Andric         pat.field[2] = none;
52940b57cec5SDimitry Andric         return;
52950b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
52960b57cec5SDimitry Andric         pat.field[1] = symbol;
52970b57cec5SDimitry Andric         pat.field[2] = none;
52980b57cec5SDimitry Andric         if (!symbol_contains_sep) {
52990b57cec5SDimitry Andric           // We insert the space into the symbol instead of
53000b57cec5SDimitry Andric           // setting pat.field[2]=space so that when
53010b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
53020b57cec5SDimitry Andric           __curr_symbol_.push_back(space_char);
53030b57cec5SDimitry Andric         }
53040b57cec5SDimitry Andric         return;
53050b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
53060b57cec5SDimitry Andric         pat.field[1] = space;
53070b57cec5SDimitry Andric         pat.field[2] = symbol;
53080b57cec5SDimitry Andric         if (symbol_contains_sep) {
53090b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
53100b57cec5SDimitry Andric           // has already appeared after the sign.
53110b57cec5SDimitry Andric           __curr_symbol_.pop_back();
53120b57cec5SDimitry Andric         }
53130b57cec5SDimitry Andric         return;
53140b57cec5SDimitry Andric       default:
53150b57cec5SDimitry Andric         break;
53160b57cec5SDimitry Andric       }
53170b57cec5SDimitry Andric       break;
53180b57cec5SDimitry Andric     case 2: // The sign string succeeds the quantity and currency symbol.
53190b57cec5SDimitry Andric       pat.field[0] = symbol;
53200b57cec5SDimitry Andric       pat.field[3] = sign;
5321cb14a3feSDimitry Andric       switch (sep_by_space) {
53220b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
53230b57cec5SDimitry Andric         pat.field[1] = none;
53240b57cec5SDimitry Andric         pat.field[2] = value;
53250b57cec5SDimitry Andric         return;
53260b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
53270b57cec5SDimitry Andric         pat.field[1] = none;
53280b57cec5SDimitry Andric         pat.field[2] = value;
53290b57cec5SDimitry Andric         if (!symbol_contains_sep) {
53300b57cec5SDimitry Andric           // We insert the space into the symbol instead of
53310b57cec5SDimitry Andric           // setting pat.field[1]=space so that when
53320b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
53330b57cec5SDimitry Andric           __curr_symbol_.push_back(space_char);
53340b57cec5SDimitry Andric         }
53350b57cec5SDimitry Andric         return;
53360b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
53370b57cec5SDimitry Andric         pat.field[1] = value;
53380b57cec5SDimitry Andric         pat.field[2] = space;
53390b57cec5SDimitry Andric         if (symbol_contains_sep) {
53400b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
53410b57cec5SDimitry Andric           // will appear before the sign.
53420b57cec5SDimitry Andric           __curr_symbol_.pop_back();
53430b57cec5SDimitry Andric         }
53440b57cec5SDimitry Andric         return;
53450b57cec5SDimitry Andric       default:
53460b57cec5SDimitry Andric         break;
53470b57cec5SDimitry Andric       }
53480b57cec5SDimitry Andric       break;
53490b57cec5SDimitry Andric     case 3: // The sign string immediately precedes the currency symbol.
53500b57cec5SDimitry Andric       pat.field[0] = sign;
53510b57cec5SDimitry Andric       pat.field[3] = value;
5352cb14a3feSDimitry Andric       switch (sep_by_space) {
53530b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
53540b57cec5SDimitry Andric         pat.field[1] = symbol;
53550b57cec5SDimitry Andric         pat.field[2] = none;
53560b57cec5SDimitry Andric         return;
53570b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
53580b57cec5SDimitry Andric         pat.field[1] = symbol;
53590b57cec5SDimitry Andric         pat.field[2] = none;
53600b57cec5SDimitry Andric         if (!symbol_contains_sep) {
53610b57cec5SDimitry Andric           // We insert the space into the symbol instead of
53620b57cec5SDimitry Andric           // setting pat.field[2]=space so that when
53630b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
53640b57cec5SDimitry Andric           __curr_symbol_.push_back(space_char);
53650b57cec5SDimitry Andric         }
53660b57cec5SDimitry Andric         return;
53670b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
53680b57cec5SDimitry Andric         pat.field[1] = space;
53690b57cec5SDimitry Andric         pat.field[2] = symbol;
53700b57cec5SDimitry Andric         if (symbol_contains_sep) {
53710b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
53720b57cec5SDimitry Andric           // has already appeared after the sign.
53730b57cec5SDimitry Andric           __curr_symbol_.pop_back();
53740b57cec5SDimitry Andric         }
53750b57cec5SDimitry Andric         return;
53760b57cec5SDimitry Andric       default:
53770b57cec5SDimitry Andric         break;
53780b57cec5SDimitry Andric       }
53790b57cec5SDimitry Andric       break;
53800b57cec5SDimitry Andric     case 4: // The sign string immediately succeeds the currency symbol.
53810b57cec5SDimitry Andric       pat.field[0] = symbol;
53820b57cec5SDimitry Andric       pat.field[3] = value;
5383cb14a3feSDimitry Andric       switch (sep_by_space) {
53840b57cec5SDimitry Andric       case 0: // No space separates the currency symbol and value.
53850b57cec5SDimitry Andric         pat.field[1] = sign;
53860b57cec5SDimitry Andric         pat.field[2] = none;
53870b57cec5SDimitry Andric         return;
53880b57cec5SDimitry Andric       case 1: // Space between currency-and-sign or currency and value.
53890b57cec5SDimitry Andric         pat.field[1] = sign;
53900b57cec5SDimitry Andric         pat.field[2] = space;
53910b57cec5SDimitry Andric         if (symbol_contains_sep) {
53920b57cec5SDimitry Andric           // Remove the separator from the symbol, since it
53930b57cec5SDimitry Andric           // should not disappear when showbase is absent.
53940b57cec5SDimitry Andric           __curr_symbol_.pop_back();
53950b57cec5SDimitry Andric         }
53960b57cec5SDimitry Andric         return;
53970b57cec5SDimitry Andric       case 2: // Space between sign and currency or value.
53980b57cec5SDimitry Andric         pat.field[1] = none;
53990b57cec5SDimitry Andric         pat.field[2] = sign;
54000b57cec5SDimitry Andric         if (!symbol_contains_sep) {
54010b57cec5SDimitry Andric           // We insert the space into the symbol instead of
54020b57cec5SDimitry Andric           // setting pat.field[1]=space so that when
54030b57cec5SDimitry Andric           // showbase is not set, the space goes away too.
54040b57cec5SDimitry Andric           __curr_symbol_.push_back(space_char);
54050b57cec5SDimitry Andric         }
54060b57cec5SDimitry Andric         return;
54070b57cec5SDimitry Andric       default:
54080b57cec5SDimitry Andric         break;
54090b57cec5SDimitry Andric       }
54100b57cec5SDimitry Andric       break;
54110b57cec5SDimitry Andric     default:
54120b57cec5SDimitry Andric       break;
54130b57cec5SDimitry Andric     }
54140b57cec5SDimitry Andric     break;
54150b57cec5SDimitry Andric   default:
54160b57cec5SDimitry Andric     break;
54170b57cec5SDimitry Andric   }
54180b57cec5SDimitry Andric   pat.field[0] = symbol;
54190b57cec5SDimitry Andric   pat.field[1] = sign;
54200b57cec5SDimitry Andric   pat.field[2] = none;
54210b57cec5SDimitry Andric   pat.field[3] = value;
54220b57cec5SDimitry Andric }
54230b57cec5SDimitry Andric 
54240b57cec5SDimitry Andric template <>
init(const char * nm)5425cb14a3feSDimitry Andric void moneypunct_byname<char, false>::init(const char* nm) {
54260b57cec5SDimitry Andric   typedef moneypunct<char, false> base;
54270b57cec5SDimitry Andric   __libcpp_unique_locale loc(nm);
54280b57cec5SDimitry Andric   if (!loc)
54295f757f3fSDimitry Andric     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
54300b57cec5SDimitry Andric 
54310b57cec5SDimitry Andric   lconv* lc = __libcpp_localeconv_l(loc.get());
5432cb14a3feSDimitry Andric   if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
54330b57cec5SDimitry Andric     __decimal_point_ = base::do_decimal_point();
5434cb14a3feSDimitry Andric   if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
54350b57cec5SDimitry Andric     __thousands_sep_ = base::do_thousands_sep();
54360b57cec5SDimitry Andric 
54370b57cec5SDimitry Andric   __grouping_    = lc->mon_grouping;
54380b57cec5SDimitry Andric   __curr_symbol_ = lc->currency_symbol;
54390b57cec5SDimitry Andric   if (lc->frac_digits != CHAR_MAX)
54400b57cec5SDimitry Andric     __frac_digits_ = lc->frac_digits;
54410b57cec5SDimitry Andric   else
54420b57cec5SDimitry Andric     __frac_digits_ = base::do_frac_digits();
54430b57cec5SDimitry Andric   if (lc->p_sign_posn == 0)
54440b57cec5SDimitry Andric     __positive_sign_ = "()";
54450b57cec5SDimitry Andric   else
54460b57cec5SDimitry Andric     __positive_sign_ = lc->positive_sign;
54470b57cec5SDimitry Andric   if (lc->n_sign_posn == 0)
54480b57cec5SDimitry Andric     __negative_sign_ = "()";
54490b57cec5SDimitry Andric   else
54500b57cec5SDimitry Andric     __negative_sign_ = lc->negative_sign;
54510b57cec5SDimitry Andric   // Assume the positive and negative formats will want spaces in
54520b57cec5SDimitry Andric   // the same places in curr_symbol since there's no way to
54530b57cec5SDimitry Andric   // represent anything else.
54540b57cec5SDimitry Andric   string_type __dummy_curr_symbol = __curr_symbol_;
5455cb14a3feSDimitry Andric   __init_pat(__pos_format_, __dummy_curr_symbol, false, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5456cb14a3feSDimitry Andric   __init_pat(__neg_format_, __curr_symbol_, false, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
54570b57cec5SDimitry Andric }
54580b57cec5SDimitry Andric 
54590b57cec5SDimitry Andric template <>
init(const char * nm)5460cb14a3feSDimitry Andric void moneypunct_byname<char, true>::init(const char* nm) {
54610b57cec5SDimitry Andric   typedef moneypunct<char, true> base;
54620b57cec5SDimitry Andric   __libcpp_unique_locale loc(nm);
54630b57cec5SDimitry Andric   if (!loc)
54645f757f3fSDimitry Andric     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
54650b57cec5SDimitry Andric 
54660b57cec5SDimitry Andric   lconv* lc = __libcpp_localeconv_l(loc.get());
5467cb14a3feSDimitry Andric   if (!checked_string_to_char_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
54680b57cec5SDimitry Andric     __decimal_point_ = base::do_decimal_point();
5469cb14a3feSDimitry Andric   if (!checked_string_to_char_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
54700b57cec5SDimitry Andric     __thousands_sep_ = base::do_thousands_sep();
54710b57cec5SDimitry Andric   __grouping_    = lc->mon_grouping;
54720b57cec5SDimitry Andric   __curr_symbol_ = lc->int_curr_symbol;
54730b57cec5SDimitry Andric   if (lc->int_frac_digits != CHAR_MAX)
54740b57cec5SDimitry Andric     __frac_digits_ = lc->int_frac_digits;
54750b57cec5SDimitry Andric   else
54760b57cec5SDimitry Andric     __frac_digits_ = base::do_frac_digits();
54770b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
54780b57cec5SDimitry Andric   if (lc->p_sign_posn == 0)
54790b57cec5SDimitry Andric #else  // _LIBCPP_MSVCRT
54800b57cec5SDimitry Andric   if (lc->int_p_sign_posn == 0)
54810b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
54820b57cec5SDimitry Andric     __positive_sign_ = "()";
54830b57cec5SDimitry Andric   else
54840b57cec5SDimitry Andric     __positive_sign_ = lc->positive_sign;
54850b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
54860b57cec5SDimitry Andric   if (lc->n_sign_posn == 0)
54870b57cec5SDimitry Andric #else  // _LIBCPP_MSVCRT
54880b57cec5SDimitry Andric   if (lc->int_n_sign_posn == 0)
54890b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
54900b57cec5SDimitry Andric     __negative_sign_ = "()";
54910b57cec5SDimitry Andric   else
54920b57cec5SDimitry Andric     __negative_sign_ = lc->negative_sign;
54930b57cec5SDimitry Andric   // Assume the positive and negative formats will want spaces in
54940b57cec5SDimitry Andric   // the same places in curr_symbol since there's no way to
54950b57cec5SDimitry Andric   // represent anything else.
54960b57cec5SDimitry Andric   string_type __dummy_curr_symbol = __curr_symbol_;
54970b57cec5SDimitry Andric #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5498cb14a3feSDimitry Andric   __init_pat(__pos_format_, __dummy_curr_symbol, true, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5499cb14a3feSDimitry Andric   __init_pat(__neg_format_, __curr_symbol_, true, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
55000b57cec5SDimitry Andric #else  // _LIBCPP_MSVCRT
5501cb14a3feSDimitry Andric   __init_pat(
5502cb14a3feSDimitry Andric       __pos_format_,
5503cb14a3feSDimitry Andric       __dummy_curr_symbol,
5504cb14a3feSDimitry Andric       true,
5505cb14a3feSDimitry Andric       lc->int_p_cs_precedes,
5506cb14a3feSDimitry Andric       lc->int_p_sep_by_space,
5507cb14a3feSDimitry Andric       lc->int_p_sign_posn,
5508cb14a3feSDimitry Andric       ' ');
5509cb14a3feSDimitry Andric   __init_pat(
5510cb14a3feSDimitry Andric       __neg_format_, __curr_symbol_, true, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn, ' ');
55110b57cec5SDimitry Andric #endif // !_LIBCPP_MSVCRT
55120b57cec5SDimitry Andric }
55130b57cec5SDimitry Andric 
5514349cc55cSDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
55150b57cec5SDimitry Andric template <>
init(const char * nm)5516cb14a3feSDimitry Andric void moneypunct_byname<wchar_t, false>::init(const char* nm) {
55170b57cec5SDimitry Andric   typedef moneypunct<wchar_t, false> base;
55180b57cec5SDimitry Andric   __libcpp_unique_locale loc(nm);
55190b57cec5SDimitry Andric   if (!loc)
55205f757f3fSDimitry Andric     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
55210b57cec5SDimitry Andric   lconv* lc = __libcpp_localeconv_l(loc.get());
5522cb14a3feSDimitry Andric   if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
55230b57cec5SDimitry Andric     __decimal_point_ = base::do_decimal_point();
5524cb14a3feSDimitry Andric   if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
55250b57cec5SDimitry Andric     __thousands_sep_ = base::do_thousands_sep();
55260b57cec5SDimitry Andric   __grouping_ = lc->mon_grouping;
55270b57cec5SDimitry Andric   wchar_t wbuf[100];
55280b57cec5SDimitry Andric   mbstate_t mb   = {0};
55290b57cec5SDimitry Andric   const char* bb = lc->currency_symbol;
55300b57cec5SDimitry Andric   size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
55310b57cec5SDimitry Andric   if (j == size_t(-1))
55320b57cec5SDimitry Andric     __throw_runtime_error("locale not supported");
55330b57cec5SDimitry Andric   wchar_t* wbe = wbuf + j;
55340b57cec5SDimitry Andric   __curr_symbol_.assign(wbuf, wbe);
55350b57cec5SDimitry Andric   if (lc->frac_digits != CHAR_MAX)
55360b57cec5SDimitry Andric     __frac_digits_ = lc->frac_digits;
55370b57cec5SDimitry Andric   else
55380b57cec5SDimitry Andric     __frac_digits_ = base::do_frac_digits();
55390b57cec5SDimitry Andric   if (lc->p_sign_posn == 0)
55400b57cec5SDimitry Andric     __positive_sign_ = L"()";
5541cb14a3feSDimitry Andric   else {
55420b57cec5SDimitry Andric     mb = mbstate_t();
55430b57cec5SDimitry Andric     bb = lc->positive_sign;
55440b57cec5SDimitry Andric     j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
55450b57cec5SDimitry Andric     if (j == size_t(-1))
55460b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
55470b57cec5SDimitry Andric     wbe = wbuf + j;
55480b57cec5SDimitry Andric     __positive_sign_.assign(wbuf, wbe);
55490b57cec5SDimitry Andric   }
55500b57cec5SDimitry Andric   if (lc->n_sign_posn == 0)
55510b57cec5SDimitry Andric     __negative_sign_ = L"()";
5552cb14a3feSDimitry Andric   else {
55530b57cec5SDimitry Andric     mb = mbstate_t();
55540b57cec5SDimitry Andric     bb = lc->negative_sign;
55550b57cec5SDimitry Andric     j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
55560b57cec5SDimitry Andric     if (j == size_t(-1))
55570b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
55580b57cec5SDimitry Andric     wbe = wbuf + j;
55590b57cec5SDimitry Andric     __negative_sign_.assign(wbuf, wbe);
55600b57cec5SDimitry Andric   }
55610b57cec5SDimitry Andric   // Assume the positive and negative formats will want spaces in
55620b57cec5SDimitry Andric   // the same places in curr_symbol since there's no way to
55630b57cec5SDimitry Andric   // represent anything else.
55640b57cec5SDimitry Andric   string_type __dummy_curr_symbol = __curr_symbol_;
5565cb14a3feSDimitry Andric   __init_pat(__pos_format_, __dummy_curr_symbol, false, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5566cb14a3feSDimitry Andric   __init_pat(__neg_format_, __curr_symbol_, false, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
55670b57cec5SDimitry Andric }
55680b57cec5SDimitry Andric 
55690b57cec5SDimitry Andric template <>
init(const char * nm)5570cb14a3feSDimitry Andric void moneypunct_byname<wchar_t, true>::init(const char* nm) {
55710b57cec5SDimitry Andric   typedef moneypunct<wchar_t, true> base;
55720b57cec5SDimitry Andric   __libcpp_unique_locale loc(nm);
55730b57cec5SDimitry Andric   if (!loc)
55745f757f3fSDimitry Andric     __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
55750b57cec5SDimitry Andric 
55760b57cec5SDimitry Andric   lconv* lc = __libcpp_localeconv_l(loc.get());
5577cb14a3feSDimitry Andric   if (!checked_string_to_wchar_convert(__decimal_point_, lc->mon_decimal_point, loc.get()))
55780b57cec5SDimitry Andric     __decimal_point_ = base::do_decimal_point();
5579cb14a3feSDimitry Andric   if (!checked_string_to_wchar_convert(__thousands_sep_, lc->mon_thousands_sep, loc.get()))
55800b57cec5SDimitry Andric     __thousands_sep_ = base::do_thousands_sep();
55810b57cec5SDimitry Andric   __grouping_ = lc->mon_grouping;
55820b57cec5SDimitry Andric   wchar_t wbuf[100];
55830b57cec5SDimitry Andric   mbstate_t mb   = {0};
55840b57cec5SDimitry Andric   const char* bb = lc->int_curr_symbol;
55850b57cec5SDimitry Andric   size_t j       = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
55860b57cec5SDimitry Andric   if (j == size_t(-1))
55870b57cec5SDimitry Andric     __throw_runtime_error("locale not supported");
55880b57cec5SDimitry Andric   wchar_t* wbe = wbuf + j;
55890b57cec5SDimitry Andric   __curr_symbol_.assign(wbuf, wbe);
55900b57cec5SDimitry Andric   if (lc->int_frac_digits != CHAR_MAX)
55910b57cec5SDimitry Andric     __frac_digits_ = lc->int_frac_digits;
55920b57cec5SDimitry Andric   else
55930b57cec5SDimitry Andric     __frac_digits_ = base::do_frac_digits();
55940b57cec5SDimitry Andric #  if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
55950b57cec5SDimitry Andric   if (lc->p_sign_posn == 0)
55960b57cec5SDimitry Andric #  else  // _LIBCPP_MSVCRT
55970b57cec5SDimitry Andric   if (lc->int_p_sign_posn == 0)
55980b57cec5SDimitry Andric #  endif // !_LIBCPP_MSVCRT
55990b57cec5SDimitry Andric     __positive_sign_ = L"()";
5600cb14a3feSDimitry Andric   else {
56010b57cec5SDimitry Andric     mb = mbstate_t();
56020b57cec5SDimitry Andric     bb = lc->positive_sign;
56030b57cec5SDimitry Andric     j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
56040b57cec5SDimitry Andric     if (j == size_t(-1))
56050b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
56060b57cec5SDimitry Andric     wbe = wbuf + j;
56070b57cec5SDimitry Andric     __positive_sign_.assign(wbuf, wbe);
56080b57cec5SDimitry Andric   }
56090b57cec5SDimitry Andric #  if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
56100b57cec5SDimitry Andric   if (lc->n_sign_posn == 0)
56110b57cec5SDimitry Andric #  else  // _LIBCPP_MSVCRT
56120b57cec5SDimitry Andric   if (lc->int_n_sign_posn == 0)
56130b57cec5SDimitry Andric #  endif // !_LIBCPP_MSVCRT
56140b57cec5SDimitry Andric     __negative_sign_ = L"()";
5615cb14a3feSDimitry Andric   else {
56160b57cec5SDimitry Andric     mb = mbstate_t();
56170b57cec5SDimitry Andric     bb = lc->negative_sign;
56180b57cec5SDimitry Andric     j  = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
56190b57cec5SDimitry Andric     if (j == size_t(-1))
56200b57cec5SDimitry Andric       __throw_runtime_error("locale not supported");
56210b57cec5SDimitry Andric     wbe = wbuf + j;
56220b57cec5SDimitry Andric     __negative_sign_.assign(wbuf, wbe);
56230b57cec5SDimitry Andric   }
56240b57cec5SDimitry Andric   // Assume the positive and negative formats will want spaces in
56250b57cec5SDimitry Andric   // the same places in curr_symbol since there's no way to
56260b57cec5SDimitry Andric   // represent anything else.
56270b57cec5SDimitry Andric   string_type __dummy_curr_symbol = __curr_symbol_;
56280b57cec5SDimitry Andric #  if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
5629cb14a3feSDimitry Andric   __init_pat(__pos_format_, __dummy_curr_symbol, true, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5630cb14a3feSDimitry Andric   __init_pat(__neg_format_, __curr_symbol_, true, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
56310b57cec5SDimitry Andric #  else  // _LIBCPP_MSVCRT
5632cb14a3feSDimitry Andric   __init_pat(
5633cb14a3feSDimitry Andric       __pos_format_,
5634cb14a3feSDimitry Andric       __dummy_curr_symbol,
5635cb14a3feSDimitry Andric       true,
5636cb14a3feSDimitry Andric       lc->int_p_cs_precedes,
5637cb14a3feSDimitry Andric       lc->int_p_sep_by_space,
5638cb14a3feSDimitry Andric       lc->int_p_sign_posn,
5639cb14a3feSDimitry Andric       L' ');
5640cb14a3feSDimitry Andric   __init_pat(
5641cb14a3feSDimitry Andric       __neg_format_, __curr_symbol_, true, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn, L' ');
56420b57cec5SDimitry Andric #  endif // !_LIBCPP_MSVCRT
56430b57cec5SDimitry Andric }
5644349cc55cSDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
56450b57cec5SDimitry Andric 
__do_nothing(void *)56460b57cec5SDimitry Andric void __do_nothing(void*) {}
56470b57cec5SDimitry Andric 
56480b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
5649349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
56500b57cec5SDimitry Andric 
56510b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
5652349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
56530b57cec5SDimitry Andric 
56540b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
5655349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
56560b57cec5SDimitry Andric 
56570b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
5658349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
56590b57cec5SDimitry Andric 
56600b57cec5SDimitry Andric template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
5661349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
56620b57cec5SDimitry Andric 
56630b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
5664349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
56650b57cec5SDimitry Andric 
56660b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
5667349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
56680b57cec5SDimitry Andric 
56690b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
5670349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
56710b57cec5SDimitry Andric 
56720b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
5673349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
56740b57cec5SDimitry Andric 
56750b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
56760b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
5677349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
5678349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
56790b57cec5SDimitry Andric 
56800b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
56810b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
5682349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
5683349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
56840b57cec5SDimitry Andric 
56850b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
5686349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
56870b57cec5SDimitry Andric 
56880b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
5689349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
56900b57cec5SDimitry Andric 
56910b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
5692349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
56930b57cec5SDimitry Andric 
56940b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
5695349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
56960b57cec5SDimitry Andric 
56970b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
5698349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
56990b57cec5SDimitry Andric 
57000b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
5701349cc55cSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
57020b57cec5SDimitry Andric 
57030b57cec5SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
5704cb14a3feSDimitry Andric _LIBCPP_IF_WIDE_CHARACTERS(
5705cb14a3feSDimitry Andric     template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;)
5706cb14a3feSDimitry Andric template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
5707cb14a3feSDimitry Andric     codecvt_byname<char16_t, char, mbstate_t>;
5708cb14a3feSDimitry Andric template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
5709cb14a3feSDimitry Andric     codecvt_byname<char32_t, char, mbstate_t>;
5710fe6060f1SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
5711e8d8bef9SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
5712e8d8bef9SDimitry Andric template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
5713e8d8bef9SDimitry Andric #endif
57140b57cec5SDimitry Andric 
57150b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD
571681ad6265SDimitry Andric 
571781ad6265SDimitry Andric _LIBCPP_POP_MACROS
5718