[flang] Fix length handling in character kind implicit conversion (#74586)
[llvm-project.git] / libcxx / src / locale.cpp
blob71f7ca482d508bcd9313212dd9c16f07c5b05277
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 //===----------------------------------------------------------------------===//
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>
25 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
26 # include <cwctype>
27 #endif
29 #if defined(_AIX)
30 # include <sys/localedef.h> // for __lc_ctype_ptr
31 #endif
33 #if defined(_LIBCPP_MSVCRT)
34 # define _CTYPE_DISABLE_MACROS
35 #endif
37 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
38 # include "__support/win32/locale_win32.h"
39 #elif !defined(__BIONIC__) && !defined(__NuttX__)
40 # include <langinfo.h>
41 #endif
43 #include "include/atomic_support.h"
44 #include "include/sso_allocator.h"
46 // On Linux, wint_t and wchar_t have different signed-ness, and this causes
47 // lots of noise in the build log, but no bugs that I know of.
48 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion")
50 _LIBCPP_PUSH_MACROS
51 #include <__undef_macros>
53 _LIBCPP_BEGIN_NAMESPACE_STD
55 struct __libcpp_unique_locale {
56 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
58 ~__libcpp_unique_locale() {
59 if (__loc_)
60 freelocale(__loc_);
63 explicit operator bool() const { return __loc_; }
65 locale_t& get() { return __loc_; }
67 locale_t __loc_;
68 private:
69 __libcpp_unique_locale(__libcpp_unique_locale const&);
70 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
73 #ifdef __cloc_defined
74 locale_t __cloc() {
75 // In theory this could create a race condition. In practice
76 // the race condition is non-fatal since it will just create
77 // a little resource leak. Better approach would be appreciated.
78 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
79 return result;
81 #endif // __cloc_defined
83 namespace {
85 struct releaser {
86 void operator()(locale::facet* p) { p->__release_shared(); }
89 template <class T, class ...Args>
90 T& make(Args ...args)
92 alignas(T) static std::byte buf[sizeof(T)];
93 auto *obj = ::new (&buf) T(args...);
94 return *obj;
97 template <typename T, size_t N>
98 inline
99 constexpr
100 size_t
101 countof(const T (&)[N])
103 return N;
106 template <typename T>
107 inline
108 constexpr
109 size_t
110 countof(const T * const begin, const T * const end)
112 return static_cast<size_t>(end - begin);
117 string
118 build_name(const string& other, const string& one, locale::category c) {
119 if (other == "*" || one == "*")
120 return "*";
121 if (c == locale::none || other == one)
122 return other;
124 // FIXME: Handle the more complicated cases, such as when the locale has
125 // different names for different categories.
126 return "*";
129 const locale::category locale::none;
130 const locale::category locale::collate;
131 const locale::category locale::ctype;
132 const locale::category locale::monetary;
133 const locale::category locale::numeric;
134 const locale::category locale::time;
135 const locale::category locale::messages;
136 const locale::category locale::all;
138 class _LIBCPP_HIDDEN locale::__imp
139 : public facet
141 enum {N = 30};
142 vector<facet*, __sso_allocator<facet*, N> > facets_;
143 string name_;
144 public:
145 explicit __imp(size_t refs = 0);
146 explicit __imp(const string& name, size_t refs = 0);
147 __imp(const __imp&);
148 __imp(const __imp&, const string&, locale::category c);
149 __imp(const __imp& other, const __imp& one, locale::category c);
150 __imp(const __imp&, facet* f, long id);
151 ~__imp();
153 const string& name() const {return name_;}
154 bool has_facet(long id) const
155 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
156 const locale::facet* use_facet(long id) const;
158 void acquire();
159 void release();
160 static __no_destroy<__imp> classic_locale_imp_;
162 private:
163 void install(facet* f, long id);
164 template <class F> void install(F* f) {install(f, f->id.__get());}
165 template <class F> void install_from(const __imp& other);
168 locale::__imp::__imp(size_t refs)
169 : facet(refs),
170 facets_(N),
171 name_("C")
173 facets_.clear();
174 install(&make<std::collate<char> >(1u));
175 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
176 install(&make<std::collate<wchar_t> >(1u));
177 #endif
178 install(&make<std::ctype<char> >(nullptr, false, 1u));
179 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
180 install(&make<std::ctype<wchar_t> >(1u));
181 #endif
182 install(&make<codecvt<char, char, mbstate_t> >(1u));
183 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
184 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
185 #endif
186 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
187 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
188 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
189 _LIBCPP_SUPPRESS_DEPRECATED_POP
190 #ifndef _LIBCPP_HAS_NO_CHAR8_T
191 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
192 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
193 #endif
194 install(&make<numpunct<char> >(1u));
195 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
196 install(&make<numpunct<wchar_t> >(1u));
197 #endif
198 install(&make<num_get<char> >(1u));
199 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
200 install(&make<num_get<wchar_t> >(1u));
201 #endif
202 install(&make<num_put<char> >(1u));
203 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
204 install(&make<num_put<wchar_t> >(1u));
205 #endif
206 install(&make<moneypunct<char, false> >(1u));
207 install(&make<moneypunct<char, true> >(1u));
208 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
209 install(&make<moneypunct<wchar_t, false> >(1u));
210 install(&make<moneypunct<wchar_t, true> >(1u));
211 #endif
212 install(&make<money_get<char> >(1u));
213 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
214 install(&make<money_get<wchar_t> >(1u));
215 #endif
216 install(&make<money_put<char> >(1u));
217 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
218 install(&make<money_put<wchar_t> >(1u));
219 #endif
220 install(&make<time_get<char> >(1u));
221 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
222 install(&make<time_get<wchar_t> >(1u));
223 #endif
224 install(&make<time_put<char> >(1u));
225 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
226 install(&make<time_put<wchar_t> >(1u));
227 #endif
228 install(&make<std::messages<char> >(1u));
229 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
230 install(&make<std::messages<wchar_t> >(1u));
231 #endif
234 locale::__imp::__imp(const string& name, size_t refs)
235 : facet(refs),
236 facets_(N),
237 name_(name)
239 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
242 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
243 facets_ = locale::classic().__locale_->facets_;
244 for (unsigned i = 0; i < facets_.size(); ++i)
245 if (facets_[i])
246 facets_[i]->__add_shared();
247 install(new collate_byname<char>(name_));
248 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
249 install(new collate_byname<wchar_t>(name_));
250 #endif
251 install(new ctype_byname<char>(name_));
252 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
253 install(new ctype_byname<wchar_t>(name_));
254 #endif
255 install(new codecvt_byname<char, char, mbstate_t>(name_));
256 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
257 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
258 #endif
259 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
260 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
261 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
262 _LIBCPP_SUPPRESS_DEPRECATED_POP
263 #ifndef _LIBCPP_HAS_NO_CHAR8_T
264 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
265 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
266 #endif
267 install(new numpunct_byname<char>(name_));
268 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
269 install(new numpunct_byname<wchar_t>(name_));
270 #endif
271 install(new moneypunct_byname<char, false>(name_));
272 install(new moneypunct_byname<char, true>(name_));
273 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
274 install(new moneypunct_byname<wchar_t, false>(name_));
275 install(new moneypunct_byname<wchar_t, true>(name_));
276 #endif
277 install(new time_get_byname<char>(name_));
278 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
279 install(new time_get_byname<wchar_t>(name_));
280 #endif
281 install(new time_put_byname<char>(name_));
282 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
283 install(new time_put_byname<wchar_t>(name_));
284 #endif
285 install(new messages_byname<char>(name_));
286 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
287 install(new messages_byname<wchar_t>(name_));
288 #endif
289 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
291 catch (...)
293 for (unsigned i = 0; i < facets_.size(); ++i)
294 if (facets_[i])
295 facets_[i]->__release_shared();
296 throw;
298 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
301 locale::__imp::__imp(const __imp& other)
302 : facets_(max<size_t>(N, other.facets_.size())),
303 name_(other.name_)
305 facets_ = other.facets_;
306 for (unsigned i = 0; i < facets_.size(); ++i)
307 if (facets_[i])
308 facets_[i]->__add_shared();
311 locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
312 : facets_(N), name_(build_name(other.name_, name, c))
314 facets_ = other.facets_;
315 for (unsigned i = 0; i < facets_.size(); ++i)
316 if (facets_[i])
317 facets_[i]->__add_shared();
318 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
321 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
322 if (c & locale::collate)
324 install(new collate_byname<char>(name));
325 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
326 install(new collate_byname<wchar_t>(name));
327 #endif
329 if (c & locale::ctype)
331 install(new ctype_byname<char>(name));
332 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
333 install(new ctype_byname<wchar_t>(name));
334 #endif
335 install(new codecvt_byname<char, char, mbstate_t>(name));
336 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
337 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
338 #endif
339 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
340 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
341 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
342 _LIBCPP_SUPPRESS_DEPRECATED_POP
343 #ifndef _LIBCPP_HAS_NO_CHAR8_T
344 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
345 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
346 #endif
348 if (c & locale::monetary)
350 install(new moneypunct_byname<char, false>(name));
351 install(new moneypunct_byname<char, true>(name));
352 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
353 install(new moneypunct_byname<wchar_t, false>(name));
354 install(new moneypunct_byname<wchar_t, true>(name));
355 #endif
357 if (c & locale::numeric)
359 install(new numpunct_byname<char>(name));
360 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
361 install(new numpunct_byname<wchar_t>(name));
362 #endif
364 if (c & locale::time)
366 install(new time_get_byname<char>(name));
367 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
368 install(new time_get_byname<wchar_t>(name));
369 #endif
370 install(new time_put_byname<char>(name));
371 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
372 install(new time_put_byname<wchar_t>(name));
373 #endif
375 if (c & locale::messages)
377 install(new messages_byname<char>(name));
378 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
379 install(new messages_byname<wchar_t>(name));
380 #endif
382 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
384 catch (...)
386 for (unsigned i = 0; i < facets_.size(); ++i)
387 if (facets_[i])
388 facets_[i]->__release_shared();
389 throw;
391 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
394 template<class F>
395 inline
396 void
397 locale::__imp::install_from(const locale::__imp& one)
399 long id = F::id.__get();
400 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
403 locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
404 : facets_(N), name_(build_name(other.name_, one.name_, c))
406 facets_ = other.facets_;
407 for (unsigned i = 0; i < facets_.size(); ++i)
408 if (facets_[i])
409 facets_[i]->__add_shared();
410 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
413 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
414 if (c & locale::collate)
416 install_from<std::collate<char> >(one);
417 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
418 install_from<std::collate<wchar_t> >(one);
419 #endif
421 if (c & locale::ctype)
423 install_from<std::ctype<char> >(one);
424 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
425 install_from<std::ctype<wchar_t> >(one);
426 #endif
427 install_from<std::codecvt<char, char, mbstate_t> >(one);
428 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
429 install_from<std::codecvt<char16_t, char, mbstate_t> >(one);
430 install_from<std::codecvt<char32_t, char, mbstate_t> >(one);
431 _LIBCPP_SUPPRESS_DEPRECATED_POP
432 #ifndef _LIBCPP_HAS_NO_CHAR8_T
433 install_from<std::codecvt<char16_t, char8_t, mbstate_t> >(one);
434 install_from<std::codecvt<char32_t, char8_t, mbstate_t> >(one);
435 #endif
436 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
437 install_from<std::codecvt<wchar_t, char, mbstate_t> >(one);
438 #endif
440 if (c & locale::monetary)
442 install_from<moneypunct<char, false> >(one);
443 install_from<moneypunct<char, true> >(one);
444 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
445 install_from<moneypunct<wchar_t, false> >(one);
446 install_from<moneypunct<wchar_t, true> >(one);
447 #endif
448 install_from<money_get<char> >(one);
449 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
450 install_from<money_get<wchar_t> >(one);
451 #endif
452 install_from<money_put<char> >(one);
453 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
454 install_from<money_put<wchar_t> >(one);
455 #endif
457 if (c & locale::numeric)
459 install_from<numpunct<char> >(one);
460 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
461 install_from<numpunct<wchar_t> >(one);
462 #endif
463 install_from<num_get<char> >(one);
464 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
465 install_from<num_get<wchar_t> >(one);
466 #endif
467 install_from<num_put<char> >(one);
468 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
469 install_from<num_put<wchar_t> >(one);
470 #endif
472 if (c & locale::time)
474 install_from<time_get<char> >(one);
475 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
476 install_from<time_get<wchar_t> >(one);
477 #endif
478 install_from<time_put<char> >(one);
479 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
480 install_from<time_put<wchar_t> >(one);
481 #endif
483 if (c & locale::messages)
485 install_from<std::messages<char> >(one);
486 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
487 install_from<std::messages<wchar_t> >(one);
488 #endif
490 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
492 catch (...)
494 for (unsigned i = 0; i < facets_.size(); ++i)
495 if (facets_[i])
496 facets_[i]->__release_shared();
497 throw;
499 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
502 locale::__imp::__imp(const __imp& other, facet* f, long id)
503 : facets_(max<size_t>(N, other.facets_.size()+1)),
504 name_("*")
506 f->__add_shared();
507 unique_ptr<facet, releaser> hold(f);
508 facets_ = other.facets_;
509 for (unsigned i = 0; i < other.facets_.size(); ++i)
510 if (facets_[i])
511 facets_[i]->__add_shared();
512 install(hold.get(), id);
515 locale::__imp::~__imp()
517 for (unsigned i = 0; i < facets_.size(); ++i)
518 if (facets_[i])
519 facets_[i]->__release_shared();
522 void
523 locale::__imp::install(facet* f, long id)
525 f->__add_shared();
526 unique_ptr<facet, releaser> hold(f);
527 if (static_cast<size_t>(id) >= facets_.size())
528 facets_.resize(static_cast<size_t>(id+1));
529 if (facets_[static_cast<size_t>(id)])
530 facets_[static_cast<size_t>(id)]->__release_shared();
531 facets_[static_cast<size_t>(id)] = hold.release();
534 const locale::facet*
535 locale::__imp::use_facet(long id) const
537 if (!has_facet(id))
538 __throw_bad_cast();
539 return facets_[static_cast<size_t>(id)];
542 // locale
544 // We don't do reference counting on the classic locale.
545 // It's never destroyed anyway, but atomic reference counting may be very
546 // expensive in parallel applications. The classic locale is used by default
547 // in all streams. Note: if a new global locale is installed, then we lose
548 // the benefit of no reference counting.
549 constinit __no_destroy<locale::__imp>
550 locale::__imp::classic_locale_imp_(__uninitialized_tag{}); // initialized below in classic()
552 const locale& locale::classic() {
553 static const __no_destroy<locale> classic_locale(__private_tag{}, [] {
554 // executed exactly once on first initialization of `classic_locale`
555 locale::__imp::classic_locale_imp_.__emplace(1u);
556 return &locale::__imp::classic_locale_imp_.__get();
557 }());
558 return classic_locale.__get();
561 locale& locale::__global() {
562 static __no_destroy<locale> g(locale::classic());
563 return g.__get();
566 void locale::__imp::acquire() {
567 if (this != &locale::__imp::classic_locale_imp_.__get())
568 __add_shared();
571 void locale::__imp::release() {
572 if (this != &locale::__imp::classic_locale_imp_.__get())
573 __release_shared();
576 locale::locale() noexcept : __locale_(__global().__locale_) { __locale_->acquire(); }
578 locale::locale(const locale& l) noexcept : __locale_(l.__locale_) { __locale_->acquire(); }
580 locale::~locale() { __locale_->release(); }
582 const locale&
583 locale::operator=(const locale& other) noexcept
585 other.__locale_->acquire();
586 __locale_->release();
587 __locale_ = other.__locale_;
588 return *this;
591 locale::locale(const char* name)
592 : __locale_(name ? new __imp(name)
593 : (__throw_runtime_error("locale constructed with null"), nullptr))
595 __locale_->acquire();
598 locale::locale(const string& name) : __locale_(new __imp(name)) { __locale_->acquire(); }
600 locale::locale(const locale& other, const char* name, category c)
601 : __locale_(name ? new __imp(*other.__locale_, name, c)
602 : (__throw_runtime_error("locale constructed with null"), nullptr))
604 __locale_->acquire();
607 locale::locale(const locale& other, const string& name, category c)
608 : __locale_(new __imp(*other.__locale_, name, c))
610 __locale_->acquire();
613 locale::locale(const locale& other, const locale& one, category c)
614 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
616 __locale_->acquire();
619 string
620 locale::name() const
622 return __locale_->name();
625 void
626 locale::__install_ctor(const locale& other, facet* f, long id)
628 if (f)
629 __locale_ = new __imp(*other.__locale_, f, id);
630 else
631 __locale_ = other.__locale_;
632 __locale_->acquire();
635 locale
636 locale::global(const locale& loc)
638 locale& g = __global();
639 locale r = g;
640 g = loc;
641 if (g.name() != "*")
642 setlocale(LC_ALL, g.name().c_str());
643 return r;
646 bool
647 locale::has_facet(id& x) const
649 return __locale_->has_facet(x.__get());
652 const locale::facet*
653 locale::use_facet(id& x) const
655 return __locale_->use_facet(x.__get());
658 bool
659 locale::operator==(const locale& y) const
661 return (__locale_ == y.__locale_)
662 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
665 // locale::facet
667 locale::facet::~facet()
671 void
672 locale::facet::__on_zero_shared() noexcept
674 delete this;
677 // locale::id
679 constinit int32_t locale::id::__next_id = 0;
681 long locale::id::__get() {
682 call_once(__flag_, [&] { __id_ = __libcpp_atomic_add(&__next_id, 1); });
683 return __id_ - 1;
686 // template <> class collate_byname<char>
688 collate_byname<char>::collate_byname(const char* n, size_t refs)
689 : collate<char>(refs),
690 __l_(newlocale(LC_ALL_MASK, n, 0))
692 if (__l_ == 0)
693 __throw_runtime_error(("collate_byname<char>::collate_byname"
694 " failed to construct for " + string(n)).c_str());
697 collate_byname<char>::collate_byname(const string& name, size_t refs)
698 : collate<char>(refs),
699 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
701 if (__l_ == 0)
702 __throw_runtime_error(("collate_byname<char>::collate_byname"
703 " failed to construct for " + name).c_str());
706 collate_byname<char>::~collate_byname()
708 freelocale(__l_);
712 collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
713 const char_type* __lo2, const char_type* __hi2) const
715 string_type lhs(__lo1, __hi1);
716 string_type rhs(__lo2, __hi2);
717 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l_);
718 if (r < 0)
719 return -1;
720 if (r > 0)
721 return 1;
722 return r;
725 collate_byname<char>::string_type
726 collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
728 const string_type in(lo, hi);
729 string_type out(strxfrm_l(0, in.c_str(), 0, __l_), char());
730 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l_);
731 return out;
734 // template <> class collate_byname<wchar_t>
736 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
737 collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
738 : collate<wchar_t>(refs),
739 __l_(newlocale(LC_ALL_MASK, n, 0))
741 if (__l_ == 0)
742 __throw_runtime_error(("collate_byname<wchar_t>::collate_byname(size_t refs)"
743 " failed to construct for " + string(n)).c_str());
746 collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
747 : collate<wchar_t>(refs),
748 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
750 if (__l_ == 0)
751 __throw_runtime_error(("collate_byname<wchar_t>::collate_byname(size_t refs)"
752 " failed to construct for " + name).c_str());
755 collate_byname<wchar_t>::~collate_byname()
757 freelocale(__l_);
761 collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
762 const char_type* __lo2, const char_type* __hi2) const
764 string_type lhs(__lo1, __hi1);
765 string_type rhs(__lo2, __hi2);
766 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l_);
767 if (r < 0)
768 return -1;
769 if (r > 0)
770 return 1;
771 return r;
774 collate_byname<wchar_t>::string_type
775 collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
777 const string_type in(lo, hi);
778 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l_), wchar_t());
779 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l_);
780 return out;
782 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
784 const ctype_base::mask ctype_base::space;
785 const ctype_base::mask ctype_base::print;
786 const ctype_base::mask ctype_base::cntrl;
787 const ctype_base::mask ctype_base::upper;
788 const ctype_base::mask ctype_base::lower;
789 const ctype_base::mask ctype_base::alpha;
790 const ctype_base::mask ctype_base::digit;
791 const ctype_base::mask ctype_base::punct;
792 const ctype_base::mask ctype_base::xdigit;
793 const ctype_base::mask ctype_base::blank;
794 const ctype_base::mask ctype_base::alnum;
795 const ctype_base::mask ctype_base::graph;
797 // template <> class ctype<wchar_t>;
799 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
800 constinit locale::id ctype<wchar_t>::id;
802 ctype<wchar_t>::~ctype()
806 bool
807 ctype<wchar_t>::do_is(mask m, char_type c) const
809 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
812 const wchar_t*
813 ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
815 for (; low != high; ++low, ++vec)
816 *vec = static_cast<mask>(isascii(*low) ?
817 ctype<char>::classic_table()[*low] : 0);
818 return low;
821 const wchar_t*
822 ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
824 for (; low != high; ++low)
825 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
826 break;
827 return low;
830 const wchar_t*
831 ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
833 for (; low != high; ++low)
834 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
835 break;
836 return low;
839 wchar_t
840 ctype<wchar_t>::do_toupper(char_type c) const
842 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
843 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
844 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
845 defined(__NetBSD__) || defined(__MVS__)
846 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
847 #else
848 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
849 #endif
852 const wchar_t*
853 ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
855 for (; low != high; ++low)
856 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
857 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
858 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
859 defined(__NetBSD__) || defined(__MVS__)
860 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
861 : *low;
862 #else
863 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
864 #endif
865 return low;
868 wchar_t
869 ctype<wchar_t>::do_tolower(char_type c) const
871 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
872 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
873 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
874 defined(__NetBSD__) || defined(__MVS__)
875 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
876 #else
877 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
878 #endif
881 const wchar_t*
882 ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
884 for (; low != high; ++low)
885 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
886 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
887 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
888 defined(__NetBSD__) || defined(__MVS__)
889 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
890 : *low;
891 #else
892 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
893 #endif
894 return low;
897 wchar_t
898 ctype<wchar_t>::do_widen(char c) const
900 return c;
903 const char*
904 ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
906 for (; low != high; ++low, ++dest)
907 *dest = *low;
908 return low;
911 char
912 ctype<wchar_t>::do_narrow(char_type c, char dfault) const
914 if (isascii(c))
915 return static_cast<char>(c);
916 return dfault;
919 const wchar_t*
920 ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
922 for (; low != high; ++low, ++dest)
923 if (isascii(*low))
924 *dest = static_cast<char>(*low);
925 else
926 *dest = dfault;
927 return low;
929 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
931 // template <> class ctype<char>;
933 constinit locale::id ctype<char>::id;
935 const size_t ctype<char>::table_size;
937 ctype<char>::ctype(const mask* tab, bool del, size_t refs)
938 : locale::facet(refs),
939 __tab_(tab),
940 __del_(del)
942 if (__tab_ == 0)
943 __tab_ = classic_table();
946 ctype<char>::~ctype()
948 if (__tab_ && __del_)
949 delete [] __tab_;
952 char
953 ctype<char>::do_toupper(char_type c) const
955 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
956 return isascii(c) ?
957 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
958 #elif defined(__NetBSD__)
959 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
960 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
961 return isascii(c) ?
962 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
963 #else
964 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
965 #endif
968 const char*
969 ctype<char>::do_toupper(char_type* low, const char_type* high) const
971 for (; low != high; ++low)
972 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
973 *low = isascii(*low) ?
974 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
975 #elif defined(__NetBSD__)
976 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
977 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
978 *low = isascii(*low) ?
979 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
980 #else
981 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
982 #endif
983 return low;
986 char
987 ctype<char>::do_tolower(char_type c) const
989 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
990 return isascii(c) ?
991 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
992 #elif defined(__NetBSD__)
993 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
994 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
995 return isascii(c) ?
996 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
997 #else
998 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
999 #endif
1002 const char*
1003 ctype<char>::do_tolower(char_type* low, const char_type* high) const
1005 for (; low != high; ++low)
1006 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1007 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
1008 #elif defined(__NetBSD__)
1009 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
1010 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1011 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
1012 #else
1013 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
1014 #endif
1015 return low;
1018 char
1019 ctype<char>::do_widen(char c) const
1021 return c;
1024 const char*
1025 ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1027 for (; low != high; ++low, ++dest)
1028 *dest = *low;
1029 return low;
1032 char
1033 ctype<char>::do_narrow(char_type c, char dfault) const
1035 if (isascii(c))
1036 return static_cast<char>(c);
1037 return dfault;
1040 const char*
1041 ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1043 for (; low != high; ++low, ++dest)
1044 if (isascii(*low))
1045 *dest = *low;
1046 else
1047 *dest = dfault;
1048 return low;
1051 #if defined(__EMSCRIPTEN__)
1052 extern "C" const unsigned short ** __ctype_b_loc();
1053 extern "C" const int ** __ctype_tolower_loc();
1054 extern "C" const int ** __ctype_toupper_loc();
1055 #endif
1057 #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
1058 const ctype<char>::mask*
1059 ctype<char>::classic_table() noexcept
1061 // clang-format off
1062 static constexpr const ctype<char>::mask builtin_table[table_size] = {
1063 cntrl, cntrl,
1064 cntrl, cntrl,
1065 cntrl, cntrl,
1066 cntrl, cntrl,
1067 cntrl, cntrl | space | blank,
1068 cntrl | space, cntrl | space,
1069 cntrl | space, cntrl | space,
1070 cntrl, cntrl,
1071 cntrl, cntrl,
1072 cntrl, cntrl,
1073 cntrl, cntrl,
1074 cntrl, cntrl,
1075 cntrl, cntrl,
1076 cntrl, cntrl,
1077 cntrl, cntrl,
1078 cntrl, cntrl,
1079 space | blank | print, punct | print,
1080 punct | print, punct | print,
1081 punct | print, punct | print,
1082 punct | print, punct | print,
1083 punct | print, punct | print,
1084 punct | print, punct | print,
1085 punct | print, punct | print,
1086 punct | print, punct | print,
1087 digit | print | xdigit, digit | print | xdigit,
1088 digit | print | xdigit, digit | print | xdigit,
1089 digit | print | xdigit, digit | print | xdigit,
1090 digit | print | xdigit, digit | print | xdigit,
1091 digit | print | xdigit, digit | print | xdigit,
1092 punct | print, punct | print,
1093 punct | print, punct | print,
1094 punct | print, punct | print,
1095 punct | print, upper | xdigit | print | alpha,
1096 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1097 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1098 upper | xdigit | print | alpha, upper | print | alpha,
1099 upper | print | alpha, upper | print | alpha,
1100 upper | print | alpha, upper | print | alpha,
1101 upper | print | alpha, upper | print | alpha,
1102 upper | print | alpha, upper | print | alpha,
1103 upper | print | alpha, upper | print | alpha,
1104 upper | print | alpha, upper | print | alpha,
1105 upper | print | alpha, upper | print | alpha,
1106 upper | print | alpha, upper | print | alpha,
1107 upper | print | alpha, upper | print | alpha,
1108 upper | print | alpha, punct | print,
1109 punct | print, punct | print,
1110 punct | print, punct | print,
1111 punct | print, lower | xdigit | print | alpha,
1112 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1113 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1114 lower | xdigit | print | alpha, lower | print | alpha,
1115 lower | print | alpha, lower | print | alpha,
1116 lower | print | alpha, lower | print | alpha,
1117 lower | print | alpha, lower | print | alpha,
1118 lower | print | alpha, lower | print | alpha,
1119 lower | print | alpha, lower | print | alpha,
1120 lower | print | alpha, lower | print | alpha,
1121 lower | print | alpha, lower | print | alpha,
1122 lower | print | alpha, lower | print | alpha,
1123 lower | print | alpha, lower | print | alpha,
1124 lower | print | alpha, punct | print,
1125 punct | print, punct | print,
1126 punct | print, cntrl,
1127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1136 // clang-format on
1137 return builtin_table;
1139 #else
1140 const ctype<char>::mask*
1141 ctype<char>::classic_table() noexcept
1143 #if defined(__APPLE__) || defined(__FreeBSD__)
1144 return _DefaultRuneLocale.__runetype;
1145 #elif defined(__NetBSD__)
1146 return _C_ctype_tab_ + 1;
1147 #elif defined(__GLIBC__)
1148 return _LIBCPP_GET_C_LOCALE->__ctype_b;
1149 #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
1150 return __pctype_func();
1151 #elif defined(__EMSCRIPTEN__)
1152 return *__ctype_b_loc();
1153 #elif defined(_NEWLIB_VERSION)
1154 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1155 return _ctype_ + 1;
1156 #elif defined(_AIX)
1157 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
1158 #elif defined(__MVS__)
1159 # if defined(__NATIVE_ASCII_F)
1160 return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1161 # else
1162 return const_cast<const ctype<char>::mask*> (__ctypec);
1163 # endif
1164 #else
1165 // Platform not supported: abort so the person doing the port knows what to
1166 // fix
1167 # warning ctype<char>::classic_table() is not implemented
1168 printf("ctype<char>::classic_table() is not implemented\n");
1169 abort();
1170 return NULL;
1171 #endif
1173 #endif
1175 #if defined(__GLIBC__)
1176 const int*
1177 ctype<char>::__classic_lower_table() noexcept
1179 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
1182 const int*
1183 ctype<char>::__classic_upper_table() noexcept
1185 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
1187 #elif defined(__NetBSD__)
1188 const short*
1189 ctype<char>::__classic_lower_table() noexcept
1191 return _C_tolower_tab_ + 1;
1194 const short*
1195 ctype<char>::__classic_upper_table() noexcept
1197 return _C_toupper_tab_ + 1;
1200 #elif defined(__EMSCRIPTEN__)
1201 const int*
1202 ctype<char>::__classic_lower_table() noexcept
1204 return *__ctype_tolower_loc();
1207 const int*
1208 ctype<char>::__classic_upper_table() noexcept
1210 return *__ctype_toupper_loc();
1212 #elif defined(__MVS__)
1213 const unsigned short*
1214 ctype<char>::__classic_lower_table() _NOEXCEPT
1216 # if defined(__NATIVE_ASCII_F)
1217 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1218 # else
1219 return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1220 # endif
1222 const unsigned short *
1223 ctype<char>::__classic_upper_table() _NOEXCEPT
1225 # if defined(__NATIVE_ASCII_F)
1226 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1227 # else
1228 return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1229 # endif
1231 #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
1233 // template <> class ctype_byname<char>
1235 ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1236 : ctype<char>(0, false, refs),
1237 __l_(newlocale(LC_ALL_MASK, name, 0))
1239 if (__l_ == 0)
1240 __throw_runtime_error(("ctype_byname<char>::ctype_byname"
1241 " failed to construct for " + string(name)).c_str());
1244 ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1245 : ctype<char>(0, false, refs),
1246 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1248 if (__l_ == 0)
1249 __throw_runtime_error(("ctype_byname<char>::ctype_byname"
1250 " failed to construct for " + name).c_str());
1253 ctype_byname<char>::~ctype_byname()
1255 freelocale(__l_);
1258 char
1259 ctype_byname<char>::do_toupper(char_type c) const
1261 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l_));
1264 const char*
1265 ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1267 for (; low != high; ++low)
1268 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l_));
1269 return low;
1272 char
1273 ctype_byname<char>::do_tolower(char_type c) const
1275 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l_));
1278 const char*
1279 ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1281 for (; low != high; ++low)
1282 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l_));
1283 return low;
1286 // template <> class ctype_byname<wchar_t>
1288 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1289 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1290 : ctype<wchar_t>(refs),
1291 __l_(newlocale(LC_ALL_MASK, name, 0))
1293 if (__l_ == 0)
1294 __throw_runtime_error(("ctype_byname<wchar_t>::ctype_byname"
1295 " failed to construct for " + string(name)).c_str());
1298 ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1299 : ctype<wchar_t>(refs),
1300 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1302 if (__l_ == 0)
1303 __throw_runtime_error(("ctype_byname<wchar_t>::ctype_byname"
1304 " failed to construct for " + name).c_str());
1307 ctype_byname<wchar_t>::~ctype_byname()
1309 freelocale(__l_);
1312 bool
1313 ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1315 #ifdef _LIBCPP_WCTYPE_IS_MASK
1316 return static_cast<bool>(iswctype_l(c, m, __l_));
1317 #else
1318 bool result = false;
1319 wint_t ch = static_cast<wint_t>(c);
1320 if ((m & space) == space) result |= (iswspace_l(ch, __l_) != 0);
1321 if ((m & print) == print) result |= (iswprint_l(ch, __l_) != 0);
1322 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l_) != 0);
1323 if ((m & upper) == upper) result |= (iswupper_l(ch, __l_) != 0);
1324 if ((m & lower) == lower) result |= (iswlower_l(ch, __l_) != 0);
1325 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l_) != 0);
1326 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l_) != 0);
1327 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l_) != 0);
1328 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l_) != 0);
1329 if ((m & blank) == blank) result |= (iswblank_l(ch, __l_) != 0);
1330 return result;
1331 #endif
1334 const wchar_t*
1335 ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1337 for (; low != high; ++low, ++vec)
1339 if (isascii(*low))
1340 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
1341 else
1343 *vec = 0;
1344 wint_t ch = static_cast<wint_t>(*low);
1345 if (iswspace_l(ch, __l_))
1346 *vec |= space;
1347 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
1348 if (iswprint_l(ch, __l_))
1349 *vec |= print;
1350 #endif
1351 if (iswcntrl_l(ch, __l_))
1352 *vec |= cntrl;
1353 if (iswupper_l(ch, __l_))
1354 *vec |= upper;
1355 if (iswlower_l(ch, __l_))
1356 *vec |= lower;
1357 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
1358 if (iswalpha_l(ch, __l_))
1359 *vec |= alpha;
1360 #endif
1361 if (iswdigit_l(ch, __l_))
1362 *vec |= digit;
1363 if (iswpunct_l(ch, __l_))
1364 *vec |= punct;
1365 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
1366 if (iswxdigit_l(ch, __l_))
1367 *vec |= xdigit;
1368 #endif
1369 if (iswblank_l(ch, __l_))
1370 *vec |= blank;
1373 return low;
1376 const wchar_t*
1377 ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1379 for (; low != high; ++low)
1381 #ifdef _LIBCPP_WCTYPE_IS_MASK
1382 if (iswctype_l(*low, m, __l_))
1383 break;
1384 #else
1385 wint_t ch = static_cast<wint_t>(*low);
1386 if ((m & space) == space && iswspace_l(ch, __l_)) break;
1387 if ((m & print) == print && iswprint_l(ch, __l_)) break;
1388 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) break;
1389 if ((m & upper) == upper && iswupper_l(ch, __l_)) break;
1390 if ((m & lower) == lower && iswlower_l(ch, __l_)) break;
1391 if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) break;
1392 if ((m & digit) == digit && iswdigit_l(ch, __l_)) break;
1393 if ((m & punct) == punct && iswpunct_l(ch, __l_)) break;
1394 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) break;
1395 if ((m & blank) == blank && iswblank_l(ch, __l_)) break;
1396 #endif
1398 return low;
1401 const wchar_t*
1402 ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1404 for (; low != high; ++low)
1406 #ifdef _LIBCPP_WCTYPE_IS_MASK
1407 if (!iswctype_l(*low, m, __l_))
1408 break;
1409 #else
1410 wint_t ch = static_cast<wint_t>(*low);
1411 if ((m & space) == space && iswspace_l(ch, __l_)) continue;
1412 if ((m & print) == print && iswprint_l(ch, __l_)) continue;
1413 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) continue;
1414 if ((m & upper) == upper && iswupper_l(ch, __l_)) continue;
1415 if ((m & lower) == lower && iswlower_l(ch, __l_)) continue;
1416 if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) continue;
1417 if ((m & digit) == digit && iswdigit_l(ch, __l_)) continue;
1418 if ((m & punct) == punct && iswpunct_l(ch, __l_)) continue;
1419 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) continue;
1420 if ((m & blank) == blank && iswblank_l(ch, __l_)) continue;
1421 break;
1422 #endif
1424 return low;
1427 wchar_t
1428 ctype_byname<wchar_t>::do_toupper(char_type c) const
1430 return towupper_l(c, __l_);
1433 const wchar_t*
1434 ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1436 for (; low != high; ++low)
1437 *low = towupper_l(*low, __l_);
1438 return low;
1441 wchar_t
1442 ctype_byname<wchar_t>::do_tolower(char_type c) const
1444 return towlower_l(c, __l_);
1447 const wchar_t*
1448 ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1450 for (; low != high; ++low)
1451 *low = towlower_l(*low, __l_);
1452 return low;
1455 wchar_t
1456 ctype_byname<wchar_t>::do_widen(char c) const
1458 return __libcpp_btowc_l(c, __l_);
1461 const char*
1462 ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1464 for (; low != high; ++low, ++dest)
1465 *dest = __libcpp_btowc_l(*low, __l_);
1466 return low;
1469 char
1470 ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1472 int r = __libcpp_wctob_l(c, __l_);
1473 return (r != EOF) ? static_cast<char>(r) : dfault;
1476 const wchar_t*
1477 ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1479 for (; low != high; ++low, ++dest)
1481 int r = __libcpp_wctob_l(*low, __l_);
1482 *dest = (r != EOF) ? static_cast<char>(r) : dfault;
1484 return low;
1486 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1488 // template <> class codecvt<char, char, mbstate_t>
1490 constinit locale::id codecvt<char, char, mbstate_t>::id;
1492 codecvt<char, char, mbstate_t>::~codecvt()
1496 codecvt<char, char, mbstate_t>::result
1497 codecvt<char, char, mbstate_t>::do_out(state_type&,
1498 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
1499 extern_type* to, extern_type*, extern_type*& to_nxt) const
1501 frm_nxt = frm;
1502 to_nxt = to;
1503 return noconv;
1506 codecvt<char, char, mbstate_t>::result
1507 codecvt<char, char, mbstate_t>::do_in(state_type&,
1508 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
1509 intern_type* to, intern_type*, intern_type*& to_nxt) const
1511 frm_nxt = frm;
1512 to_nxt = to;
1513 return noconv;
1516 codecvt<char, char, mbstate_t>::result
1517 codecvt<char, char, mbstate_t>::do_unshift(state_type&,
1518 extern_type* to, extern_type*, extern_type*& to_nxt) const
1520 to_nxt = to;
1521 return noconv;
1525 codecvt<char, char, mbstate_t>::do_encoding() const noexcept
1527 return 1;
1530 bool
1531 codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
1533 return true;
1537 codecvt<char, char, mbstate_t>::do_length(state_type&,
1538 const extern_type* frm, const extern_type* end, size_t mx) const
1540 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
1544 codecvt<char, char, mbstate_t>::do_max_length() const noexcept
1546 return 1;
1549 // template <> class codecvt<wchar_t, char, mbstate_t>
1551 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1552 constinit locale::id codecvt<wchar_t, char, mbstate_t>::id;
1554 codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1555 : locale::facet(refs),
1556 __l_(_LIBCPP_GET_C_LOCALE)
1560 codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1561 : locale::facet(refs),
1562 __l_(newlocale(LC_ALL_MASK, nm, 0))
1564 if (__l_ == 0)
1565 __throw_runtime_error(("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1566 " failed to construct for " + string(nm)).c_str());
1569 codecvt<wchar_t, char, mbstate_t>::~codecvt()
1571 if (__l_ != _LIBCPP_GET_C_LOCALE)
1572 freelocale(__l_);
1575 codecvt<wchar_t, char, mbstate_t>::result
1576 codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
1577 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1578 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1580 // look for first internal null in frm
1581 const intern_type* fend = frm;
1582 for (; fend != frm_end; ++fend)
1583 if (*fend == 0)
1584 break;
1585 // loop over all null-terminated sequences in frm
1586 to_nxt = to;
1587 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1589 // save state in case it is needed to recover to_nxt on error
1590 mbstate_t save_state = st;
1591 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1592 static_cast<size_t>(to_end-to), &st, __l_);
1593 if (n == size_t(-1))
1595 // need to recover to_nxt
1596 for (to_nxt = to; frm != frm_nxt; ++frm)
1598 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l_);
1599 if (n == size_t(-1))
1600 break;
1601 to_nxt += n;
1603 frm_nxt = frm;
1604 return error;
1606 if (n == 0)
1607 return partial;
1608 to_nxt += n;
1609 if (to_nxt == to_end)
1610 break;
1611 if (fend != frm_end) // set up next null terminated sequence
1613 // Try to write the terminating null
1614 extern_type tmp[MB_LEN_MAX];
1615 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
1616 if (n == size_t(-1)) // on error
1617 return error;
1618 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
1619 return partial;
1620 for (extern_type* p = tmp; n; --n) // write it
1621 *to_nxt++ = *p++;
1622 ++frm_nxt;
1623 // look for next null in frm
1624 for (fend = frm_nxt; fend != frm_end; ++fend)
1625 if (*fend == 0)
1626 break;
1629 return frm_nxt == frm_end ? ok : partial;
1632 codecvt<wchar_t, char, mbstate_t>::result
1633 codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
1634 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1635 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1637 // look for first internal null in frm
1638 const extern_type* fend = frm;
1639 for (; fend != frm_end; ++fend)
1640 if (*fend == 0)
1641 break;
1642 // loop over all null-terminated sequences in frm
1643 to_nxt = to;
1644 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1646 // save state in case it is needed to recover to_nxt on error
1647 mbstate_t save_state = st;
1648 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1649 static_cast<size_t>(to_end-to), &st, __l_);
1650 if (n == size_t(-1))
1652 // need to recover to_nxt
1653 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1655 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1656 &save_state, __l_);
1657 switch (n)
1659 case 0:
1660 ++frm;
1661 break;
1662 case size_t(-1):
1663 frm_nxt = frm;
1664 return error;
1665 case size_t(-2):
1666 frm_nxt = frm;
1667 return partial;
1668 default:
1669 frm += n;
1670 break;
1673 frm_nxt = frm;
1674 return frm_nxt == frm_end ? ok : partial;
1676 if (n == size_t(-1))
1677 return error;
1678 to_nxt += n;
1679 if (to_nxt == to_end)
1680 break;
1681 if (fend != frm_end) // set up next null terminated sequence
1683 // Try to write the terminating null
1684 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l_);
1685 if (n != 0) // on error
1686 return error;
1687 ++to_nxt;
1688 ++frm_nxt;
1689 // look for next null in frm
1690 for (fend = frm_nxt; fend != frm_end; ++fend)
1691 if (*fend == 0)
1692 break;
1695 return frm_nxt == frm_end ? ok : partial;
1698 codecvt<wchar_t, char, mbstate_t>::result
1699 codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1700 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1702 to_nxt = to;
1703 extern_type tmp[MB_LEN_MAX];
1704 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
1705 if (n == size_t(-1) || n == 0) // on error
1706 return error;
1707 --n;
1708 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
1709 return partial;
1710 for (extern_type* p = tmp; n; --n) // write it
1711 *to_nxt++ = *p++;
1712 return ok;
1716 codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
1718 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l_) != 0)
1719 return -1;
1721 // stateless encoding
1722 if (__l_ == 0 || __libcpp_mb_cur_max_l(__l_) == 1) // there are no known constant length encodings
1723 return 1; // which take more than 1 char to form a wchar_t
1724 return 0;
1727 bool
1728 codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
1730 return false;
1734 codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1735 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1737 int nbytes = 0;
1738 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1740 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l_);
1741 switch (n)
1743 case 0:
1744 ++nbytes;
1745 ++frm;
1746 break;
1747 case size_t(-1):
1748 case size_t(-2):
1749 return nbytes;
1750 default:
1751 nbytes += n;
1752 frm += n;
1753 break;
1756 return nbytes;
1760 codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
1762 return __l_ == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l_));
1764 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1766 // Valid UTF ranges
1767 // UTF-32 UTF-16 UTF-8 # of code points
1768 // first second first second third fourth
1769 // 000000 - 00007F 0000 - 007F 00 - 7F 127
1770 // 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1771 // 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1772 // 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1773 // 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1774 // 00D800 - 00DFFF invalid
1775 // 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1776 // 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1777 // 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1778 // 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1780 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
1781 static
1782 codecvt_base::result
1783 utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1784 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1785 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1787 frm_nxt = frm;
1788 to_nxt = to;
1789 if (mode & generate_header)
1791 if (to_end-to_nxt < 3)
1792 return codecvt_base::partial;
1793 *to_nxt++ = static_cast<uint8_t>(0xEF);
1794 *to_nxt++ = static_cast<uint8_t>(0xBB);
1795 *to_nxt++ = static_cast<uint8_t>(0xBF);
1797 for (; frm_nxt < frm_end; ++frm_nxt)
1799 uint16_t wc1 = *frm_nxt;
1800 if (wc1 > Maxcode)
1801 return codecvt_base::error;
1802 if (wc1 < 0x0080)
1804 if (to_end-to_nxt < 1)
1805 return codecvt_base::partial;
1806 *to_nxt++ = static_cast<uint8_t>(wc1);
1808 else if (wc1 < 0x0800)
1810 if (to_end-to_nxt < 2)
1811 return codecvt_base::partial;
1812 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1813 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1815 else if (wc1 < 0xD800)
1817 if (to_end-to_nxt < 3)
1818 return codecvt_base::partial;
1819 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1820 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1821 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1823 else if (wc1 < 0xDC00)
1825 if (frm_end-frm_nxt < 2)
1826 return codecvt_base::partial;
1827 uint16_t wc2 = frm_nxt[1];
1828 if ((wc2 & 0xFC00) != 0xDC00)
1829 return codecvt_base::error;
1830 if (to_end-to_nxt < 4)
1831 return codecvt_base::partial;
1832 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1833 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1834 return codecvt_base::error;
1835 ++frm_nxt;
1836 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1837 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1838 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1839 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1840 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1842 else if (wc1 < 0xE000)
1844 return codecvt_base::error;
1846 else
1848 if (to_end-to_nxt < 3)
1849 return codecvt_base::partial;
1850 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1852 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1855 return codecvt_base::ok;
1858 static
1859 codecvt_base::result
1860 utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1861 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1862 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1864 frm_nxt = frm;
1865 to_nxt = to;
1866 if (mode & generate_header)
1868 if (to_end-to_nxt < 3)
1869 return codecvt_base::partial;
1870 *to_nxt++ = static_cast<uint8_t>(0xEF);
1871 *to_nxt++ = static_cast<uint8_t>(0xBB);
1872 *to_nxt++ = static_cast<uint8_t>(0xBF);
1874 for (; frm_nxt < frm_end; ++frm_nxt)
1876 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1877 if (wc1 > Maxcode)
1878 return codecvt_base::error;
1879 if (wc1 < 0x0080)
1881 if (to_end-to_nxt < 1)
1882 return codecvt_base::partial;
1883 *to_nxt++ = static_cast<uint8_t>(wc1);
1885 else if (wc1 < 0x0800)
1887 if (to_end-to_nxt < 2)
1888 return codecvt_base::partial;
1889 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1890 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1892 else if (wc1 < 0xD800)
1894 if (to_end-to_nxt < 3)
1895 return codecvt_base::partial;
1896 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1897 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1898 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1900 else if (wc1 < 0xDC00)
1902 if (frm_end-frm_nxt < 2)
1903 return codecvt_base::partial;
1904 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1905 if ((wc2 & 0xFC00) != 0xDC00)
1906 return codecvt_base::error;
1907 if (to_end-to_nxt < 4)
1908 return codecvt_base::partial;
1909 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1910 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1911 return codecvt_base::error;
1912 ++frm_nxt;
1913 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1914 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1915 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1916 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1917 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1919 else if (wc1 < 0xE000)
1921 return codecvt_base::error;
1923 else
1925 if (to_end-to_nxt < 3)
1926 return codecvt_base::partial;
1927 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1928 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1929 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1932 return codecvt_base::ok;
1935 static
1936 codecvt_base::result
1937 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1938 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1939 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1941 frm_nxt = frm;
1942 to_nxt = to;
1943 if (mode & consume_header)
1945 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1946 frm_nxt[2] == 0xBF)
1947 frm_nxt += 3;
1949 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1951 uint8_t c1 = *frm_nxt;
1952 if (c1 > Maxcode)
1953 return codecvt_base::error;
1954 if (c1 < 0x80)
1956 *to_nxt = static_cast<uint16_t>(c1);
1957 ++frm_nxt;
1959 else if (c1 < 0xC2)
1961 return codecvt_base::error;
1963 else if (c1 < 0xE0)
1965 if (frm_end-frm_nxt < 2)
1966 return codecvt_base::partial;
1967 uint8_t c2 = frm_nxt[1];
1968 if ((c2 & 0xC0) != 0x80)
1969 return codecvt_base::error;
1970 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1971 if (t > Maxcode)
1972 return codecvt_base::error;
1973 *to_nxt = t;
1974 frm_nxt += 2;
1976 else if (c1 < 0xF0)
1978 if (frm_end-frm_nxt < 2)
1979 return codecvt_base::partial;
1980 uint8_t c2 = frm_nxt[1];
1981 switch (c1)
1983 case 0xE0:
1984 if ((c2 & 0xE0) != 0xA0)
1985 return codecvt_base::error;
1986 break;
1987 case 0xED:
1988 if ((c2 & 0xE0) != 0x80)
1989 return codecvt_base::error;
1990 break;
1991 default:
1992 if ((c2 & 0xC0) != 0x80)
1993 return codecvt_base::error;
1994 break;
1996 if (frm_end-frm_nxt < 3)
1997 return codecvt_base::partial;
1998 uint8_t c3 = frm_nxt[2];
1999 if ((c3 & 0xC0) != 0x80)
2000 return codecvt_base::error;
2001 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2002 | ((c2 & 0x3F) << 6)
2003 | (c3 & 0x3F));
2004 if (t > Maxcode)
2005 return codecvt_base::error;
2006 *to_nxt = t;
2007 frm_nxt += 3;
2009 else if (c1 < 0xF5)
2011 if (frm_end-frm_nxt < 2)
2012 return codecvt_base::partial;
2013 uint8_t c2 = frm_nxt[1];
2014 switch (c1)
2016 case 0xF0:
2017 if (!(0x90 <= c2 && c2 <= 0xBF))
2018 return codecvt_base::error;
2019 break;
2020 case 0xF4:
2021 if ((c2 & 0xF0) != 0x80)
2022 return codecvt_base::error;
2023 break;
2024 default:
2025 if ((c2 & 0xC0) != 0x80)
2026 return codecvt_base::error;
2027 break;
2029 if (frm_end-frm_nxt < 3)
2030 return codecvt_base::partial;
2031 uint8_t c3 = frm_nxt[2];
2032 if ((c3 & 0xC0) != 0x80)
2033 return codecvt_base::error;
2034 if (frm_end-frm_nxt < 4)
2035 return codecvt_base::partial;
2036 uint8_t c4 = frm_nxt[3];
2037 if ((c4 & 0xC0) != 0x80)
2038 return codecvt_base::error;
2039 if (to_end-to_nxt < 2)
2040 return codecvt_base::partial;
2041 if ((((c1 & 7UL) << 18) +
2042 ((c2 & 0x3FUL) << 12) +
2043 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2044 return codecvt_base::error;
2045 *to_nxt = static_cast<uint16_t>(
2046 0xD800
2047 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2048 | ((c2 & 0x0F) << 2)
2049 | ((c3 & 0x30) >> 4));
2050 *++to_nxt = static_cast<uint16_t>(
2051 0xDC00
2052 | ((c3 & 0x0F) << 6)
2053 | (c4 & 0x3F));
2054 frm_nxt += 4;
2056 else
2058 return codecvt_base::error;
2061 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2064 static
2065 codecvt_base::result
2066 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2067 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2068 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2070 frm_nxt = frm;
2071 to_nxt = to;
2072 if (mode & consume_header)
2074 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2075 frm_nxt[2] == 0xBF)
2076 frm_nxt += 3;
2078 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2080 uint8_t c1 = *frm_nxt;
2081 if (c1 > Maxcode)
2082 return codecvt_base::error;
2083 if (c1 < 0x80)
2085 *to_nxt = static_cast<uint32_t>(c1);
2086 ++frm_nxt;
2088 else if (c1 < 0xC2)
2090 return codecvt_base::error;
2092 else if (c1 < 0xE0)
2094 if (frm_end-frm_nxt < 2)
2095 return codecvt_base::partial;
2096 uint8_t c2 = frm_nxt[1];
2097 if ((c2 & 0xC0) != 0x80)
2098 return codecvt_base::error;
2099 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2100 if (t > Maxcode)
2101 return codecvt_base::error;
2102 *to_nxt = static_cast<uint32_t>(t);
2103 frm_nxt += 2;
2105 else if (c1 < 0xF0)
2107 if (frm_end-frm_nxt < 2)
2108 return codecvt_base::partial;
2109 uint8_t c2 = frm_nxt[1];
2110 switch (c1)
2112 case 0xE0:
2113 if ((c2 & 0xE0) != 0xA0)
2114 return codecvt_base::error;
2115 break;
2116 case 0xED:
2117 if ((c2 & 0xE0) != 0x80)
2118 return codecvt_base::error;
2119 break;
2120 default:
2121 if ((c2 & 0xC0) != 0x80)
2122 return codecvt_base::error;
2123 break;
2125 if (frm_end-frm_nxt < 3)
2126 return codecvt_base::partial;
2127 uint8_t c3 = frm_nxt[2];
2128 if ((c3 & 0xC0) != 0x80)
2129 return codecvt_base::error;
2130 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2131 | ((c2 & 0x3F) << 6)
2132 | (c3 & 0x3F));
2133 if (t > Maxcode)
2134 return codecvt_base::error;
2135 *to_nxt = static_cast<uint32_t>(t);
2136 frm_nxt += 3;
2138 else if (c1 < 0xF5)
2140 if (frm_end-frm_nxt < 2)
2141 return codecvt_base::partial;
2142 uint8_t c2 = frm_nxt[1];
2143 switch (c1)
2145 case 0xF0:
2146 if (!(0x90 <= c2 && c2 <= 0xBF))
2147 return codecvt_base::error;
2148 break;
2149 case 0xF4:
2150 if ((c2 & 0xF0) != 0x80)
2151 return codecvt_base::error;
2152 break;
2153 default:
2154 if ((c2 & 0xC0) != 0x80)
2155 return codecvt_base::error;
2156 break;
2158 if (frm_end-frm_nxt < 3)
2159 return codecvt_base::partial;
2160 uint8_t c3 = frm_nxt[2];
2161 if ((c3 & 0xC0) != 0x80)
2162 return codecvt_base::error;
2163 if (frm_end-frm_nxt < 4)
2164 return codecvt_base::partial;
2165 uint8_t c4 = frm_nxt[3];
2166 if ((c4 & 0xC0) != 0x80)
2167 return codecvt_base::error;
2168 if (to_end-to_nxt < 2)
2169 return codecvt_base::partial;
2170 if ((((c1 & 7UL) << 18) +
2171 ((c2 & 0x3FUL) << 12) +
2172 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2173 return codecvt_base::error;
2174 *to_nxt = static_cast<uint32_t>(
2175 0xD800
2176 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2177 | ((c2 & 0x0F) << 2)
2178 | ((c3 & 0x30) >> 4));
2179 *++to_nxt = static_cast<uint32_t>(
2180 0xDC00
2181 | ((c3 & 0x0F) << 6)
2182 | (c4 & 0x3F));
2183 frm_nxt += 4;
2185 else
2187 return codecvt_base::error;
2190 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2193 static
2195 utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2196 size_t mx, unsigned long Maxcode = 0x10FFFF,
2197 codecvt_mode mode = codecvt_mode(0))
2199 const uint8_t* frm_nxt = frm;
2200 if (mode & consume_header)
2202 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2203 frm_nxt[2] == 0xBF)
2204 frm_nxt += 3;
2206 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2208 uint8_t c1 = *frm_nxt;
2209 if (c1 > Maxcode)
2210 break;
2211 if (c1 < 0x80)
2213 ++frm_nxt;
2215 else if (c1 < 0xC2)
2217 break;
2219 else if (c1 < 0xE0)
2221 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2222 break;
2223 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2224 if (t > Maxcode)
2225 break;
2226 frm_nxt += 2;
2228 else if (c1 < 0xF0)
2230 if (frm_end-frm_nxt < 3)
2231 break;
2232 uint8_t c2 = frm_nxt[1];
2233 uint8_t c3 = frm_nxt[2];
2234 switch (c1)
2236 case 0xE0:
2237 if ((c2 & 0xE0) != 0xA0)
2238 return static_cast<int>(frm_nxt - frm);
2239 break;
2240 case 0xED:
2241 if ((c2 & 0xE0) != 0x80)
2242 return static_cast<int>(frm_nxt - frm);
2243 break;
2244 default:
2245 if ((c2 & 0xC0) != 0x80)
2246 return static_cast<int>(frm_nxt - frm);
2247 break;
2249 if ((c3 & 0xC0) != 0x80)
2250 break;
2251 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2252 break;
2253 frm_nxt += 3;
2255 else if (c1 < 0xF5)
2257 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2258 break;
2259 uint8_t c2 = frm_nxt[1];
2260 uint8_t c3 = frm_nxt[2];
2261 uint8_t c4 = frm_nxt[3];
2262 switch (c1)
2264 case 0xF0:
2265 if (!(0x90 <= c2 && c2 <= 0xBF))
2266 return static_cast<int>(frm_nxt - frm);
2267 break;
2268 case 0xF4:
2269 if ((c2 & 0xF0) != 0x80)
2270 return static_cast<int>(frm_nxt - frm);
2271 break;
2272 default:
2273 if ((c2 & 0xC0) != 0x80)
2274 return static_cast<int>(frm_nxt - frm);
2275 break;
2277 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2278 break;
2279 if ((((c1 & 7UL) << 18) +
2280 ((c2 & 0x3FUL) << 12) +
2281 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2282 break;
2283 ++nchar16_t;
2284 frm_nxt += 4;
2286 else
2288 break;
2291 return static_cast<int>(frm_nxt - frm);
2294 static
2295 codecvt_base::result
2296 ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2297 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2298 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2300 frm_nxt = frm;
2301 to_nxt = to;
2302 if (mode & generate_header)
2304 if (to_end-to_nxt < 3)
2305 return codecvt_base::partial;
2306 *to_nxt++ = static_cast<uint8_t>(0xEF);
2307 *to_nxt++ = static_cast<uint8_t>(0xBB);
2308 *to_nxt++ = static_cast<uint8_t>(0xBF);
2310 for (; frm_nxt < frm_end; ++frm_nxt)
2312 uint32_t wc = *frm_nxt;
2313 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2314 return codecvt_base::error;
2315 if (wc < 0x000080)
2317 if (to_end-to_nxt < 1)
2318 return codecvt_base::partial;
2319 *to_nxt++ = static_cast<uint8_t>(wc);
2321 else if (wc < 0x000800)
2323 if (to_end-to_nxt < 2)
2324 return codecvt_base::partial;
2325 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2326 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2328 else if (wc < 0x010000)
2330 if (to_end-to_nxt < 3)
2331 return codecvt_base::partial;
2332 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2333 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2334 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2336 else // if (wc < 0x110000)
2338 if (to_end-to_nxt < 4)
2339 return codecvt_base::partial;
2340 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2341 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2342 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2343 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2346 return codecvt_base::ok;
2349 static
2350 codecvt_base::result
2351 utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2352 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2353 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2355 frm_nxt = frm;
2356 to_nxt = to;
2357 if (mode & consume_header)
2359 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2360 frm_nxt[2] == 0xBF)
2361 frm_nxt += 3;
2363 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2365 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2366 if (c1 < 0x80)
2368 if (c1 > Maxcode)
2369 return codecvt_base::error;
2370 *to_nxt = static_cast<uint32_t>(c1);
2371 ++frm_nxt;
2373 else if (c1 < 0xC2)
2375 return codecvt_base::error;
2377 else if (c1 < 0xE0)
2379 if (frm_end-frm_nxt < 2)
2380 return codecvt_base::partial;
2381 uint8_t c2 = frm_nxt[1];
2382 if ((c2 & 0xC0) != 0x80)
2383 return codecvt_base::error;
2384 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2385 | (c2 & 0x3F));
2386 if (t > Maxcode)
2387 return codecvt_base::error;
2388 *to_nxt = t;
2389 frm_nxt += 2;
2391 else if (c1 < 0xF0)
2393 if (frm_end-frm_nxt < 2)
2394 return codecvt_base::partial;
2395 uint8_t c2 = frm_nxt[1];
2396 switch (c1)
2398 case 0xE0:
2399 if ((c2 & 0xE0) != 0xA0)
2400 return codecvt_base::error;
2401 break;
2402 case 0xED:
2403 if ((c2 & 0xE0) != 0x80)
2404 return codecvt_base::error;
2405 break;
2406 default:
2407 if ((c2 & 0xC0) != 0x80)
2408 return codecvt_base::error;
2409 break;
2411 if (frm_end-frm_nxt < 3)
2412 return codecvt_base::partial;
2413 uint8_t c3 = frm_nxt[2];
2414 if ((c3 & 0xC0) != 0x80)
2415 return codecvt_base::error;
2416 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2417 | ((c2 & 0x3F) << 6)
2418 | (c3 & 0x3F));
2419 if (t > Maxcode)
2420 return codecvt_base::error;
2421 *to_nxt = t;
2422 frm_nxt += 3;
2424 else if (c1 < 0xF5)
2426 if (frm_end-frm_nxt < 2)
2427 return codecvt_base::partial;
2428 uint8_t c2 = frm_nxt[1];
2429 switch (c1)
2431 case 0xF0:
2432 if (!(0x90 <= c2 && c2 <= 0xBF))
2433 return codecvt_base::error;
2434 break;
2435 case 0xF4:
2436 if ((c2 & 0xF0) != 0x80)
2437 return codecvt_base::error;
2438 break;
2439 default:
2440 if ((c2 & 0xC0) != 0x80)
2441 return codecvt_base::error;
2442 break;
2444 if (frm_end-frm_nxt < 3)
2445 return codecvt_base::partial;
2446 uint8_t c3 = frm_nxt[2];
2447 if ((c3 & 0xC0) != 0x80)
2448 return codecvt_base::error;
2449 if (frm_end-frm_nxt < 4)
2450 return codecvt_base::partial;
2451 uint8_t c4 = frm_nxt[3];
2452 if ((c4 & 0xC0) != 0x80)
2453 return codecvt_base::error;
2454 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2455 | ((c2 & 0x3F) << 12)
2456 | ((c3 & 0x3F) << 6)
2457 | (c4 & 0x3F));
2458 if (t > Maxcode)
2459 return codecvt_base::error;
2460 *to_nxt = t;
2461 frm_nxt += 4;
2463 else
2465 return codecvt_base::error;
2468 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2471 static
2473 utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2474 size_t mx, unsigned long Maxcode = 0x10FFFF,
2475 codecvt_mode mode = codecvt_mode(0))
2477 const uint8_t* frm_nxt = frm;
2478 if (mode & consume_header)
2480 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2481 frm_nxt[2] == 0xBF)
2482 frm_nxt += 3;
2484 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2486 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2487 if (c1 < 0x80)
2489 if (c1 > Maxcode)
2490 break;
2491 ++frm_nxt;
2493 else if (c1 < 0xC2)
2495 break;
2497 else if (c1 < 0xE0)
2499 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2500 break;
2501 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2502 break;
2503 frm_nxt += 2;
2505 else if (c1 < 0xF0)
2507 if (frm_end-frm_nxt < 3)
2508 break;
2509 uint8_t c2 = frm_nxt[1];
2510 uint8_t c3 = frm_nxt[2];
2511 switch (c1)
2513 case 0xE0:
2514 if ((c2 & 0xE0) != 0xA0)
2515 return static_cast<int>(frm_nxt - frm);
2516 break;
2517 case 0xED:
2518 if ((c2 & 0xE0) != 0x80)
2519 return static_cast<int>(frm_nxt - frm);
2520 break;
2521 default:
2522 if ((c2 & 0xC0) != 0x80)
2523 return static_cast<int>(frm_nxt - frm);
2524 break;
2526 if ((c3 & 0xC0) != 0x80)
2527 break;
2528 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2529 break;
2530 frm_nxt += 3;
2532 else if (c1 < 0xF5)
2534 if (frm_end-frm_nxt < 4)
2535 break;
2536 uint8_t c2 = frm_nxt[1];
2537 uint8_t c3 = frm_nxt[2];
2538 uint8_t c4 = frm_nxt[3];
2539 switch (c1)
2541 case 0xF0:
2542 if (!(0x90 <= c2 && c2 <= 0xBF))
2543 return static_cast<int>(frm_nxt - frm);
2544 break;
2545 case 0xF4:
2546 if ((c2 & 0xF0) != 0x80)
2547 return static_cast<int>(frm_nxt - frm);
2548 break;
2549 default:
2550 if ((c2 & 0xC0) != 0x80)
2551 return static_cast<int>(frm_nxt - frm);
2552 break;
2554 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2555 break;
2556 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2557 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
2558 break;
2559 frm_nxt += 4;
2561 else
2563 break;
2566 return static_cast<int>(frm_nxt - frm);
2569 static
2570 codecvt_base::result
2571 ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2572 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2573 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2575 frm_nxt = frm;
2576 to_nxt = to;
2577 if (mode & generate_header)
2579 if (to_end-to_nxt < 3)
2580 return codecvt_base::partial;
2581 *to_nxt++ = static_cast<uint8_t>(0xEF);
2582 *to_nxt++ = static_cast<uint8_t>(0xBB);
2583 *to_nxt++ = static_cast<uint8_t>(0xBF);
2585 for (; frm_nxt < frm_end; ++frm_nxt)
2587 uint16_t wc = *frm_nxt;
2588 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2589 return codecvt_base::error;
2590 if (wc < 0x0080)
2592 if (to_end-to_nxt < 1)
2593 return codecvt_base::partial;
2594 *to_nxt++ = static_cast<uint8_t>(wc);
2596 else if (wc < 0x0800)
2598 if (to_end-to_nxt < 2)
2599 return codecvt_base::partial;
2600 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2601 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2603 else // if (wc <= 0xFFFF)
2605 if (to_end-to_nxt < 3)
2606 return codecvt_base::partial;
2607 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2608 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2609 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2612 return codecvt_base::ok;
2615 static
2616 codecvt_base::result
2617 utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2618 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2619 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2621 frm_nxt = frm;
2622 to_nxt = to;
2623 if (mode & consume_header)
2625 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2626 frm_nxt[2] == 0xBF)
2627 frm_nxt += 3;
2629 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2631 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2632 if (c1 < 0x80)
2634 if (c1 > Maxcode)
2635 return codecvt_base::error;
2636 *to_nxt = static_cast<uint16_t>(c1);
2637 ++frm_nxt;
2639 else if (c1 < 0xC2)
2641 return codecvt_base::error;
2643 else if (c1 < 0xE0)
2645 if (frm_end-frm_nxt < 2)
2646 return codecvt_base::partial;
2647 uint8_t c2 = frm_nxt[1];
2648 if ((c2 & 0xC0) != 0x80)
2649 return codecvt_base::error;
2650 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2651 | (c2 & 0x3F));
2652 if (t > Maxcode)
2653 return codecvt_base::error;
2654 *to_nxt = t;
2655 frm_nxt += 2;
2657 else if (c1 < 0xF0)
2659 if (frm_end-frm_nxt < 2)
2660 return codecvt_base::partial;
2661 uint8_t c2 = frm_nxt[1];
2662 switch (c1)
2664 case 0xE0:
2665 if ((c2 & 0xE0) != 0xA0)
2666 return codecvt_base::error;
2667 break;
2668 case 0xED:
2669 if ((c2 & 0xE0) != 0x80)
2670 return codecvt_base::error;
2671 break;
2672 default:
2673 if ((c2 & 0xC0) != 0x80)
2674 return codecvt_base::error;
2675 break;
2677 if (frm_end-frm_nxt < 3)
2678 return codecvt_base::partial;
2679 uint8_t c3 = frm_nxt[2];
2680 if ((c3 & 0xC0) != 0x80)
2681 return codecvt_base::error;
2682 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2683 | ((c2 & 0x3F) << 6)
2684 | (c3 & 0x3F));
2685 if (t > Maxcode)
2686 return codecvt_base::error;
2687 *to_nxt = t;
2688 frm_nxt += 3;
2690 else
2692 return codecvt_base::error;
2695 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2698 static
2700 utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2701 size_t mx, unsigned long Maxcode = 0x10FFFF,
2702 codecvt_mode mode = codecvt_mode(0))
2704 const uint8_t* frm_nxt = frm;
2705 if (mode & consume_header)
2707 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2708 frm_nxt[2] == 0xBF)
2709 frm_nxt += 3;
2711 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2713 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2714 if (c1 < 0x80)
2716 if (c1 > Maxcode)
2717 break;
2718 ++frm_nxt;
2720 else if (c1 < 0xC2)
2722 break;
2724 else if (c1 < 0xE0)
2726 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2727 break;
2728 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2729 break;
2730 frm_nxt += 2;
2732 else if (c1 < 0xF0)
2734 if (frm_end-frm_nxt < 3)
2735 break;
2736 uint8_t c2 = frm_nxt[1];
2737 uint8_t c3 = frm_nxt[2];
2738 switch (c1)
2740 case 0xE0:
2741 if ((c2 & 0xE0) != 0xA0)
2742 return static_cast<int>(frm_nxt - frm);
2743 break;
2744 case 0xED:
2745 if ((c2 & 0xE0) != 0x80)
2746 return static_cast<int>(frm_nxt - frm);
2747 break;
2748 default:
2749 if ((c2 & 0xC0) != 0x80)
2750 return static_cast<int>(frm_nxt - frm);
2751 break;
2753 if ((c3 & 0xC0) != 0x80)
2754 break;
2755 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2756 break;
2757 frm_nxt += 3;
2759 else
2761 break;
2764 return static_cast<int>(frm_nxt - frm);
2767 static
2768 codecvt_base::result
2769 ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2770 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2771 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2773 frm_nxt = frm;
2774 to_nxt = to;
2775 if (mode & generate_header)
2777 if (to_end-to_nxt < 2)
2778 return codecvt_base::partial;
2779 *to_nxt++ = static_cast<uint8_t>(0xFE);
2780 *to_nxt++ = static_cast<uint8_t>(0xFF);
2782 for (; frm_nxt < frm_end; ++frm_nxt)
2784 uint32_t wc = *frm_nxt;
2785 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2786 return codecvt_base::error;
2787 if (wc < 0x010000)
2789 if (to_end-to_nxt < 2)
2790 return codecvt_base::partial;
2791 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2792 *to_nxt++ = static_cast<uint8_t>(wc);
2794 else
2796 if (to_end-to_nxt < 4)
2797 return codecvt_base::partial;
2798 uint16_t t = static_cast<uint16_t>(
2799 0xD800
2800 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2801 | ((wc & 0x00FC00) >> 10));
2802 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2803 *to_nxt++ = static_cast<uint8_t>(t);
2804 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2805 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2806 *to_nxt++ = static_cast<uint8_t>(t);
2809 return codecvt_base::ok;
2812 static
2813 codecvt_base::result
2814 utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2815 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2816 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2818 frm_nxt = frm;
2819 to_nxt = to;
2820 if (mode & consume_header)
2822 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2823 frm_nxt += 2;
2825 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2827 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2828 if ((c1 & 0xFC00) == 0xDC00)
2829 return codecvt_base::error;
2830 if ((c1 & 0xFC00) != 0xD800)
2832 if (c1 > Maxcode)
2833 return codecvt_base::error;
2834 *to_nxt = static_cast<uint32_t>(c1);
2835 frm_nxt += 2;
2837 else
2839 if (frm_end-frm_nxt < 4)
2840 return codecvt_base::partial;
2841 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2842 if ((c2 & 0xFC00) != 0xDC00)
2843 return codecvt_base::error;
2844 uint32_t t = static_cast<uint32_t>(
2845 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2846 | ((c1 & 0x003F) << 10)
2847 | (c2 & 0x03FF));
2848 if (t > Maxcode)
2849 return codecvt_base::error;
2850 *to_nxt = t;
2851 frm_nxt += 4;
2854 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2857 static
2859 utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2860 size_t mx, unsigned long Maxcode = 0x10FFFF,
2861 codecvt_mode mode = codecvt_mode(0))
2863 const uint8_t* frm_nxt = frm;
2864 if (mode & consume_header)
2866 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2867 frm_nxt += 2;
2869 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2871 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2872 if ((c1 & 0xFC00) == 0xDC00)
2873 break;
2874 if ((c1 & 0xFC00) != 0xD800)
2876 if (c1 > Maxcode)
2877 break;
2878 frm_nxt += 2;
2880 else
2882 if (frm_end-frm_nxt < 4)
2883 break;
2884 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2885 if ((c2 & 0xFC00) != 0xDC00)
2886 break;
2887 uint32_t t = static_cast<uint32_t>(
2888 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2889 | ((c1 & 0x003F) << 10)
2890 | (c2 & 0x03FF));
2891 if (t > Maxcode)
2892 break;
2893 frm_nxt += 4;
2896 return static_cast<int>(frm_nxt - frm);
2899 static
2900 codecvt_base::result
2901 ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2902 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2903 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2905 frm_nxt = frm;
2906 to_nxt = to;
2907 if (mode & generate_header)
2909 if (to_end - to_nxt < 2)
2910 return codecvt_base::partial;
2911 *to_nxt++ = static_cast<uint8_t>(0xFF);
2912 *to_nxt++ = static_cast<uint8_t>(0xFE);
2914 for (; frm_nxt < frm_end; ++frm_nxt)
2916 uint32_t wc = *frm_nxt;
2917 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2918 return codecvt_base::error;
2919 if (wc < 0x010000)
2921 if (to_end-to_nxt < 2)
2922 return codecvt_base::partial;
2923 *to_nxt++ = static_cast<uint8_t>(wc);
2924 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2926 else
2928 if (to_end-to_nxt < 4)
2929 return codecvt_base::partial;
2930 uint16_t t = static_cast<uint16_t>(
2931 0xD800
2932 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2933 | ((wc & 0x00FC00) >> 10));
2934 *to_nxt++ = static_cast<uint8_t>(t);
2935 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2936 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2937 *to_nxt++ = static_cast<uint8_t>(t);
2938 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2941 return codecvt_base::ok;
2944 static
2945 codecvt_base::result
2946 utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2947 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2948 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2950 frm_nxt = frm;
2951 to_nxt = to;
2952 if (mode & consume_header)
2954 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2955 frm_nxt += 2;
2957 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2959 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2960 if ((c1 & 0xFC00) == 0xDC00)
2961 return codecvt_base::error;
2962 if ((c1 & 0xFC00) != 0xD800)
2964 if (c1 > Maxcode)
2965 return codecvt_base::error;
2966 *to_nxt = static_cast<uint32_t>(c1);
2967 frm_nxt += 2;
2969 else
2971 if (frm_end-frm_nxt < 4)
2972 return codecvt_base::partial;
2973 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2974 if ((c2 & 0xFC00) != 0xDC00)
2975 return codecvt_base::error;
2976 uint32_t t = static_cast<uint32_t>(
2977 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2978 | ((c1 & 0x003F) << 10)
2979 | (c2 & 0x03FF));
2980 if (t > Maxcode)
2981 return codecvt_base::error;
2982 *to_nxt = t;
2983 frm_nxt += 4;
2986 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2989 static
2991 utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2992 size_t mx, unsigned long Maxcode = 0x10FFFF,
2993 codecvt_mode mode = codecvt_mode(0))
2995 const uint8_t* frm_nxt = frm;
2996 if (mode & consume_header)
2998 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2999 frm_nxt += 2;
3001 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3003 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3004 if ((c1 & 0xFC00) == 0xDC00)
3005 break;
3006 if ((c1 & 0xFC00) != 0xD800)
3008 if (c1 > Maxcode)
3009 break;
3010 frm_nxt += 2;
3012 else
3014 if (frm_end-frm_nxt < 4)
3015 break;
3016 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
3017 if ((c2 & 0xFC00) != 0xDC00)
3018 break;
3019 uint32_t t = static_cast<uint32_t>(
3020 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3021 | ((c1 & 0x003F) << 10)
3022 | (c2 & 0x03FF));
3023 if (t > Maxcode)
3024 break;
3025 frm_nxt += 4;
3028 return static_cast<int>(frm_nxt - frm);
3031 static
3032 codecvt_base::result
3033 ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3034 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3035 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3037 frm_nxt = frm;
3038 to_nxt = to;
3039 if (mode & generate_header)
3041 if (to_end-to_nxt < 2)
3042 return codecvt_base::partial;
3043 *to_nxt++ = static_cast<uint8_t>(0xFE);
3044 *to_nxt++ = static_cast<uint8_t>(0xFF);
3046 for (; frm_nxt < frm_end; ++frm_nxt)
3048 uint16_t wc = *frm_nxt;
3049 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3050 return codecvt_base::error;
3051 if (to_end-to_nxt < 2)
3052 return codecvt_base::partial;
3053 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3054 *to_nxt++ = static_cast<uint8_t>(wc);
3056 return codecvt_base::ok;
3059 static
3060 codecvt_base::result
3061 utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3062 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3063 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3065 frm_nxt = frm;
3066 to_nxt = to;
3067 if (mode & consume_header)
3069 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3070 frm_nxt += 2;
3072 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3074 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3075 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3076 return codecvt_base::error;
3077 *to_nxt = c1;
3078 frm_nxt += 2;
3080 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3083 static
3085 utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3086 size_t mx, unsigned long Maxcode = 0x10FFFF,
3087 codecvt_mode mode = codecvt_mode(0))
3089 const uint8_t* frm_nxt = frm;
3090 if (mode & consume_header)
3092 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3093 frm_nxt += 2;
3095 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3097 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3098 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3099 break;
3100 frm_nxt += 2;
3102 return static_cast<int>(frm_nxt - frm);
3105 static
3106 codecvt_base::result
3107 ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3108 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3109 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3111 frm_nxt = frm;
3112 to_nxt = to;
3113 if (mode & generate_header)
3115 if (to_end-to_nxt < 2)
3116 return codecvt_base::partial;
3117 *to_nxt++ = static_cast<uint8_t>(0xFF);
3118 *to_nxt++ = static_cast<uint8_t>(0xFE);
3120 for (; frm_nxt < frm_end; ++frm_nxt)
3122 uint16_t wc = *frm_nxt;
3123 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3124 return codecvt_base::error;
3125 if (to_end-to_nxt < 2)
3126 return codecvt_base::partial;
3127 *to_nxt++ = static_cast<uint8_t>(wc);
3128 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3130 return codecvt_base::ok;
3133 static
3134 codecvt_base::result
3135 utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3136 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3137 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3139 frm_nxt = frm;
3140 to_nxt = to;
3141 if (mode & consume_header)
3143 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3144 frm_nxt += 2;
3146 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3148 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3149 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3150 return codecvt_base::error;
3151 *to_nxt = c1;
3152 frm_nxt += 2;
3154 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3157 static
3159 utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3160 size_t mx, unsigned long Maxcode = 0x10FFFF,
3161 codecvt_mode mode = codecvt_mode(0))
3163 const uint8_t* frm_nxt = frm;
3164 frm_nxt = frm;
3165 if (mode & consume_header)
3167 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3168 frm_nxt += 2;
3170 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3172 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3173 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3174 break;
3175 frm_nxt += 2;
3177 return static_cast<int>(frm_nxt - frm);
3180 _LIBCPP_SUPPRESS_DEPRECATED_POP
3182 // template <> class codecvt<char16_t, char, mbstate_t>
3184 constinit locale::id codecvt<char16_t, char, mbstate_t>::id;
3186 codecvt<char16_t, char, mbstate_t>::~codecvt()
3190 codecvt<char16_t, char, mbstate_t>::result
3191 codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
3192 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3193 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3195 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3196 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3197 const uint16_t* _frm_nxt = _frm;
3198 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3199 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3200 uint8_t* _to_nxt = _to;
3201 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3202 frm_nxt = frm + (_frm_nxt - _frm);
3203 to_nxt = to + (_to_nxt - _to);
3204 return r;
3207 codecvt<char16_t, char, mbstate_t>::result
3208 codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
3209 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3210 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3212 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3213 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3214 const uint8_t* _frm_nxt = _frm;
3215 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3216 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3217 uint16_t* _to_nxt = _to;
3218 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3219 frm_nxt = frm + (_frm_nxt - _frm);
3220 to_nxt = to + (_to_nxt - _to);
3221 return r;
3224 codecvt<char16_t, char, mbstate_t>::result
3225 codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3226 extern_type* to, extern_type*, extern_type*& to_nxt) const
3228 to_nxt = to;
3229 return noconv;
3233 codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
3235 return 0;
3238 bool
3239 codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
3241 return false;
3245 codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3246 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3248 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3249 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3250 return utf8_to_utf16_length(_frm, _frm_end, mx);
3254 codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
3256 return 4;
3259 #ifndef _LIBCPP_HAS_NO_CHAR8_T
3261 // template <> class codecvt<char16_t, char8_t, mbstate_t>
3263 constinit locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3265 codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3269 codecvt<char16_t, char8_t, mbstate_t>::result
3270 codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3271 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3272 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3274 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3275 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3276 const uint16_t* _frm_nxt = _frm;
3277 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3278 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3279 uint8_t* _to_nxt = _to;
3280 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3281 frm_nxt = frm + (_frm_nxt - _frm);
3282 to_nxt = to + (_to_nxt - _to);
3283 return r;
3286 codecvt<char16_t, char8_t, mbstate_t>::result
3287 codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3288 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3289 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3291 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3292 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3293 const uint8_t* _frm_nxt = _frm;
3294 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3295 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3296 uint16_t* _to_nxt = _to;
3297 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3298 frm_nxt = frm + (_frm_nxt - _frm);
3299 to_nxt = to + (_to_nxt - _to);
3300 return r;
3303 codecvt<char16_t, char8_t, mbstate_t>::result
3304 codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3305 extern_type* to, extern_type*, extern_type*& to_nxt) const
3307 to_nxt = to;
3308 return noconv;
3312 codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
3314 return 0;
3317 bool
3318 codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3320 return false;
3324 codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3325 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3327 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3328 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3329 return utf8_to_utf16_length(_frm, _frm_end, mx);
3333 codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
3335 return 4;
3338 #endif
3340 // template <> class codecvt<char32_t, char, mbstate_t>
3342 constinit locale::id codecvt<char32_t, char, mbstate_t>::id;
3344 codecvt<char32_t, char, mbstate_t>::~codecvt()
3348 codecvt<char32_t, char, mbstate_t>::result
3349 codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
3350 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3351 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3353 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3354 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3355 const uint32_t* _frm_nxt = _frm;
3356 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3357 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3358 uint8_t* _to_nxt = _to;
3359 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3360 frm_nxt = frm + (_frm_nxt - _frm);
3361 to_nxt = to + (_to_nxt - _to);
3362 return r;
3365 codecvt<char32_t, char, mbstate_t>::result
3366 codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
3367 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3368 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3370 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3371 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3372 const uint8_t* _frm_nxt = _frm;
3373 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3374 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3375 uint32_t* _to_nxt = _to;
3376 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3377 frm_nxt = frm + (_frm_nxt - _frm);
3378 to_nxt = to + (_to_nxt - _to);
3379 return r;
3382 codecvt<char32_t, char, mbstate_t>::result
3383 codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3384 extern_type* to, extern_type*, extern_type*& to_nxt) const
3386 to_nxt = to;
3387 return noconv;
3391 codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
3393 return 0;
3396 bool
3397 codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
3399 return false;
3403 codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3404 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3406 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3407 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3408 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3412 codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
3414 return 4;
3417 #ifndef _LIBCPP_HAS_NO_CHAR8_T
3419 // template <> class codecvt<char32_t, char8_t, mbstate_t>
3421 constinit locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3423 codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3427 codecvt<char32_t, char8_t, mbstate_t>::result
3428 codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3429 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3430 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3432 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3433 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3434 const uint32_t* _frm_nxt = _frm;
3435 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3436 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3437 uint8_t* _to_nxt = _to;
3438 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3439 frm_nxt = frm + (_frm_nxt - _frm);
3440 to_nxt = to + (_to_nxt - _to);
3441 return r;
3444 codecvt<char32_t, char8_t, mbstate_t>::result
3445 codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3446 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3447 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3449 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3450 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3451 const uint8_t* _frm_nxt = _frm;
3452 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3453 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3454 uint32_t* _to_nxt = _to;
3455 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3456 frm_nxt = frm + (_frm_nxt - _frm);
3457 to_nxt = to + (_to_nxt - _to);
3458 return r;
3461 codecvt<char32_t, char8_t, mbstate_t>::result
3462 codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3463 extern_type* to, extern_type*, extern_type*& to_nxt) const
3465 to_nxt = to;
3466 return noconv;
3470 codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
3472 return 0;
3475 bool
3476 codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3478 return false;
3482 codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3483 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3485 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3486 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3487 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3491 codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
3493 return 4;
3496 #endif
3498 // __codecvt_utf8<wchar_t>
3500 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3501 __codecvt_utf8<wchar_t>::result
3502 __codecvt_utf8<wchar_t>::do_out(state_type&,
3503 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3504 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3506 #if defined(_LIBCPP_SHORT_WCHAR)
3507 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3508 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3509 const uint16_t* _frm_nxt = _frm;
3510 #else
3511 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3512 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3513 const uint32_t* _frm_nxt = _frm;
3514 #endif
3515 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3516 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3517 uint8_t* _to_nxt = _to;
3518 #if defined(_LIBCPP_SHORT_WCHAR)
3519 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3520 __maxcode_, __mode_);
3521 #else
3522 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3523 __maxcode_, __mode_);
3524 #endif
3525 frm_nxt = frm + (_frm_nxt - _frm);
3526 to_nxt = to + (_to_nxt - _to);
3527 return r;
3530 __codecvt_utf8<wchar_t>::result
3531 __codecvt_utf8<wchar_t>::do_in(state_type&,
3532 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3533 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3535 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3536 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3537 const uint8_t* _frm_nxt = _frm;
3538 #if defined(_LIBCPP_SHORT_WCHAR)
3539 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3540 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3541 uint16_t* _to_nxt = _to;
3542 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3543 __maxcode_, __mode_);
3544 #else
3545 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3546 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3547 uint32_t* _to_nxt = _to;
3548 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3549 __maxcode_, __mode_);
3550 #endif
3551 frm_nxt = frm + (_frm_nxt - _frm);
3552 to_nxt = to + (_to_nxt - _to);
3553 return r;
3556 __codecvt_utf8<wchar_t>::result
3557 __codecvt_utf8<wchar_t>::do_unshift(state_type&,
3558 extern_type* to, extern_type*, extern_type*& to_nxt) const
3560 to_nxt = to;
3561 return noconv;
3565 __codecvt_utf8<wchar_t>::do_encoding() const noexcept
3567 return 0;
3570 bool
3571 __codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
3573 return false;
3577 __codecvt_utf8<wchar_t>::do_length(state_type&,
3578 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3580 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3581 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3582 #if defined(_LIBCPP_SHORT_WCHAR)
3583 return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3584 #else
3585 return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3586 #endif
3589 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3591 __codecvt_utf8<wchar_t>::do_max_length() const noexcept
3593 #if defined(_LIBCPP_SHORT_WCHAR)
3594 if (__mode_ & consume_header)
3595 return 6;
3596 return 3;
3597 #else
3598 if (__mode_ & consume_header)
3599 return 7;
3600 return 4;
3601 #endif
3603 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3605 // __codecvt_utf8<char16_t>
3607 __codecvt_utf8<char16_t>::result
3608 __codecvt_utf8<char16_t>::do_out(state_type&,
3609 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3610 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3612 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3613 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3614 const uint16_t* _frm_nxt = _frm;
3615 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3616 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3617 uint8_t* _to_nxt = _to;
3618 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3619 __maxcode_, __mode_);
3620 frm_nxt = frm + (_frm_nxt - _frm);
3621 to_nxt = to + (_to_nxt - _to);
3622 return r;
3625 __codecvt_utf8<char16_t>::result
3626 __codecvt_utf8<char16_t>::do_in(state_type&,
3627 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3628 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3630 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3631 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3632 const uint8_t* _frm_nxt = _frm;
3633 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3634 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3635 uint16_t* _to_nxt = _to;
3636 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3637 __maxcode_, __mode_);
3638 frm_nxt = frm + (_frm_nxt - _frm);
3639 to_nxt = to + (_to_nxt - _to);
3640 return r;
3643 __codecvt_utf8<char16_t>::result
3644 __codecvt_utf8<char16_t>::do_unshift(state_type&,
3645 extern_type* to, extern_type*, extern_type*& to_nxt) const
3647 to_nxt = to;
3648 return noconv;
3652 __codecvt_utf8<char16_t>::do_encoding() const noexcept
3654 return 0;
3657 bool
3658 __codecvt_utf8<char16_t>::do_always_noconv() const noexcept
3660 return false;
3664 __codecvt_utf8<char16_t>::do_length(state_type&,
3665 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3667 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3668 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3669 return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3672 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3674 __codecvt_utf8<char16_t>::do_max_length() const noexcept
3676 if (__mode_ & consume_header)
3677 return 6;
3678 return 3;
3680 _LIBCPP_SUPPRESS_DEPRECATED_POP
3682 // __codecvt_utf8<char32_t>
3684 __codecvt_utf8<char32_t>::result
3685 __codecvt_utf8<char32_t>::do_out(state_type&,
3686 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3687 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3689 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3690 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3691 const uint32_t* _frm_nxt = _frm;
3692 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3693 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3694 uint8_t* _to_nxt = _to;
3695 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3696 __maxcode_, __mode_);
3697 frm_nxt = frm + (_frm_nxt - _frm);
3698 to_nxt = to + (_to_nxt - _to);
3699 return r;
3702 __codecvt_utf8<char32_t>::result
3703 __codecvt_utf8<char32_t>::do_in(state_type&,
3704 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3705 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3707 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3708 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3709 const uint8_t* _frm_nxt = _frm;
3710 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3711 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3712 uint32_t* _to_nxt = _to;
3713 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3714 __maxcode_, __mode_);
3715 frm_nxt = frm + (_frm_nxt - _frm);
3716 to_nxt = to + (_to_nxt - _to);
3717 return r;
3720 __codecvt_utf8<char32_t>::result
3721 __codecvt_utf8<char32_t>::do_unshift(state_type&,
3722 extern_type* to, extern_type*, extern_type*& to_nxt) const
3724 to_nxt = to;
3725 return noconv;
3729 __codecvt_utf8<char32_t>::do_encoding() const noexcept
3731 return 0;
3734 bool
3735 __codecvt_utf8<char32_t>::do_always_noconv() const noexcept
3737 return false;
3741 __codecvt_utf8<char32_t>::do_length(state_type&,
3742 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3744 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3745 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3746 return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3749 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3751 __codecvt_utf8<char32_t>::do_max_length() const noexcept
3753 if (__mode_ & consume_header)
3754 return 7;
3755 return 4;
3757 _LIBCPP_SUPPRESS_DEPRECATED_POP
3759 // __codecvt_utf16<wchar_t, false>
3761 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3762 __codecvt_utf16<wchar_t, false>::result
3763 __codecvt_utf16<wchar_t, false>::do_out(state_type&,
3764 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3765 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3767 #if defined(_LIBCPP_SHORT_WCHAR)
3768 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3769 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3770 const uint16_t* _frm_nxt = _frm;
3771 #else
3772 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3773 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3774 const uint32_t* _frm_nxt = _frm;
3775 #endif
3776 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3777 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3778 uint8_t* _to_nxt = _to;
3779 #if defined(_LIBCPP_SHORT_WCHAR)
3780 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3781 __maxcode_, __mode_);
3782 #else
3783 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3784 __maxcode_, __mode_);
3785 #endif
3786 frm_nxt = frm + (_frm_nxt - _frm);
3787 to_nxt = to + (_to_nxt - _to);
3788 return r;
3791 __codecvt_utf16<wchar_t, false>::result
3792 __codecvt_utf16<wchar_t, false>::do_in(state_type&,
3793 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3794 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3796 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3797 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3798 const uint8_t* _frm_nxt = _frm;
3799 #if defined(_LIBCPP_SHORT_WCHAR)
3800 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3801 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3802 uint16_t* _to_nxt = _to;
3803 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3804 __maxcode_, __mode_);
3805 #else
3806 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3807 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3808 uint32_t* _to_nxt = _to;
3809 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3810 __maxcode_, __mode_);
3811 #endif
3812 frm_nxt = frm + (_frm_nxt - _frm);
3813 to_nxt = to + (_to_nxt - _to);
3814 return r;
3817 __codecvt_utf16<wchar_t, false>::result
3818 __codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3819 extern_type* to, extern_type*, extern_type*& to_nxt) const
3821 to_nxt = to;
3822 return noconv;
3826 __codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
3828 return 0;
3831 bool
3832 __codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
3834 return false;
3838 __codecvt_utf16<wchar_t, false>::do_length(state_type&,
3839 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3841 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3842 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3843 #if defined(_LIBCPP_SHORT_WCHAR)
3844 return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3845 #else
3846 return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3847 #endif
3851 __codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
3853 #if defined(_LIBCPP_SHORT_WCHAR)
3854 if (__mode_ & consume_header)
3855 return 4;
3856 return 2;
3857 #else
3858 if (__mode_ & consume_header)
3859 return 6;
3860 return 4;
3861 #endif
3864 // __codecvt_utf16<wchar_t, true>
3866 __codecvt_utf16<wchar_t, true>::result
3867 __codecvt_utf16<wchar_t, true>::do_out(state_type&,
3868 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3869 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3871 #if defined(_LIBCPP_SHORT_WCHAR)
3872 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3873 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3874 const uint16_t* _frm_nxt = _frm;
3875 #else
3876 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3877 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3878 const uint32_t* _frm_nxt = _frm;
3879 #endif
3880 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3881 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3882 uint8_t* _to_nxt = _to;
3883 #if defined(_LIBCPP_SHORT_WCHAR)
3884 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3885 __maxcode_, __mode_);
3886 #else
3887 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3888 __maxcode_, __mode_);
3889 #endif
3890 frm_nxt = frm + (_frm_nxt - _frm);
3891 to_nxt = to + (_to_nxt - _to);
3892 return r;
3895 __codecvt_utf16<wchar_t, true>::result
3896 __codecvt_utf16<wchar_t, true>::do_in(state_type&,
3897 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3898 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3900 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3901 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3902 const uint8_t* _frm_nxt = _frm;
3903 #if defined(_LIBCPP_SHORT_WCHAR)
3904 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3905 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3906 uint16_t* _to_nxt = _to;
3907 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3908 __maxcode_, __mode_);
3909 #else
3910 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3911 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3912 uint32_t* _to_nxt = _to;
3913 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3914 __maxcode_, __mode_);
3915 #endif
3916 frm_nxt = frm + (_frm_nxt - _frm);
3917 to_nxt = to + (_to_nxt - _to);
3918 return r;
3921 __codecvt_utf16<wchar_t, true>::result
3922 __codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3923 extern_type* to, extern_type*, extern_type*& to_nxt) const
3925 to_nxt = to;
3926 return noconv;
3930 __codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
3932 return 0;
3935 bool
3936 __codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
3938 return false;
3942 __codecvt_utf16<wchar_t, true>::do_length(state_type&,
3943 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3945 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3946 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3947 #if defined(_LIBCPP_SHORT_WCHAR)
3948 return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3949 #else
3950 return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3951 #endif
3955 __codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
3957 #if defined(_LIBCPP_SHORT_WCHAR)
3958 if (__mode_ & consume_header)
3959 return 4;
3960 return 2;
3961 #else
3962 if (__mode_ & consume_header)
3963 return 6;
3964 return 4;
3965 #endif
3967 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3969 // __codecvt_utf16<char16_t, false>
3971 __codecvt_utf16<char16_t, false>::result
3972 __codecvt_utf16<char16_t, false>::do_out(state_type&,
3973 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3974 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3976 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3977 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3978 const uint16_t* _frm_nxt = _frm;
3979 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3980 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3981 uint8_t* _to_nxt = _to;
3982 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3983 __maxcode_, __mode_);
3984 frm_nxt = frm + (_frm_nxt - _frm);
3985 to_nxt = to + (_to_nxt - _to);
3986 return r;
3989 __codecvt_utf16<char16_t, false>::result
3990 __codecvt_utf16<char16_t, false>::do_in(state_type&,
3991 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3992 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3994 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3995 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3996 const uint8_t* _frm_nxt = _frm;
3997 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3998 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3999 uint16_t* _to_nxt = _to;
4000 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4001 __maxcode_, __mode_);
4002 frm_nxt = frm + (_frm_nxt - _frm);
4003 to_nxt = to + (_to_nxt - _to);
4004 return r;
4007 __codecvt_utf16<char16_t, false>::result
4008 __codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4009 extern_type* to, extern_type*, extern_type*& to_nxt) const
4011 to_nxt = to;
4012 return noconv;
4016 __codecvt_utf16<char16_t, false>::do_encoding() const noexcept
4018 return 0;
4021 bool
4022 __codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
4024 return false;
4028 __codecvt_utf16<char16_t, false>::do_length(state_type&,
4029 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4031 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4032 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4033 return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4036 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4038 __codecvt_utf16<char16_t, false>::do_max_length() const noexcept
4040 if (__mode_ & consume_header)
4041 return 4;
4042 return 2;
4044 _LIBCPP_SUPPRESS_DEPRECATED_POP
4046 // __codecvt_utf16<char16_t, true>
4048 __codecvt_utf16<char16_t, true>::result
4049 __codecvt_utf16<char16_t, true>::do_out(state_type&,
4050 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4051 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4053 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4054 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4055 const uint16_t* _frm_nxt = _frm;
4056 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4057 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4058 uint8_t* _to_nxt = _to;
4059 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4060 __maxcode_, __mode_);
4061 frm_nxt = frm + (_frm_nxt - _frm);
4062 to_nxt = to + (_to_nxt - _to);
4063 return r;
4066 __codecvt_utf16<char16_t, true>::result
4067 __codecvt_utf16<char16_t, true>::do_in(state_type&,
4068 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4069 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4071 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4072 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4073 const uint8_t* _frm_nxt = _frm;
4074 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4075 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4076 uint16_t* _to_nxt = _to;
4077 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4078 __maxcode_, __mode_);
4079 frm_nxt = frm + (_frm_nxt - _frm);
4080 to_nxt = to + (_to_nxt - _to);
4081 return r;
4084 __codecvt_utf16<char16_t, true>::result
4085 __codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4086 extern_type* to, extern_type*, extern_type*& to_nxt) const
4088 to_nxt = to;
4089 return noconv;
4093 __codecvt_utf16<char16_t, true>::do_encoding() const noexcept
4095 return 0;
4098 bool
4099 __codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
4101 return false;
4105 __codecvt_utf16<char16_t, true>::do_length(state_type&,
4106 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4108 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4109 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4110 return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4113 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4115 __codecvt_utf16<char16_t, true>::do_max_length() const noexcept
4117 if (__mode_ & consume_header)
4118 return 4;
4119 return 2;
4121 _LIBCPP_SUPPRESS_DEPRECATED_POP
4123 // __codecvt_utf16<char32_t, false>
4125 __codecvt_utf16<char32_t, false>::result
4126 __codecvt_utf16<char32_t, false>::do_out(state_type&,
4127 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4128 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4130 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4131 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4132 const uint32_t* _frm_nxt = _frm;
4133 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4134 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4135 uint8_t* _to_nxt = _to;
4136 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4137 __maxcode_, __mode_);
4138 frm_nxt = frm + (_frm_nxt - _frm);
4139 to_nxt = to + (_to_nxt - _to);
4140 return r;
4143 __codecvt_utf16<char32_t, false>::result
4144 __codecvt_utf16<char32_t, false>::do_in(state_type&,
4145 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4146 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4148 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4149 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4150 const uint8_t* _frm_nxt = _frm;
4151 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4152 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4153 uint32_t* _to_nxt = _to;
4154 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4155 __maxcode_, __mode_);
4156 frm_nxt = frm + (_frm_nxt - _frm);
4157 to_nxt = to + (_to_nxt - _to);
4158 return r;
4161 __codecvt_utf16<char32_t, false>::result
4162 __codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4163 extern_type* to, extern_type*, extern_type*& to_nxt) const
4165 to_nxt = to;
4166 return noconv;
4170 __codecvt_utf16<char32_t, false>::do_encoding() const noexcept
4172 return 0;
4175 bool
4176 __codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
4178 return false;
4182 __codecvt_utf16<char32_t, false>::do_length(state_type&,
4183 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4185 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4186 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4187 return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4190 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4192 __codecvt_utf16<char32_t, false>::do_max_length() const noexcept
4194 if (__mode_ & consume_header)
4195 return 6;
4196 return 4;
4198 _LIBCPP_SUPPRESS_DEPRECATED_POP
4200 // __codecvt_utf16<char32_t, true>
4202 __codecvt_utf16<char32_t, true>::result
4203 __codecvt_utf16<char32_t, true>::do_out(state_type&,
4204 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4205 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4207 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4208 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4209 const uint32_t* _frm_nxt = _frm;
4210 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4211 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4212 uint8_t* _to_nxt = _to;
4213 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4214 __maxcode_, __mode_);
4215 frm_nxt = frm + (_frm_nxt - _frm);
4216 to_nxt = to + (_to_nxt - _to);
4217 return r;
4220 __codecvt_utf16<char32_t, true>::result
4221 __codecvt_utf16<char32_t, true>::do_in(state_type&,
4222 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4223 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4225 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4226 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4227 const uint8_t* _frm_nxt = _frm;
4228 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4229 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4230 uint32_t* _to_nxt = _to;
4231 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4232 __maxcode_, __mode_);
4233 frm_nxt = frm + (_frm_nxt - _frm);
4234 to_nxt = to + (_to_nxt - _to);
4235 return r;
4238 __codecvt_utf16<char32_t, true>::result
4239 __codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4240 extern_type* to, extern_type*, extern_type*& to_nxt) const
4242 to_nxt = to;
4243 return noconv;
4247 __codecvt_utf16<char32_t, true>::do_encoding() const noexcept
4249 return 0;
4252 bool
4253 __codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
4255 return false;
4259 __codecvt_utf16<char32_t, true>::do_length(state_type&,
4260 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4262 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4263 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4264 return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4267 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4269 __codecvt_utf16<char32_t, true>::do_max_length() const noexcept
4271 if (__mode_ & consume_header)
4272 return 6;
4273 return 4;
4275 _LIBCPP_SUPPRESS_DEPRECATED_POP
4277 // __codecvt_utf8_utf16<wchar_t>
4279 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4280 __codecvt_utf8_utf16<wchar_t>::result
4281 __codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4282 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4283 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4285 #if defined(_LIBCPP_SHORT_WCHAR)
4286 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4287 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4288 const uint16_t* _frm_nxt = _frm;
4289 #else
4290 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4291 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4292 const uint32_t* _frm_nxt = _frm;
4293 #endif
4294 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4295 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4296 uint8_t* _to_nxt = _to;
4297 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4298 __maxcode_, __mode_);
4299 frm_nxt = frm + (_frm_nxt - _frm);
4300 to_nxt = to + (_to_nxt - _to);
4301 return r;
4304 __codecvt_utf8_utf16<wchar_t>::result
4305 __codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4306 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4307 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4309 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4310 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4311 const uint8_t* _frm_nxt = _frm;
4312 #if defined(_LIBCPP_SHORT_WCHAR)
4313 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4314 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4315 uint16_t* _to_nxt = _to;
4316 #else
4317 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4318 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4319 uint32_t* _to_nxt = _to;
4320 #endif
4321 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4322 __maxcode_, __mode_);
4323 frm_nxt = frm + (_frm_nxt - _frm);
4324 to_nxt = to + (_to_nxt - _to);
4325 return r;
4328 __codecvt_utf8_utf16<wchar_t>::result
4329 __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4330 extern_type* to, extern_type*, extern_type*& to_nxt) const
4332 to_nxt = to;
4333 return noconv;
4337 __codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
4339 return 0;
4342 bool
4343 __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
4345 return false;
4349 __codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4350 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4352 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4353 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4354 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4358 __codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
4360 if (__mode_ & consume_header)
4361 return 7;
4362 return 4;
4364 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4366 // __codecvt_utf8_utf16<char16_t>
4368 __codecvt_utf8_utf16<char16_t>::result
4369 __codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4370 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4371 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4373 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4374 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4375 const uint16_t* _frm_nxt = _frm;
4376 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4377 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4378 uint8_t* _to_nxt = _to;
4379 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4380 __maxcode_, __mode_);
4381 frm_nxt = frm + (_frm_nxt - _frm);
4382 to_nxt = to + (_to_nxt - _to);
4383 return r;
4386 __codecvt_utf8_utf16<char16_t>::result
4387 __codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4388 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4389 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4391 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4392 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4393 const uint8_t* _frm_nxt = _frm;
4394 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4395 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4396 uint16_t* _to_nxt = _to;
4397 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4398 __maxcode_, __mode_);
4399 frm_nxt = frm + (_frm_nxt - _frm);
4400 to_nxt = to + (_to_nxt - _to);
4401 return r;
4404 __codecvt_utf8_utf16<char16_t>::result
4405 __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4406 extern_type* to, extern_type*, extern_type*& to_nxt) const
4408 to_nxt = to;
4409 return noconv;
4413 __codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
4415 return 0;
4418 bool
4419 __codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
4421 return false;
4425 __codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4426 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4428 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4429 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4430 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4433 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4435 __codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
4437 if (__mode_ & consume_header)
4438 return 7;
4439 return 4;
4441 _LIBCPP_SUPPRESS_DEPRECATED_POP
4443 // __codecvt_utf8_utf16<char32_t>
4445 __codecvt_utf8_utf16<char32_t>::result
4446 __codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4447 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4448 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4450 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4451 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4452 const uint32_t* _frm_nxt = _frm;
4453 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4454 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4455 uint8_t* _to_nxt = _to;
4456 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4457 __maxcode_, __mode_);
4458 frm_nxt = frm + (_frm_nxt - _frm);
4459 to_nxt = to + (_to_nxt - _to);
4460 return r;
4463 __codecvt_utf8_utf16<char32_t>::result
4464 __codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4465 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4466 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4468 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4469 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4470 const uint8_t* _frm_nxt = _frm;
4471 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4472 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4473 uint32_t* _to_nxt = _to;
4474 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4475 __maxcode_, __mode_);
4476 frm_nxt = frm + (_frm_nxt - _frm);
4477 to_nxt = to + (_to_nxt - _to);
4478 return r;
4481 __codecvt_utf8_utf16<char32_t>::result
4482 __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4483 extern_type* to, extern_type*, extern_type*& to_nxt) const
4485 to_nxt = to;
4486 return noconv;
4490 __codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
4492 return 0;
4495 bool
4496 __codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
4498 return false;
4502 __codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4503 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4505 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4506 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4507 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4510 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4512 __codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
4514 if (__mode_ & consume_header)
4515 return 7;
4516 return 4;
4518 _LIBCPP_SUPPRESS_DEPRECATED_POP
4520 // __narrow_to_utf8<16>
4522 __narrow_to_utf8<16>::~__narrow_to_utf8()
4526 // __narrow_to_utf8<32>
4528 __narrow_to_utf8<32>::~__narrow_to_utf8()
4532 // __widen_from_utf8<16>
4534 __widen_from_utf8<16>::~__widen_from_utf8()
4538 // __widen_from_utf8<32>
4540 __widen_from_utf8<32>::~__widen_from_utf8()
4544 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4545 static bool checked_string_to_wchar_convert(wchar_t& dest,
4546 const char* ptr,
4547 locale_t loc) {
4548 if (*ptr == '\0')
4549 return false;
4550 mbstate_t mb = {};
4551 wchar_t out;
4552 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4553 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4554 return false;
4556 dest = out;
4557 return true;
4559 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4561 #ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4562 static bool is_narrow_non_breaking_space(const char* ptr) {
4563 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4564 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4567 static bool is_non_breaking_space(const char* ptr) {
4568 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4569 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4571 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4573 static bool checked_string_to_char_convert(char& dest,
4574 const char* ptr,
4575 locale_t __loc) {
4576 if (*ptr == '\0')
4577 return false;
4578 if (!ptr[1]) {
4579 dest = *ptr;
4580 return true;
4583 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4584 // First convert the MBS into a wide char then attempt to narrow it using
4585 // wctob_l.
4586 wchar_t wout;
4587 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4588 return false;
4589 int res;
4590 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4591 dest = res;
4592 return true;
4594 // FIXME: Work around specific multibyte sequences that we can reasonably
4595 // translate into a different single byte.
4596 switch (wout) {
4597 case L'\u202F': // narrow non-breaking space
4598 case L'\u00A0': // non-breaking space
4599 dest = ' ';
4600 return true;
4601 default:
4602 return false;
4604 #else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4605 // FIXME: Work around specific multibyte sequences that we can reasonably
4606 // translate into a different single byte.
4607 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4608 dest = ' ';
4609 return true;
4612 return false;
4613 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4614 __libcpp_unreachable();
4618 // numpunct<char> && numpunct<wchar_t>
4620 constinit locale::id numpunct<char>::id;
4621 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4622 constinit locale::id numpunct<wchar_t>::id;
4623 #endif
4625 numpunct<char>::numpunct(size_t refs)
4626 : locale::facet(refs),
4627 __decimal_point_('.'),
4628 __thousands_sep_(',')
4632 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4633 numpunct<wchar_t>::numpunct(size_t refs)
4634 : locale::facet(refs),
4635 __decimal_point_(L'.'),
4636 __thousands_sep_(L',')
4639 #endif
4641 numpunct<char>::~numpunct()
4645 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4646 numpunct<wchar_t>::~numpunct()
4649 #endif
4651 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4652 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4653 wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4654 #endif
4656 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4657 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4658 wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4659 #endif
4661 string numpunct< char >::do_grouping() const {return __grouping_;}
4662 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4663 string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4664 #endif
4666 string numpunct< char >::do_truename() const {return "true";}
4667 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4668 wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4669 #endif
4671 string numpunct< char >::do_falsename() const {return "false";}
4672 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4673 wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4674 #endif
4676 // numpunct_byname<char>
4678 numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4679 : numpunct<char>(refs)
4681 __init(nm);
4684 numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4685 : numpunct<char>(refs)
4687 __init(nm.c_str());
4690 numpunct_byname<char>::~numpunct_byname()
4694 void
4695 numpunct_byname<char>::__init(const char* nm)
4697 typedef numpunct<char> base;
4698 if (strcmp(nm, "C") != 0)
4700 __libcpp_unique_locale loc(nm);
4701 if (!loc)
4702 __throw_runtime_error(("numpunct_byname<char>::numpunct_byname"
4703 " failed to construct for " + string(nm)).c_str());
4705 lconv* lc = __libcpp_localeconv_l(loc.get());
4706 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4707 loc.get()))
4708 __decimal_point_ = base::do_decimal_point();
4709 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4710 loc.get()))
4711 __thousands_sep_ = base::do_thousands_sep();
4712 __grouping_ = lc->grouping;
4713 // localization for truename and falsename is not available
4717 // numpunct_byname<wchar_t>
4719 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4720 numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4721 : numpunct<wchar_t>(refs)
4723 __init(nm);
4726 numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4727 : numpunct<wchar_t>(refs)
4729 __init(nm.c_str());
4732 numpunct_byname<wchar_t>::~numpunct_byname()
4736 void
4737 numpunct_byname<wchar_t>::__init(const char* nm)
4739 if (strcmp(nm, "C") != 0)
4741 __libcpp_unique_locale loc(nm);
4742 if (!loc)
4743 __throw_runtime_error(("numpunct_byname<wchar_t>::numpunct_byname"
4744 " failed to construct for " + string(nm)).c_str());
4746 lconv* lc = __libcpp_localeconv_l(loc.get());
4747 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4748 loc.get());
4749 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4750 loc.get());
4751 __grouping_ = lc->grouping;
4752 // localization for truename and falsename is not available
4755 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4757 // num_get helpers
4760 __num_get_base::__get_base(ios_base& iob)
4762 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4763 if (__basefield == ios_base::oct)
4764 return 8;
4765 else if (__basefield == ios_base::hex)
4766 return 16;
4767 else if (__basefield == 0)
4768 return 0;
4769 return 10;
4772 const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4774 void
4775 __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4776 ios_base::iostate& __err)
4778 // if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4779 // we always have at least a single entry in [__g, __g_end); the end of the input sequence
4780 if (__grouping.size() != 0 && __g_end - __g > 1)
4782 reverse(__g, __g_end);
4783 const char* __ig = __grouping.data();
4784 const char* __eg = __ig + __grouping.size();
4785 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4787 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4789 if (static_cast<unsigned>(*__ig) != *__r)
4791 __err = ios_base::failbit;
4792 return;
4795 if (__eg - __ig > 1)
4796 ++__ig;
4798 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4800 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
4801 __err = ios_base::failbit;
4806 void
4807 __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4808 ios_base::fmtflags __flags)
4810 if ((__flags & ios_base::showpos) &&
4811 (__flags & ios_base::basefield) != ios_base::oct &&
4812 (__flags & ios_base::basefield) != ios_base::hex &&
4813 __signd)
4814 *__fmtp++ = '+';
4815 if (__flags & ios_base::showbase)
4816 *__fmtp++ = '#';
4817 while(*__len)
4818 *__fmtp++ = *__len++;
4819 if ((__flags & ios_base::basefield) == ios_base::oct)
4820 *__fmtp = 'o';
4821 else if ((__flags & ios_base::basefield) == ios_base::hex)
4823 if (__flags & ios_base::uppercase)
4824 *__fmtp = 'X';
4825 else
4826 *__fmtp = 'x';
4828 else if (__signd)
4829 *__fmtp = 'd';
4830 else
4831 *__fmtp = 'u';
4834 bool
4835 __num_put_base::__format_float(char* __fmtp, const char* __len,
4836 ios_base::fmtflags __flags)
4838 bool specify_precision = true;
4839 if (__flags & ios_base::showpos)
4840 *__fmtp++ = '+';
4841 if (__flags & ios_base::showpoint)
4842 *__fmtp++ = '#';
4843 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4844 bool uppercase = (__flags & ios_base::uppercase) != 0;
4845 if (floatfield == (ios_base::fixed | ios_base::scientific))
4846 specify_precision = false;
4847 else
4849 *__fmtp++ = '.';
4850 *__fmtp++ = '*';
4852 while(*__len)
4853 *__fmtp++ = *__len++;
4854 if (floatfield == ios_base::fixed)
4856 if (uppercase)
4857 *__fmtp = 'F';
4858 else
4859 *__fmtp = 'f';
4861 else if (floatfield == ios_base::scientific)
4863 if (uppercase)
4864 *__fmtp = 'E';
4865 else
4866 *__fmtp = 'e';
4868 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4870 if (uppercase)
4871 *__fmtp = 'A';
4872 else
4873 *__fmtp = 'a';
4875 else
4877 if (uppercase)
4878 *__fmtp = 'G';
4879 else
4880 *__fmtp = 'g';
4882 return specify_precision;
4885 char*
4886 __num_put_base::__identify_padding(char* __nb, char* __ne,
4887 const ios_base& __iob)
4889 switch (__iob.flags() & ios_base::adjustfield)
4891 case ios_base::internal:
4892 if (__nb[0] == '-' || __nb[0] == '+')
4893 return __nb+1;
4894 if (__ne - __nb >= 2 && __nb[0] == '0'
4895 && (__nb[1] == 'x' || __nb[1] == 'X'))
4896 return __nb+2;
4897 break;
4898 case ios_base::left:
4899 return __ne;
4900 case ios_base::right:
4901 default:
4902 break;
4904 return __nb;
4907 // time_get
4909 static
4910 string*
4911 init_weeks()
4913 static string weeks[14];
4914 weeks[0] = "Sunday";
4915 weeks[1] = "Monday";
4916 weeks[2] = "Tuesday";
4917 weeks[3] = "Wednesday";
4918 weeks[4] = "Thursday";
4919 weeks[5] = "Friday";
4920 weeks[6] = "Saturday";
4921 weeks[7] = "Sun";
4922 weeks[8] = "Mon";
4923 weeks[9] = "Tue";
4924 weeks[10] = "Wed";
4925 weeks[11] = "Thu";
4926 weeks[12] = "Fri";
4927 weeks[13] = "Sat";
4928 return weeks;
4931 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4932 static
4933 wstring*
4934 init_wweeks()
4936 static wstring weeks[14];
4937 weeks[0] = L"Sunday";
4938 weeks[1] = L"Monday";
4939 weeks[2] = L"Tuesday";
4940 weeks[3] = L"Wednesday";
4941 weeks[4] = L"Thursday";
4942 weeks[5] = L"Friday";
4943 weeks[6] = L"Saturday";
4944 weeks[7] = L"Sun";
4945 weeks[8] = L"Mon";
4946 weeks[9] = L"Tue";
4947 weeks[10] = L"Wed";
4948 weeks[11] = L"Thu";
4949 weeks[12] = L"Fri";
4950 weeks[13] = L"Sat";
4951 return weeks;
4953 #endif
4955 template <>
4956 const string*
4957 __time_get_c_storage<char>::__weeks() const
4959 static const string* weeks = init_weeks();
4960 return weeks;
4963 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4964 template <>
4965 const wstring*
4966 __time_get_c_storage<wchar_t>::__weeks() const
4968 static const wstring* weeks = init_wweeks();
4969 return weeks;
4971 #endif
4973 static
4974 string*
4975 init_months()
4977 static string months[24];
4978 months[0] = "January";
4979 months[1] = "February";
4980 months[2] = "March";
4981 months[3] = "April";
4982 months[4] = "May";
4983 months[5] = "June";
4984 months[6] = "July";
4985 months[7] = "August";
4986 months[8] = "September";
4987 months[9] = "October";
4988 months[10] = "November";
4989 months[11] = "December";
4990 months[12] = "Jan";
4991 months[13] = "Feb";
4992 months[14] = "Mar";
4993 months[15] = "Apr";
4994 months[16] = "May";
4995 months[17] = "Jun";
4996 months[18] = "Jul";
4997 months[19] = "Aug";
4998 months[20] = "Sep";
4999 months[21] = "Oct";
5000 months[22] = "Nov";
5001 months[23] = "Dec";
5002 return months;
5005 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5006 static
5007 wstring*
5008 init_wmonths()
5010 static wstring months[24];
5011 months[0] = L"January";
5012 months[1] = L"February";
5013 months[2] = L"March";
5014 months[3] = L"April";
5015 months[4] = L"May";
5016 months[5] = L"June";
5017 months[6] = L"July";
5018 months[7] = L"August";
5019 months[8] = L"September";
5020 months[9] = L"October";
5021 months[10] = L"November";
5022 months[11] = L"December";
5023 months[12] = L"Jan";
5024 months[13] = L"Feb";
5025 months[14] = L"Mar";
5026 months[15] = L"Apr";
5027 months[16] = L"May";
5028 months[17] = L"Jun";
5029 months[18] = L"Jul";
5030 months[19] = L"Aug";
5031 months[20] = L"Sep";
5032 months[21] = L"Oct";
5033 months[22] = L"Nov";
5034 months[23] = L"Dec";
5035 return months;
5037 #endif
5039 template <>
5040 const string*
5041 __time_get_c_storage<char>::__months() const
5043 static const string* months = init_months();
5044 return months;
5047 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5048 template <>
5049 const wstring*
5050 __time_get_c_storage<wchar_t>::__months() const
5052 static const wstring* months = init_wmonths();
5053 return months;
5055 #endif
5057 static
5058 string*
5059 init_am_pm()
5061 static string am_pm[2];
5062 am_pm[0] = "AM";
5063 am_pm[1] = "PM";
5064 return am_pm;
5067 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5068 static
5069 wstring*
5070 init_wam_pm()
5072 static wstring am_pm[2];
5073 am_pm[0] = L"AM";
5074 am_pm[1] = L"PM";
5075 return am_pm;
5077 #endif
5079 template <>
5080 const string*
5081 __time_get_c_storage<char>::__am_pm() const
5083 static const string* am_pm = init_am_pm();
5084 return am_pm;
5087 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5088 template <>
5089 const wstring*
5090 __time_get_c_storage<wchar_t>::__am_pm() const
5092 static const wstring* am_pm = init_wam_pm();
5093 return am_pm;
5095 #endif
5097 template <>
5098 const string&
5099 __time_get_c_storage<char>::__x() const
5101 static string s("%m/%d/%y");
5102 return s;
5105 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5106 template <>
5107 const wstring&
5108 __time_get_c_storage<wchar_t>::__x() const
5110 static wstring s(L"%m/%d/%y");
5111 return s;
5113 #endif
5115 template <>
5116 const string&
5117 __time_get_c_storage<char>::__X() const
5119 static string s("%H:%M:%S");
5120 return s;
5123 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5124 template <>
5125 const wstring&
5126 __time_get_c_storage<wchar_t>::__X() const
5128 static wstring s(L"%H:%M:%S");
5129 return s;
5131 #endif
5133 template <>
5134 const string&
5135 __time_get_c_storage<char>::__c() const
5137 static string s("%a %b %d %H:%M:%S %Y");
5138 return s;
5141 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5142 template <>
5143 const wstring&
5144 __time_get_c_storage<wchar_t>::__c() const
5146 static wstring s(L"%a %b %d %H:%M:%S %Y");
5147 return s;
5149 #endif
5151 template <>
5152 const string&
5153 __time_get_c_storage<char>::__r() const
5155 static string s("%I:%M:%S %p");
5156 return s;
5159 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5160 template <>
5161 const wstring&
5162 __time_get_c_storage<wchar_t>::__r() const
5164 static wstring s(L"%I:%M:%S %p");
5165 return s;
5167 #endif
5169 // time_get_byname
5171 __time_get::__time_get(const char* nm)
5172 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5174 if (__loc_ == 0)
5175 __throw_runtime_error(("time_get_byname failed to construct for " + string(nm)).c_str());
5178 __time_get::__time_get(const string& nm)
5179 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5181 if (__loc_ == 0)
5182 __throw_runtime_error(("time_get_byname failed to construct for " + nm).c_str());
5185 __time_get::~__time_get()
5187 freelocale(__loc_);
5190 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
5192 template <>
5193 string
5194 __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5196 tm t = {0};
5197 t.tm_sec = 59;
5198 t.tm_min = 55;
5199 t.tm_hour = 23;
5200 t.tm_mday = 31;
5201 t.tm_mon = 11;
5202 t.tm_year = 161;
5203 t.tm_wday = 6;
5204 t.tm_yday = 364;
5205 t.tm_isdst = -1;
5206 char buf[100];
5207 char f[3] = {0};
5208 f[0] = '%';
5209 f[1] = fmt;
5210 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
5211 char* bb = buf;
5212 char* be = buf + n;
5213 string result;
5214 while (bb != be)
5216 if (ct.is(ctype_base::space, *bb))
5218 result.push_back(' ');
5219 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5221 continue;
5223 char* w = bb;
5224 ios_base::iostate err = ios_base::goodbit;
5225 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
5226 ct, err, false)
5227 - this->__weeks_;
5228 if (i < 14)
5230 result.push_back('%');
5231 if (i < 7)
5232 result.push_back('A');
5233 else
5234 result.push_back('a');
5235 bb = w;
5236 continue;
5238 w = bb;
5239 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5240 ct, err, false)
5241 - this->__months_;
5242 if (i < 24)
5244 result.push_back('%');
5245 if (i < 12)
5246 result.push_back('B');
5247 else
5248 result.push_back('b');
5249 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5250 result.back() = 'm';
5251 bb = w;
5252 continue;
5254 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5256 w = bb;
5257 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5258 ct, err, false) - this->__am_pm_;
5259 if (i < 2)
5261 result.push_back('%');
5262 result.push_back('p');
5263 bb = w;
5264 continue;
5267 w = bb;
5268 if (ct.is(ctype_base::digit, *bb))
5270 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5272 case 6:
5273 result.push_back('%');
5274 result.push_back('w');
5275 break;
5276 case 7:
5277 result.push_back('%');
5278 result.push_back('u');
5279 break;
5280 case 11:
5281 result.push_back('%');
5282 result.push_back('I');
5283 break;
5284 case 12:
5285 result.push_back('%');
5286 result.push_back('m');
5287 break;
5288 case 23:
5289 result.push_back('%');
5290 result.push_back('H');
5291 break;
5292 case 31:
5293 result.push_back('%');
5294 result.push_back('d');
5295 break;
5296 case 55:
5297 result.push_back('%');
5298 result.push_back('M');
5299 break;
5300 case 59:
5301 result.push_back('%');
5302 result.push_back('S');
5303 break;
5304 case 61:
5305 result.push_back('%');
5306 result.push_back('y');
5307 break;
5308 case 364:
5309 result.push_back('%');
5310 result.push_back('j');
5311 break;
5312 case 2061:
5313 result.push_back('%');
5314 result.push_back('Y');
5315 break;
5316 default:
5317 for (; w != bb; ++w)
5318 result.push_back(*w);
5319 break;
5321 continue;
5323 if (*bb == '%')
5325 result.push_back('%');
5326 result.push_back('%');
5327 ++bb;
5328 continue;
5330 result.push_back(*bb);
5331 ++bb;
5333 return result;
5336 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces")
5338 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5339 template <>
5340 wstring
5341 __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5343 tm t = {0};
5344 t.tm_sec = 59;
5345 t.tm_min = 55;
5346 t.tm_hour = 23;
5347 t.tm_mday = 31;
5348 t.tm_mon = 11;
5349 t.tm_year = 161;
5350 t.tm_wday = 6;
5351 t.tm_yday = 364;
5352 t.tm_isdst = -1;
5353 char buf[100];
5354 char f[3] = {0};
5355 f[0] = '%';
5356 f[1] = fmt;
5357 strftime_l(buf, countof(buf), f, &t, __loc_);
5358 wchar_t wbuf[100];
5359 wchar_t* wbb = wbuf;
5360 mbstate_t mb = {0};
5361 const char* bb = buf;
5362 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
5363 if (j == size_t(-1))
5364 __throw_runtime_error("locale not supported");
5365 wchar_t* wbe = wbb + j;
5366 wstring result;
5367 while (wbb != wbe)
5369 if (ct.is(ctype_base::space, *wbb))
5371 result.push_back(L' ');
5372 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5374 continue;
5376 wchar_t* w = wbb;
5377 ios_base::iostate err = ios_base::goodbit;
5378 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
5379 ct, err, false)
5380 - this->__weeks_;
5381 if (i < 14)
5383 result.push_back(L'%');
5384 if (i < 7)
5385 result.push_back(L'A');
5386 else
5387 result.push_back(L'a');
5388 wbb = w;
5389 continue;
5391 w = wbb;
5392 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5393 ct, err, false)
5394 - this->__months_;
5395 if (i < 24)
5397 result.push_back(L'%');
5398 if (i < 12)
5399 result.push_back(L'B');
5400 else
5401 result.push_back(L'b');
5402 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5403 result.back() = L'm';
5404 wbb = w;
5405 continue;
5407 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5409 w = wbb;
5410 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5411 ct, err, false) - this->__am_pm_;
5412 if (i < 2)
5414 result.push_back(L'%');
5415 result.push_back(L'p');
5416 wbb = w;
5417 continue;
5420 w = wbb;
5421 if (ct.is(ctype_base::digit, *wbb))
5423 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5425 case 6:
5426 result.push_back(L'%');
5427 result.push_back(L'w');
5428 break;
5429 case 7:
5430 result.push_back(L'%');
5431 result.push_back(L'u');
5432 break;
5433 case 11:
5434 result.push_back(L'%');
5435 result.push_back(L'I');
5436 break;
5437 case 12:
5438 result.push_back(L'%');
5439 result.push_back(L'm');
5440 break;
5441 case 23:
5442 result.push_back(L'%');
5443 result.push_back(L'H');
5444 break;
5445 case 31:
5446 result.push_back(L'%');
5447 result.push_back(L'd');
5448 break;
5449 case 55:
5450 result.push_back(L'%');
5451 result.push_back(L'M');
5452 break;
5453 case 59:
5454 result.push_back(L'%');
5455 result.push_back(L'S');
5456 break;
5457 case 61:
5458 result.push_back(L'%');
5459 result.push_back(L'y');
5460 break;
5461 case 364:
5462 result.push_back(L'%');
5463 result.push_back(L'j');
5464 break;
5465 case 2061:
5466 result.push_back(L'%');
5467 result.push_back(L'Y');
5468 break;
5469 default:
5470 for (; w != wbb; ++w)
5471 result.push_back(*w);
5472 break;
5474 continue;
5476 if (ct.narrow(*wbb, 0) == '%')
5478 result.push_back(L'%');
5479 result.push_back(L'%');
5480 ++wbb;
5481 continue;
5483 result.push_back(*wbb);
5484 ++wbb;
5486 return result;
5488 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5490 template <>
5491 void
5492 __time_get_storage<char>::init(const ctype<char>& ct)
5494 tm t = {0};
5495 char buf[100];
5496 // __weeks_
5497 for (int i = 0; i < 7; ++i)
5499 t.tm_wday = i;
5500 strftime_l(buf, countof(buf), "%A", &t, __loc_);
5501 __weeks_[i] = buf;
5502 strftime_l(buf, countof(buf), "%a", &t, __loc_);
5503 __weeks_[i+7] = buf;
5505 // __months_
5506 for (int i = 0; i < 12; ++i)
5508 t.tm_mon = i;
5509 strftime_l(buf, countof(buf), "%B", &t, __loc_);
5510 __months_[i] = buf;
5511 strftime_l(buf, countof(buf), "%b", &t, __loc_);
5512 __months_[i+12] = buf;
5514 // __am_pm_
5515 t.tm_hour = 1;
5516 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5517 __am_pm_[0] = buf;
5518 t.tm_hour = 13;
5519 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5520 __am_pm_[1] = buf;
5521 __c_ = __analyze('c', ct);
5522 __r_ = __analyze('r', ct);
5523 __x_ = __analyze('x', ct);
5524 __X_ = __analyze('X', ct);
5527 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5528 template <>
5529 void
5530 __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5532 tm t = {0};
5533 char buf[100];
5534 wchar_t wbuf[100];
5535 wchar_t* wbe;
5536 mbstate_t mb = {0};
5537 // __weeks_
5538 for (int i = 0; i < 7; ++i)
5540 t.tm_wday = i;
5541 strftime_l(buf, countof(buf), "%A", &t, __loc_);
5542 mb = mbstate_t();
5543 const char* bb = buf;
5544 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5545 if (j == size_t(-1) || j == 0)
5546 __throw_runtime_error("locale not supported");
5547 wbe = wbuf + j;
5548 __weeks_[i].assign(wbuf, wbe);
5549 strftime_l(buf, countof(buf), "%a", &t, __loc_);
5550 mb = mbstate_t();
5551 bb = buf;
5552 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5553 if (j == size_t(-1) || j == 0)
5554 __throw_runtime_error("locale not supported");
5555 wbe = wbuf + j;
5556 __weeks_[i+7].assign(wbuf, wbe);
5558 // __months_
5559 for (int i = 0; i < 12; ++i)
5561 t.tm_mon = i;
5562 strftime_l(buf, countof(buf), "%B", &t, __loc_);
5563 mb = mbstate_t();
5564 const char* bb = buf;
5565 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5566 if (j == size_t(-1) || j == 0)
5567 __throw_runtime_error("locale not supported");
5568 wbe = wbuf + j;
5569 __months_[i].assign(wbuf, wbe);
5570 strftime_l(buf, countof(buf), "%b", &t, __loc_);
5571 mb = mbstate_t();
5572 bb = buf;
5573 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5574 if (j == size_t(-1) || j == 0)
5575 __throw_runtime_error("locale not supported");
5576 wbe = wbuf + j;
5577 __months_[i+12].assign(wbuf, wbe);
5579 // __am_pm_
5580 t.tm_hour = 1;
5581 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5582 mb = mbstate_t();
5583 const char* bb = buf;
5584 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5585 if (j == size_t(-1))
5586 __throw_runtime_error("locale not supported");
5587 wbe = wbuf + j;
5588 __am_pm_[0].assign(wbuf, wbe);
5589 t.tm_hour = 13;
5590 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5591 mb = mbstate_t();
5592 bb = buf;
5593 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5594 if (j == size_t(-1))
5595 __throw_runtime_error("locale not supported");
5596 wbe = wbuf + j;
5597 __am_pm_[1].assign(wbuf, wbe);
5598 __c_ = __analyze('c', ct);
5599 __r_ = __analyze('r', ct);
5600 __x_ = __analyze('x', ct);
5601 __X_ = __analyze('X', ct);
5603 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5605 template <class CharT>
5606 struct _LIBCPP_HIDDEN __time_get_temp
5607 : public ctype_byname<CharT>
5609 explicit __time_get_temp(const char* nm)
5610 : ctype_byname<CharT>(nm, 1) {}
5611 explicit __time_get_temp(const string& nm)
5612 : ctype_byname<CharT>(nm, 1) {}
5615 template <>
5616 __time_get_storage<char>::__time_get_storage(const char* __nm)
5617 : __time_get(__nm)
5619 const __time_get_temp<char> ct(__nm);
5620 init(ct);
5623 template <>
5624 __time_get_storage<char>::__time_get_storage(const string& __nm)
5625 : __time_get(__nm)
5627 const __time_get_temp<char> ct(__nm);
5628 init(ct);
5631 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5632 template <>
5633 __time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5634 : __time_get(__nm)
5636 const __time_get_temp<wchar_t> ct(__nm);
5637 init(ct);
5640 template <>
5641 __time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5642 : __time_get(__nm)
5644 const __time_get_temp<wchar_t> ct(__nm);
5645 init(ct);
5647 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5649 template <>
5650 time_base::dateorder
5651 __time_get_storage<char>::__do_date_order() const
5653 unsigned i;
5654 for (i = 0; i < __x_.size(); ++i)
5655 if (__x_[i] == '%')
5656 break;
5657 ++i;
5658 switch (__x_[i])
5660 case 'y':
5661 case 'Y':
5662 for (++i; i < __x_.size(); ++i)
5663 if (__x_[i] == '%')
5664 break;
5665 if (i == __x_.size())
5666 break;
5667 ++i;
5668 switch (__x_[i])
5670 case 'm':
5671 for (++i; i < __x_.size(); ++i)
5672 if (__x_[i] == '%')
5673 break;
5674 if (i == __x_.size())
5675 break;
5676 ++i;
5677 if (__x_[i] == 'd')
5678 return time_base::ymd;
5679 break;
5680 case 'd':
5681 for (++i; i < __x_.size(); ++i)
5682 if (__x_[i] == '%')
5683 break;
5684 if (i == __x_.size())
5685 break;
5686 ++i;
5687 if (__x_[i] == 'm')
5688 return time_base::ydm;
5689 break;
5691 break;
5692 case 'm':
5693 for (++i; i < __x_.size(); ++i)
5694 if (__x_[i] == '%')
5695 break;
5696 if (i == __x_.size())
5697 break;
5698 ++i;
5699 if (__x_[i] == 'd')
5701 for (++i; i < __x_.size(); ++i)
5702 if (__x_[i] == '%')
5703 break;
5704 if (i == __x_.size())
5705 break;
5706 ++i;
5707 if (__x_[i] == 'y' || __x_[i] == 'Y')
5708 return time_base::mdy;
5709 break;
5711 break;
5712 case 'd':
5713 for (++i; i < __x_.size(); ++i)
5714 if (__x_[i] == '%')
5715 break;
5716 if (i == __x_.size())
5717 break;
5718 ++i;
5719 if (__x_[i] == 'm')
5721 for (++i; i < __x_.size(); ++i)
5722 if (__x_[i] == '%')
5723 break;
5724 if (i == __x_.size())
5725 break;
5726 ++i;
5727 if (__x_[i] == 'y' || __x_[i] == 'Y')
5728 return time_base::dmy;
5729 break;
5731 break;
5733 return time_base::no_order;
5736 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5737 template <>
5738 time_base::dateorder
5739 __time_get_storage<wchar_t>::__do_date_order() const
5741 unsigned i;
5742 for (i = 0; i < __x_.size(); ++i)
5743 if (__x_[i] == L'%')
5744 break;
5745 ++i;
5746 switch (__x_[i])
5748 case L'y':
5749 case L'Y':
5750 for (++i; i < __x_.size(); ++i)
5751 if (__x_[i] == L'%')
5752 break;
5753 if (i == __x_.size())
5754 break;
5755 ++i;
5756 switch (__x_[i])
5758 case L'm':
5759 for (++i; i < __x_.size(); ++i)
5760 if (__x_[i] == L'%')
5761 break;
5762 if (i == __x_.size())
5763 break;
5764 ++i;
5765 if (__x_[i] == L'd')
5766 return time_base::ymd;
5767 break;
5768 case L'd':
5769 for (++i; i < __x_.size(); ++i)
5770 if (__x_[i] == L'%')
5771 break;
5772 if (i == __x_.size())
5773 break;
5774 ++i;
5775 if (__x_[i] == L'm')
5776 return time_base::ydm;
5777 break;
5779 break;
5780 case L'm':
5781 for (++i; i < __x_.size(); ++i)
5782 if (__x_[i] == L'%')
5783 break;
5784 if (i == __x_.size())
5785 break;
5786 ++i;
5787 if (__x_[i] == L'd')
5789 for (++i; i < __x_.size(); ++i)
5790 if (__x_[i] == L'%')
5791 break;
5792 if (i == __x_.size())
5793 break;
5794 ++i;
5795 if (__x_[i] == L'y' || __x_[i] == L'Y')
5796 return time_base::mdy;
5797 break;
5799 break;
5800 case L'd':
5801 for (++i; i < __x_.size(); ++i)
5802 if (__x_[i] == L'%')
5803 break;
5804 if (i == __x_.size())
5805 break;
5806 ++i;
5807 if (__x_[i] == L'm')
5809 for (++i; i < __x_.size(); ++i)
5810 if (__x_[i] == L'%')
5811 break;
5812 if (i == __x_.size())
5813 break;
5814 ++i;
5815 if (__x_[i] == L'y' || __x_[i] == L'Y')
5816 return time_base::dmy;
5817 break;
5819 break;
5821 return time_base::no_order;
5823 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5825 // time_put
5827 __time_put::__time_put(const char* nm)
5828 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5830 if (__loc_ == 0)
5831 __throw_runtime_error(("time_put_byname failed to construct for " + string(nm)).c_str());
5834 __time_put::__time_put(const string& nm)
5835 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5837 if (__loc_ == 0)
5838 __throw_runtime_error(("time_put_byname failed to construct for " + nm).c_str());
5841 __time_put::~__time_put()
5843 if (__loc_ != _LIBCPP_GET_C_LOCALE)
5844 freelocale(__loc_);
5847 void
5848 __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5849 char __fmt, char __mod) const
5851 char fmt[] = {'%', __fmt, __mod, 0};
5852 if (__mod != 0)
5853 swap(fmt[1], fmt[2]);
5854 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
5855 __ne = __nb + n;
5858 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5859 void
5860 __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5861 char __fmt, char __mod) const
5863 char __nar[100];
5864 char* __ne = __nar + 100;
5865 __do_put(__nar, __ne, __tm, __fmt, __mod);
5866 mbstate_t mb = {0};
5867 const char* __nb = __nar;
5868 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5869 if (j == size_t(-1))
5870 __throw_runtime_error("locale not supported");
5871 __we = __wb + j;
5873 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5875 // moneypunct_byname
5877 template <class charT>
5878 static
5879 void
5880 __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5881 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5882 charT space_char)
5884 const char sign = static_cast<char>(money_base::sign);
5885 const char space = static_cast<char>(money_base::space);
5886 const char none = static_cast<char>(money_base::none);
5887 const char symbol = static_cast<char>(money_base::symbol);
5888 const char value = static_cast<char>(money_base::value);
5889 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5891 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5892 // function'. "Space between sign and symbol or value" means that
5893 // if the sign is adjacent to the symbol, there's a space between
5894 // them, and otherwise there's a space between the sign and value.
5896 // C11's localeconv specifies that the fourth character of an
5897 // international curr_symbol is used to separate the sign and
5898 // value when sep_by_space says to do so. C++ can't represent
5899 // that, so we just use a space. When sep_by_space says to
5900 // separate the symbol and value-or-sign with a space, we rearrange the
5901 // curr_symbol to put its spacing character on the correct side of
5902 // the symbol.
5904 // We also need to avoid adding an extra space between the sign
5905 // and value when the currency symbol is suppressed (by not
5906 // setting showbase). We match glibc's strfmon by interpreting
5907 // sep_by_space==1 as "omit the space when the currency symbol is
5908 // absent".
5910 // Users who want to get this right should use ICU instead.
5912 switch (cs_precedes)
5914 case 0: // value before curr_symbol
5915 if (symbol_contains_sep) {
5916 // Move the separator to before the symbol, to place it
5917 // between the value and symbol.
5918 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5919 __curr_symbol_.end());
5921 switch (sign_posn)
5923 case 0: // Parentheses surround the quantity and currency symbol.
5924 pat.field[0] = sign;
5925 pat.field[1] = value;
5926 pat.field[2] = none; // Any space appears in the symbol.
5927 pat.field[3] = symbol;
5928 switch (sep_by_space)
5930 case 0: // No space separates the currency symbol and value.
5931 // This case may have changed between C99 and C11;
5932 // assume the currency symbol matches the intention.
5933 case 2: // Space between sign and currency or value.
5934 // The "sign" is two parentheses, so no space here either.
5935 return;
5936 case 1: // Space between currency-and-sign or currency and value.
5937 if (!symbol_contains_sep) {
5938 // We insert the space into the symbol instead of
5939 // setting pat.field[2]=space so that when
5940 // showbase is not set, the space goes away too.
5941 __curr_symbol_.insert(0, 1, space_char);
5943 return;
5944 default:
5945 break;
5947 break;
5948 case 1: // The sign string precedes the quantity and currency symbol.
5949 pat.field[0] = sign;
5950 pat.field[3] = symbol;
5951 switch (sep_by_space)
5953 case 0: // No space separates the currency symbol and value.
5954 pat.field[1] = value;
5955 pat.field[2] = none;
5956 return;
5957 case 1: // Space between currency-and-sign or currency and value.
5958 pat.field[1] = value;
5959 pat.field[2] = none;
5960 if (!symbol_contains_sep) {
5961 // We insert the space into the symbol instead of
5962 // setting pat.field[2]=space so that when
5963 // showbase is not set, the space goes away too.
5964 __curr_symbol_.insert(0, 1, space_char);
5966 return;
5967 case 2: // Space between sign and currency or value.
5968 pat.field[1] = space;
5969 pat.field[2] = value;
5970 if (symbol_contains_sep) {
5971 // Remove the separator from the symbol, since it
5972 // has already appeared after the sign.
5973 __curr_symbol_.erase(__curr_symbol_.begin());
5975 return;
5976 default:
5977 break;
5979 break;
5980 case 2: // The sign string succeeds the quantity and currency symbol.
5981 pat.field[0] = value;
5982 pat.field[3] = sign;
5983 switch (sep_by_space)
5985 case 0: // No space separates the currency symbol and value.
5986 pat.field[1] = none;
5987 pat.field[2] = symbol;
5988 return;
5989 case 1: // Space between currency-and-sign or currency and value.
5990 if (!symbol_contains_sep) {
5991 // We insert the space into the symbol instead of
5992 // setting pat.field[1]=space so that when
5993 // showbase is not set, the space goes away too.
5994 __curr_symbol_.insert(0, 1, space_char);
5996 pat.field[1] = none;
5997 pat.field[2] = symbol;
5998 return;
5999 case 2: // Space between sign and currency or value.
6000 pat.field[1] = symbol;
6001 pat.field[2] = space;
6002 if (symbol_contains_sep) {
6003 // Remove the separator from the symbol, since it
6004 // should not be removed if showbase is absent.
6005 __curr_symbol_.erase(__curr_symbol_.begin());
6007 return;
6008 default:
6009 break;
6011 break;
6012 case 3: // The sign string immediately precedes the currency symbol.
6013 pat.field[0] = value;
6014 pat.field[3] = symbol;
6015 switch (sep_by_space)
6017 case 0: // No space separates the currency symbol and value.
6018 pat.field[1] = none;
6019 pat.field[2] = sign;
6020 return;
6021 case 1: // Space between currency-and-sign or currency and value.
6022 pat.field[1] = space;
6023 pat.field[2] = sign;
6024 if (symbol_contains_sep) {
6025 // Remove the separator from the symbol, since it
6026 // has already appeared before the sign.
6027 __curr_symbol_.erase(__curr_symbol_.begin());
6029 return;
6030 case 2: // Space between sign and currency or value.
6031 pat.field[1] = sign;
6032 pat.field[2] = none;
6033 if (!symbol_contains_sep) {
6034 // We insert the space into the symbol instead of
6035 // setting pat.field[2]=space so that when
6036 // showbase is not set, the space goes away too.
6037 __curr_symbol_.insert(0, 1, space_char);
6039 return;
6040 default:
6041 break;
6043 break;
6044 case 4: // The sign string immediately succeeds the currency symbol.
6045 pat.field[0] = value;
6046 pat.field[3] = sign;
6047 switch (sep_by_space)
6049 case 0: // No space separates the currency symbol and value.
6050 pat.field[1] = none;
6051 pat.field[2] = symbol;
6052 return;
6053 case 1: // Space between currency-and-sign or currency and value.
6054 pat.field[1] = none;
6055 pat.field[2] = symbol;
6056 if (!symbol_contains_sep) {
6057 // We insert the space into the symbol instead of
6058 // setting pat.field[1]=space so that when
6059 // showbase is not set, the space goes away too.
6060 __curr_symbol_.insert(0, 1, space_char);
6062 return;
6063 case 2: // Space between sign and currency or value.
6064 pat.field[1] = symbol;
6065 pat.field[2] = space;
6066 if (symbol_contains_sep) {
6067 // Remove the separator from the symbol, since it
6068 // should not disappear when showbase is absent.
6069 __curr_symbol_.erase(__curr_symbol_.begin());
6071 return;
6072 default:
6073 break;
6075 break;
6076 default:
6077 break;
6079 break;
6080 case 1: // curr_symbol before value
6081 switch (sign_posn)
6083 case 0: // Parentheses surround the quantity and currency symbol.
6084 pat.field[0] = sign;
6085 pat.field[1] = symbol;
6086 pat.field[2] = none; // Any space appears in the symbol.
6087 pat.field[3] = value;
6088 switch (sep_by_space)
6090 case 0: // No space separates the currency symbol and value.
6091 // This case may have changed between C99 and C11;
6092 // assume the currency symbol matches the intention.
6093 case 2: // Space between sign and currency or value.
6094 // The "sign" is two parentheses, so no space here either.
6095 return;
6096 case 1: // Space between currency-and-sign or currency and value.
6097 if (!symbol_contains_sep) {
6098 // We insert the space into the symbol instead of
6099 // setting pat.field[2]=space so that when
6100 // showbase is not set, the space goes away too.
6101 __curr_symbol_.insert(0, 1, space_char);
6103 return;
6104 default:
6105 break;
6107 break;
6108 case 1: // The sign string precedes the quantity and currency symbol.
6109 pat.field[0] = sign;
6110 pat.field[3] = value;
6111 switch (sep_by_space)
6113 case 0: // No space separates the currency symbol and value.
6114 pat.field[1] = symbol;
6115 pat.field[2] = none;
6116 return;
6117 case 1: // Space between currency-and-sign or currency and value.
6118 pat.field[1] = symbol;
6119 pat.field[2] = none;
6120 if (!symbol_contains_sep) {
6121 // We insert the space into the symbol instead of
6122 // setting pat.field[2]=space so that when
6123 // showbase is not set, the space goes away too.
6124 __curr_symbol_.push_back(space_char);
6126 return;
6127 case 2: // Space between sign and currency or value.
6128 pat.field[1] = space;
6129 pat.field[2] = symbol;
6130 if (symbol_contains_sep) {
6131 // Remove the separator from the symbol, since it
6132 // has already appeared after the sign.
6133 __curr_symbol_.pop_back();
6135 return;
6136 default:
6137 break;
6139 break;
6140 case 2: // The sign string succeeds the quantity and currency symbol.
6141 pat.field[0] = symbol;
6142 pat.field[3] = sign;
6143 switch (sep_by_space)
6145 case 0: // No space separates the currency symbol and value.
6146 pat.field[1] = none;
6147 pat.field[2] = value;
6148 return;
6149 case 1: // Space between currency-and-sign or currency and value.
6150 pat.field[1] = none;
6151 pat.field[2] = value;
6152 if (!symbol_contains_sep) {
6153 // We insert the space into the symbol instead of
6154 // setting pat.field[1]=space so that when
6155 // showbase is not set, the space goes away too.
6156 __curr_symbol_.push_back(space_char);
6158 return;
6159 case 2: // Space between sign and currency or value.
6160 pat.field[1] = value;
6161 pat.field[2] = space;
6162 if (symbol_contains_sep) {
6163 // Remove the separator from the symbol, since it
6164 // will appear before the sign.
6165 __curr_symbol_.pop_back();
6167 return;
6168 default:
6169 break;
6171 break;
6172 case 3: // The sign string immediately precedes the currency symbol.
6173 pat.field[0] = sign;
6174 pat.field[3] = value;
6175 switch (sep_by_space)
6177 case 0: // No space separates the currency symbol and value.
6178 pat.field[1] = symbol;
6179 pat.field[2] = none;
6180 return;
6181 case 1: // Space between currency-and-sign or currency and value.
6182 pat.field[1] = symbol;
6183 pat.field[2] = none;
6184 if (!symbol_contains_sep) {
6185 // We insert the space into the symbol instead of
6186 // setting pat.field[2]=space so that when
6187 // showbase is not set, the space goes away too.
6188 __curr_symbol_.push_back(space_char);
6190 return;
6191 case 2: // Space between sign and currency or value.
6192 pat.field[1] = space;
6193 pat.field[2] = symbol;
6194 if (symbol_contains_sep) {
6195 // Remove the separator from the symbol, since it
6196 // has already appeared after the sign.
6197 __curr_symbol_.pop_back();
6199 return;
6200 default:
6201 break;
6203 break;
6204 case 4: // The sign string immediately succeeds the currency symbol.
6205 pat.field[0] = symbol;
6206 pat.field[3] = value;
6207 switch (sep_by_space)
6209 case 0: // No space separates the currency symbol and value.
6210 pat.field[1] = sign;
6211 pat.field[2] = none;
6212 return;
6213 case 1: // Space between currency-and-sign or currency and value.
6214 pat.field[1] = sign;
6215 pat.field[2] = space;
6216 if (symbol_contains_sep) {
6217 // Remove the separator from the symbol, since it
6218 // should not disappear when showbase is absent.
6219 __curr_symbol_.pop_back();
6221 return;
6222 case 2: // Space between sign and currency or value.
6223 pat.field[1] = none;
6224 pat.field[2] = sign;
6225 if (!symbol_contains_sep) {
6226 // We insert the space into the symbol instead of
6227 // setting pat.field[1]=space so that when
6228 // showbase is not set, the space goes away too.
6229 __curr_symbol_.push_back(space_char);
6231 return;
6232 default:
6233 break;
6235 break;
6236 default:
6237 break;
6239 break;
6240 default:
6241 break;
6243 pat.field[0] = symbol;
6244 pat.field[1] = sign;
6245 pat.field[2] = none;
6246 pat.field[3] = value;
6249 template<>
6250 void
6251 moneypunct_byname<char, false>::init(const char* nm)
6253 typedef moneypunct<char, false> base;
6254 __libcpp_unique_locale loc(nm);
6255 if (!loc)
6256 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6258 lconv* lc = __libcpp_localeconv_l(loc.get());
6259 if (!checked_string_to_char_convert(__decimal_point_,
6260 lc->mon_decimal_point,
6261 loc.get()))
6262 __decimal_point_ = base::do_decimal_point();
6263 if (!checked_string_to_char_convert(__thousands_sep_,
6264 lc->mon_thousands_sep,
6265 loc.get()))
6266 __thousands_sep_ = base::do_thousands_sep();
6268 __grouping_ = lc->mon_grouping;
6269 __curr_symbol_ = lc->currency_symbol;
6270 if (lc->frac_digits != CHAR_MAX)
6271 __frac_digits_ = lc->frac_digits;
6272 else
6273 __frac_digits_ = base::do_frac_digits();
6274 if (lc->p_sign_posn == 0)
6275 __positive_sign_ = "()";
6276 else
6277 __positive_sign_ = lc->positive_sign;
6278 if (lc->n_sign_posn == 0)
6279 __negative_sign_ = "()";
6280 else
6281 __negative_sign_ = lc->negative_sign;
6282 // Assume the positive and negative formats will want spaces in
6283 // the same places in curr_symbol since there's no way to
6284 // represent anything else.
6285 string_type __dummy_curr_symbol = __curr_symbol_;
6286 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6287 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6288 __init_pat(__neg_format_, __curr_symbol_, false,
6289 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
6292 template<>
6293 void
6294 moneypunct_byname<char, true>::init(const char* nm)
6296 typedef moneypunct<char, true> base;
6297 __libcpp_unique_locale loc(nm);
6298 if (!loc)
6299 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6301 lconv* lc = __libcpp_localeconv_l(loc.get());
6302 if (!checked_string_to_char_convert(__decimal_point_,
6303 lc->mon_decimal_point,
6304 loc.get()))
6305 __decimal_point_ = base::do_decimal_point();
6306 if (!checked_string_to_char_convert(__thousands_sep_,
6307 lc->mon_thousands_sep,
6308 loc.get()))
6309 __thousands_sep_ = base::do_thousands_sep();
6310 __grouping_ = lc->mon_grouping;
6311 __curr_symbol_ = lc->int_curr_symbol;
6312 if (lc->int_frac_digits != CHAR_MAX)
6313 __frac_digits_ = lc->int_frac_digits;
6314 else
6315 __frac_digits_ = base::do_frac_digits();
6316 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6317 if (lc->p_sign_posn == 0)
6318 #else // _LIBCPP_MSVCRT
6319 if (lc->int_p_sign_posn == 0)
6320 #endif // !_LIBCPP_MSVCRT
6321 __positive_sign_ = "()";
6322 else
6323 __positive_sign_ = lc->positive_sign;
6324 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6325 if(lc->n_sign_posn == 0)
6326 #else // _LIBCPP_MSVCRT
6327 if (lc->int_n_sign_posn == 0)
6328 #endif // !_LIBCPP_MSVCRT
6329 __negative_sign_ = "()";
6330 else
6331 __negative_sign_ = lc->negative_sign;
6332 // Assume the positive and negative formats will want spaces in
6333 // the same places in curr_symbol since there's no way to
6334 // represent anything else.
6335 string_type __dummy_curr_symbol = __curr_symbol_;
6336 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6337 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6338 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6339 __init_pat(__neg_format_, __curr_symbol_, true,
6340 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
6341 #else // _LIBCPP_MSVCRT
6342 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6343 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6344 lc->int_p_sign_posn, ' ');
6345 __init_pat(__neg_format_, __curr_symbol_, true,
6346 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6347 lc->int_n_sign_posn, ' ');
6348 #endif // !_LIBCPP_MSVCRT
6351 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
6352 template<>
6353 void
6354 moneypunct_byname<wchar_t, false>::init(const char* nm)
6356 typedef moneypunct<wchar_t, false> base;
6357 __libcpp_unique_locale loc(nm);
6358 if (!loc)
6359 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6360 lconv* lc = __libcpp_localeconv_l(loc.get());
6361 if (!checked_string_to_wchar_convert(__decimal_point_,
6362 lc->mon_decimal_point,
6363 loc.get()))
6364 __decimal_point_ = base::do_decimal_point();
6365 if (!checked_string_to_wchar_convert(__thousands_sep_,
6366 lc->mon_thousands_sep,
6367 loc.get()))
6368 __thousands_sep_ = base::do_thousands_sep();
6369 __grouping_ = lc->mon_grouping;
6370 wchar_t wbuf[100];
6371 mbstate_t mb = {0};
6372 const char* bb = lc->currency_symbol;
6373 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6374 if (j == size_t(-1))
6375 __throw_runtime_error("locale not supported");
6376 wchar_t* wbe = wbuf + j;
6377 __curr_symbol_.assign(wbuf, wbe);
6378 if (lc->frac_digits != CHAR_MAX)
6379 __frac_digits_ = lc->frac_digits;
6380 else
6381 __frac_digits_ = base::do_frac_digits();
6382 if (lc->p_sign_posn == 0)
6383 __positive_sign_ = L"()";
6384 else
6386 mb = mbstate_t();
6387 bb = lc->positive_sign;
6388 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6389 if (j == size_t(-1))
6390 __throw_runtime_error("locale not supported");
6391 wbe = wbuf + j;
6392 __positive_sign_.assign(wbuf, wbe);
6394 if (lc->n_sign_posn == 0)
6395 __negative_sign_ = L"()";
6396 else
6398 mb = mbstate_t();
6399 bb = lc->negative_sign;
6400 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6401 if (j == size_t(-1))
6402 __throw_runtime_error("locale not supported");
6403 wbe = wbuf + j;
6404 __negative_sign_.assign(wbuf, wbe);
6406 // Assume the positive and negative formats will want spaces in
6407 // the same places in curr_symbol since there's no way to
6408 // represent anything else.
6409 string_type __dummy_curr_symbol = __curr_symbol_;
6410 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6411 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6412 __init_pat(__neg_format_, __curr_symbol_, false,
6413 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6416 template<>
6417 void
6418 moneypunct_byname<wchar_t, true>::init(const char* nm)
6420 typedef moneypunct<wchar_t, true> base;
6421 __libcpp_unique_locale loc(nm);
6422 if (!loc)
6423 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6425 lconv* lc = __libcpp_localeconv_l(loc.get());
6426 if (!checked_string_to_wchar_convert(__decimal_point_,
6427 lc->mon_decimal_point,
6428 loc.get()))
6429 __decimal_point_ = base::do_decimal_point();
6430 if (!checked_string_to_wchar_convert(__thousands_sep_,
6431 lc->mon_thousands_sep,
6432 loc.get()))
6433 __thousands_sep_ = base::do_thousands_sep();
6434 __grouping_ = lc->mon_grouping;
6435 wchar_t wbuf[100];
6436 mbstate_t mb = {0};
6437 const char* bb = lc->int_curr_symbol;
6438 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6439 if (j == size_t(-1))
6440 __throw_runtime_error("locale not supported");
6441 wchar_t* wbe = wbuf + j;
6442 __curr_symbol_.assign(wbuf, wbe);
6443 if (lc->int_frac_digits != CHAR_MAX)
6444 __frac_digits_ = lc->int_frac_digits;
6445 else
6446 __frac_digits_ = base::do_frac_digits();
6447 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6448 if (lc->p_sign_posn == 0)
6449 #else // _LIBCPP_MSVCRT
6450 if (lc->int_p_sign_posn == 0)
6451 #endif // !_LIBCPP_MSVCRT
6452 __positive_sign_ = L"()";
6453 else
6455 mb = mbstate_t();
6456 bb = lc->positive_sign;
6457 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6458 if (j == size_t(-1))
6459 __throw_runtime_error("locale not supported");
6460 wbe = wbuf + j;
6461 __positive_sign_.assign(wbuf, wbe);
6463 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6464 if (lc->n_sign_posn == 0)
6465 #else // _LIBCPP_MSVCRT
6466 if (lc->int_n_sign_posn == 0)
6467 #endif // !_LIBCPP_MSVCRT
6468 __negative_sign_ = L"()";
6469 else
6471 mb = mbstate_t();
6472 bb = lc->negative_sign;
6473 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6474 if (j == size_t(-1))
6475 __throw_runtime_error("locale not supported");
6476 wbe = wbuf + j;
6477 __negative_sign_.assign(wbuf, wbe);
6479 // Assume the positive and negative formats will want spaces in
6480 // the same places in curr_symbol since there's no way to
6481 // represent anything else.
6482 string_type __dummy_curr_symbol = __curr_symbol_;
6483 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6484 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6485 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6486 __init_pat(__neg_format_, __curr_symbol_, true,
6487 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6488 #else // _LIBCPP_MSVCRT
6489 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6490 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6491 lc->int_p_sign_posn, L' ');
6492 __init_pat(__neg_format_, __curr_symbol_, true,
6493 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6494 lc->int_n_sign_posn, L' ');
6495 #endif // !_LIBCPP_MSVCRT
6497 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
6499 void __do_nothing(void*) {}
6501 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6502 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
6504 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6505 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
6507 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6508 _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
6510 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6511 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
6513 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6514 _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
6516 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6517 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
6519 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6520 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
6522 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6523 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
6525 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6526 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
6528 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6529 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6530 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6531 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
6533 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6534 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6535 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6536 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
6538 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6539 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
6541 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6542 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
6544 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6545 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
6547 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6548 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
6550 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6551 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
6553 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6554 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
6556 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6557 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;)
6558 template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6559 template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
6560 #ifndef _LIBCPP_HAS_NO_CHAR8_T
6561 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6562 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6563 #endif
6565 _LIBCPP_END_NAMESPACE_STD
6567 _LIBCPP_POP_MACROS