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