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