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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of libcxx/src/locale.cpp