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