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