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