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

source code of libcxx/src/locale.cpp