Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / src / locale.cpp
blob317b4dec7d241e5e53366f263ef216658c915e48
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/unreachable.h>
10 #include <algorithm>
11 #include <clocale>
12 #include <codecvt>
13 #include <cstdio>
14 #include <cstdlib>
15 #include <cstring>
16 #include <locale>
17 #include <string>
18 #include <type_traits>
19 #include <typeinfo>
20 #include <vector>
22 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
23 # include <cwctype>
24 #endif
26 #if defined(_AIX)
27 # include <sys/localedef.h> // for __lc_ctype_ptr
28 #endif
30 #if defined(_LIBCPP_MSVCRT)
31 # define _CTYPE_DISABLE_MACROS
32 #endif
34 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
35 # include "__support/win32/locale_win32.h"
36 #elif !defined(__BIONIC__) && !defined(__NuttX__)
37 # include <langinfo.h>
38 #endif
40 #include "include/atomic_support.h"
41 #include "include/sso_allocator.h"
43 // On Linux, wint_t and wchar_t have different signed-ness, and this causes
44 // lots of noise in the build log, but no bugs that I know of.
45 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion")
47 _LIBCPP_PUSH_MACROS
48 #include <__undef_macros>
50 _LIBCPP_BEGIN_NAMESPACE_STD
52 struct __libcpp_unique_locale {
53 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
55 ~__libcpp_unique_locale() {
56 if (__loc_)
57 freelocale(__loc_);
60 explicit operator bool() const { return __loc_; }
62 locale_t& get() { return __loc_; }
64 locale_t __loc_;
65 private:
66 __libcpp_unique_locale(__libcpp_unique_locale const&);
67 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
70 #ifdef __cloc_defined
71 locale_t __cloc() {
72 // In theory this could create a race condition. In practice
73 // the race condition is non-fatal since it will just create
74 // a little resource leak. Better approach would be appreciated.
75 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
76 return result;
78 #endif // __cloc_defined
80 namespace {
82 struct release
84 void operator()(locale::facet* p) {p->__release_shared();}
87 template <class T, class ...Args>
88 T& make(Args ...args)
90 static typename aligned_storage<sizeof(T)>::type buf;
91 auto *obj = ::new (&buf) T(args...);
92 return *obj;
95 template <typename T, size_t N>
96 inline
97 constexpr
98 size_t
99 countof(const T (&)[N])
101 return N;
104 template <typename T>
105 inline
106 constexpr
107 size_t
108 countof(const T * const begin, const T * const end)
110 return static_cast<size_t>(end - begin);
115 string
116 build_name(const string& other, const string& one, locale::category c) {
117 if (other == "*" || one == "*")
118 return "*";
119 if (c == locale::none || other == one)
120 return other;
122 // FIXME: Handle the more complicated cases, such as when the locale has
123 // different names for different categories.
124 return "*";
127 const locale::category locale::none;
128 const locale::category locale::collate;
129 const locale::category locale::ctype;
130 const locale::category locale::monetary;
131 const locale::category locale::numeric;
132 const locale::category locale::time;
133 const locale::category locale::messages;
134 const locale::category locale::all;
136 class _LIBCPP_HIDDEN locale::__imp
137 : public facet
139 enum {N = 30};
140 vector<facet*, __sso_allocator<facet*, N> > facets_;
141 string name_;
142 public:
143 explicit __imp(size_t refs = 0);
144 explicit __imp(const string& name, size_t refs = 0);
145 __imp(const __imp&);
146 __imp(const __imp&, const string&, locale::category c);
147 __imp(const __imp& other, const __imp& one, locale::category c);
148 __imp(const __imp&, facet* f, long id);
149 ~__imp();
151 const string& name() const {return name_;}
152 bool has_facet(long id) const
153 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
154 const locale::facet* use_facet(long id) const;
156 static const locale& make_classic();
157 static locale& make_global();
158 private:
159 void install(facet* f, long id);
160 template <class F> void install(F* f) {install(f, f->id.__get());}
161 template <class F> void install_from(const __imp& other);
164 locale::__imp::__imp(size_t refs)
165 : facet(refs),
166 facets_(N),
167 name_("C")
169 facets_.clear();
170 install(&make<_VSTD::collate<char> >(1u));
171 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
172 install(&make<_VSTD::collate<wchar_t> >(1u));
173 #endif
174 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
175 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
176 install(&make<_VSTD::ctype<wchar_t> >(1u));
177 #endif
178 install(&make<codecvt<char, char, mbstate_t> >(1u));
179 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
180 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
181 #endif
182 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
183 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
184 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
185 _LIBCPP_SUPPRESS_DEPRECATED_POP
186 #ifndef _LIBCPP_HAS_NO_CHAR8_T
187 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
188 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
189 #endif
190 install(&make<numpunct<char> >(1u));
191 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
192 install(&make<numpunct<wchar_t> >(1u));
193 #endif
194 install(&make<num_get<char> >(1u));
195 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
196 install(&make<num_get<wchar_t> >(1u));
197 #endif
198 install(&make<num_put<char> >(1u));
199 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
200 install(&make<num_put<wchar_t> >(1u));
201 #endif
202 install(&make<moneypunct<char, false> >(1u));
203 install(&make<moneypunct<char, true> >(1u));
204 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
205 install(&make<moneypunct<wchar_t, false> >(1u));
206 install(&make<moneypunct<wchar_t, true> >(1u));
207 #endif
208 install(&make<money_get<char> >(1u));
209 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
210 install(&make<money_get<wchar_t> >(1u));
211 #endif
212 install(&make<money_put<char> >(1u));
213 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
214 install(&make<money_put<wchar_t> >(1u));
215 #endif
216 install(&make<time_get<char> >(1u));
217 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
218 install(&make<time_get<wchar_t> >(1u));
219 #endif
220 install(&make<time_put<char> >(1u));
221 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
222 install(&make<time_put<wchar_t> >(1u));
223 #endif
224 install(&make<_VSTD::messages<char> >(1u));
225 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
226 install(&make<_VSTD::messages<wchar_t> >(1u));
227 #endif
230 locale::__imp::__imp(const string& name, size_t refs)
231 : facet(refs),
232 facets_(N),
233 name_(name)
235 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
238 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
239 facets_ = locale::classic().__locale_->facets_;
240 for (unsigned i = 0; i < facets_.size(); ++i)
241 if (facets_[i])
242 facets_[i]->__add_shared();
243 install(new collate_byname<char>(name_));
244 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
245 install(new collate_byname<wchar_t>(name_));
246 #endif
247 install(new ctype_byname<char>(name_));
248 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
249 install(new ctype_byname<wchar_t>(name_));
250 #endif
251 install(new codecvt_byname<char, char, mbstate_t>(name_));
252 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
253 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
254 #endif
255 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
256 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
257 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
258 _LIBCPP_SUPPRESS_DEPRECATED_POP
259 #ifndef _LIBCPP_HAS_NO_CHAR8_T
260 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
261 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
262 #endif
263 install(new numpunct_byname<char>(name_));
264 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
265 install(new numpunct_byname<wchar_t>(name_));
266 #endif
267 install(new moneypunct_byname<char, false>(name_));
268 install(new moneypunct_byname<char, true>(name_));
269 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
270 install(new moneypunct_byname<wchar_t, false>(name_));
271 install(new moneypunct_byname<wchar_t, true>(name_));
272 #endif
273 install(new time_get_byname<char>(name_));
274 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
275 install(new time_get_byname<wchar_t>(name_));
276 #endif
277 install(new time_put_byname<char>(name_));
278 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
279 install(new time_put_byname<wchar_t>(name_));
280 #endif
281 install(new messages_byname<char>(name_));
282 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
283 install(new messages_byname<wchar_t>(name_));
284 #endif
285 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
287 catch (...)
289 for (unsigned i = 0; i < facets_.size(); ++i)
290 if (facets_[i])
291 facets_[i]->__release_shared();
292 throw;
294 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
297 locale::__imp::__imp(const __imp& other)
298 : facets_(max<size_t>(N, other.facets_.size())),
299 name_(other.name_)
301 facets_ = other.facets_;
302 for (unsigned i = 0; i < facets_.size(); ++i)
303 if (facets_[i])
304 facets_[i]->__add_shared();
307 locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
308 : facets_(N), name_(build_name(other.name_, name, c))
310 facets_ = other.facets_;
311 for (unsigned i = 0; i < facets_.size(); ++i)
312 if (facets_[i])
313 facets_[i]->__add_shared();
314 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
317 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
318 if (c & locale::collate)
320 install(new collate_byname<char>(name));
321 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
322 install(new collate_byname<wchar_t>(name));
323 #endif
325 if (c & locale::ctype)
327 install(new ctype_byname<char>(name));
328 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
329 install(new ctype_byname<wchar_t>(name));
330 #endif
331 install(new codecvt_byname<char, char, mbstate_t>(name));
332 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
333 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
334 #endif
335 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
336 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
337 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
338 _LIBCPP_SUPPRESS_DEPRECATED_POP
339 #ifndef _LIBCPP_HAS_NO_CHAR8_T
340 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
341 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
342 #endif
344 if (c & locale::monetary)
346 install(new moneypunct_byname<char, false>(name));
347 install(new moneypunct_byname<char, true>(name));
348 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
349 install(new moneypunct_byname<wchar_t, false>(name));
350 install(new moneypunct_byname<wchar_t, true>(name));
351 #endif
353 if (c & locale::numeric)
355 install(new numpunct_byname<char>(name));
356 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
357 install(new numpunct_byname<wchar_t>(name));
358 #endif
360 if (c & locale::time)
362 install(new time_get_byname<char>(name));
363 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
364 install(new time_get_byname<wchar_t>(name));
365 #endif
366 install(new time_put_byname<char>(name));
367 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
368 install(new time_put_byname<wchar_t>(name));
369 #endif
371 if (c & locale::messages)
373 install(new messages_byname<char>(name));
374 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
375 install(new messages_byname<wchar_t>(name));
376 #endif
378 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
380 catch (...)
382 for (unsigned i = 0; i < facets_.size(); ++i)
383 if (facets_[i])
384 facets_[i]->__release_shared();
385 throw;
387 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
390 template<class F>
391 inline
392 void
393 locale::__imp::install_from(const locale::__imp& one)
395 long id = F::id.__get();
396 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
399 locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
400 : facets_(N), name_(build_name(other.name_, one.name_, c))
402 facets_ = other.facets_;
403 for (unsigned i = 0; i < facets_.size(); ++i)
404 if (facets_[i])
405 facets_[i]->__add_shared();
406 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
409 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
410 if (c & locale::collate)
412 install_from<_VSTD::collate<char> >(one);
413 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
414 install_from<_VSTD::collate<wchar_t> >(one);
415 #endif
417 if (c & locale::ctype)
419 install_from<_VSTD::ctype<char> >(one);
420 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
421 install_from<_VSTD::ctype<wchar_t> >(one);
422 #endif
423 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
424 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
425 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
426 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
427 _LIBCPP_SUPPRESS_DEPRECATED_POP
428 #ifndef _LIBCPP_HAS_NO_CHAR8_T
429 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
430 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
431 #endif
432 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
433 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
434 #endif
436 if (c & locale::monetary)
438 install_from<moneypunct<char, false> >(one);
439 install_from<moneypunct<char, true> >(one);
440 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
441 install_from<moneypunct<wchar_t, false> >(one);
442 install_from<moneypunct<wchar_t, true> >(one);
443 #endif
444 install_from<money_get<char> >(one);
445 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
446 install_from<money_get<wchar_t> >(one);
447 #endif
448 install_from<money_put<char> >(one);
449 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
450 install_from<money_put<wchar_t> >(one);
451 #endif
453 if (c & locale::numeric)
455 install_from<numpunct<char> >(one);
456 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
457 install_from<numpunct<wchar_t> >(one);
458 #endif
459 install_from<num_get<char> >(one);
460 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
461 install_from<num_get<wchar_t> >(one);
462 #endif
463 install_from<num_put<char> >(one);
464 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
465 install_from<num_put<wchar_t> >(one);
466 #endif
468 if (c & locale::time)
470 install_from<time_get<char> >(one);
471 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
472 install_from<time_get<wchar_t> >(one);
473 #endif
474 install_from<time_put<char> >(one);
475 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
476 install_from<time_put<wchar_t> >(one);
477 #endif
479 if (c & locale::messages)
481 install_from<_VSTD::messages<char> >(one);
482 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
483 install_from<_VSTD::messages<wchar_t> >(one);
484 #endif
486 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
488 catch (...)
490 for (unsigned i = 0; i < facets_.size(); ++i)
491 if (facets_[i])
492 facets_[i]->__release_shared();
493 throw;
495 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
498 locale::__imp::__imp(const __imp& other, facet* f, long id)
499 : facets_(max<size_t>(N, other.facets_.size()+1)),
500 name_("*")
502 f->__add_shared();
503 unique_ptr<facet, release> hold(f);
504 facets_ = other.facets_;
505 for (unsigned i = 0; i < other.facets_.size(); ++i)
506 if (facets_[i])
507 facets_[i]->__add_shared();
508 install(hold.get(), id);
511 locale::__imp::~__imp()
513 for (unsigned i = 0; i < facets_.size(); ++i)
514 if (facets_[i])
515 facets_[i]->__release_shared();
518 void
519 locale::__imp::install(facet* f, long id)
521 f->__add_shared();
522 unique_ptr<facet, release> hold(f);
523 if (static_cast<size_t>(id) >= facets_.size())
524 facets_.resize(static_cast<size_t>(id+1));
525 if (facets_[static_cast<size_t>(id)])
526 facets_[static_cast<size_t>(id)]->__release_shared();
527 facets_[static_cast<size_t>(id)] = hold.release();
530 const locale::facet*
531 locale::__imp::use_facet(long id) const
533 if (!has_facet(id))
534 __throw_bad_cast();
535 return facets_[static_cast<size_t>(id)];
538 // locale
540 const locale&
541 locale::__imp::make_classic()
543 // only one thread can get in here and it only gets in once
544 static aligned_storage<sizeof(locale)>::type buf;
545 locale* c = reinterpret_cast<locale*>(&buf);
546 c->__locale_ = &make<__imp>(1u);
547 return *c;
550 const locale&
551 locale::classic()
553 static const locale& c = __imp::make_classic();
554 return c;
557 locale&
558 locale::__imp::make_global()
560 // only one thread can get in here and it only gets in once
561 static aligned_storage<sizeof(locale)>::type buf;
562 auto *obj = ::new (&buf) locale(locale::classic());
563 return *obj;
566 locale&
567 locale::__global()
569 static locale& g = __imp::make_global();
570 return g;
573 locale::locale() noexcept
574 : __locale_(__global().__locale_)
576 __locale_->__add_shared();
579 locale::locale(const locale& l) noexcept
580 : __locale_(l.__locale_)
582 __locale_->__add_shared();
585 locale::~locale()
587 __locale_->__release_shared();
590 const locale&
591 locale::operator=(const locale& other) noexcept
593 other.__locale_->__add_shared();
594 __locale_->__release_shared();
595 __locale_ = other.__locale_;
596 return *this;
599 locale::locale(const char* name)
600 : __locale_(name ? new __imp(name)
601 : (__throw_runtime_error("locale constructed with null"), nullptr))
603 __locale_->__add_shared();
606 locale::locale(const string& name)
607 : __locale_(new __imp(name))
609 __locale_->__add_shared();
612 locale::locale(const locale& other, const char* name, category c)
613 : __locale_(name ? new __imp(*other.__locale_, name, c)
614 : (__throw_runtime_error("locale constructed with null"), nullptr))
616 __locale_->__add_shared();
619 locale::locale(const locale& other, const string& name, category c)
620 : __locale_(new __imp(*other.__locale_, name, c))
622 __locale_->__add_shared();
625 locale::locale(const locale& other, const locale& one, category c)
626 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
628 __locale_->__add_shared();
631 string
632 locale::name() const
634 return __locale_->name();
637 void
638 locale::__install_ctor(const locale& other, facet* f, long id)
640 if (f)
641 __locale_ = new __imp(*other.__locale_, f, id);
642 else
643 __locale_ = other.__locale_;
644 __locale_->__add_shared();
647 locale
648 locale::global(const locale& loc)
650 locale& g = __global();
651 locale r = g;
652 g = loc;
653 if (g.name() != "*")
654 setlocale(LC_ALL, g.name().c_str());
655 return r;
658 bool
659 locale::has_facet(id& x) const
661 return __locale_->has_facet(x.__get());
664 const locale::facet*
665 locale::use_facet(id& x) const
667 return __locale_->use_facet(x.__get());
670 bool
671 locale::operator==(const locale& y) const
673 return (__locale_ == y.__locale_)
674 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
677 // locale::facet
679 locale::facet::~facet()
683 void
684 locale::facet::__on_zero_shared() noexcept
686 delete this;
689 // locale::id
691 constinit int32_t locale::id::__next_id = 0;
693 long locale::id::__get() {
694 call_once(__flag_, [&] { __id_ = __libcpp_atomic_add(&__next_id, 1); });
695 return __id_ - 1;
698 // template <> class collate_byname<char>
700 collate_byname<char>::collate_byname(const char* n, size_t refs)
701 : collate<char>(refs),
702 __l_(newlocale(LC_ALL_MASK, n, 0))
704 if (__l_ == 0)
705 __throw_runtime_error(("collate_byname<char>::collate_byname"
706 " failed to construct for " + string(n)).c_str());
709 collate_byname<char>::collate_byname(const string& name, size_t refs)
710 : collate<char>(refs),
711 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
713 if (__l_ == 0)
714 __throw_runtime_error(("collate_byname<char>::collate_byname"
715 " failed to construct for " + name).c_str());
718 collate_byname<char>::~collate_byname()
720 freelocale(__l_);
724 collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
725 const char_type* __lo2, const char_type* __hi2) const
727 string_type lhs(__lo1, __hi1);
728 string_type rhs(__lo2, __hi2);
729 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l_);
730 if (r < 0)
731 return -1;
732 if (r > 0)
733 return 1;
734 return r;
737 collate_byname<char>::string_type
738 collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
740 const string_type in(lo, hi);
741 string_type out(strxfrm_l(0, in.c_str(), 0, __l_), char());
742 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l_);
743 return out;
746 // template <> class collate_byname<wchar_t>
748 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
749 collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
750 : collate<wchar_t>(refs),
751 __l_(newlocale(LC_ALL_MASK, n, 0))
753 if (__l_ == 0)
754 __throw_runtime_error(("collate_byname<wchar_t>::collate_byname(size_t refs)"
755 " failed to construct for " + string(n)).c_str());
758 collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
759 : collate<wchar_t>(refs),
760 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
762 if (__l_ == 0)
763 __throw_runtime_error(("collate_byname<wchar_t>::collate_byname(size_t refs)"
764 " failed to construct for " + name).c_str());
767 collate_byname<wchar_t>::~collate_byname()
769 freelocale(__l_);
773 collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
774 const char_type* __lo2, const char_type* __hi2) const
776 string_type lhs(__lo1, __hi1);
777 string_type rhs(__lo2, __hi2);
778 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l_);
779 if (r < 0)
780 return -1;
781 if (r > 0)
782 return 1;
783 return r;
786 collate_byname<wchar_t>::string_type
787 collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
789 const string_type in(lo, hi);
790 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l_), wchar_t());
791 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l_);
792 return out;
794 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
796 const ctype_base::mask ctype_base::space;
797 const ctype_base::mask ctype_base::print;
798 const ctype_base::mask ctype_base::cntrl;
799 const ctype_base::mask ctype_base::upper;
800 const ctype_base::mask ctype_base::lower;
801 const ctype_base::mask ctype_base::alpha;
802 const ctype_base::mask ctype_base::digit;
803 const ctype_base::mask ctype_base::punct;
804 const ctype_base::mask ctype_base::xdigit;
805 const ctype_base::mask ctype_base::blank;
806 const ctype_base::mask ctype_base::alnum;
807 const ctype_base::mask ctype_base::graph;
809 // template <> class ctype<wchar_t>;
811 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
812 constinit locale::id ctype<wchar_t>::id;
814 ctype<wchar_t>::~ctype()
818 bool
819 ctype<wchar_t>::do_is(mask m, char_type c) const
821 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
824 const wchar_t*
825 ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
827 for (; low != high; ++low, ++vec)
828 *vec = static_cast<mask>(isascii(*low) ?
829 ctype<char>::classic_table()[*low] : 0);
830 return low;
833 const wchar_t*
834 ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
836 for (; low != high; ++low)
837 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
838 break;
839 return low;
842 const wchar_t*
843 ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
845 for (; low != high; ++low)
846 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
847 break;
848 return low;
851 wchar_t
852 ctype<wchar_t>::do_toupper(char_type c) const
854 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
855 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
856 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
857 defined(__NetBSD__) || defined(__MVS__)
858 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
859 #else
860 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
861 #endif
864 const wchar_t*
865 ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
867 for (; low != high; ++low)
868 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
869 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
870 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
871 defined(__NetBSD__) || defined(__MVS__)
872 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
873 : *low;
874 #else
875 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
876 #endif
877 return low;
880 wchar_t
881 ctype<wchar_t>::do_tolower(char_type c) const
883 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
884 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
885 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
886 defined(__NetBSD__) || defined(__MVS__)
887 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
888 #else
889 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
890 #endif
893 const wchar_t*
894 ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
896 for (; low != high; ++low)
897 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
898 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
899 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
900 defined(__NetBSD__) || defined(__MVS__)
901 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
902 : *low;
903 #else
904 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
905 #endif
906 return low;
909 wchar_t
910 ctype<wchar_t>::do_widen(char c) const
912 return c;
915 const char*
916 ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
918 for (; low != high; ++low, ++dest)
919 *dest = *low;
920 return low;
923 char
924 ctype<wchar_t>::do_narrow(char_type c, char dfault) const
926 if (isascii(c))
927 return static_cast<char>(c);
928 return dfault;
931 const wchar_t*
932 ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
934 for (; low != high; ++low, ++dest)
935 if (isascii(*low))
936 *dest = static_cast<char>(*low);
937 else
938 *dest = dfault;
939 return low;
941 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
943 // template <> class ctype<char>;
945 constinit locale::id ctype<char>::id;
947 const size_t ctype<char>::table_size;
949 ctype<char>::ctype(const mask* tab, bool del, size_t refs)
950 : locale::facet(refs),
951 __tab_(tab),
952 __del_(del)
954 if (__tab_ == 0)
955 __tab_ = classic_table();
958 ctype<char>::~ctype()
960 if (__tab_ && __del_)
961 delete [] __tab_;
964 char
965 ctype<char>::do_toupper(char_type c) const
967 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
968 return isascii(c) ?
969 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
970 #elif defined(__NetBSD__)
971 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
972 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
973 return isascii(c) ?
974 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
975 #else
976 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
977 #endif
980 const char*
981 ctype<char>::do_toupper(char_type* low, const char_type* high) const
983 for (; low != high; ++low)
984 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
985 *low = isascii(*low) ?
986 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
987 #elif defined(__NetBSD__)
988 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
989 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
990 *low = isascii(*low) ?
991 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
992 #else
993 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
994 #endif
995 return low;
998 char
999 ctype<char>::do_tolower(char_type c) const
1001 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1002 return isascii(c) ?
1003 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
1004 #elif defined(__NetBSD__)
1005 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
1006 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1007 return isascii(c) ?
1008 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
1009 #else
1010 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
1011 #endif
1014 const char*
1015 ctype<char>::do_tolower(char_type* low, const char_type* high) const
1017 for (; low != high; ++low)
1018 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1019 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
1020 #elif defined(__NetBSD__)
1021 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
1022 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1023 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
1024 #else
1025 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
1026 #endif
1027 return low;
1030 char
1031 ctype<char>::do_widen(char c) const
1033 return c;
1036 const char*
1037 ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1039 for (; low != high; ++low, ++dest)
1040 *dest = *low;
1041 return low;
1044 char
1045 ctype<char>::do_narrow(char_type c, char dfault) const
1047 if (isascii(c))
1048 return static_cast<char>(c);
1049 return dfault;
1052 const char*
1053 ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1055 for (; low != high; ++low, ++dest)
1056 if (isascii(*low))
1057 *dest = *low;
1058 else
1059 *dest = dfault;
1060 return low;
1063 #if defined(__EMSCRIPTEN__)
1064 extern "C" const unsigned short ** __ctype_b_loc();
1065 extern "C" const int ** __ctype_tolower_loc();
1066 extern "C" const int ** __ctype_toupper_loc();
1067 #endif
1069 #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
1070 const ctype<char>::mask*
1071 ctype<char>::classic_table() noexcept
1073 static constexpr const ctype<char>::mask builtin_table[table_size] = {
1074 cntrl, cntrl,
1075 cntrl, cntrl,
1076 cntrl, cntrl,
1077 cntrl, cntrl,
1078 cntrl, cntrl | space | blank,
1079 cntrl | space, cntrl | space,
1080 cntrl | space, cntrl | space,
1081 cntrl, cntrl,
1082 cntrl, cntrl,
1083 cntrl, cntrl,
1084 cntrl, cntrl,
1085 cntrl, cntrl,
1086 cntrl, cntrl,
1087 cntrl, cntrl,
1088 cntrl, cntrl,
1089 cntrl, cntrl,
1090 space | blank | print, punct | print,
1091 punct | print, punct | print,
1092 punct | print, punct | print,
1093 punct | print, punct | print,
1094 punct | print, punct | print,
1095 punct | print, punct | print,
1096 punct | print, punct | print,
1097 punct | print, punct | print,
1098 digit | print | xdigit, digit | print | xdigit,
1099 digit | print | xdigit, digit | print | xdigit,
1100 digit | print | xdigit, digit | print | xdigit,
1101 digit | print | xdigit, digit | print | xdigit,
1102 digit | print | xdigit, digit | print | xdigit,
1103 punct | print, punct | print,
1104 punct | print, punct | print,
1105 punct | print, punct | print,
1106 punct | print, upper | xdigit | print | alpha,
1107 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1108 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1109 upper | xdigit | print | alpha, upper | print | alpha,
1110 upper | print | alpha, upper | print | alpha,
1111 upper | print | alpha, upper | print | alpha,
1112 upper | print | alpha, upper | print | alpha,
1113 upper | print | alpha, upper | print | alpha,
1114 upper | print | alpha, upper | print | alpha,
1115 upper | print | alpha, upper | print | alpha,
1116 upper | print | alpha, upper | print | alpha,
1117 upper | print | alpha, upper | print | alpha,
1118 upper | print | alpha, upper | print | alpha,
1119 upper | print | alpha, punct | print,
1120 punct | print, punct | print,
1121 punct | print, punct | print,
1122 punct | print, lower | xdigit | print | alpha,
1123 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1124 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1125 lower | xdigit | print | alpha, lower | print | alpha,
1126 lower | print | alpha, lower | print | alpha,
1127 lower | print | alpha, lower | print | alpha,
1128 lower | print | alpha, lower | print | alpha,
1129 lower | print | alpha, lower | print | alpha,
1130 lower | print | alpha, lower | print | alpha,
1131 lower | print | alpha, lower | print | alpha,
1132 lower | print | alpha, lower | print | alpha,
1133 lower | print | alpha, lower | print | alpha,
1134 lower | print | alpha, lower | print | alpha,
1135 lower | print | alpha, punct | print,
1136 punct | print, punct | print,
1137 punct | print, cntrl,
1138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1147 return builtin_table;
1149 #else
1150 const ctype<char>::mask*
1151 ctype<char>::classic_table() noexcept
1153 #if defined(__APPLE__) || defined(__FreeBSD__)
1154 return _DefaultRuneLocale.__runetype;
1155 #elif defined(__NetBSD__)
1156 return _C_ctype_tab_ + 1;
1157 #elif defined(__GLIBC__)
1158 return _LIBCPP_GET_C_LOCALE->__ctype_b;
1159 #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
1160 return __pctype_func();
1161 #elif defined(__EMSCRIPTEN__)
1162 return *__ctype_b_loc();
1163 #elif defined(_NEWLIB_VERSION)
1164 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1165 return _ctype_ + 1;
1166 #elif defined(_AIX)
1167 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
1168 #elif defined(__MVS__)
1169 # if defined(__NATIVE_ASCII_F)
1170 return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1171 # else
1172 return const_cast<const ctype<char>::mask*> (__ctypec);
1173 # endif
1174 #else
1175 // Platform not supported: abort so the person doing the port knows what to
1176 // fix
1177 # warning ctype<char>::classic_table() is not implemented
1178 printf("ctype<char>::classic_table() is not implemented\n");
1179 abort();
1180 return NULL;
1181 #endif
1183 #endif
1185 #if defined(__GLIBC__)
1186 const int*
1187 ctype<char>::__classic_lower_table() noexcept
1189 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
1192 const int*
1193 ctype<char>::__classic_upper_table() noexcept
1195 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
1197 #elif defined(__NetBSD__)
1198 const short*
1199 ctype<char>::__classic_lower_table() noexcept
1201 return _C_tolower_tab_ + 1;
1204 const short*
1205 ctype<char>::__classic_upper_table() noexcept
1207 return _C_toupper_tab_ + 1;
1210 #elif defined(__EMSCRIPTEN__)
1211 const int*
1212 ctype<char>::__classic_lower_table() noexcept
1214 return *__ctype_tolower_loc();
1217 const int*
1218 ctype<char>::__classic_upper_table() noexcept
1220 return *__ctype_toupper_loc();
1222 #elif defined(__MVS__)
1223 const unsigned short*
1224 ctype<char>::__classic_lower_table() _NOEXCEPT
1226 # if defined(__NATIVE_ASCII_F)
1227 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1228 # else
1229 return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1230 # endif
1232 const unsigned short *
1233 ctype<char>::__classic_upper_table() _NOEXCEPT
1235 # if defined(__NATIVE_ASCII_F)
1236 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1237 # else
1238 return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1239 # endif
1241 #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
1243 // template <> class ctype_byname<char>
1245 ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1246 : ctype<char>(0, false, refs),
1247 __l_(newlocale(LC_ALL_MASK, name, 0))
1249 if (__l_ == 0)
1250 __throw_runtime_error(("ctype_byname<char>::ctype_byname"
1251 " failed to construct for " + string(name)).c_str());
1254 ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1255 : ctype<char>(0, false, refs),
1256 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1258 if (__l_ == 0)
1259 __throw_runtime_error(("ctype_byname<char>::ctype_byname"
1260 " failed to construct for " + name).c_str());
1263 ctype_byname<char>::~ctype_byname()
1265 freelocale(__l_);
1268 char
1269 ctype_byname<char>::do_toupper(char_type c) const
1271 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l_));
1274 const char*
1275 ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1277 for (; low != high; ++low)
1278 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l_));
1279 return low;
1282 char
1283 ctype_byname<char>::do_tolower(char_type c) const
1285 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l_));
1288 const char*
1289 ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1291 for (; low != high; ++low)
1292 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l_));
1293 return low;
1296 // template <> class ctype_byname<wchar_t>
1298 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1299 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1300 : ctype<wchar_t>(refs),
1301 __l_(newlocale(LC_ALL_MASK, name, 0))
1303 if (__l_ == 0)
1304 __throw_runtime_error(("ctype_byname<wchar_t>::ctype_byname"
1305 " failed to construct for " + string(name)).c_str());
1308 ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1309 : ctype<wchar_t>(refs),
1310 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1312 if (__l_ == 0)
1313 __throw_runtime_error(("ctype_byname<wchar_t>::ctype_byname"
1314 " failed to construct for " + name).c_str());
1317 ctype_byname<wchar_t>::~ctype_byname()
1319 freelocale(__l_);
1322 bool
1323 ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1325 #ifdef _LIBCPP_WCTYPE_IS_MASK
1326 return static_cast<bool>(iswctype_l(c, m, __l_));
1327 #else
1328 bool result = false;
1329 wint_t ch = static_cast<wint_t>(c);
1330 if ((m & space) == space) result |= (iswspace_l(ch, __l_) != 0);
1331 if ((m & print) == print) result |= (iswprint_l(ch, __l_) != 0);
1332 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l_) != 0);
1333 if ((m & upper) == upper) result |= (iswupper_l(ch, __l_) != 0);
1334 if ((m & lower) == lower) result |= (iswlower_l(ch, __l_) != 0);
1335 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l_) != 0);
1336 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l_) != 0);
1337 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l_) != 0);
1338 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l_) != 0);
1339 if ((m & blank) == blank) result |= (iswblank_l(ch, __l_) != 0);
1340 return result;
1341 #endif
1344 const wchar_t*
1345 ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1347 for (; low != high; ++low, ++vec)
1349 if (isascii(*low))
1350 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
1351 else
1353 *vec = 0;
1354 wint_t ch = static_cast<wint_t>(*low);
1355 if (iswspace_l(ch, __l_))
1356 *vec |= space;
1357 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
1358 if (iswprint_l(ch, __l_))
1359 *vec |= print;
1360 #endif
1361 if (iswcntrl_l(ch, __l_))
1362 *vec |= cntrl;
1363 if (iswupper_l(ch, __l_))
1364 *vec |= upper;
1365 if (iswlower_l(ch, __l_))
1366 *vec |= lower;
1367 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
1368 if (iswalpha_l(ch, __l_))
1369 *vec |= alpha;
1370 #endif
1371 if (iswdigit_l(ch, __l_))
1372 *vec |= digit;
1373 if (iswpunct_l(ch, __l_))
1374 *vec |= punct;
1375 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
1376 if (iswxdigit_l(ch, __l_))
1377 *vec |= xdigit;
1378 #endif
1379 if (iswblank_l(ch, __l_))
1380 *vec |= blank;
1383 return low;
1386 const wchar_t*
1387 ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1389 for (; low != high; ++low)
1391 #ifdef _LIBCPP_WCTYPE_IS_MASK
1392 if (iswctype_l(*low, m, __l_))
1393 break;
1394 #else
1395 wint_t ch = static_cast<wint_t>(*low);
1396 if ((m & space) == space && iswspace_l(ch, __l_)) break;
1397 if ((m & print) == print && iswprint_l(ch, __l_)) break;
1398 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) break;
1399 if ((m & upper) == upper && iswupper_l(ch, __l_)) break;
1400 if ((m & lower) == lower && iswlower_l(ch, __l_)) break;
1401 if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) break;
1402 if ((m & digit) == digit && iswdigit_l(ch, __l_)) break;
1403 if ((m & punct) == punct && iswpunct_l(ch, __l_)) break;
1404 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) break;
1405 if ((m & blank) == blank && iswblank_l(ch, __l_)) break;
1406 #endif
1408 return low;
1411 const wchar_t*
1412 ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1414 for (; low != high; ++low)
1416 #ifdef _LIBCPP_WCTYPE_IS_MASK
1417 if (!iswctype_l(*low, m, __l_))
1418 break;
1419 #else
1420 wint_t ch = static_cast<wint_t>(*low);
1421 if ((m & space) == space && iswspace_l(ch, __l_)) continue;
1422 if ((m & print) == print && iswprint_l(ch, __l_)) continue;
1423 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) continue;
1424 if ((m & upper) == upper && iswupper_l(ch, __l_)) continue;
1425 if ((m & lower) == lower && iswlower_l(ch, __l_)) continue;
1426 if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) continue;
1427 if ((m & digit) == digit && iswdigit_l(ch, __l_)) continue;
1428 if ((m & punct) == punct && iswpunct_l(ch, __l_)) continue;
1429 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) continue;
1430 if ((m & blank) == blank && iswblank_l(ch, __l_)) continue;
1431 break;
1432 #endif
1434 return low;
1437 wchar_t
1438 ctype_byname<wchar_t>::do_toupper(char_type c) const
1440 return towupper_l(c, __l_);
1443 const wchar_t*
1444 ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1446 for (; low != high; ++low)
1447 *low = towupper_l(*low, __l_);
1448 return low;
1451 wchar_t
1452 ctype_byname<wchar_t>::do_tolower(char_type c) const
1454 return towlower_l(c, __l_);
1457 const wchar_t*
1458 ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1460 for (; low != high; ++low)
1461 *low = towlower_l(*low, __l_);
1462 return low;
1465 wchar_t
1466 ctype_byname<wchar_t>::do_widen(char c) const
1468 return __libcpp_btowc_l(c, __l_);
1471 const char*
1472 ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1474 for (; low != high; ++low, ++dest)
1475 *dest = __libcpp_btowc_l(*low, __l_);
1476 return low;
1479 char
1480 ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1482 int r = __libcpp_wctob_l(c, __l_);
1483 return (r != EOF) ? static_cast<char>(r) : dfault;
1486 const wchar_t*
1487 ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1489 for (; low != high; ++low, ++dest)
1491 int r = __libcpp_wctob_l(*low, __l_);
1492 *dest = (r != EOF) ? static_cast<char>(r) : dfault;
1494 return low;
1496 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1498 // template <> class codecvt<char, char, mbstate_t>
1500 constinit locale::id codecvt<char, char, mbstate_t>::id;
1502 codecvt<char, char, mbstate_t>::~codecvt()
1506 codecvt<char, char, mbstate_t>::result
1507 codecvt<char, char, mbstate_t>::do_out(state_type&,
1508 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
1509 extern_type* to, extern_type*, extern_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_in(state_type&,
1518 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
1519 intern_type* to, intern_type*, intern_type*& to_nxt) const
1521 frm_nxt = frm;
1522 to_nxt = to;
1523 return noconv;
1526 codecvt<char, char, mbstate_t>::result
1527 codecvt<char, char, mbstate_t>::do_unshift(state_type&,
1528 extern_type* to, extern_type*, extern_type*& to_nxt) const
1530 to_nxt = to;
1531 return noconv;
1535 codecvt<char, char, mbstate_t>::do_encoding() const noexcept
1537 return 1;
1540 bool
1541 codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
1543 return true;
1547 codecvt<char, char, mbstate_t>::do_length(state_type&,
1548 const extern_type* frm, const extern_type* end, size_t mx) const
1550 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
1554 codecvt<char, char, mbstate_t>::do_max_length() const noexcept
1556 return 1;
1559 // template <> class codecvt<wchar_t, char, mbstate_t>
1561 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1562 constinit locale::id codecvt<wchar_t, char, mbstate_t>::id;
1564 codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1565 : locale::facet(refs),
1566 __l_(_LIBCPP_GET_C_LOCALE)
1570 codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1571 : locale::facet(refs),
1572 __l_(newlocale(LC_ALL_MASK, nm, 0))
1574 if (__l_ == 0)
1575 __throw_runtime_error(("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1576 " failed to construct for " + string(nm)).c_str());
1579 codecvt<wchar_t, char, mbstate_t>::~codecvt()
1581 if (__l_ != _LIBCPP_GET_C_LOCALE)
1582 freelocale(__l_);
1585 codecvt<wchar_t, char, mbstate_t>::result
1586 codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
1587 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1588 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1590 // look for first internal null in frm
1591 const intern_type* fend = frm;
1592 for (; fend != frm_end; ++fend)
1593 if (*fend == 0)
1594 break;
1595 // loop over all null-terminated sequences in frm
1596 to_nxt = to;
1597 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1599 // save state in case it is needed to recover to_nxt on error
1600 mbstate_t save_state = st;
1601 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1602 static_cast<size_t>(to_end-to), &st, __l_);
1603 if (n == size_t(-1))
1605 // need to recover to_nxt
1606 for (to_nxt = to; frm != frm_nxt; ++frm)
1608 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l_);
1609 if (n == size_t(-1))
1610 break;
1611 to_nxt += n;
1613 frm_nxt = frm;
1614 return error;
1616 if (n == 0)
1617 return partial;
1618 to_nxt += n;
1619 if (to_nxt == to_end)
1620 break;
1621 if (fend != frm_end) // set up next null terminated sequence
1623 // Try to write the terminating null
1624 extern_type tmp[MB_LEN_MAX];
1625 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
1626 if (n == size_t(-1)) // on error
1627 return error;
1628 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
1629 return partial;
1630 for (extern_type* p = tmp; n; --n) // write it
1631 *to_nxt++ = *p++;
1632 ++frm_nxt;
1633 // look for next null in frm
1634 for (fend = frm_nxt; fend != frm_end; ++fend)
1635 if (*fend == 0)
1636 break;
1639 return frm_nxt == frm_end ? ok : partial;
1642 codecvt<wchar_t, char, mbstate_t>::result
1643 codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
1644 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1645 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1647 // look for first internal null in frm
1648 const extern_type* fend = frm;
1649 for (; fend != frm_end; ++fend)
1650 if (*fend == 0)
1651 break;
1652 // loop over all null-terminated sequences in frm
1653 to_nxt = to;
1654 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1656 // save state in case it is needed to recover to_nxt on error
1657 mbstate_t save_state = st;
1658 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1659 static_cast<size_t>(to_end-to), &st, __l_);
1660 if (n == size_t(-1))
1662 // need to recover to_nxt
1663 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1665 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1666 &save_state, __l_);
1667 switch (n)
1669 case 0:
1670 ++frm;
1671 break;
1672 case size_t(-1):
1673 frm_nxt = frm;
1674 return error;
1675 case size_t(-2):
1676 frm_nxt = frm;
1677 return partial;
1678 default:
1679 frm += n;
1680 break;
1683 frm_nxt = frm;
1684 return frm_nxt == frm_end ? ok : partial;
1686 if (n == size_t(-1))
1687 return error;
1688 to_nxt += n;
1689 if (to_nxt == to_end)
1690 break;
1691 if (fend != frm_end) // set up next null terminated sequence
1693 // Try to write the terminating null
1694 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l_);
1695 if (n != 0) // on error
1696 return error;
1697 ++to_nxt;
1698 ++frm_nxt;
1699 // look for next null in frm
1700 for (fend = frm_nxt; fend != frm_end; ++fend)
1701 if (*fend == 0)
1702 break;
1705 return frm_nxt == frm_end ? ok : partial;
1708 codecvt<wchar_t, char, mbstate_t>::result
1709 codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1710 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1712 to_nxt = to;
1713 extern_type tmp[MB_LEN_MAX];
1714 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
1715 if (n == size_t(-1) || n == 0) // on error
1716 return error;
1717 --n;
1718 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
1719 return partial;
1720 for (extern_type* p = tmp; n; --n) // write it
1721 *to_nxt++ = *p++;
1722 return ok;
1726 codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
1728 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l_) != 0)
1729 return -1;
1731 // stateless encoding
1732 if (__l_ == 0 || __libcpp_mb_cur_max_l(__l_) == 1) // there are no known constant length encodings
1733 return 1; // which take more than 1 char to form a wchar_t
1734 return 0;
1737 bool
1738 codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
1740 return false;
1744 codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1745 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1747 int nbytes = 0;
1748 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1750 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l_);
1751 switch (n)
1753 case 0:
1754 ++nbytes;
1755 ++frm;
1756 break;
1757 case size_t(-1):
1758 case size_t(-2):
1759 return nbytes;
1760 default:
1761 nbytes += n;
1762 frm += n;
1763 break;
1766 return nbytes;
1770 codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
1772 return __l_ == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l_));
1774 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1776 // Valid UTF ranges
1777 // UTF-32 UTF-16 UTF-8 # of code points
1778 // first second first second third fourth
1779 // 000000 - 00007F 0000 - 007F 00 - 7F 127
1780 // 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1781 // 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1782 // 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1783 // 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1784 // 00D800 - 00DFFF invalid
1785 // 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1786 // 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1787 // 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1788 // 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1790 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
1791 static
1792 codecvt_base::result
1793 utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1794 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1795 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1797 frm_nxt = frm;
1798 to_nxt = to;
1799 if (mode & generate_header)
1801 if (to_end-to_nxt < 3)
1802 return codecvt_base::partial;
1803 *to_nxt++ = static_cast<uint8_t>(0xEF);
1804 *to_nxt++ = static_cast<uint8_t>(0xBB);
1805 *to_nxt++ = static_cast<uint8_t>(0xBF);
1807 for (; frm_nxt < frm_end; ++frm_nxt)
1809 uint16_t wc1 = *frm_nxt;
1810 if (wc1 > Maxcode)
1811 return codecvt_base::error;
1812 if (wc1 < 0x0080)
1814 if (to_end-to_nxt < 1)
1815 return codecvt_base::partial;
1816 *to_nxt++ = static_cast<uint8_t>(wc1);
1818 else if (wc1 < 0x0800)
1820 if (to_end-to_nxt < 2)
1821 return codecvt_base::partial;
1822 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1823 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1825 else if (wc1 < 0xD800)
1827 if (to_end-to_nxt < 3)
1828 return codecvt_base::partial;
1829 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1830 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1831 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1833 else if (wc1 < 0xDC00)
1835 if (frm_end-frm_nxt < 2)
1836 return codecvt_base::partial;
1837 uint16_t wc2 = frm_nxt[1];
1838 if ((wc2 & 0xFC00) != 0xDC00)
1839 return codecvt_base::error;
1840 if (to_end-to_nxt < 4)
1841 return codecvt_base::partial;
1842 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1843 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1844 return codecvt_base::error;
1845 ++frm_nxt;
1846 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1847 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1848 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1849 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1852 else if (wc1 < 0xE000)
1854 return codecvt_base::error;
1856 else
1858 if (to_end-to_nxt < 3)
1859 return codecvt_base::partial;
1860 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1861 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1862 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1865 return codecvt_base::ok;
1868 static
1869 codecvt_base::result
1870 utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1871 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1872 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1874 frm_nxt = frm;
1875 to_nxt = to;
1876 if (mode & generate_header)
1878 if (to_end-to_nxt < 3)
1879 return codecvt_base::partial;
1880 *to_nxt++ = static_cast<uint8_t>(0xEF);
1881 *to_nxt++ = static_cast<uint8_t>(0xBB);
1882 *to_nxt++ = static_cast<uint8_t>(0xBF);
1884 for (; frm_nxt < frm_end; ++frm_nxt)
1886 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1887 if (wc1 > Maxcode)
1888 return codecvt_base::error;
1889 if (wc1 < 0x0080)
1891 if (to_end-to_nxt < 1)
1892 return codecvt_base::partial;
1893 *to_nxt++ = static_cast<uint8_t>(wc1);
1895 else if (wc1 < 0x0800)
1897 if (to_end-to_nxt < 2)
1898 return codecvt_base::partial;
1899 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1900 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1902 else if (wc1 < 0xD800)
1904 if (to_end-to_nxt < 3)
1905 return codecvt_base::partial;
1906 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1907 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1908 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1910 else if (wc1 < 0xDC00)
1912 if (frm_end-frm_nxt < 2)
1913 return codecvt_base::partial;
1914 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1915 if ((wc2 & 0xFC00) != 0xDC00)
1916 return codecvt_base::error;
1917 if (to_end-to_nxt < 4)
1918 return codecvt_base::partial;
1919 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1920 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1921 return codecvt_base::error;
1922 ++frm_nxt;
1923 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1924 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1925 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1926 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1927 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1929 else if (wc1 < 0xE000)
1931 return codecvt_base::error;
1933 else
1935 if (to_end-to_nxt < 3)
1936 return codecvt_base::partial;
1937 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1938 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1939 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1942 return codecvt_base::ok;
1945 static
1946 codecvt_base::result
1947 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1948 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1949 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1951 frm_nxt = frm;
1952 to_nxt = to;
1953 if (mode & consume_header)
1955 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1956 frm_nxt[2] == 0xBF)
1957 frm_nxt += 3;
1959 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1961 uint8_t c1 = *frm_nxt;
1962 if (c1 > Maxcode)
1963 return codecvt_base::error;
1964 if (c1 < 0x80)
1966 *to_nxt = static_cast<uint16_t>(c1);
1967 ++frm_nxt;
1969 else if (c1 < 0xC2)
1971 return codecvt_base::error;
1973 else if (c1 < 0xE0)
1975 if (frm_end-frm_nxt < 2)
1976 return codecvt_base::partial;
1977 uint8_t c2 = frm_nxt[1];
1978 if ((c2 & 0xC0) != 0x80)
1979 return codecvt_base::error;
1980 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1981 if (t > Maxcode)
1982 return codecvt_base::error;
1983 *to_nxt = t;
1984 frm_nxt += 2;
1986 else if (c1 < 0xF0)
1988 if (frm_end-frm_nxt < 3)
1989 return codecvt_base::partial;
1990 uint8_t c2 = frm_nxt[1];
1991 uint8_t c3 = frm_nxt[2];
1992 switch (c1)
1994 case 0xE0:
1995 if ((c2 & 0xE0) != 0xA0)
1996 return codecvt_base::error;
1997 break;
1998 case 0xED:
1999 if ((c2 & 0xE0) != 0x80)
2000 return codecvt_base::error;
2001 break;
2002 default:
2003 if ((c2 & 0xC0) != 0x80)
2004 return codecvt_base::error;
2005 break;
2007 if ((c3 & 0xC0) != 0x80)
2008 return codecvt_base::error;
2009 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2010 | ((c2 & 0x3F) << 6)
2011 | (c3 & 0x3F));
2012 if (t > Maxcode)
2013 return codecvt_base::error;
2014 *to_nxt = t;
2015 frm_nxt += 3;
2017 else if (c1 < 0xF5)
2019 if (frm_end-frm_nxt < 4)
2020 return codecvt_base::partial;
2021 uint8_t c2 = frm_nxt[1];
2022 uint8_t c3 = frm_nxt[2];
2023 uint8_t c4 = frm_nxt[3];
2024 switch (c1)
2026 case 0xF0:
2027 if (!(0x90 <= c2 && c2 <= 0xBF))
2028 return codecvt_base::error;
2029 break;
2030 case 0xF4:
2031 if ((c2 & 0xF0) != 0x80)
2032 return codecvt_base::error;
2033 break;
2034 default:
2035 if ((c2 & 0xC0) != 0x80)
2036 return codecvt_base::error;
2037 break;
2039 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2040 return codecvt_base::error;
2041 if (to_end-to_nxt < 2)
2042 return codecvt_base::partial;
2043 if ((((c1 & 7UL) << 18) +
2044 ((c2 & 0x3FUL) << 12) +
2045 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2046 return codecvt_base::error;
2047 *to_nxt = static_cast<uint16_t>(
2048 0xD800
2049 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2050 | ((c2 & 0x0F) << 2)
2051 | ((c3 & 0x30) >> 4));
2052 *++to_nxt = static_cast<uint16_t>(
2053 0xDC00
2054 | ((c3 & 0x0F) << 6)
2055 | (c4 & 0x3F));
2056 frm_nxt += 4;
2058 else
2060 return codecvt_base::error;
2063 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2066 static
2067 codecvt_base::result
2068 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2069 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2070 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2072 frm_nxt = frm;
2073 to_nxt = to;
2074 if (mode & consume_header)
2076 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2077 frm_nxt[2] == 0xBF)
2078 frm_nxt += 3;
2080 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2082 uint8_t c1 = *frm_nxt;
2083 if (c1 > Maxcode)
2084 return codecvt_base::error;
2085 if (c1 < 0x80)
2087 *to_nxt = static_cast<uint32_t>(c1);
2088 ++frm_nxt;
2090 else if (c1 < 0xC2)
2092 return codecvt_base::error;
2094 else if (c1 < 0xE0)
2096 if (frm_end-frm_nxt < 2)
2097 return codecvt_base::partial;
2098 uint8_t c2 = frm_nxt[1];
2099 if ((c2 & 0xC0) != 0x80)
2100 return codecvt_base::error;
2101 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2102 if (t > Maxcode)
2103 return codecvt_base::error;
2104 *to_nxt = static_cast<uint32_t>(t);
2105 frm_nxt += 2;
2107 else if (c1 < 0xF0)
2109 if (frm_end-frm_nxt < 3)
2110 return codecvt_base::partial;
2111 uint8_t c2 = frm_nxt[1];
2112 uint8_t c3 = frm_nxt[2];
2113 switch (c1)
2115 case 0xE0:
2116 if ((c2 & 0xE0) != 0xA0)
2117 return codecvt_base::error;
2118 break;
2119 case 0xED:
2120 if ((c2 & 0xE0) != 0x80)
2121 return codecvt_base::error;
2122 break;
2123 default:
2124 if ((c2 & 0xC0) != 0x80)
2125 return codecvt_base::error;
2126 break;
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 < 4)
2141 return codecvt_base::partial;
2142 uint8_t c2 = frm_nxt[1];
2143 uint8_t c3 = frm_nxt[2];
2144 uint8_t c4 = frm_nxt[3];
2145 switch (c1)
2147 case 0xF0:
2148 if (!(0x90 <= c2 && c2 <= 0xBF))
2149 return codecvt_base::error;
2150 break;
2151 case 0xF4:
2152 if ((c2 & 0xF0) != 0x80)
2153 return codecvt_base::error;
2154 break;
2155 default:
2156 if ((c2 & 0xC0) != 0x80)
2157 return codecvt_base::error;
2158 break;
2160 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2161 return codecvt_base::error;
2162 if (to_end-to_nxt < 2)
2163 return codecvt_base::partial;
2164 if ((((c1 & 7UL) << 18) +
2165 ((c2 & 0x3FUL) << 12) +
2166 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2167 return codecvt_base::error;
2168 *to_nxt = static_cast<uint32_t>(
2169 0xD800
2170 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2171 | ((c2 & 0x0F) << 2)
2172 | ((c3 & 0x30) >> 4));
2173 *++to_nxt = static_cast<uint32_t>(
2174 0xDC00
2175 | ((c3 & 0x0F) << 6)
2176 | (c4 & 0x3F));
2177 frm_nxt += 4;
2179 else
2181 return codecvt_base::error;
2184 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2187 static
2189 utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2190 size_t mx, unsigned long Maxcode = 0x10FFFF,
2191 codecvt_mode mode = codecvt_mode(0))
2193 const uint8_t* frm_nxt = frm;
2194 if (mode & consume_header)
2196 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2197 frm_nxt[2] == 0xBF)
2198 frm_nxt += 3;
2200 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2202 uint8_t c1 = *frm_nxt;
2203 if (c1 > Maxcode)
2204 break;
2205 if (c1 < 0x80)
2207 ++frm_nxt;
2209 else if (c1 < 0xC2)
2211 break;
2213 else if (c1 < 0xE0)
2215 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2216 break;
2217 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2218 if (t > Maxcode)
2219 break;
2220 frm_nxt += 2;
2222 else if (c1 < 0xF0)
2224 if (frm_end-frm_nxt < 3)
2225 break;
2226 uint8_t c2 = frm_nxt[1];
2227 uint8_t c3 = frm_nxt[2];
2228 switch (c1)
2230 case 0xE0:
2231 if ((c2 & 0xE0) != 0xA0)
2232 return static_cast<int>(frm_nxt - frm);
2233 break;
2234 case 0xED:
2235 if ((c2 & 0xE0) != 0x80)
2236 return static_cast<int>(frm_nxt - frm);
2237 break;
2238 default:
2239 if ((c2 & 0xC0) != 0x80)
2240 return static_cast<int>(frm_nxt - frm);
2241 break;
2243 if ((c3 & 0xC0) != 0x80)
2244 break;
2245 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2246 break;
2247 frm_nxt += 3;
2249 else if (c1 < 0xF5)
2251 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2252 break;
2253 uint8_t c2 = frm_nxt[1];
2254 uint8_t c3 = frm_nxt[2];
2255 uint8_t c4 = frm_nxt[3];
2256 switch (c1)
2258 case 0xF0:
2259 if (!(0x90 <= c2 && c2 <= 0xBF))
2260 return static_cast<int>(frm_nxt - frm);
2261 break;
2262 case 0xF4:
2263 if ((c2 & 0xF0) != 0x80)
2264 return static_cast<int>(frm_nxt - frm);
2265 break;
2266 default:
2267 if ((c2 & 0xC0) != 0x80)
2268 return static_cast<int>(frm_nxt - frm);
2269 break;
2271 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2272 break;
2273 if ((((c1 & 7UL) << 18) +
2274 ((c2 & 0x3FUL) << 12) +
2275 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2276 break;
2277 ++nchar16_t;
2278 frm_nxt += 4;
2280 else
2282 break;
2285 return static_cast<int>(frm_nxt - frm);
2288 static
2289 codecvt_base::result
2290 ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2291 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2292 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2294 frm_nxt = frm;
2295 to_nxt = to;
2296 if (mode & generate_header)
2298 if (to_end-to_nxt < 3)
2299 return codecvt_base::partial;
2300 *to_nxt++ = static_cast<uint8_t>(0xEF);
2301 *to_nxt++ = static_cast<uint8_t>(0xBB);
2302 *to_nxt++ = static_cast<uint8_t>(0xBF);
2304 for (; frm_nxt < frm_end; ++frm_nxt)
2306 uint32_t wc = *frm_nxt;
2307 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2308 return codecvt_base::error;
2309 if (wc < 0x000080)
2311 if (to_end-to_nxt < 1)
2312 return codecvt_base::partial;
2313 *to_nxt++ = static_cast<uint8_t>(wc);
2315 else if (wc < 0x000800)
2317 if (to_end-to_nxt < 2)
2318 return codecvt_base::partial;
2319 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2320 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2322 else if (wc < 0x010000)
2324 if (to_end-to_nxt < 3)
2325 return codecvt_base::partial;
2326 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2327 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2328 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2330 else // if (wc < 0x110000)
2332 if (to_end-to_nxt < 4)
2333 return codecvt_base::partial;
2334 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2335 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2336 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2337 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2340 return codecvt_base::ok;
2343 static
2344 codecvt_base::result
2345 utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2346 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2347 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2349 frm_nxt = frm;
2350 to_nxt = to;
2351 if (mode & consume_header)
2353 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2354 frm_nxt[2] == 0xBF)
2355 frm_nxt += 3;
2357 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2359 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2360 if (c1 < 0x80)
2362 if (c1 > Maxcode)
2363 return codecvt_base::error;
2364 *to_nxt = static_cast<uint32_t>(c1);
2365 ++frm_nxt;
2367 else if (c1 < 0xC2)
2369 return codecvt_base::error;
2371 else if (c1 < 0xE0)
2373 if (frm_end-frm_nxt < 2)
2374 return codecvt_base::partial;
2375 uint8_t c2 = frm_nxt[1];
2376 if ((c2 & 0xC0) != 0x80)
2377 return codecvt_base::error;
2378 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2379 | (c2 & 0x3F));
2380 if (t > Maxcode)
2381 return codecvt_base::error;
2382 *to_nxt = t;
2383 frm_nxt += 2;
2385 else if (c1 < 0xF0)
2387 if (frm_end-frm_nxt < 3)
2388 return codecvt_base::partial;
2389 uint8_t c2 = frm_nxt[1];
2390 uint8_t c3 = frm_nxt[2];
2391 switch (c1)
2393 case 0xE0:
2394 if ((c2 & 0xE0) != 0xA0)
2395 return codecvt_base::error;
2396 break;
2397 case 0xED:
2398 if ((c2 & 0xE0) != 0x80)
2399 return codecvt_base::error;
2400 break;
2401 default:
2402 if ((c2 & 0xC0) != 0x80)
2403 return codecvt_base::error;
2404 break;
2406 if ((c3 & 0xC0) != 0x80)
2407 return codecvt_base::error;
2408 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2409 | ((c2 & 0x3F) << 6)
2410 | (c3 & 0x3F));
2411 if (t > Maxcode)
2412 return codecvt_base::error;
2413 *to_nxt = t;
2414 frm_nxt += 3;
2416 else if (c1 < 0xF5)
2418 if (frm_end-frm_nxt < 4)
2419 return codecvt_base::partial;
2420 uint8_t c2 = frm_nxt[1];
2421 uint8_t c3 = frm_nxt[2];
2422 uint8_t c4 = frm_nxt[3];
2423 switch (c1)
2425 case 0xF0:
2426 if (!(0x90 <= c2 && c2 <= 0xBF))
2427 return codecvt_base::error;
2428 break;
2429 case 0xF4:
2430 if ((c2 & 0xF0) != 0x80)
2431 return codecvt_base::error;
2432 break;
2433 default:
2434 if ((c2 & 0xC0) != 0x80)
2435 return codecvt_base::error;
2436 break;
2438 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2439 return codecvt_base::error;
2440 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2441 | ((c2 & 0x3F) << 12)
2442 | ((c3 & 0x3F) << 6)
2443 | (c4 & 0x3F));
2444 if (t > Maxcode)
2445 return codecvt_base::error;
2446 *to_nxt = t;
2447 frm_nxt += 4;
2449 else
2451 return codecvt_base::error;
2454 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2457 static
2459 utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2460 size_t mx, unsigned long Maxcode = 0x10FFFF,
2461 codecvt_mode mode = codecvt_mode(0))
2463 const uint8_t* frm_nxt = frm;
2464 if (mode & consume_header)
2466 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2467 frm_nxt[2] == 0xBF)
2468 frm_nxt += 3;
2470 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2472 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2473 if (c1 < 0x80)
2475 if (c1 > Maxcode)
2476 break;
2477 ++frm_nxt;
2479 else if (c1 < 0xC2)
2481 break;
2483 else if (c1 < 0xE0)
2485 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2486 break;
2487 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2488 break;
2489 frm_nxt += 2;
2491 else if (c1 < 0xF0)
2493 if (frm_end-frm_nxt < 3)
2494 break;
2495 uint8_t c2 = frm_nxt[1];
2496 uint8_t c3 = frm_nxt[2];
2497 switch (c1)
2499 case 0xE0:
2500 if ((c2 & 0xE0) != 0xA0)
2501 return static_cast<int>(frm_nxt - frm);
2502 break;
2503 case 0xED:
2504 if ((c2 & 0xE0) != 0x80)
2505 return static_cast<int>(frm_nxt - frm);
2506 break;
2507 default:
2508 if ((c2 & 0xC0) != 0x80)
2509 return static_cast<int>(frm_nxt - frm);
2510 break;
2512 if ((c3 & 0xC0) != 0x80)
2513 break;
2514 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2515 break;
2516 frm_nxt += 3;
2518 else if (c1 < 0xF5)
2520 if (frm_end-frm_nxt < 4)
2521 break;
2522 uint8_t c2 = frm_nxt[1];
2523 uint8_t c3 = frm_nxt[2];
2524 uint8_t c4 = frm_nxt[3];
2525 switch (c1)
2527 case 0xF0:
2528 if (!(0x90 <= c2 && c2 <= 0xBF))
2529 return static_cast<int>(frm_nxt - frm);
2530 break;
2531 case 0xF4:
2532 if ((c2 & 0xF0) != 0x80)
2533 return static_cast<int>(frm_nxt - frm);
2534 break;
2535 default:
2536 if ((c2 & 0xC0) != 0x80)
2537 return static_cast<int>(frm_nxt - frm);
2538 break;
2540 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2541 break;
2542 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2543 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
2544 break;
2545 frm_nxt += 4;
2547 else
2549 break;
2552 return static_cast<int>(frm_nxt - frm);
2555 static
2556 codecvt_base::result
2557 ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2558 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2559 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2561 frm_nxt = frm;
2562 to_nxt = to;
2563 if (mode & generate_header)
2565 if (to_end-to_nxt < 3)
2566 return codecvt_base::partial;
2567 *to_nxt++ = static_cast<uint8_t>(0xEF);
2568 *to_nxt++ = static_cast<uint8_t>(0xBB);
2569 *to_nxt++ = static_cast<uint8_t>(0xBF);
2571 for (; frm_nxt < frm_end; ++frm_nxt)
2573 uint16_t wc = *frm_nxt;
2574 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2575 return codecvt_base::error;
2576 if (wc < 0x0080)
2578 if (to_end-to_nxt < 1)
2579 return codecvt_base::partial;
2580 *to_nxt++ = static_cast<uint8_t>(wc);
2582 else if (wc < 0x0800)
2584 if (to_end-to_nxt < 2)
2585 return codecvt_base::partial;
2586 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2587 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2589 else // if (wc <= 0xFFFF)
2591 if (to_end-to_nxt < 3)
2592 return codecvt_base::partial;
2593 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2594 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2595 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2598 return codecvt_base::ok;
2601 static
2602 codecvt_base::result
2603 utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2604 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2605 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2607 frm_nxt = frm;
2608 to_nxt = to;
2609 if (mode & consume_header)
2611 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2612 frm_nxt[2] == 0xBF)
2613 frm_nxt += 3;
2615 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2617 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2618 if (c1 < 0x80)
2620 if (c1 > Maxcode)
2621 return codecvt_base::error;
2622 *to_nxt = static_cast<uint16_t>(c1);
2623 ++frm_nxt;
2625 else if (c1 < 0xC2)
2627 return codecvt_base::error;
2629 else if (c1 < 0xE0)
2631 if (frm_end-frm_nxt < 2)
2632 return codecvt_base::partial;
2633 uint8_t c2 = frm_nxt[1];
2634 if ((c2 & 0xC0) != 0x80)
2635 return codecvt_base::error;
2636 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2637 | (c2 & 0x3F));
2638 if (t > Maxcode)
2639 return codecvt_base::error;
2640 *to_nxt = t;
2641 frm_nxt += 2;
2643 else if (c1 < 0xF0)
2645 if (frm_end-frm_nxt < 3)
2646 return codecvt_base::partial;
2647 uint8_t c2 = frm_nxt[1];
2648 uint8_t c3 = frm_nxt[2];
2649 switch (c1)
2651 case 0xE0:
2652 if ((c2 & 0xE0) != 0xA0)
2653 return codecvt_base::error;
2654 break;
2655 case 0xED:
2656 if ((c2 & 0xE0) != 0x80)
2657 return codecvt_base::error;
2658 break;
2659 default:
2660 if ((c2 & 0xC0) != 0x80)
2661 return codecvt_base::error;
2662 break;
2664 if ((c3 & 0xC0) != 0x80)
2665 return codecvt_base::error;
2666 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2667 | ((c2 & 0x3F) << 6)
2668 | (c3 & 0x3F));
2669 if (t > Maxcode)
2670 return codecvt_base::error;
2671 *to_nxt = t;
2672 frm_nxt += 3;
2674 else
2676 return codecvt_base::error;
2679 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2682 static
2684 utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2685 size_t mx, unsigned long Maxcode = 0x10FFFF,
2686 codecvt_mode mode = codecvt_mode(0))
2688 const uint8_t* frm_nxt = frm;
2689 if (mode & consume_header)
2691 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2692 frm_nxt[2] == 0xBF)
2693 frm_nxt += 3;
2695 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2697 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2698 if (c1 < 0x80)
2700 if (c1 > Maxcode)
2701 break;
2702 ++frm_nxt;
2704 else if (c1 < 0xC2)
2706 break;
2708 else if (c1 < 0xE0)
2710 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2711 break;
2712 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2713 break;
2714 frm_nxt += 2;
2716 else if (c1 < 0xF0)
2718 if (frm_end-frm_nxt < 3)
2719 break;
2720 uint8_t c2 = frm_nxt[1];
2721 uint8_t c3 = frm_nxt[2];
2722 switch (c1)
2724 case 0xE0:
2725 if ((c2 & 0xE0) != 0xA0)
2726 return static_cast<int>(frm_nxt - frm);
2727 break;
2728 case 0xED:
2729 if ((c2 & 0xE0) != 0x80)
2730 return static_cast<int>(frm_nxt - frm);
2731 break;
2732 default:
2733 if ((c2 & 0xC0) != 0x80)
2734 return static_cast<int>(frm_nxt - frm);
2735 break;
2737 if ((c3 & 0xC0) != 0x80)
2738 break;
2739 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2740 break;
2741 frm_nxt += 3;
2743 else
2745 break;
2748 return static_cast<int>(frm_nxt - frm);
2751 static
2752 codecvt_base::result
2753 ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2754 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2755 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2757 frm_nxt = frm;
2758 to_nxt = to;
2759 if (mode & generate_header)
2761 if (to_end-to_nxt < 2)
2762 return codecvt_base::partial;
2763 *to_nxt++ = static_cast<uint8_t>(0xFE);
2764 *to_nxt++ = static_cast<uint8_t>(0xFF);
2766 for (; frm_nxt < frm_end; ++frm_nxt)
2768 uint32_t wc = *frm_nxt;
2769 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2770 return codecvt_base::error;
2771 if (wc < 0x010000)
2773 if (to_end-to_nxt < 2)
2774 return codecvt_base::partial;
2775 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2776 *to_nxt++ = static_cast<uint8_t>(wc);
2778 else
2780 if (to_end-to_nxt < 4)
2781 return codecvt_base::partial;
2782 uint16_t t = static_cast<uint16_t>(
2783 0xD800
2784 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2785 | ((wc & 0x00FC00) >> 10));
2786 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2787 *to_nxt++ = static_cast<uint8_t>(t);
2788 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2789 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2790 *to_nxt++ = static_cast<uint8_t>(t);
2793 return codecvt_base::ok;
2796 static
2797 codecvt_base::result
2798 utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2799 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2800 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2802 frm_nxt = frm;
2803 to_nxt = to;
2804 if (mode & consume_header)
2806 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2807 frm_nxt += 2;
2809 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2811 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2812 if ((c1 & 0xFC00) == 0xDC00)
2813 return codecvt_base::error;
2814 if ((c1 & 0xFC00) != 0xD800)
2816 if (c1 > Maxcode)
2817 return codecvt_base::error;
2818 *to_nxt = static_cast<uint32_t>(c1);
2819 frm_nxt += 2;
2821 else
2823 if (frm_end-frm_nxt < 4)
2824 return codecvt_base::partial;
2825 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2826 if ((c2 & 0xFC00) != 0xDC00)
2827 return codecvt_base::error;
2828 uint32_t t = static_cast<uint32_t>(
2829 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2830 | ((c1 & 0x003F) << 10)
2831 | (c2 & 0x03FF));
2832 if (t > Maxcode)
2833 return codecvt_base::error;
2834 *to_nxt = t;
2835 frm_nxt += 4;
2838 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2841 static
2843 utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2844 size_t mx, unsigned long Maxcode = 0x10FFFF,
2845 codecvt_mode mode = codecvt_mode(0))
2847 const uint8_t* frm_nxt = frm;
2848 if (mode & consume_header)
2850 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2851 frm_nxt += 2;
2853 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2855 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2856 if ((c1 & 0xFC00) == 0xDC00)
2857 break;
2858 if ((c1 & 0xFC00) != 0xD800)
2860 if (c1 > Maxcode)
2861 break;
2862 frm_nxt += 2;
2864 else
2866 if (frm_end-frm_nxt < 4)
2867 break;
2868 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2869 if ((c2 & 0xFC00) != 0xDC00)
2870 break;
2871 uint32_t t = static_cast<uint32_t>(
2872 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2873 | ((c1 & 0x003F) << 10)
2874 | (c2 & 0x03FF));
2875 if (t > Maxcode)
2876 break;
2877 frm_nxt += 4;
2880 return static_cast<int>(frm_nxt - frm);
2883 static
2884 codecvt_base::result
2885 ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2886 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2887 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2889 frm_nxt = frm;
2890 to_nxt = to;
2891 if (mode & generate_header)
2893 if (to_end - to_nxt < 2)
2894 return codecvt_base::partial;
2895 *to_nxt++ = static_cast<uint8_t>(0xFF);
2896 *to_nxt++ = static_cast<uint8_t>(0xFE);
2898 for (; frm_nxt < frm_end; ++frm_nxt)
2900 uint32_t wc = *frm_nxt;
2901 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2902 return codecvt_base::error;
2903 if (wc < 0x010000)
2905 if (to_end-to_nxt < 2)
2906 return codecvt_base::partial;
2907 *to_nxt++ = static_cast<uint8_t>(wc);
2908 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2910 else
2912 if (to_end-to_nxt < 4)
2913 return codecvt_base::partial;
2914 uint16_t t = static_cast<uint16_t>(
2915 0xD800
2916 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2917 | ((wc & 0x00FC00) >> 10));
2918 *to_nxt++ = static_cast<uint8_t>(t);
2919 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2920 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2921 *to_nxt++ = static_cast<uint8_t>(t);
2922 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2925 return codecvt_base::ok;
2928 static
2929 codecvt_base::result
2930 utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2931 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2932 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2934 frm_nxt = frm;
2935 to_nxt = to;
2936 if (mode & consume_header)
2938 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2939 frm_nxt += 2;
2941 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2943 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2944 if ((c1 & 0xFC00) == 0xDC00)
2945 return codecvt_base::error;
2946 if ((c1 & 0xFC00) != 0xD800)
2948 if (c1 > Maxcode)
2949 return codecvt_base::error;
2950 *to_nxt = static_cast<uint32_t>(c1);
2951 frm_nxt += 2;
2953 else
2955 if (frm_end-frm_nxt < 4)
2956 return codecvt_base::partial;
2957 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2958 if ((c2 & 0xFC00) != 0xDC00)
2959 return codecvt_base::error;
2960 uint32_t t = static_cast<uint32_t>(
2961 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2962 | ((c1 & 0x003F) << 10)
2963 | (c2 & 0x03FF));
2964 if (t > Maxcode)
2965 return codecvt_base::error;
2966 *to_nxt = t;
2967 frm_nxt += 4;
2970 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2973 static
2975 utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2976 size_t mx, unsigned long Maxcode = 0x10FFFF,
2977 codecvt_mode mode = codecvt_mode(0))
2979 const uint8_t* frm_nxt = frm;
2980 if (mode & consume_header)
2982 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2983 frm_nxt += 2;
2985 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2987 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2988 if ((c1 & 0xFC00) == 0xDC00)
2989 break;
2990 if ((c1 & 0xFC00) != 0xD800)
2992 if (c1 > Maxcode)
2993 break;
2994 frm_nxt += 2;
2996 else
2998 if (frm_end-frm_nxt < 4)
2999 break;
3000 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
3001 if ((c2 & 0xFC00) != 0xDC00)
3002 break;
3003 uint32_t t = static_cast<uint32_t>(
3004 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3005 | ((c1 & 0x003F) << 10)
3006 | (c2 & 0x03FF));
3007 if (t > Maxcode)
3008 break;
3009 frm_nxt += 4;
3012 return static_cast<int>(frm_nxt - frm);
3015 static
3016 codecvt_base::result
3017 ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3018 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3019 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3021 frm_nxt = frm;
3022 to_nxt = to;
3023 if (mode & generate_header)
3025 if (to_end-to_nxt < 2)
3026 return codecvt_base::partial;
3027 *to_nxt++ = static_cast<uint8_t>(0xFE);
3028 *to_nxt++ = static_cast<uint8_t>(0xFF);
3030 for (; frm_nxt < frm_end; ++frm_nxt)
3032 uint16_t wc = *frm_nxt;
3033 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3034 return codecvt_base::error;
3035 if (to_end-to_nxt < 2)
3036 return codecvt_base::partial;
3037 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3038 *to_nxt++ = static_cast<uint8_t>(wc);
3040 return codecvt_base::ok;
3043 static
3044 codecvt_base::result
3045 utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3046 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3047 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3049 frm_nxt = frm;
3050 to_nxt = to;
3051 if (mode & consume_header)
3053 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3054 frm_nxt += 2;
3056 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3058 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3059 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3060 return codecvt_base::error;
3061 *to_nxt = c1;
3062 frm_nxt += 2;
3064 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3067 static
3069 utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3070 size_t mx, unsigned long Maxcode = 0x10FFFF,
3071 codecvt_mode mode = codecvt_mode(0))
3073 const uint8_t* frm_nxt = frm;
3074 if (mode & consume_header)
3076 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3077 frm_nxt += 2;
3079 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3081 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3082 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3083 break;
3084 frm_nxt += 2;
3086 return static_cast<int>(frm_nxt - frm);
3089 static
3090 codecvt_base::result
3091 ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3092 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3093 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3095 frm_nxt = frm;
3096 to_nxt = to;
3097 if (mode & generate_header)
3099 if (to_end-to_nxt < 2)
3100 return codecvt_base::partial;
3101 *to_nxt++ = static_cast<uint8_t>(0xFF);
3102 *to_nxt++ = static_cast<uint8_t>(0xFE);
3104 for (; frm_nxt < frm_end; ++frm_nxt)
3106 uint16_t wc = *frm_nxt;
3107 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3108 return codecvt_base::error;
3109 if (to_end-to_nxt < 2)
3110 return codecvt_base::partial;
3111 *to_nxt++ = static_cast<uint8_t>(wc);
3112 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3114 return codecvt_base::ok;
3117 static
3118 codecvt_base::result
3119 utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3120 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3121 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3123 frm_nxt = frm;
3124 to_nxt = to;
3125 if (mode & consume_header)
3127 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3128 frm_nxt += 2;
3130 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3132 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3133 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3134 return codecvt_base::error;
3135 *to_nxt = c1;
3136 frm_nxt += 2;
3138 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3141 static
3143 utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3144 size_t mx, unsigned long Maxcode = 0x10FFFF,
3145 codecvt_mode mode = codecvt_mode(0))
3147 const uint8_t* frm_nxt = frm;
3148 frm_nxt = frm;
3149 if (mode & consume_header)
3151 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3152 frm_nxt += 2;
3154 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3156 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3157 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3158 break;
3159 frm_nxt += 2;
3161 return static_cast<int>(frm_nxt - frm);
3164 _LIBCPP_SUPPRESS_DEPRECATED_POP
3166 // template <> class codecvt<char16_t, char, mbstate_t>
3168 constinit locale::id codecvt<char16_t, char, mbstate_t>::id;
3170 codecvt<char16_t, char, mbstate_t>::~codecvt()
3174 codecvt<char16_t, char, mbstate_t>::result
3175 codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
3176 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3177 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3179 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3180 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3181 const uint16_t* _frm_nxt = _frm;
3182 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3183 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3184 uint8_t* _to_nxt = _to;
3185 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3186 frm_nxt = frm + (_frm_nxt - _frm);
3187 to_nxt = to + (_to_nxt - _to);
3188 return r;
3191 codecvt<char16_t, char, mbstate_t>::result
3192 codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
3193 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3194 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3196 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3197 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3198 const uint8_t* _frm_nxt = _frm;
3199 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3200 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3201 uint16_t* _to_nxt = _to;
3202 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3203 frm_nxt = frm + (_frm_nxt - _frm);
3204 to_nxt = to + (_to_nxt - _to);
3205 return r;
3208 codecvt<char16_t, char, mbstate_t>::result
3209 codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3210 extern_type* to, extern_type*, extern_type*& to_nxt) const
3212 to_nxt = to;
3213 return noconv;
3217 codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
3219 return 0;
3222 bool
3223 codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
3225 return false;
3229 codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3230 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3232 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3233 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3234 return utf8_to_utf16_length(_frm, _frm_end, mx);
3238 codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
3240 return 4;
3243 #ifndef _LIBCPP_HAS_NO_CHAR8_T
3245 // template <> class codecvt<char16_t, char8_t, mbstate_t>
3247 constinit locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3249 codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3253 codecvt<char16_t, char8_t, mbstate_t>::result
3254 codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3255 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3256 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3258 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3259 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3260 const uint16_t* _frm_nxt = _frm;
3261 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3262 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3263 uint8_t* _to_nxt = _to;
3264 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3265 frm_nxt = frm + (_frm_nxt - _frm);
3266 to_nxt = to + (_to_nxt - _to);
3267 return r;
3270 codecvt<char16_t, char8_t, mbstate_t>::result
3271 codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3272 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3273 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3275 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3276 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3277 const uint8_t* _frm_nxt = _frm;
3278 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3279 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3280 uint16_t* _to_nxt = _to;
3281 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3282 frm_nxt = frm + (_frm_nxt - _frm);
3283 to_nxt = to + (_to_nxt - _to);
3284 return r;
3287 codecvt<char16_t, char8_t, mbstate_t>::result
3288 codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3289 extern_type* to, extern_type*, extern_type*& to_nxt) const
3291 to_nxt = to;
3292 return noconv;
3296 codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
3298 return 0;
3301 bool
3302 codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3304 return false;
3308 codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3309 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3311 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3312 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3313 return utf8_to_utf16_length(_frm, _frm_end, mx);
3317 codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
3319 return 4;
3322 #endif
3324 // template <> class codecvt<char32_t, char, mbstate_t>
3326 constinit locale::id codecvt<char32_t, char, mbstate_t>::id;
3328 codecvt<char32_t, char, mbstate_t>::~codecvt()
3332 codecvt<char32_t, char, mbstate_t>::result
3333 codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
3334 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3335 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3337 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3338 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3339 const uint32_t* _frm_nxt = _frm;
3340 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3341 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3342 uint8_t* _to_nxt = _to;
3343 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3344 frm_nxt = frm + (_frm_nxt - _frm);
3345 to_nxt = to + (_to_nxt - _to);
3346 return r;
3349 codecvt<char32_t, char, mbstate_t>::result
3350 codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
3351 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3352 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3354 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3355 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3356 const uint8_t* _frm_nxt = _frm;
3357 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3358 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3359 uint32_t* _to_nxt = _to;
3360 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3361 frm_nxt = frm + (_frm_nxt - _frm);
3362 to_nxt = to + (_to_nxt - _to);
3363 return r;
3366 codecvt<char32_t, char, mbstate_t>::result
3367 codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3368 extern_type* to, extern_type*, extern_type*& to_nxt) const
3370 to_nxt = to;
3371 return noconv;
3375 codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
3377 return 0;
3380 bool
3381 codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
3383 return false;
3387 codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3388 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3390 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3391 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3392 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3396 codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
3398 return 4;
3401 #ifndef _LIBCPP_HAS_NO_CHAR8_T
3403 // template <> class codecvt<char32_t, char8_t, mbstate_t>
3405 constinit locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3407 codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3411 codecvt<char32_t, char8_t, mbstate_t>::result
3412 codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3413 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3414 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3416 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3417 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3418 const uint32_t* _frm_nxt = _frm;
3419 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3420 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3421 uint8_t* _to_nxt = _to;
3422 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3423 frm_nxt = frm + (_frm_nxt - _frm);
3424 to_nxt = to + (_to_nxt - _to);
3425 return r;
3428 codecvt<char32_t, char8_t, mbstate_t>::result
3429 codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3430 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3431 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3433 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3434 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3435 const uint8_t* _frm_nxt = _frm;
3436 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3437 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3438 uint32_t* _to_nxt = _to;
3439 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3440 frm_nxt = frm + (_frm_nxt - _frm);
3441 to_nxt = to + (_to_nxt - _to);
3442 return r;
3445 codecvt<char32_t, char8_t, mbstate_t>::result
3446 codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3447 extern_type* to, extern_type*, extern_type*& to_nxt) const
3449 to_nxt = to;
3450 return noconv;
3454 codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
3456 return 0;
3459 bool
3460 codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3462 return false;
3466 codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3467 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3469 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3470 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3471 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3475 codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
3477 return 4;
3480 #endif
3482 // __codecvt_utf8<wchar_t>
3484 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3485 __codecvt_utf8<wchar_t>::result
3486 __codecvt_utf8<wchar_t>::do_out(state_type&,
3487 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3488 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3490 #if defined(_LIBCPP_SHORT_WCHAR)
3491 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3492 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3493 const uint16_t* _frm_nxt = _frm;
3494 #else
3495 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3496 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3497 const uint32_t* _frm_nxt = _frm;
3498 #endif
3499 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3500 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3501 uint8_t* _to_nxt = _to;
3502 #if defined(_LIBCPP_SHORT_WCHAR)
3503 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3504 __maxcode_, __mode_);
3505 #else
3506 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3507 __maxcode_, __mode_);
3508 #endif
3509 frm_nxt = frm + (_frm_nxt - _frm);
3510 to_nxt = to + (_to_nxt - _to);
3511 return r;
3514 __codecvt_utf8<wchar_t>::result
3515 __codecvt_utf8<wchar_t>::do_in(state_type&,
3516 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3517 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3519 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3520 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3521 const uint8_t* _frm_nxt = _frm;
3522 #if defined(_LIBCPP_SHORT_WCHAR)
3523 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3524 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3525 uint16_t* _to_nxt = _to;
3526 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3527 __maxcode_, __mode_);
3528 #else
3529 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3530 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3531 uint32_t* _to_nxt = _to;
3532 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3533 __maxcode_, __mode_);
3534 #endif
3535 frm_nxt = frm + (_frm_nxt - _frm);
3536 to_nxt = to + (_to_nxt - _to);
3537 return r;
3540 __codecvt_utf8<wchar_t>::result
3541 __codecvt_utf8<wchar_t>::do_unshift(state_type&,
3542 extern_type* to, extern_type*, extern_type*& to_nxt) const
3544 to_nxt = to;
3545 return noconv;
3549 __codecvt_utf8<wchar_t>::do_encoding() const noexcept
3551 return 0;
3554 bool
3555 __codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
3557 return false;
3561 __codecvt_utf8<wchar_t>::do_length(state_type&,
3562 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3564 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3565 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3566 #if defined(_LIBCPP_SHORT_WCHAR)
3567 return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3568 #else
3569 return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3570 #endif
3573 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3575 __codecvt_utf8<wchar_t>::do_max_length() const noexcept
3577 #if defined(_LIBCPP_SHORT_WCHAR)
3578 if (__mode_ & consume_header)
3579 return 6;
3580 return 3;
3581 #else
3582 if (__mode_ & consume_header)
3583 return 7;
3584 return 4;
3585 #endif
3587 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3589 // __codecvt_utf8<char16_t>
3591 __codecvt_utf8<char16_t>::result
3592 __codecvt_utf8<char16_t>::do_out(state_type&,
3593 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3594 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3596 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3597 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3598 const uint16_t* _frm_nxt = _frm;
3599 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3600 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3601 uint8_t* _to_nxt = _to;
3602 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3603 __maxcode_, __mode_);
3604 frm_nxt = frm + (_frm_nxt - _frm);
3605 to_nxt = to + (_to_nxt - _to);
3606 return r;
3609 __codecvt_utf8<char16_t>::result
3610 __codecvt_utf8<char16_t>::do_in(state_type&,
3611 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3612 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3614 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3615 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3616 const uint8_t* _frm_nxt = _frm;
3617 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3618 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3619 uint16_t* _to_nxt = _to;
3620 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3621 __maxcode_, __mode_);
3622 frm_nxt = frm + (_frm_nxt - _frm);
3623 to_nxt = to + (_to_nxt - _to);
3624 return r;
3627 __codecvt_utf8<char16_t>::result
3628 __codecvt_utf8<char16_t>::do_unshift(state_type&,
3629 extern_type* to, extern_type*, extern_type*& to_nxt) const
3631 to_nxt = to;
3632 return noconv;
3636 __codecvt_utf8<char16_t>::do_encoding() const noexcept
3638 return 0;
3641 bool
3642 __codecvt_utf8<char16_t>::do_always_noconv() const noexcept
3644 return false;
3648 __codecvt_utf8<char16_t>::do_length(state_type&,
3649 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3651 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3652 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3653 return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3656 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3658 __codecvt_utf8<char16_t>::do_max_length() const noexcept
3660 if (__mode_ & consume_header)
3661 return 6;
3662 return 3;
3664 _LIBCPP_SUPPRESS_DEPRECATED_POP
3666 // __codecvt_utf8<char32_t>
3668 __codecvt_utf8<char32_t>::result
3669 __codecvt_utf8<char32_t>::do_out(state_type&,
3670 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3671 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3673 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3674 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3675 const uint32_t* _frm_nxt = _frm;
3676 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3677 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3678 uint8_t* _to_nxt = _to;
3679 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3680 __maxcode_, __mode_);
3681 frm_nxt = frm + (_frm_nxt - _frm);
3682 to_nxt = to + (_to_nxt - _to);
3683 return r;
3686 __codecvt_utf8<char32_t>::result
3687 __codecvt_utf8<char32_t>::do_in(state_type&,
3688 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3689 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3691 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3692 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3693 const uint8_t* _frm_nxt = _frm;
3694 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3695 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3696 uint32_t* _to_nxt = _to;
3697 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3698 __maxcode_, __mode_);
3699 frm_nxt = frm + (_frm_nxt - _frm);
3700 to_nxt = to + (_to_nxt - _to);
3701 return r;
3704 __codecvt_utf8<char32_t>::result
3705 __codecvt_utf8<char32_t>::do_unshift(state_type&,
3706 extern_type* to, extern_type*, extern_type*& to_nxt) const
3708 to_nxt = to;
3709 return noconv;
3713 __codecvt_utf8<char32_t>::do_encoding() const noexcept
3715 return 0;
3718 bool
3719 __codecvt_utf8<char32_t>::do_always_noconv() const noexcept
3721 return false;
3725 __codecvt_utf8<char32_t>::do_length(state_type&,
3726 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3728 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3729 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3730 return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3733 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3735 __codecvt_utf8<char32_t>::do_max_length() const noexcept
3737 if (__mode_ & consume_header)
3738 return 7;
3739 return 4;
3741 _LIBCPP_SUPPRESS_DEPRECATED_POP
3743 // __codecvt_utf16<wchar_t, false>
3745 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3746 __codecvt_utf16<wchar_t, false>::result
3747 __codecvt_utf16<wchar_t, false>::do_out(state_type&,
3748 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3749 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3751 #if defined(_LIBCPP_SHORT_WCHAR)
3752 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3753 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3754 const uint16_t* _frm_nxt = _frm;
3755 #else
3756 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3757 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3758 const uint32_t* _frm_nxt = _frm;
3759 #endif
3760 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3761 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3762 uint8_t* _to_nxt = _to;
3763 #if defined(_LIBCPP_SHORT_WCHAR)
3764 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3765 __maxcode_, __mode_);
3766 #else
3767 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3768 __maxcode_, __mode_);
3769 #endif
3770 frm_nxt = frm + (_frm_nxt - _frm);
3771 to_nxt = to + (_to_nxt - _to);
3772 return r;
3775 __codecvt_utf16<wchar_t, false>::result
3776 __codecvt_utf16<wchar_t, false>::do_in(state_type&,
3777 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3778 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3780 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3781 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3782 const uint8_t* _frm_nxt = _frm;
3783 #if defined(_LIBCPP_SHORT_WCHAR)
3784 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3785 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3786 uint16_t* _to_nxt = _to;
3787 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3788 __maxcode_, __mode_);
3789 #else
3790 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3791 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3792 uint32_t* _to_nxt = _to;
3793 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3794 __maxcode_, __mode_);
3795 #endif
3796 frm_nxt = frm + (_frm_nxt - _frm);
3797 to_nxt = to + (_to_nxt - _to);
3798 return r;
3801 __codecvt_utf16<wchar_t, false>::result
3802 __codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3803 extern_type* to, extern_type*, extern_type*& to_nxt) const
3805 to_nxt = to;
3806 return noconv;
3810 __codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
3812 return 0;
3815 bool
3816 __codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
3818 return false;
3822 __codecvt_utf16<wchar_t, false>::do_length(state_type&,
3823 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3825 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3826 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3827 #if defined(_LIBCPP_SHORT_WCHAR)
3828 return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3829 #else
3830 return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3831 #endif
3835 __codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
3837 #if defined(_LIBCPP_SHORT_WCHAR)
3838 if (__mode_ & consume_header)
3839 return 4;
3840 return 2;
3841 #else
3842 if (__mode_ & consume_header)
3843 return 6;
3844 return 4;
3845 #endif
3848 // __codecvt_utf16<wchar_t, true>
3850 __codecvt_utf16<wchar_t, true>::result
3851 __codecvt_utf16<wchar_t, true>::do_out(state_type&,
3852 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3853 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3855 #if defined(_LIBCPP_SHORT_WCHAR)
3856 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3857 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3858 const uint16_t* _frm_nxt = _frm;
3859 #else
3860 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3861 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3862 const uint32_t* _frm_nxt = _frm;
3863 #endif
3864 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3865 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3866 uint8_t* _to_nxt = _to;
3867 #if defined(_LIBCPP_SHORT_WCHAR)
3868 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3869 __maxcode_, __mode_);
3870 #else
3871 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3872 __maxcode_, __mode_);
3873 #endif
3874 frm_nxt = frm + (_frm_nxt - _frm);
3875 to_nxt = to + (_to_nxt - _to);
3876 return r;
3879 __codecvt_utf16<wchar_t, true>::result
3880 __codecvt_utf16<wchar_t, true>::do_in(state_type&,
3881 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3882 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3884 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3885 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3886 const uint8_t* _frm_nxt = _frm;
3887 #if defined(_LIBCPP_SHORT_WCHAR)
3888 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3889 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3890 uint16_t* _to_nxt = _to;
3891 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3892 __maxcode_, __mode_);
3893 #else
3894 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3895 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3896 uint32_t* _to_nxt = _to;
3897 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3898 __maxcode_, __mode_);
3899 #endif
3900 frm_nxt = frm + (_frm_nxt - _frm);
3901 to_nxt = to + (_to_nxt - _to);
3902 return r;
3905 __codecvt_utf16<wchar_t, true>::result
3906 __codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3907 extern_type* to, extern_type*, extern_type*& to_nxt) const
3909 to_nxt = to;
3910 return noconv;
3914 __codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
3916 return 0;
3919 bool
3920 __codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
3922 return false;
3926 __codecvt_utf16<wchar_t, true>::do_length(state_type&,
3927 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3929 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3930 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3931 #if defined(_LIBCPP_SHORT_WCHAR)
3932 return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3933 #else
3934 return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3935 #endif
3939 __codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
3941 #if defined(_LIBCPP_SHORT_WCHAR)
3942 if (__mode_ & consume_header)
3943 return 4;
3944 return 2;
3945 #else
3946 if (__mode_ & consume_header)
3947 return 6;
3948 return 4;
3949 #endif
3951 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3953 // __codecvt_utf16<char16_t, false>
3955 __codecvt_utf16<char16_t, false>::result
3956 __codecvt_utf16<char16_t, false>::do_out(state_type&,
3957 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3958 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3960 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3961 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3962 const uint16_t* _frm_nxt = _frm;
3963 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3964 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3965 uint8_t* _to_nxt = _to;
3966 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3967 __maxcode_, __mode_);
3968 frm_nxt = frm + (_frm_nxt - _frm);
3969 to_nxt = to + (_to_nxt - _to);
3970 return r;
3973 __codecvt_utf16<char16_t, false>::result
3974 __codecvt_utf16<char16_t, false>::do_in(state_type&,
3975 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3976 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3978 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3979 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3980 const uint8_t* _frm_nxt = _frm;
3981 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3982 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3983 uint16_t* _to_nxt = _to;
3984 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3985 __maxcode_, __mode_);
3986 frm_nxt = frm + (_frm_nxt - _frm);
3987 to_nxt = to + (_to_nxt - _to);
3988 return r;
3991 __codecvt_utf16<char16_t, false>::result
3992 __codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3993 extern_type* to, extern_type*, extern_type*& to_nxt) const
3995 to_nxt = to;
3996 return noconv;
4000 __codecvt_utf16<char16_t, false>::do_encoding() const noexcept
4002 return 0;
4005 bool
4006 __codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
4008 return false;
4012 __codecvt_utf16<char16_t, false>::do_length(state_type&,
4013 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4015 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4016 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4017 return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4020 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4022 __codecvt_utf16<char16_t, false>::do_max_length() const noexcept
4024 if (__mode_ & consume_header)
4025 return 4;
4026 return 2;
4028 _LIBCPP_SUPPRESS_DEPRECATED_POP
4030 // __codecvt_utf16<char16_t, true>
4032 __codecvt_utf16<char16_t, true>::result
4033 __codecvt_utf16<char16_t, true>::do_out(state_type&,
4034 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4035 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4037 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4038 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4039 const uint16_t* _frm_nxt = _frm;
4040 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4041 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4042 uint8_t* _to_nxt = _to;
4043 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4044 __maxcode_, __mode_);
4045 frm_nxt = frm + (_frm_nxt - _frm);
4046 to_nxt = to + (_to_nxt - _to);
4047 return r;
4050 __codecvt_utf16<char16_t, true>::result
4051 __codecvt_utf16<char16_t, true>::do_in(state_type&,
4052 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4053 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4055 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4056 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4057 const uint8_t* _frm_nxt = _frm;
4058 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4059 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4060 uint16_t* _to_nxt = _to;
4061 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4062 __maxcode_, __mode_);
4063 frm_nxt = frm + (_frm_nxt - _frm);
4064 to_nxt = to + (_to_nxt - _to);
4065 return r;
4068 __codecvt_utf16<char16_t, true>::result
4069 __codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4070 extern_type* to, extern_type*, extern_type*& to_nxt) const
4072 to_nxt = to;
4073 return noconv;
4077 __codecvt_utf16<char16_t, true>::do_encoding() const noexcept
4079 return 0;
4082 bool
4083 __codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
4085 return false;
4089 __codecvt_utf16<char16_t, true>::do_length(state_type&,
4090 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4092 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4093 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4094 return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4097 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4099 __codecvt_utf16<char16_t, true>::do_max_length() const noexcept
4101 if (__mode_ & consume_header)
4102 return 4;
4103 return 2;
4105 _LIBCPP_SUPPRESS_DEPRECATED_POP
4107 // __codecvt_utf16<char32_t, false>
4109 __codecvt_utf16<char32_t, false>::result
4110 __codecvt_utf16<char32_t, false>::do_out(state_type&,
4111 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4112 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4114 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4115 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4116 const uint32_t* _frm_nxt = _frm;
4117 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4118 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4119 uint8_t* _to_nxt = _to;
4120 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4121 __maxcode_, __mode_);
4122 frm_nxt = frm + (_frm_nxt - _frm);
4123 to_nxt = to + (_to_nxt - _to);
4124 return r;
4127 __codecvt_utf16<char32_t, false>::result
4128 __codecvt_utf16<char32_t, false>::do_in(state_type&,
4129 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4130 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4132 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4133 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4134 const uint8_t* _frm_nxt = _frm;
4135 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4136 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4137 uint32_t* _to_nxt = _to;
4138 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4139 __maxcode_, __mode_);
4140 frm_nxt = frm + (_frm_nxt - _frm);
4141 to_nxt = to + (_to_nxt - _to);
4142 return r;
4145 __codecvt_utf16<char32_t, false>::result
4146 __codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4147 extern_type* to, extern_type*, extern_type*& to_nxt) const
4149 to_nxt = to;
4150 return noconv;
4154 __codecvt_utf16<char32_t, false>::do_encoding() const noexcept
4156 return 0;
4159 bool
4160 __codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
4162 return false;
4166 __codecvt_utf16<char32_t, false>::do_length(state_type&,
4167 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4169 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4170 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4171 return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4174 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4176 __codecvt_utf16<char32_t, false>::do_max_length() const noexcept
4178 if (__mode_ & consume_header)
4179 return 6;
4180 return 4;
4182 _LIBCPP_SUPPRESS_DEPRECATED_POP
4184 // __codecvt_utf16<char32_t, true>
4186 __codecvt_utf16<char32_t, true>::result
4187 __codecvt_utf16<char32_t, true>::do_out(state_type&,
4188 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4189 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4191 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4192 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4193 const uint32_t* _frm_nxt = _frm;
4194 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4195 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4196 uint8_t* _to_nxt = _to;
4197 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4198 __maxcode_, __mode_);
4199 frm_nxt = frm + (_frm_nxt - _frm);
4200 to_nxt = to + (_to_nxt - _to);
4201 return r;
4204 __codecvt_utf16<char32_t, true>::result
4205 __codecvt_utf16<char32_t, true>::do_in(state_type&,
4206 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4207 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4209 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4210 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4211 const uint8_t* _frm_nxt = _frm;
4212 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4213 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4214 uint32_t* _to_nxt = _to;
4215 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4216 __maxcode_, __mode_);
4217 frm_nxt = frm + (_frm_nxt - _frm);
4218 to_nxt = to + (_to_nxt - _to);
4219 return r;
4222 __codecvt_utf16<char32_t, true>::result
4223 __codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4224 extern_type* to, extern_type*, extern_type*& to_nxt) const
4226 to_nxt = to;
4227 return noconv;
4231 __codecvt_utf16<char32_t, true>::do_encoding() const noexcept
4233 return 0;
4236 bool
4237 __codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
4239 return false;
4243 __codecvt_utf16<char32_t, true>::do_length(state_type&,
4244 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4246 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4247 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4248 return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4251 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4253 __codecvt_utf16<char32_t, true>::do_max_length() const noexcept
4255 if (__mode_ & consume_header)
4256 return 6;
4257 return 4;
4259 _LIBCPP_SUPPRESS_DEPRECATED_POP
4261 // __codecvt_utf8_utf16<wchar_t>
4263 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4264 __codecvt_utf8_utf16<wchar_t>::result
4265 __codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4266 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4267 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4269 #if defined(_LIBCPP_SHORT_WCHAR)
4270 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4271 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4272 const uint16_t* _frm_nxt = _frm;
4273 #else
4274 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4275 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4276 const uint32_t* _frm_nxt = _frm;
4277 #endif
4278 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4279 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4280 uint8_t* _to_nxt = _to;
4281 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4282 __maxcode_, __mode_);
4283 frm_nxt = frm + (_frm_nxt - _frm);
4284 to_nxt = to + (_to_nxt - _to);
4285 return r;
4288 __codecvt_utf8_utf16<wchar_t>::result
4289 __codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4290 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4291 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4293 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4294 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4295 const uint8_t* _frm_nxt = _frm;
4296 #if defined(_LIBCPP_SHORT_WCHAR)
4297 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4298 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4299 uint16_t* _to_nxt = _to;
4300 #else
4301 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4302 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4303 uint32_t* _to_nxt = _to;
4304 #endif
4305 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4306 __maxcode_, __mode_);
4307 frm_nxt = frm + (_frm_nxt - _frm);
4308 to_nxt = to + (_to_nxt - _to);
4309 return r;
4312 __codecvt_utf8_utf16<wchar_t>::result
4313 __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4314 extern_type* to, extern_type*, extern_type*& to_nxt) const
4316 to_nxt = to;
4317 return noconv;
4321 __codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
4323 return 0;
4326 bool
4327 __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
4329 return false;
4333 __codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4334 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4336 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4337 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4338 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4342 __codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
4344 if (__mode_ & consume_header)
4345 return 7;
4346 return 4;
4348 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4350 // __codecvt_utf8_utf16<char16_t>
4352 __codecvt_utf8_utf16<char16_t>::result
4353 __codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4354 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4355 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4357 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4358 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4359 const uint16_t* _frm_nxt = _frm;
4360 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4361 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4362 uint8_t* _to_nxt = _to;
4363 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4364 __maxcode_, __mode_);
4365 frm_nxt = frm + (_frm_nxt - _frm);
4366 to_nxt = to + (_to_nxt - _to);
4367 return r;
4370 __codecvt_utf8_utf16<char16_t>::result
4371 __codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4372 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4373 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4375 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4376 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4377 const uint8_t* _frm_nxt = _frm;
4378 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4379 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4380 uint16_t* _to_nxt = _to;
4381 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4382 __maxcode_, __mode_);
4383 frm_nxt = frm + (_frm_nxt - _frm);
4384 to_nxt = to + (_to_nxt - _to);
4385 return r;
4388 __codecvt_utf8_utf16<char16_t>::result
4389 __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4390 extern_type* to, extern_type*, extern_type*& to_nxt) const
4392 to_nxt = to;
4393 return noconv;
4397 __codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
4399 return 0;
4402 bool
4403 __codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
4405 return false;
4409 __codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4410 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4412 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4413 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4414 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4417 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4419 __codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
4421 if (__mode_ & consume_header)
4422 return 7;
4423 return 4;
4425 _LIBCPP_SUPPRESS_DEPRECATED_POP
4427 // __codecvt_utf8_utf16<char32_t>
4429 __codecvt_utf8_utf16<char32_t>::result
4430 __codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4431 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4432 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4434 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4435 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4436 const uint32_t* _frm_nxt = _frm;
4437 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4438 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4439 uint8_t* _to_nxt = _to;
4440 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4441 __maxcode_, __mode_);
4442 frm_nxt = frm + (_frm_nxt - _frm);
4443 to_nxt = to + (_to_nxt - _to);
4444 return r;
4447 __codecvt_utf8_utf16<char32_t>::result
4448 __codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4449 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4450 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4452 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4453 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4454 const uint8_t* _frm_nxt = _frm;
4455 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4456 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4457 uint32_t* _to_nxt = _to;
4458 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4459 __maxcode_, __mode_);
4460 frm_nxt = frm + (_frm_nxt - _frm);
4461 to_nxt = to + (_to_nxt - _to);
4462 return r;
4465 __codecvt_utf8_utf16<char32_t>::result
4466 __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4467 extern_type* to, extern_type*, extern_type*& to_nxt) const
4469 to_nxt = to;
4470 return noconv;
4474 __codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
4476 return 0;
4479 bool
4480 __codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
4482 return false;
4486 __codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4487 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4489 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4490 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4491 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4494 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4496 __codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
4498 if (__mode_ & consume_header)
4499 return 7;
4500 return 4;
4502 _LIBCPP_SUPPRESS_DEPRECATED_POP
4504 // __narrow_to_utf8<16>
4506 __narrow_to_utf8<16>::~__narrow_to_utf8()
4510 // __narrow_to_utf8<32>
4512 __narrow_to_utf8<32>::~__narrow_to_utf8()
4516 // __widen_from_utf8<16>
4518 __widen_from_utf8<16>::~__widen_from_utf8()
4522 // __widen_from_utf8<32>
4524 __widen_from_utf8<32>::~__widen_from_utf8()
4528 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4529 static bool checked_string_to_wchar_convert(wchar_t& dest,
4530 const char* ptr,
4531 locale_t loc) {
4532 if (*ptr == '\0')
4533 return false;
4534 mbstate_t mb = {};
4535 wchar_t out;
4536 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4537 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4538 return false;
4540 dest = out;
4541 return true;
4543 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4545 #ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4546 static bool is_narrow_non_breaking_space(const char* ptr) {
4547 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4548 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4551 static bool is_non_breaking_space(const char* ptr) {
4552 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4553 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4555 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4557 static bool checked_string_to_char_convert(char& dest,
4558 const char* ptr,
4559 locale_t __loc) {
4560 if (*ptr == '\0')
4561 return false;
4562 if (!ptr[1]) {
4563 dest = *ptr;
4564 return true;
4567 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4568 // First convert the MBS into a wide char then attempt to narrow it using
4569 // wctob_l.
4570 wchar_t wout;
4571 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4572 return false;
4573 int res;
4574 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4575 dest = res;
4576 return true;
4578 // FIXME: Work around specific multibyte sequences that we can reasonably
4579 // translate into a different single byte.
4580 switch (wout) {
4581 case L'\u202F': // narrow non-breaking space
4582 case L'\u00A0': // non-breaking space
4583 dest = ' ';
4584 return true;
4585 default:
4586 return false;
4588 #else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4589 // FIXME: Work around specific multibyte sequences that we can reasonably
4590 // translate into a different single byte.
4591 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4592 dest = ' ';
4593 return true;
4596 return false;
4597 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4598 __libcpp_unreachable();
4602 // numpunct<char> && numpunct<wchar_t>
4604 constinit locale::id numpunct<char>::id;
4605 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4606 constinit locale::id numpunct<wchar_t>::id;
4607 #endif
4609 numpunct<char>::numpunct(size_t refs)
4610 : locale::facet(refs),
4611 __decimal_point_('.'),
4612 __thousands_sep_(',')
4616 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4617 numpunct<wchar_t>::numpunct(size_t refs)
4618 : locale::facet(refs),
4619 __decimal_point_(L'.'),
4620 __thousands_sep_(L',')
4623 #endif
4625 numpunct<char>::~numpunct()
4629 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4630 numpunct<wchar_t>::~numpunct()
4633 #endif
4635 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4636 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4637 wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4638 #endif
4640 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4641 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4642 wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4643 #endif
4645 string numpunct< char >::do_grouping() const {return __grouping_;}
4646 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4647 string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4648 #endif
4650 string numpunct< char >::do_truename() const {return "true";}
4651 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4652 wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4653 #endif
4655 string numpunct< char >::do_falsename() const {return "false";}
4656 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4657 wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4658 #endif
4660 // numpunct_byname<char>
4662 numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4663 : numpunct<char>(refs)
4665 __init(nm);
4668 numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4669 : numpunct<char>(refs)
4671 __init(nm.c_str());
4674 numpunct_byname<char>::~numpunct_byname()
4678 void
4679 numpunct_byname<char>::__init(const char* nm)
4681 typedef numpunct<char> base;
4682 if (strcmp(nm, "C") != 0)
4684 __libcpp_unique_locale loc(nm);
4685 if (!loc)
4686 __throw_runtime_error(("numpunct_byname<char>::numpunct_byname"
4687 " failed to construct for " + string(nm)).c_str());
4689 lconv* lc = __libcpp_localeconv_l(loc.get());
4690 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4691 loc.get()))
4692 __decimal_point_ = base::do_decimal_point();
4693 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4694 loc.get()))
4695 __thousands_sep_ = base::do_thousands_sep();
4696 __grouping_ = lc->grouping;
4697 // localization for truename and falsename is not available
4701 // numpunct_byname<wchar_t>
4703 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4704 numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4705 : numpunct<wchar_t>(refs)
4707 __init(nm);
4710 numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4711 : numpunct<wchar_t>(refs)
4713 __init(nm.c_str());
4716 numpunct_byname<wchar_t>::~numpunct_byname()
4720 void
4721 numpunct_byname<wchar_t>::__init(const char* nm)
4723 if (strcmp(nm, "C") != 0)
4725 __libcpp_unique_locale loc(nm);
4726 if (!loc)
4727 __throw_runtime_error(("numpunct_byname<wchar_t>::numpunct_byname"
4728 " failed to construct for " + string(nm)).c_str());
4730 lconv* lc = __libcpp_localeconv_l(loc.get());
4731 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4732 loc.get());
4733 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4734 loc.get());
4735 __grouping_ = lc->grouping;
4736 // localization for truename and falsename is not available
4739 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4741 // num_get helpers
4744 __num_get_base::__get_base(ios_base& iob)
4746 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4747 if (__basefield == ios_base::oct)
4748 return 8;
4749 else if (__basefield == ios_base::hex)
4750 return 16;
4751 else if (__basefield == 0)
4752 return 0;
4753 return 10;
4756 const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4758 void
4759 __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4760 ios_base::iostate& __err)
4762 // if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4763 // we always have at least a single entry in [__g, __g_end); the end of the input sequence
4764 if (__grouping.size() != 0 && __g_end - __g > 1)
4766 reverse(__g, __g_end);
4767 const char* __ig = __grouping.data();
4768 const char* __eg = __ig + __grouping.size();
4769 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4771 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4773 if (static_cast<unsigned>(*__ig) != *__r)
4775 __err = ios_base::failbit;
4776 return;
4779 if (__eg - __ig > 1)
4780 ++__ig;
4782 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4784 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
4785 __err = ios_base::failbit;
4790 void
4791 __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4792 ios_base::fmtflags __flags)
4794 if ((__flags & ios_base::showpos) &&
4795 (__flags & ios_base::basefield) != ios_base::oct &&
4796 (__flags & ios_base::basefield) != ios_base::hex &&
4797 __signd)
4798 *__fmtp++ = '+';
4799 if (__flags & ios_base::showbase)
4800 *__fmtp++ = '#';
4801 while(*__len)
4802 *__fmtp++ = *__len++;
4803 if ((__flags & ios_base::basefield) == ios_base::oct)
4804 *__fmtp = 'o';
4805 else if ((__flags & ios_base::basefield) == ios_base::hex)
4807 if (__flags & ios_base::uppercase)
4808 *__fmtp = 'X';
4809 else
4810 *__fmtp = 'x';
4812 else if (__signd)
4813 *__fmtp = 'd';
4814 else
4815 *__fmtp = 'u';
4818 bool
4819 __num_put_base::__format_float(char* __fmtp, const char* __len,
4820 ios_base::fmtflags __flags)
4822 bool specify_precision = true;
4823 if (__flags & ios_base::showpos)
4824 *__fmtp++ = '+';
4825 if (__flags & ios_base::showpoint)
4826 *__fmtp++ = '#';
4827 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4828 bool uppercase = (__flags & ios_base::uppercase) != 0;
4829 if (floatfield == (ios_base::fixed | ios_base::scientific))
4830 specify_precision = false;
4831 else
4833 *__fmtp++ = '.';
4834 *__fmtp++ = '*';
4836 while(*__len)
4837 *__fmtp++ = *__len++;
4838 if (floatfield == ios_base::fixed)
4840 if (uppercase)
4841 *__fmtp = 'F';
4842 else
4843 *__fmtp = 'f';
4845 else if (floatfield == ios_base::scientific)
4847 if (uppercase)
4848 *__fmtp = 'E';
4849 else
4850 *__fmtp = 'e';
4852 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4854 if (uppercase)
4855 *__fmtp = 'A';
4856 else
4857 *__fmtp = 'a';
4859 else
4861 if (uppercase)
4862 *__fmtp = 'G';
4863 else
4864 *__fmtp = 'g';
4866 return specify_precision;
4869 char*
4870 __num_put_base::__identify_padding(char* __nb, char* __ne,
4871 const ios_base& __iob)
4873 switch (__iob.flags() & ios_base::adjustfield)
4875 case ios_base::internal:
4876 if (__nb[0] == '-' || __nb[0] == '+')
4877 return __nb+1;
4878 if (__ne - __nb >= 2 && __nb[0] == '0'
4879 && (__nb[1] == 'x' || __nb[1] == 'X'))
4880 return __nb+2;
4881 break;
4882 case ios_base::left:
4883 return __ne;
4884 case ios_base::right:
4885 default:
4886 break;
4888 return __nb;
4891 // time_get
4893 static
4894 string*
4895 init_weeks()
4897 static string weeks[14];
4898 weeks[0] = "Sunday";
4899 weeks[1] = "Monday";
4900 weeks[2] = "Tuesday";
4901 weeks[3] = "Wednesday";
4902 weeks[4] = "Thursday";
4903 weeks[5] = "Friday";
4904 weeks[6] = "Saturday";
4905 weeks[7] = "Sun";
4906 weeks[8] = "Mon";
4907 weeks[9] = "Tue";
4908 weeks[10] = "Wed";
4909 weeks[11] = "Thu";
4910 weeks[12] = "Fri";
4911 weeks[13] = "Sat";
4912 return weeks;
4915 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4916 static
4917 wstring*
4918 init_wweeks()
4920 static wstring weeks[14];
4921 weeks[0] = L"Sunday";
4922 weeks[1] = L"Monday";
4923 weeks[2] = L"Tuesday";
4924 weeks[3] = L"Wednesday";
4925 weeks[4] = L"Thursday";
4926 weeks[5] = L"Friday";
4927 weeks[6] = L"Saturday";
4928 weeks[7] = L"Sun";
4929 weeks[8] = L"Mon";
4930 weeks[9] = L"Tue";
4931 weeks[10] = L"Wed";
4932 weeks[11] = L"Thu";
4933 weeks[12] = L"Fri";
4934 weeks[13] = L"Sat";
4935 return weeks;
4937 #endif
4939 template <>
4940 const string*
4941 __time_get_c_storage<char>::__weeks() const
4943 static const string* weeks = init_weeks();
4944 return weeks;
4947 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4948 template <>
4949 const wstring*
4950 __time_get_c_storage<wchar_t>::__weeks() const
4952 static const wstring* weeks = init_wweeks();
4953 return weeks;
4955 #endif
4957 static
4958 string*
4959 init_months()
4961 static string months[24];
4962 months[0] = "January";
4963 months[1] = "February";
4964 months[2] = "March";
4965 months[3] = "April";
4966 months[4] = "May";
4967 months[5] = "June";
4968 months[6] = "July";
4969 months[7] = "August";
4970 months[8] = "September";
4971 months[9] = "October";
4972 months[10] = "November";
4973 months[11] = "December";
4974 months[12] = "Jan";
4975 months[13] = "Feb";
4976 months[14] = "Mar";
4977 months[15] = "Apr";
4978 months[16] = "May";
4979 months[17] = "Jun";
4980 months[18] = "Jul";
4981 months[19] = "Aug";
4982 months[20] = "Sep";
4983 months[21] = "Oct";
4984 months[22] = "Nov";
4985 months[23] = "Dec";
4986 return months;
4989 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4990 static
4991 wstring*
4992 init_wmonths()
4994 static wstring months[24];
4995 months[0] = L"January";
4996 months[1] = L"February";
4997 months[2] = L"March";
4998 months[3] = L"April";
4999 months[4] = L"May";
5000 months[5] = L"June";
5001 months[6] = L"July";
5002 months[7] = L"August";
5003 months[8] = L"September";
5004 months[9] = L"October";
5005 months[10] = L"November";
5006 months[11] = L"December";
5007 months[12] = L"Jan";
5008 months[13] = L"Feb";
5009 months[14] = L"Mar";
5010 months[15] = L"Apr";
5011 months[16] = L"May";
5012 months[17] = L"Jun";
5013 months[18] = L"Jul";
5014 months[19] = L"Aug";
5015 months[20] = L"Sep";
5016 months[21] = L"Oct";
5017 months[22] = L"Nov";
5018 months[23] = L"Dec";
5019 return months;
5021 #endif
5023 template <>
5024 const string*
5025 __time_get_c_storage<char>::__months() const
5027 static const string* months = init_months();
5028 return months;
5031 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5032 template <>
5033 const wstring*
5034 __time_get_c_storage<wchar_t>::__months() const
5036 static const wstring* months = init_wmonths();
5037 return months;
5039 #endif
5041 static
5042 string*
5043 init_am_pm()
5045 static string am_pm[2];
5046 am_pm[0] = "AM";
5047 am_pm[1] = "PM";
5048 return am_pm;
5051 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5052 static
5053 wstring*
5054 init_wam_pm()
5056 static wstring am_pm[2];
5057 am_pm[0] = L"AM";
5058 am_pm[1] = L"PM";
5059 return am_pm;
5061 #endif
5063 template <>
5064 const string*
5065 __time_get_c_storage<char>::__am_pm() const
5067 static const string* am_pm = init_am_pm();
5068 return am_pm;
5071 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5072 template <>
5073 const wstring*
5074 __time_get_c_storage<wchar_t>::__am_pm() const
5076 static const wstring* am_pm = init_wam_pm();
5077 return am_pm;
5079 #endif
5081 template <>
5082 const string&
5083 __time_get_c_storage<char>::__x() const
5085 static string s("%m/%d/%y");
5086 return s;
5089 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5090 template <>
5091 const wstring&
5092 __time_get_c_storage<wchar_t>::__x() const
5094 static wstring s(L"%m/%d/%y");
5095 return s;
5097 #endif
5099 template <>
5100 const string&
5101 __time_get_c_storage<char>::__X() const
5103 static string s("%H:%M:%S");
5104 return s;
5107 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5108 template <>
5109 const wstring&
5110 __time_get_c_storage<wchar_t>::__X() const
5112 static wstring s(L"%H:%M:%S");
5113 return s;
5115 #endif
5117 template <>
5118 const string&
5119 __time_get_c_storage<char>::__c() const
5121 static string s("%a %b %d %H:%M:%S %Y");
5122 return s;
5125 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5126 template <>
5127 const wstring&
5128 __time_get_c_storage<wchar_t>::__c() const
5130 static wstring s(L"%a %b %d %H:%M:%S %Y");
5131 return s;
5133 #endif
5135 template <>
5136 const string&
5137 __time_get_c_storage<char>::__r() const
5139 static string s("%I:%M:%S %p");
5140 return s;
5143 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5144 template <>
5145 const wstring&
5146 __time_get_c_storage<wchar_t>::__r() const
5148 static wstring s(L"%I:%M:%S %p");
5149 return s;
5151 #endif
5153 // time_get_byname
5155 __time_get::__time_get(const char* nm)
5156 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5158 if (__loc_ == 0)
5159 __throw_runtime_error(("time_get_byname failed to construct for " + string(nm)).c_str());
5162 __time_get::__time_get(const string& nm)
5163 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5165 if (__loc_ == 0)
5166 __throw_runtime_error(("time_get_byname failed to construct for " + nm).c_str());
5169 __time_get::~__time_get()
5171 freelocale(__loc_);
5174 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
5176 template <>
5177 string
5178 __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5180 tm t = {0};
5181 t.tm_sec = 59;
5182 t.tm_min = 55;
5183 t.tm_hour = 23;
5184 t.tm_mday = 31;
5185 t.tm_mon = 11;
5186 t.tm_year = 161;
5187 t.tm_wday = 6;
5188 t.tm_yday = 364;
5189 t.tm_isdst = -1;
5190 char buf[100];
5191 char f[3] = {0};
5192 f[0] = '%';
5193 f[1] = fmt;
5194 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
5195 char* bb = buf;
5196 char* be = buf + n;
5197 string result;
5198 while (bb != be)
5200 if (ct.is(ctype_base::space, *bb))
5202 result.push_back(' ');
5203 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5205 continue;
5207 char* w = bb;
5208 ios_base::iostate err = ios_base::goodbit;
5209 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
5210 ct, err, false)
5211 - this->__weeks_;
5212 if (i < 14)
5214 result.push_back('%');
5215 if (i < 7)
5216 result.push_back('A');
5217 else
5218 result.push_back('a');
5219 bb = w;
5220 continue;
5222 w = bb;
5223 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5224 ct, err, false)
5225 - this->__months_;
5226 if (i < 24)
5228 result.push_back('%');
5229 if (i < 12)
5230 result.push_back('B');
5231 else
5232 result.push_back('b');
5233 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5234 result.back() = 'm';
5235 bb = w;
5236 continue;
5238 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5240 w = bb;
5241 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5242 ct, err, false) - this->__am_pm_;
5243 if (i < 2)
5245 result.push_back('%');
5246 result.push_back('p');
5247 bb = w;
5248 continue;
5251 w = bb;
5252 if (ct.is(ctype_base::digit, *bb))
5254 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5256 case 6:
5257 result.push_back('%');
5258 result.push_back('w');
5259 break;
5260 case 7:
5261 result.push_back('%');
5262 result.push_back('u');
5263 break;
5264 case 11:
5265 result.push_back('%');
5266 result.push_back('I');
5267 break;
5268 case 12:
5269 result.push_back('%');
5270 result.push_back('m');
5271 break;
5272 case 23:
5273 result.push_back('%');
5274 result.push_back('H');
5275 break;
5276 case 31:
5277 result.push_back('%');
5278 result.push_back('d');
5279 break;
5280 case 55:
5281 result.push_back('%');
5282 result.push_back('M');
5283 break;
5284 case 59:
5285 result.push_back('%');
5286 result.push_back('S');
5287 break;
5288 case 61:
5289 result.push_back('%');
5290 result.push_back('y');
5291 break;
5292 case 364:
5293 result.push_back('%');
5294 result.push_back('j');
5295 break;
5296 case 2061:
5297 result.push_back('%');
5298 result.push_back('Y');
5299 break;
5300 default:
5301 for (; w != bb; ++w)
5302 result.push_back(*w);
5303 break;
5305 continue;
5307 if (*bb == '%')
5309 result.push_back('%');
5310 result.push_back('%');
5311 ++bb;
5312 continue;
5314 result.push_back(*bb);
5315 ++bb;
5317 return result;
5320 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces")
5322 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5323 template <>
5324 wstring
5325 __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5327 tm t = {0};
5328 t.tm_sec = 59;
5329 t.tm_min = 55;
5330 t.tm_hour = 23;
5331 t.tm_mday = 31;
5332 t.tm_mon = 11;
5333 t.tm_year = 161;
5334 t.tm_wday = 6;
5335 t.tm_yday = 364;
5336 t.tm_isdst = -1;
5337 char buf[100];
5338 char f[3] = {0};
5339 f[0] = '%';
5340 f[1] = fmt;
5341 strftime_l(buf, countof(buf), f, &t, __loc_);
5342 wchar_t wbuf[100];
5343 wchar_t* wbb = wbuf;
5344 mbstate_t mb = {0};
5345 const char* bb = buf;
5346 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
5347 if (j == size_t(-1))
5348 __throw_runtime_error("locale not supported");
5349 wchar_t* wbe = wbb + j;
5350 wstring result;
5351 while (wbb != wbe)
5353 if (ct.is(ctype_base::space, *wbb))
5355 result.push_back(L' ');
5356 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5358 continue;
5360 wchar_t* w = wbb;
5361 ios_base::iostate err = ios_base::goodbit;
5362 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
5363 ct, err, false)
5364 - this->__weeks_;
5365 if (i < 14)
5367 result.push_back(L'%');
5368 if (i < 7)
5369 result.push_back(L'A');
5370 else
5371 result.push_back(L'a');
5372 wbb = w;
5373 continue;
5375 w = wbb;
5376 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5377 ct, err, false)
5378 - this->__months_;
5379 if (i < 24)
5381 result.push_back(L'%');
5382 if (i < 12)
5383 result.push_back(L'B');
5384 else
5385 result.push_back(L'b');
5386 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5387 result.back() = L'm';
5388 wbb = w;
5389 continue;
5391 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5393 w = wbb;
5394 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5395 ct, err, false) - this->__am_pm_;
5396 if (i < 2)
5398 result.push_back(L'%');
5399 result.push_back(L'p');
5400 wbb = w;
5401 continue;
5404 w = wbb;
5405 if (ct.is(ctype_base::digit, *wbb))
5407 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5409 case 6:
5410 result.push_back(L'%');
5411 result.push_back(L'w');
5412 break;
5413 case 7:
5414 result.push_back(L'%');
5415 result.push_back(L'u');
5416 break;
5417 case 11:
5418 result.push_back(L'%');
5419 result.push_back(L'I');
5420 break;
5421 case 12:
5422 result.push_back(L'%');
5423 result.push_back(L'm');
5424 break;
5425 case 23:
5426 result.push_back(L'%');
5427 result.push_back(L'H');
5428 break;
5429 case 31:
5430 result.push_back(L'%');
5431 result.push_back(L'd');
5432 break;
5433 case 55:
5434 result.push_back(L'%');
5435 result.push_back(L'M');
5436 break;
5437 case 59:
5438 result.push_back(L'%');
5439 result.push_back(L'S');
5440 break;
5441 case 61:
5442 result.push_back(L'%');
5443 result.push_back(L'y');
5444 break;
5445 case 364:
5446 result.push_back(L'%');
5447 result.push_back(L'j');
5448 break;
5449 case 2061:
5450 result.push_back(L'%');
5451 result.push_back(L'Y');
5452 break;
5453 default:
5454 for (; w != wbb; ++w)
5455 result.push_back(*w);
5456 break;
5458 continue;
5460 if (ct.narrow(*wbb, 0) == '%')
5462 result.push_back(L'%');
5463 result.push_back(L'%');
5464 ++wbb;
5465 continue;
5467 result.push_back(*wbb);
5468 ++wbb;
5470 return result;
5472 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5474 template <>
5475 void
5476 __time_get_storage<char>::init(const ctype<char>& ct)
5478 tm t = {0};
5479 char buf[100];
5480 // __weeks_
5481 for (int i = 0; i < 7; ++i)
5483 t.tm_wday = i;
5484 strftime_l(buf, countof(buf), "%A", &t, __loc_);
5485 __weeks_[i] = buf;
5486 strftime_l(buf, countof(buf), "%a", &t, __loc_);
5487 __weeks_[i+7] = buf;
5489 // __months_
5490 for (int i = 0; i < 12; ++i)
5492 t.tm_mon = i;
5493 strftime_l(buf, countof(buf), "%B", &t, __loc_);
5494 __months_[i] = buf;
5495 strftime_l(buf, countof(buf), "%b", &t, __loc_);
5496 __months_[i+12] = buf;
5498 // __am_pm_
5499 t.tm_hour = 1;
5500 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5501 __am_pm_[0] = buf;
5502 t.tm_hour = 13;
5503 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5504 __am_pm_[1] = buf;
5505 __c_ = __analyze('c', ct);
5506 __r_ = __analyze('r', ct);
5507 __x_ = __analyze('x', ct);
5508 __X_ = __analyze('X', ct);
5511 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5512 template <>
5513 void
5514 __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5516 tm t = {0};
5517 char buf[100];
5518 wchar_t wbuf[100];
5519 wchar_t* wbe;
5520 mbstate_t mb = {0};
5521 // __weeks_
5522 for (int i = 0; i < 7; ++i)
5524 t.tm_wday = i;
5525 strftime_l(buf, countof(buf), "%A", &t, __loc_);
5526 mb = mbstate_t();
5527 const char* bb = buf;
5528 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5529 if (j == size_t(-1) || j == 0)
5530 __throw_runtime_error("locale not supported");
5531 wbe = wbuf + j;
5532 __weeks_[i].assign(wbuf, wbe);
5533 strftime_l(buf, countof(buf), "%a", &t, __loc_);
5534 mb = mbstate_t();
5535 bb = buf;
5536 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5537 if (j == size_t(-1) || j == 0)
5538 __throw_runtime_error("locale not supported");
5539 wbe = wbuf + j;
5540 __weeks_[i+7].assign(wbuf, wbe);
5542 // __months_
5543 for (int i = 0; i < 12; ++i)
5545 t.tm_mon = i;
5546 strftime_l(buf, countof(buf), "%B", &t, __loc_);
5547 mb = mbstate_t();
5548 const char* bb = buf;
5549 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5550 if (j == size_t(-1) || j == 0)
5551 __throw_runtime_error("locale not supported");
5552 wbe = wbuf + j;
5553 __months_[i].assign(wbuf, wbe);
5554 strftime_l(buf, countof(buf), "%b", &t, __loc_);
5555 mb = mbstate_t();
5556 bb = buf;
5557 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5558 if (j == size_t(-1) || j == 0)
5559 __throw_runtime_error("locale not supported");
5560 wbe = wbuf + j;
5561 __months_[i+12].assign(wbuf, wbe);
5563 // __am_pm_
5564 t.tm_hour = 1;
5565 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5566 mb = mbstate_t();
5567 const char* bb = buf;
5568 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5569 if (j == size_t(-1))
5570 __throw_runtime_error("locale not supported");
5571 wbe = wbuf + j;
5572 __am_pm_[0].assign(wbuf, wbe);
5573 t.tm_hour = 13;
5574 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5575 mb = mbstate_t();
5576 bb = buf;
5577 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5578 if (j == size_t(-1))
5579 __throw_runtime_error("locale not supported");
5580 wbe = wbuf + j;
5581 __am_pm_[1].assign(wbuf, wbe);
5582 __c_ = __analyze('c', ct);
5583 __r_ = __analyze('r', ct);
5584 __x_ = __analyze('x', ct);
5585 __X_ = __analyze('X', ct);
5587 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5589 template <class CharT>
5590 struct _LIBCPP_HIDDEN __time_get_temp
5591 : public ctype_byname<CharT>
5593 explicit __time_get_temp(const char* nm)
5594 : ctype_byname<CharT>(nm, 1) {}
5595 explicit __time_get_temp(const string& nm)
5596 : ctype_byname<CharT>(nm, 1) {}
5599 template <>
5600 __time_get_storage<char>::__time_get_storage(const char* __nm)
5601 : __time_get(__nm)
5603 const __time_get_temp<char> ct(__nm);
5604 init(ct);
5607 template <>
5608 __time_get_storage<char>::__time_get_storage(const string& __nm)
5609 : __time_get(__nm)
5611 const __time_get_temp<char> ct(__nm);
5612 init(ct);
5615 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5616 template <>
5617 __time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5618 : __time_get(__nm)
5620 const __time_get_temp<wchar_t> ct(__nm);
5621 init(ct);
5624 template <>
5625 __time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5626 : __time_get(__nm)
5628 const __time_get_temp<wchar_t> ct(__nm);
5629 init(ct);
5631 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5633 template <>
5634 time_base::dateorder
5635 __time_get_storage<char>::__do_date_order() const
5637 unsigned i;
5638 for (i = 0; i < __x_.size(); ++i)
5639 if (__x_[i] == '%')
5640 break;
5641 ++i;
5642 switch (__x_[i])
5644 case 'y':
5645 case 'Y':
5646 for (++i; i < __x_.size(); ++i)
5647 if (__x_[i] == '%')
5648 break;
5649 if (i == __x_.size())
5650 break;
5651 ++i;
5652 switch (__x_[i])
5654 case 'm':
5655 for (++i; i < __x_.size(); ++i)
5656 if (__x_[i] == '%')
5657 break;
5658 if (i == __x_.size())
5659 break;
5660 ++i;
5661 if (__x_[i] == 'd')
5662 return time_base::ymd;
5663 break;
5664 case 'd':
5665 for (++i; i < __x_.size(); ++i)
5666 if (__x_[i] == '%')
5667 break;
5668 if (i == __x_.size())
5669 break;
5670 ++i;
5671 if (__x_[i] == 'm')
5672 return time_base::ydm;
5673 break;
5675 break;
5676 case 'm':
5677 for (++i; i < __x_.size(); ++i)
5678 if (__x_[i] == '%')
5679 break;
5680 if (i == __x_.size())
5681 break;
5682 ++i;
5683 if (__x_[i] == 'd')
5685 for (++i; i < __x_.size(); ++i)
5686 if (__x_[i] == '%')
5687 break;
5688 if (i == __x_.size())
5689 break;
5690 ++i;
5691 if (__x_[i] == 'y' || __x_[i] == 'Y')
5692 return time_base::mdy;
5693 break;
5695 break;
5696 case 'd':
5697 for (++i; i < __x_.size(); ++i)
5698 if (__x_[i] == '%')
5699 break;
5700 if (i == __x_.size())
5701 break;
5702 ++i;
5703 if (__x_[i] == 'm')
5705 for (++i; i < __x_.size(); ++i)
5706 if (__x_[i] == '%')
5707 break;
5708 if (i == __x_.size())
5709 break;
5710 ++i;
5711 if (__x_[i] == 'y' || __x_[i] == 'Y')
5712 return time_base::dmy;
5713 break;
5715 break;
5717 return time_base::no_order;
5720 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5721 template <>
5722 time_base::dateorder
5723 __time_get_storage<wchar_t>::__do_date_order() const
5725 unsigned i;
5726 for (i = 0; i < __x_.size(); ++i)
5727 if (__x_[i] == L'%')
5728 break;
5729 ++i;
5730 switch (__x_[i])
5732 case L'y':
5733 case L'Y':
5734 for (++i; i < __x_.size(); ++i)
5735 if (__x_[i] == L'%')
5736 break;
5737 if (i == __x_.size())
5738 break;
5739 ++i;
5740 switch (__x_[i])
5742 case L'm':
5743 for (++i; i < __x_.size(); ++i)
5744 if (__x_[i] == L'%')
5745 break;
5746 if (i == __x_.size())
5747 break;
5748 ++i;
5749 if (__x_[i] == L'd')
5750 return time_base::ymd;
5751 break;
5752 case L'd':
5753 for (++i; i < __x_.size(); ++i)
5754 if (__x_[i] == L'%')
5755 break;
5756 if (i == __x_.size())
5757 break;
5758 ++i;
5759 if (__x_[i] == L'm')
5760 return time_base::ydm;
5761 break;
5763 break;
5764 case L'm':
5765 for (++i; i < __x_.size(); ++i)
5766 if (__x_[i] == L'%')
5767 break;
5768 if (i == __x_.size())
5769 break;
5770 ++i;
5771 if (__x_[i] == L'd')
5773 for (++i; i < __x_.size(); ++i)
5774 if (__x_[i] == L'%')
5775 break;
5776 if (i == __x_.size())
5777 break;
5778 ++i;
5779 if (__x_[i] == L'y' || __x_[i] == L'Y')
5780 return time_base::mdy;
5781 break;
5783 break;
5784 case L'd':
5785 for (++i; i < __x_.size(); ++i)
5786 if (__x_[i] == L'%')
5787 break;
5788 if (i == __x_.size())
5789 break;
5790 ++i;
5791 if (__x_[i] == L'm')
5793 for (++i; i < __x_.size(); ++i)
5794 if (__x_[i] == L'%')
5795 break;
5796 if (i == __x_.size())
5797 break;
5798 ++i;
5799 if (__x_[i] == L'y' || __x_[i] == L'Y')
5800 return time_base::dmy;
5801 break;
5803 break;
5805 return time_base::no_order;
5807 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5809 // time_put
5811 __time_put::__time_put(const char* nm)
5812 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5814 if (__loc_ == 0)
5815 __throw_runtime_error(("time_put_byname failed to construct for " + string(nm)).c_str());
5818 __time_put::__time_put(const string& nm)
5819 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5821 if (__loc_ == 0)
5822 __throw_runtime_error(("time_put_byname failed to construct for " + nm).c_str());
5825 __time_put::~__time_put()
5827 if (__loc_ != _LIBCPP_GET_C_LOCALE)
5828 freelocale(__loc_);
5831 void
5832 __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5833 char __fmt, char __mod) const
5835 char fmt[] = {'%', __fmt, __mod, 0};
5836 if (__mod != 0)
5837 swap(fmt[1], fmt[2]);
5838 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
5839 __ne = __nb + n;
5842 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5843 void
5844 __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5845 char __fmt, char __mod) const
5847 char __nar[100];
5848 char* __ne = __nar + 100;
5849 __do_put(__nar, __ne, __tm, __fmt, __mod);
5850 mbstate_t mb = {0};
5851 const char* __nb = __nar;
5852 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5853 if (j == size_t(-1))
5854 __throw_runtime_error("locale not supported");
5855 __we = __wb + j;
5857 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5859 // moneypunct_byname
5861 template <class charT>
5862 static
5863 void
5864 __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5865 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5866 charT space_char)
5868 const char sign = static_cast<char>(money_base::sign);
5869 const char space = static_cast<char>(money_base::space);
5870 const char none = static_cast<char>(money_base::none);
5871 const char symbol = static_cast<char>(money_base::symbol);
5872 const char value = static_cast<char>(money_base::value);
5873 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5875 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5876 // function'. "Space between sign and symbol or value" means that
5877 // if the sign is adjacent to the symbol, there's a space between
5878 // them, and otherwise there's a space between the sign and value.
5880 // C11's localeconv specifies that the fourth character of an
5881 // international curr_symbol is used to separate the sign and
5882 // value when sep_by_space says to do so. C++ can't represent
5883 // that, so we just use a space. When sep_by_space says to
5884 // separate the symbol and value-or-sign with a space, we rearrange the
5885 // curr_symbol to put its spacing character on the correct side of
5886 // the symbol.
5888 // We also need to avoid adding an extra space between the sign
5889 // and value when the currency symbol is suppressed (by not
5890 // setting showbase). We match glibc's strfmon by interpreting
5891 // sep_by_space==1 as "omit the space when the currency symbol is
5892 // absent".
5894 // Users who want to get this right should use ICU instead.
5896 switch (cs_precedes)
5898 case 0: // value before curr_symbol
5899 if (symbol_contains_sep) {
5900 // Move the separator to before the symbol, to place it
5901 // between the value and symbol.
5902 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5903 __curr_symbol_.end());
5905 switch (sign_posn)
5907 case 0: // Parentheses surround the quantity and currency symbol.
5908 pat.field[0] = sign;
5909 pat.field[1] = value;
5910 pat.field[2] = none; // Any space appears in the symbol.
5911 pat.field[3] = symbol;
5912 switch (sep_by_space)
5914 case 0: // No space separates the currency symbol and value.
5915 // This case may have changed between C99 and C11;
5916 // assume the currency symbol matches the intention.
5917 case 2: // Space between sign and currency or value.
5918 // The "sign" is two parentheses, so no space here either.
5919 return;
5920 case 1: // Space between currency-and-sign or currency and value.
5921 if (!symbol_contains_sep) {
5922 // We insert the space into the symbol instead of
5923 // setting pat.field[2]=space so that when
5924 // showbase is not set, the space goes away too.
5925 __curr_symbol_.insert(0, 1, space_char);
5927 return;
5928 default:
5929 break;
5931 break;
5932 case 1: // The sign string precedes the quantity and currency symbol.
5933 pat.field[0] = sign;
5934 pat.field[3] = symbol;
5935 switch (sep_by_space)
5937 case 0: // No space separates the currency symbol and value.
5938 pat.field[1] = value;
5939 pat.field[2] = none;
5940 return;
5941 case 1: // Space between currency-and-sign or currency and value.
5942 pat.field[1] = value;
5943 pat.field[2] = none;
5944 if (!symbol_contains_sep) {
5945 // We insert the space into the symbol instead of
5946 // setting pat.field[2]=space so that when
5947 // showbase is not set, the space goes away too.
5948 __curr_symbol_.insert(0, 1, space_char);
5950 return;
5951 case 2: // Space between sign and currency or value.
5952 pat.field[1] = space;
5953 pat.field[2] = value;
5954 if (symbol_contains_sep) {
5955 // Remove the separator from the symbol, since it
5956 // has already appeared after the sign.
5957 __curr_symbol_.erase(__curr_symbol_.begin());
5959 return;
5960 default:
5961 break;
5963 break;
5964 case 2: // The sign string succeeds the quantity and currency symbol.
5965 pat.field[0] = value;
5966 pat.field[3] = sign;
5967 switch (sep_by_space)
5969 case 0: // No space separates the currency symbol and value.
5970 pat.field[1] = none;
5971 pat.field[2] = symbol;
5972 return;
5973 case 1: // Space between currency-and-sign or currency and value.
5974 if (!symbol_contains_sep) {
5975 // We insert the space into the symbol instead of
5976 // setting pat.field[1]=space so that when
5977 // showbase is not set, the space goes away too.
5978 __curr_symbol_.insert(0, 1, space_char);
5980 pat.field[1] = none;
5981 pat.field[2] = symbol;
5982 return;
5983 case 2: // Space between sign and currency or value.
5984 pat.field[1] = symbol;
5985 pat.field[2] = space;
5986 if (symbol_contains_sep) {
5987 // Remove the separator from the symbol, since it
5988 // should not be removed if showbase is absent.
5989 __curr_symbol_.erase(__curr_symbol_.begin());
5991 return;
5992 default:
5993 break;
5995 break;
5996 case 3: // The sign string immediately precedes the currency symbol.
5997 pat.field[0] = value;
5998 pat.field[3] = symbol;
5999 switch (sep_by_space)
6001 case 0: // No space separates the currency symbol and value.
6002 pat.field[1] = none;
6003 pat.field[2] = sign;
6004 return;
6005 case 1: // Space between currency-and-sign or currency and value.
6006 pat.field[1] = space;
6007 pat.field[2] = sign;
6008 if (symbol_contains_sep) {
6009 // Remove the separator from the symbol, since it
6010 // has already appeared before the sign.
6011 __curr_symbol_.erase(__curr_symbol_.begin());
6013 return;
6014 case 2: // Space between sign and currency or value.
6015 pat.field[1] = sign;
6016 pat.field[2] = none;
6017 if (!symbol_contains_sep) {
6018 // We insert the space into the symbol instead of
6019 // setting pat.field[2]=space so that when
6020 // showbase is not set, the space goes away too.
6021 __curr_symbol_.insert(0, 1, space_char);
6023 return;
6024 default:
6025 break;
6027 break;
6028 case 4: // The sign string immediately succeeds the currency symbol.
6029 pat.field[0] = value;
6030 pat.field[3] = sign;
6031 switch (sep_by_space)
6033 case 0: // No space separates the currency symbol and value.
6034 pat.field[1] = none;
6035 pat.field[2] = symbol;
6036 return;
6037 case 1: // Space between currency-and-sign or currency and value.
6038 pat.field[1] = none;
6039 pat.field[2] = symbol;
6040 if (!symbol_contains_sep) {
6041 // We insert the space into the symbol instead of
6042 // setting pat.field[1]=space so that when
6043 // showbase is not set, the space goes away too.
6044 __curr_symbol_.insert(0, 1, space_char);
6046 return;
6047 case 2: // Space between sign and currency or value.
6048 pat.field[1] = symbol;
6049 pat.field[2] = space;
6050 if (symbol_contains_sep) {
6051 // Remove the separator from the symbol, since it
6052 // should not disappear when showbase is absent.
6053 __curr_symbol_.erase(__curr_symbol_.begin());
6055 return;
6056 default:
6057 break;
6059 break;
6060 default:
6061 break;
6063 break;
6064 case 1: // curr_symbol before value
6065 switch (sign_posn)
6067 case 0: // Parentheses surround the quantity and currency symbol.
6068 pat.field[0] = sign;
6069 pat.field[1] = symbol;
6070 pat.field[2] = none; // Any space appears in the symbol.
6071 pat.field[3] = value;
6072 switch (sep_by_space)
6074 case 0: // No space separates the currency symbol and value.
6075 // This case may have changed between C99 and C11;
6076 // assume the currency symbol matches the intention.
6077 case 2: // Space between sign and currency or value.
6078 // The "sign" is two parentheses, so no space here either.
6079 return;
6080 case 1: // Space between currency-and-sign or currency and value.
6081 if (!symbol_contains_sep) {
6082 // We insert the space into the symbol instead of
6083 // setting pat.field[2]=space so that when
6084 // showbase is not set, the space goes away too.
6085 __curr_symbol_.insert(0, 1, space_char);
6087 return;
6088 default:
6089 break;
6091 break;
6092 case 1: // The sign string precedes the quantity and currency symbol.
6093 pat.field[0] = sign;
6094 pat.field[3] = value;
6095 switch (sep_by_space)
6097 case 0: // No space separates the currency symbol and value.
6098 pat.field[1] = symbol;
6099 pat.field[2] = none;
6100 return;
6101 case 1: // Space between currency-and-sign or currency and value.
6102 pat.field[1] = symbol;
6103 pat.field[2] = none;
6104 if (!symbol_contains_sep) {
6105 // We insert the space into the symbol instead of
6106 // setting pat.field[2]=space so that when
6107 // showbase is not set, the space goes away too.
6108 __curr_symbol_.push_back(space_char);
6110 return;
6111 case 2: // Space between sign and currency or value.
6112 pat.field[1] = space;
6113 pat.field[2] = symbol;
6114 if (symbol_contains_sep) {
6115 // Remove the separator from the symbol, since it
6116 // has already appeared after the sign.
6117 __curr_symbol_.pop_back();
6119 return;
6120 default:
6121 break;
6123 break;
6124 case 2: // The sign string succeeds the quantity and currency symbol.
6125 pat.field[0] = symbol;
6126 pat.field[3] = sign;
6127 switch (sep_by_space)
6129 case 0: // No space separates the currency symbol and value.
6130 pat.field[1] = none;
6131 pat.field[2] = value;
6132 return;
6133 case 1: // Space between currency-and-sign or currency and value.
6134 pat.field[1] = none;
6135 pat.field[2] = value;
6136 if (!symbol_contains_sep) {
6137 // We insert the space into the symbol instead of
6138 // setting pat.field[1]=space so that when
6139 // showbase is not set, the space goes away too.
6140 __curr_symbol_.push_back(space_char);
6142 return;
6143 case 2: // Space between sign and currency or value.
6144 pat.field[1] = value;
6145 pat.field[2] = space;
6146 if (symbol_contains_sep) {
6147 // Remove the separator from the symbol, since it
6148 // will appear before the sign.
6149 __curr_symbol_.pop_back();
6151 return;
6152 default:
6153 break;
6155 break;
6156 case 3: // The sign string immediately precedes the currency symbol.
6157 pat.field[0] = sign;
6158 pat.field[3] = value;
6159 switch (sep_by_space)
6161 case 0: // No space separates the currency symbol and value.
6162 pat.field[1] = symbol;
6163 pat.field[2] = none;
6164 return;
6165 case 1: // Space between currency-and-sign or currency and value.
6166 pat.field[1] = symbol;
6167 pat.field[2] = none;
6168 if (!symbol_contains_sep) {
6169 // We insert the space into the symbol instead of
6170 // setting pat.field[2]=space so that when
6171 // showbase is not set, the space goes away too.
6172 __curr_symbol_.push_back(space_char);
6174 return;
6175 case 2: // Space between sign and currency or value.
6176 pat.field[1] = space;
6177 pat.field[2] = symbol;
6178 if (symbol_contains_sep) {
6179 // Remove the separator from the symbol, since it
6180 // has already appeared after the sign.
6181 __curr_symbol_.pop_back();
6183 return;
6184 default:
6185 break;
6187 break;
6188 case 4: // The sign string immediately succeeds the currency symbol.
6189 pat.field[0] = symbol;
6190 pat.field[3] = value;
6191 switch (sep_by_space)
6193 case 0: // No space separates the currency symbol and value.
6194 pat.field[1] = sign;
6195 pat.field[2] = none;
6196 return;
6197 case 1: // Space between currency-and-sign or currency and value.
6198 pat.field[1] = sign;
6199 pat.field[2] = space;
6200 if (symbol_contains_sep) {
6201 // Remove the separator from the symbol, since it
6202 // should not disappear when showbase is absent.
6203 __curr_symbol_.pop_back();
6205 return;
6206 case 2: // Space between sign and currency or value.
6207 pat.field[1] = none;
6208 pat.field[2] = sign;
6209 if (!symbol_contains_sep) {
6210 // We insert the space into the symbol instead of
6211 // setting pat.field[1]=space so that when
6212 // showbase is not set, the space goes away too.
6213 __curr_symbol_.push_back(space_char);
6215 return;
6216 default:
6217 break;
6219 break;
6220 default:
6221 break;
6223 break;
6224 default:
6225 break;
6227 pat.field[0] = symbol;
6228 pat.field[1] = sign;
6229 pat.field[2] = none;
6230 pat.field[3] = value;
6233 template<>
6234 void
6235 moneypunct_byname<char, false>::init(const char* nm)
6237 typedef moneypunct<char, false> base;
6238 __libcpp_unique_locale loc(nm);
6239 if (!loc)
6240 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6242 lconv* lc = __libcpp_localeconv_l(loc.get());
6243 if (!checked_string_to_char_convert(__decimal_point_,
6244 lc->mon_decimal_point,
6245 loc.get()))
6246 __decimal_point_ = base::do_decimal_point();
6247 if (!checked_string_to_char_convert(__thousands_sep_,
6248 lc->mon_thousands_sep,
6249 loc.get()))
6250 __thousands_sep_ = base::do_thousands_sep();
6252 __grouping_ = lc->mon_grouping;
6253 __curr_symbol_ = lc->currency_symbol;
6254 if (lc->frac_digits != CHAR_MAX)
6255 __frac_digits_ = lc->frac_digits;
6256 else
6257 __frac_digits_ = base::do_frac_digits();
6258 if (lc->p_sign_posn == 0)
6259 __positive_sign_ = "()";
6260 else
6261 __positive_sign_ = lc->positive_sign;
6262 if (lc->n_sign_posn == 0)
6263 __negative_sign_ = "()";
6264 else
6265 __negative_sign_ = lc->negative_sign;
6266 // Assume the positive and negative formats will want spaces in
6267 // the same places in curr_symbol since there's no way to
6268 // represent anything else.
6269 string_type __dummy_curr_symbol = __curr_symbol_;
6270 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6271 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6272 __init_pat(__neg_format_, __curr_symbol_, false,
6273 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
6276 template<>
6277 void
6278 moneypunct_byname<char, true>::init(const char* nm)
6280 typedef moneypunct<char, true> base;
6281 __libcpp_unique_locale loc(nm);
6282 if (!loc)
6283 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6285 lconv* lc = __libcpp_localeconv_l(loc.get());
6286 if (!checked_string_to_char_convert(__decimal_point_,
6287 lc->mon_decimal_point,
6288 loc.get()))
6289 __decimal_point_ = base::do_decimal_point();
6290 if (!checked_string_to_char_convert(__thousands_sep_,
6291 lc->mon_thousands_sep,
6292 loc.get()))
6293 __thousands_sep_ = base::do_thousands_sep();
6294 __grouping_ = lc->mon_grouping;
6295 __curr_symbol_ = lc->int_curr_symbol;
6296 if (lc->int_frac_digits != CHAR_MAX)
6297 __frac_digits_ = lc->int_frac_digits;
6298 else
6299 __frac_digits_ = base::do_frac_digits();
6300 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6301 if (lc->p_sign_posn == 0)
6302 #else // _LIBCPP_MSVCRT
6303 if (lc->int_p_sign_posn == 0)
6304 #endif // !_LIBCPP_MSVCRT
6305 __positive_sign_ = "()";
6306 else
6307 __positive_sign_ = lc->positive_sign;
6308 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6309 if(lc->n_sign_posn == 0)
6310 #else // _LIBCPP_MSVCRT
6311 if (lc->int_n_sign_posn == 0)
6312 #endif // !_LIBCPP_MSVCRT
6313 __negative_sign_ = "()";
6314 else
6315 __negative_sign_ = lc->negative_sign;
6316 // Assume the positive and negative formats will want spaces in
6317 // the same places in curr_symbol since there's no way to
6318 // represent anything else.
6319 string_type __dummy_curr_symbol = __curr_symbol_;
6320 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6321 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6322 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6323 __init_pat(__neg_format_, __curr_symbol_, true,
6324 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
6325 #else // _LIBCPP_MSVCRT
6326 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6327 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6328 lc->int_p_sign_posn, ' ');
6329 __init_pat(__neg_format_, __curr_symbol_, true,
6330 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6331 lc->int_n_sign_posn, ' ');
6332 #endif // !_LIBCPP_MSVCRT
6335 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
6336 template<>
6337 void
6338 moneypunct_byname<wchar_t, false>::init(const char* nm)
6340 typedef moneypunct<wchar_t, false> base;
6341 __libcpp_unique_locale loc(nm);
6342 if (!loc)
6343 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6344 lconv* lc = __libcpp_localeconv_l(loc.get());
6345 if (!checked_string_to_wchar_convert(__decimal_point_,
6346 lc->mon_decimal_point,
6347 loc.get()))
6348 __decimal_point_ = base::do_decimal_point();
6349 if (!checked_string_to_wchar_convert(__thousands_sep_,
6350 lc->mon_thousands_sep,
6351 loc.get()))
6352 __thousands_sep_ = base::do_thousands_sep();
6353 __grouping_ = lc->mon_grouping;
6354 wchar_t wbuf[100];
6355 mbstate_t mb = {0};
6356 const char* bb = lc->currency_symbol;
6357 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6358 if (j == size_t(-1))
6359 __throw_runtime_error("locale not supported");
6360 wchar_t* wbe = wbuf + j;
6361 __curr_symbol_.assign(wbuf, wbe);
6362 if (lc->frac_digits != CHAR_MAX)
6363 __frac_digits_ = lc->frac_digits;
6364 else
6365 __frac_digits_ = base::do_frac_digits();
6366 if (lc->p_sign_posn == 0)
6367 __positive_sign_ = L"()";
6368 else
6370 mb = mbstate_t();
6371 bb = lc->positive_sign;
6372 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6373 if (j == size_t(-1))
6374 __throw_runtime_error("locale not supported");
6375 wbe = wbuf + j;
6376 __positive_sign_.assign(wbuf, wbe);
6378 if (lc->n_sign_posn == 0)
6379 __negative_sign_ = L"()";
6380 else
6382 mb = mbstate_t();
6383 bb = lc->negative_sign;
6384 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6385 if (j == size_t(-1))
6386 __throw_runtime_error("locale not supported");
6387 wbe = wbuf + j;
6388 __negative_sign_.assign(wbuf, wbe);
6390 // Assume the positive and negative formats will want spaces in
6391 // the same places in curr_symbol since there's no way to
6392 // represent anything else.
6393 string_type __dummy_curr_symbol = __curr_symbol_;
6394 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6395 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6396 __init_pat(__neg_format_, __curr_symbol_, false,
6397 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6400 template<>
6401 void
6402 moneypunct_byname<wchar_t, true>::init(const char* nm)
6404 typedef moneypunct<wchar_t, true> base;
6405 __libcpp_unique_locale loc(nm);
6406 if (!loc)
6407 __throw_runtime_error(("moneypunct_byname failed to construct for " + string(nm)).c_str());
6409 lconv* lc = __libcpp_localeconv_l(loc.get());
6410 if (!checked_string_to_wchar_convert(__decimal_point_,
6411 lc->mon_decimal_point,
6412 loc.get()))
6413 __decimal_point_ = base::do_decimal_point();
6414 if (!checked_string_to_wchar_convert(__thousands_sep_,
6415 lc->mon_thousands_sep,
6416 loc.get()))
6417 __thousands_sep_ = base::do_thousands_sep();
6418 __grouping_ = lc->mon_grouping;
6419 wchar_t wbuf[100];
6420 mbstate_t mb = {0};
6421 const char* bb = lc->int_curr_symbol;
6422 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6423 if (j == size_t(-1))
6424 __throw_runtime_error("locale not supported");
6425 wchar_t* wbe = wbuf + j;
6426 __curr_symbol_.assign(wbuf, wbe);
6427 if (lc->int_frac_digits != CHAR_MAX)
6428 __frac_digits_ = lc->int_frac_digits;
6429 else
6430 __frac_digits_ = base::do_frac_digits();
6431 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6432 if (lc->p_sign_posn == 0)
6433 #else // _LIBCPP_MSVCRT
6434 if (lc->int_p_sign_posn == 0)
6435 #endif // !_LIBCPP_MSVCRT
6436 __positive_sign_ = L"()";
6437 else
6439 mb = mbstate_t();
6440 bb = lc->positive_sign;
6441 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6442 if (j == size_t(-1))
6443 __throw_runtime_error("locale not supported");
6444 wbe = wbuf + j;
6445 __positive_sign_.assign(wbuf, wbe);
6447 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6448 if (lc->n_sign_posn == 0)
6449 #else // _LIBCPP_MSVCRT
6450 if (lc->int_n_sign_posn == 0)
6451 #endif // !_LIBCPP_MSVCRT
6452 __negative_sign_ = L"()";
6453 else
6455 mb = mbstate_t();
6456 bb = lc->negative_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 __negative_sign_.assign(wbuf, wbe);
6463 // Assume the positive and negative formats will want spaces in
6464 // the same places in curr_symbol since there's no way to
6465 // represent anything else.
6466 string_type __dummy_curr_symbol = __curr_symbol_;
6467 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6468 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6469 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6470 __init_pat(__neg_format_, __curr_symbol_, true,
6471 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6472 #else // _LIBCPP_MSVCRT
6473 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6474 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6475 lc->int_p_sign_posn, L' ');
6476 __init_pat(__neg_format_, __curr_symbol_, true,
6477 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6478 lc->int_n_sign_posn, L' ');
6479 #endif // !_LIBCPP_MSVCRT
6481 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
6483 void __do_nothing(void*) {}
6485 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6486 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
6488 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6489 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
6491 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6492 _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
6494 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6495 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
6497 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6498 _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
6500 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6501 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
6503 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6504 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
6506 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6507 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
6509 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6510 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
6512 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6513 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6514 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6515 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
6517 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6518 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6519 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6520 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
6522 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6523 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
6525 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6526 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
6528 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6529 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
6531 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6532 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
6534 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6535 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
6537 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6538 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
6540 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6541 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;)
6542 template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6543 template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
6544 #ifndef _LIBCPP_HAS_NO_CHAR8_T
6545 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6546 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6547 #endif
6549 _LIBCPP_END_NAMESPACE_STD
6551 _LIBCPP_POP_MACROS