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