[NFC][Py Reformat] Reformat python files in libcxx/libcxxabi
[llvm-project.git] / libcxx / src / locale.cpp
blob930bf4f8f3a2b499b3f089882e496ed616bfc064
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 _LIBCPP_CONSTEXPR
98 size_t
99 countof(const T (&)[N])
101 return N;
104 template <typename T>
105 inline
106 _LIBCPP_CONSTEXPR
107 size_t
108 countof(const T * const begin, const T * const end)
110 return static_cast<size_t>(end - begin);
113 _LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
115 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
116 throw runtime_error(msg);
117 #else
118 (void)msg;
119 _VSTD::abort();
120 #endif
125 const locale::category locale::none;
126 const locale::category locale::collate;
127 const locale::category locale::ctype;
128 const locale::category locale::monetary;
129 const locale::category locale::numeric;
130 const locale::category locale::time;
131 const locale::category locale::messages;
132 const locale::category locale::all;
134 class _LIBCPP_HIDDEN locale::__imp
135 : public facet
137 enum {N = 30};
138 vector<facet*, __sso_allocator<facet*, N> > facets_;
139 string name_;
140 public:
141 explicit __imp(size_t refs = 0);
142 explicit __imp(const string& name, size_t refs = 0);
143 __imp(const __imp&);
144 __imp(const __imp&, const string&, locale::category c);
145 __imp(const __imp& other, const __imp& one, locale::category c);
146 __imp(const __imp&, facet* f, long id);
147 ~__imp();
149 const string& name() const {return name_;}
150 bool has_facet(long id) const
151 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
152 const locale::facet* use_facet(long id) const;
154 static const locale& make_classic();
155 static locale& make_global();
156 private:
157 void install(facet* f, long id);
158 template <class F> void install(F* f) {install(f, f->id.__get());}
159 template <class F> void install_from(const __imp& other);
162 locale::__imp::__imp(size_t refs)
163 : facet(refs),
164 facets_(N),
165 name_("C")
167 facets_.clear();
168 install(&make<_VSTD::collate<char> >(1u));
169 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
170 install(&make<_VSTD::collate<wchar_t> >(1u));
171 #endif
172 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
173 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
174 install(&make<_VSTD::ctype<wchar_t> >(1u));
175 #endif
176 install(&make<codecvt<char, char, mbstate_t> >(1u));
177 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
178 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
179 #endif
180 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
181 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
182 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
183 _LIBCPP_SUPPRESS_DEPRECATED_POP
184 #ifndef _LIBCPP_HAS_NO_CHAR8_T
185 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
186 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
187 #endif
188 install(&make<numpunct<char> >(1u));
189 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
190 install(&make<numpunct<wchar_t> >(1u));
191 #endif
192 install(&make<num_get<char> >(1u));
193 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
194 install(&make<num_get<wchar_t> >(1u));
195 #endif
196 install(&make<num_put<char> >(1u));
197 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
198 install(&make<num_put<wchar_t> >(1u));
199 #endif
200 install(&make<moneypunct<char, false> >(1u));
201 install(&make<moneypunct<char, true> >(1u));
202 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
203 install(&make<moneypunct<wchar_t, false> >(1u));
204 install(&make<moneypunct<wchar_t, true> >(1u));
205 #endif
206 install(&make<money_get<char> >(1u));
207 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
208 install(&make<money_get<wchar_t> >(1u));
209 #endif
210 install(&make<money_put<char> >(1u));
211 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
212 install(&make<money_put<wchar_t> >(1u));
213 #endif
214 install(&make<time_get<char> >(1u));
215 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
216 install(&make<time_get<wchar_t> >(1u));
217 #endif
218 install(&make<time_put<char> >(1u));
219 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
220 install(&make<time_put<wchar_t> >(1u));
221 #endif
222 install(&make<_VSTD::messages<char> >(1u));
223 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
224 install(&make<_VSTD::messages<wchar_t> >(1u));
225 #endif
228 locale::__imp::__imp(const string& name, size_t refs)
229 : facet(refs),
230 facets_(N),
231 name_(name)
233 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
236 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
237 facets_ = locale::classic().__locale_->facets_;
238 for (unsigned i = 0; i < facets_.size(); ++i)
239 if (facets_[i])
240 facets_[i]->__add_shared();
241 install(new collate_byname<char>(name_));
242 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
243 install(new collate_byname<wchar_t>(name_));
244 #endif
245 install(new ctype_byname<char>(name_));
246 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
247 install(new ctype_byname<wchar_t>(name_));
248 #endif
249 install(new codecvt_byname<char, char, mbstate_t>(name_));
250 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
251 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
252 #endif
253 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
254 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
255 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
256 _LIBCPP_SUPPRESS_DEPRECATED_POP
257 #ifndef _LIBCPP_HAS_NO_CHAR8_T
258 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
259 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
260 #endif
261 install(new numpunct_byname<char>(name_));
262 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
263 install(new numpunct_byname<wchar_t>(name_));
264 #endif
265 install(new moneypunct_byname<char, false>(name_));
266 install(new moneypunct_byname<char, true>(name_));
267 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
268 install(new moneypunct_byname<wchar_t, false>(name_));
269 install(new moneypunct_byname<wchar_t, true>(name_));
270 #endif
271 install(new time_get_byname<char>(name_));
272 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
273 install(new time_get_byname<wchar_t>(name_));
274 #endif
275 install(new time_put_byname<char>(name_));
276 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
277 install(new time_put_byname<wchar_t>(name_));
278 #endif
279 install(new messages_byname<char>(name_));
280 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
281 install(new messages_byname<wchar_t>(name_));
282 #endif
283 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
285 catch (...)
287 for (unsigned i = 0; i < facets_.size(); ++i)
288 if (facets_[i])
289 facets_[i]->__release_shared();
290 throw;
292 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
295 locale::__imp::__imp(const __imp& other)
296 : facets_(max<size_t>(N, other.facets_.size())),
297 name_(other.name_)
299 facets_ = other.facets_;
300 for (unsigned i = 0; i < facets_.size(); ++i)
301 if (facets_[i])
302 facets_[i]->__add_shared();
305 locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
306 : facets_(N),
307 name_("*")
309 facets_ = other.facets_;
310 for (unsigned i = 0; i < facets_.size(); ++i)
311 if (facets_[i])
312 facets_[i]->__add_shared();
313 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
316 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
317 if (c & locale::collate)
319 install(new collate_byname<char>(name));
320 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
321 install(new collate_byname<wchar_t>(name));
322 #endif
324 if (c & locale::ctype)
326 install(new ctype_byname<char>(name));
327 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
328 install(new ctype_byname<wchar_t>(name));
329 #endif
330 install(new codecvt_byname<char, char, mbstate_t>(name));
331 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
332 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
333 #endif
334 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
335 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
336 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
337 _LIBCPP_SUPPRESS_DEPRECATED_POP
338 #ifndef _LIBCPP_HAS_NO_CHAR8_T
339 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
340 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
341 #endif
343 if (c & locale::monetary)
345 install(new moneypunct_byname<char, false>(name));
346 install(new moneypunct_byname<char, true>(name));
347 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
348 install(new moneypunct_byname<wchar_t, false>(name));
349 install(new moneypunct_byname<wchar_t, true>(name));
350 #endif
352 if (c & locale::numeric)
354 install(new numpunct_byname<char>(name));
355 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
356 install(new numpunct_byname<wchar_t>(name));
357 #endif
359 if (c & locale::time)
361 install(new time_get_byname<char>(name));
362 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
363 install(new time_get_byname<wchar_t>(name));
364 #endif
365 install(new time_put_byname<char>(name));
366 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
367 install(new time_put_byname<wchar_t>(name));
368 #endif
370 if (c & locale::messages)
372 install(new messages_byname<char>(name));
373 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
374 install(new messages_byname<wchar_t>(name));
375 #endif
377 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
379 catch (...)
381 for (unsigned i = 0; i < facets_.size(); ++i)
382 if (facets_[i])
383 facets_[i]->__release_shared();
384 throw;
386 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
389 template<class F>
390 inline
391 void
392 locale::__imp::install_from(const locale::__imp& one)
394 long id = F::id.__get();
395 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
398 locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
399 : facets_(N),
400 name_("*")
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 int32_t locale::id::__next_id = 0;
693 namespace
696 class __fake_bind
698 locale::id* id_;
699 void (locale::id::* pmf_)();
700 public:
701 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
702 : id_(id), pmf_(pmf) {}
704 void operator()() const
706 (id_->*pmf_)();
712 long
713 locale::id::__get()
715 call_once(__flag_, __fake_bind(&locale::id::__init, this));
716 return __id_ - 1;
719 void
720 locale::id::__init()
722 __id_ = __libcpp_atomic_add(&__next_id, 1);
725 // template <> class collate_byname<char>
727 collate_byname<char>::collate_byname(const char* n, size_t refs)
728 : collate<char>(refs),
729 __l_(newlocale(LC_ALL_MASK, n, 0))
731 if (__l_ == 0)
732 __throw_runtime_error("collate_byname<char>::collate_byname"
733 " failed to construct for " + string(n));
736 collate_byname<char>::collate_byname(const string& name, size_t refs)
737 : collate<char>(refs),
738 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
740 if (__l_ == 0)
741 __throw_runtime_error("collate_byname<char>::collate_byname"
742 " failed to construct for " + name);
745 collate_byname<char>::~collate_byname()
747 freelocale(__l_);
751 collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
752 const char_type* __lo2, const char_type* __hi2) const
754 string_type lhs(__lo1, __hi1);
755 string_type rhs(__lo2, __hi2);
756 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l_);
757 if (r < 0)
758 return -1;
759 if (r > 0)
760 return 1;
761 return r;
764 collate_byname<char>::string_type
765 collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
767 const string_type in(lo, hi);
768 string_type out(strxfrm_l(0, in.c_str(), 0, __l_), char());
769 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l_);
770 return out;
773 // template <> class collate_byname<wchar_t>
775 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
776 collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
777 : collate<wchar_t>(refs),
778 __l_(newlocale(LC_ALL_MASK, n, 0))
780 if (__l_ == 0)
781 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
782 " failed to construct for " + string(n));
785 collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
786 : collate<wchar_t>(refs),
787 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
789 if (__l_ == 0)
790 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
791 " failed to construct for " + name);
794 collate_byname<wchar_t>::~collate_byname()
796 freelocale(__l_);
800 collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
801 const char_type* __lo2, const char_type* __hi2) const
803 string_type lhs(__lo1, __hi1);
804 string_type rhs(__lo2, __hi2);
805 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l_);
806 if (r < 0)
807 return -1;
808 if (r > 0)
809 return 1;
810 return r;
813 collate_byname<wchar_t>::string_type
814 collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
816 const string_type in(lo, hi);
817 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l_), wchar_t());
818 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l_);
819 return out;
821 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
823 const ctype_base::mask ctype_base::space;
824 const ctype_base::mask ctype_base::print;
825 const ctype_base::mask ctype_base::cntrl;
826 const ctype_base::mask ctype_base::upper;
827 const ctype_base::mask ctype_base::lower;
828 const ctype_base::mask ctype_base::alpha;
829 const ctype_base::mask ctype_base::digit;
830 const ctype_base::mask ctype_base::punct;
831 const ctype_base::mask ctype_base::xdigit;
832 const ctype_base::mask ctype_base::blank;
833 const ctype_base::mask ctype_base::alnum;
834 const ctype_base::mask ctype_base::graph;
836 // template <> class ctype<wchar_t>;
838 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
839 locale::id ctype<wchar_t>::id;
841 ctype<wchar_t>::~ctype()
845 bool
846 ctype<wchar_t>::do_is(mask m, char_type c) const
848 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
851 const wchar_t*
852 ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
854 for (; low != high; ++low, ++vec)
855 *vec = static_cast<mask>(isascii(*low) ?
856 ctype<char>::classic_table()[*low] : 0);
857 return low;
860 const wchar_t*
861 ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
863 for (; low != high; ++low)
864 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
865 break;
866 return low;
869 const wchar_t*
870 ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
872 for (; low != high; ++low)
873 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
874 break;
875 return low;
878 wchar_t
879 ctype<wchar_t>::do_toupper(char_type c) const
881 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
882 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
883 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
884 defined(__NetBSD__) || defined(__MVS__)
885 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
886 #else
887 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
888 #endif
891 const wchar_t*
892 ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
894 for (; low != high; ++low)
895 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
896 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
897 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
898 defined(__NetBSD__) || defined(__MVS__)
899 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
900 : *low;
901 #else
902 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
903 #endif
904 return low;
907 wchar_t
908 ctype<wchar_t>::do_tolower(char_type c) const
910 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
911 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
912 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
913 defined(__NetBSD__) || defined(__MVS__)
914 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
915 #else
916 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
917 #endif
920 const wchar_t*
921 ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
923 for (; low != high; ++low)
924 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
925 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
926 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
927 defined(__NetBSD__) || defined(__MVS__)
928 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
929 : *low;
930 #else
931 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
932 #endif
933 return low;
936 wchar_t
937 ctype<wchar_t>::do_widen(char c) const
939 return c;
942 const char*
943 ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
945 for (; low != high; ++low, ++dest)
946 *dest = *low;
947 return low;
950 char
951 ctype<wchar_t>::do_narrow(char_type c, char dfault) const
953 if (isascii(c))
954 return static_cast<char>(c);
955 return dfault;
958 const wchar_t*
959 ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
961 for (; low != high; ++low, ++dest)
962 if (isascii(*low))
963 *dest = static_cast<char>(*low);
964 else
965 *dest = dfault;
966 return low;
968 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
970 // template <> class ctype<char>;
972 locale::id ctype<char>::id;
974 const size_t ctype<char>::table_size;
976 ctype<char>::ctype(const mask* tab, bool del, size_t refs)
977 : locale::facet(refs),
978 __tab_(tab),
979 __del_(del)
981 if (__tab_ == 0)
982 __tab_ = classic_table();
985 ctype<char>::~ctype()
987 if (__tab_ && __del_)
988 delete [] __tab_;
991 char
992 ctype<char>::do_toupper(char_type c) const
994 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
995 return isascii(c) ?
996 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
997 #elif defined(__NetBSD__)
998 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
999 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1000 return isascii(c) ?
1001 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
1002 #else
1003 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
1004 #endif
1007 const char*
1008 ctype<char>::do_toupper(char_type* low, const char_type* high) const
1010 for (; low != high; ++low)
1011 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1012 *low = isascii(*low) ?
1013 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
1014 #elif defined(__NetBSD__)
1015 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
1016 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1017 *low = isascii(*low) ?
1018 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
1019 #else
1020 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
1021 #endif
1022 return low;
1025 char
1026 ctype<char>::do_tolower(char_type c) const
1028 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1029 return isascii(c) ?
1030 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
1031 #elif defined(__NetBSD__)
1032 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
1033 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1034 return isascii(c) ?
1035 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
1036 #else
1037 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
1038 #endif
1041 const char*
1042 ctype<char>::do_tolower(char_type* low, const char_type* high) const
1044 for (; low != high; ++low)
1045 #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
1046 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
1047 #elif defined(__NetBSD__)
1048 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
1049 #elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
1050 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
1051 #else
1052 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
1053 #endif
1054 return low;
1057 char
1058 ctype<char>::do_widen(char c) const
1060 return c;
1063 const char*
1064 ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1066 for (; low != high; ++low, ++dest)
1067 *dest = *low;
1068 return low;
1071 char
1072 ctype<char>::do_narrow(char_type c, char dfault) const
1074 if (isascii(c))
1075 return static_cast<char>(c);
1076 return dfault;
1079 const char*
1080 ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1082 for (; low != high; ++low, ++dest)
1083 if (isascii(*low))
1084 *dest = *low;
1085 else
1086 *dest = dfault;
1087 return low;
1090 #if defined(__EMSCRIPTEN__)
1091 extern "C" const unsigned short ** __ctype_b_loc();
1092 extern "C" const int ** __ctype_tolower_loc();
1093 extern "C" const int ** __ctype_toupper_loc();
1094 #endif
1096 #ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
1097 const ctype<char>::mask*
1098 ctype<char>::classic_table() noexcept
1100 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1101 cntrl, cntrl,
1102 cntrl, cntrl,
1103 cntrl, cntrl,
1104 cntrl, cntrl,
1105 cntrl, cntrl | space | blank,
1106 cntrl | space, cntrl | space,
1107 cntrl | space, cntrl | space,
1108 cntrl, cntrl,
1109 cntrl, cntrl,
1110 cntrl, cntrl,
1111 cntrl, cntrl,
1112 cntrl, cntrl,
1113 cntrl, cntrl,
1114 cntrl, cntrl,
1115 cntrl, cntrl,
1116 cntrl, cntrl,
1117 space | blank | print, punct | print,
1118 punct | print, punct | print,
1119 punct | print, punct | print,
1120 punct | print, punct | print,
1121 punct | print, punct | print,
1122 punct | print, punct | print,
1123 punct | print, punct | print,
1124 punct | print, punct | print,
1125 digit | print | xdigit, digit | print | xdigit,
1126 digit | print | xdigit, digit | print | xdigit,
1127 digit | print | xdigit, digit | print | xdigit,
1128 digit | print | xdigit, digit | print | xdigit,
1129 digit | print | xdigit, digit | print | xdigit,
1130 punct | print, punct | print,
1131 punct | print, punct | print,
1132 punct | print, punct | print,
1133 punct | print, upper | xdigit | print | alpha,
1134 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1135 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1136 upper | xdigit | print | alpha, upper | print | alpha,
1137 upper | print | alpha, upper | print | alpha,
1138 upper | print | alpha, upper | print | alpha,
1139 upper | print | alpha, upper | print | alpha,
1140 upper | print | alpha, upper | print | alpha,
1141 upper | print | alpha, upper | print | alpha,
1142 upper | print | alpha, upper | print | alpha,
1143 upper | print | alpha, upper | print | alpha,
1144 upper | print | alpha, upper | print | alpha,
1145 upper | print | alpha, upper | print | alpha,
1146 upper | print | alpha, punct | print,
1147 punct | print, punct | print,
1148 punct | print, punct | print,
1149 punct | print, lower | xdigit | print | alpha,
1150 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1151 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1152 lower | xdigit | print | alpha, lower | print | alpha,
1153 lower | print | alpha, lower | print | alpha,
1154 lower | print | alpha, lower | print | alpha,
1155 lower | print | alpha, lower | print | alpha,
1156 lower | print | alpha, lower | print | alpha,
1157 lower | print | alpha, lower | print | alpha,
1158 lower | print | alpha, lower | print | alpha,
1159 lower | print | alpha, lower | print | alpha,
1160 lower | print | alpha, lower | print | alpha,
1161 lower | print | alpha, lower | print | alpha,
1162 lower | print | alpha, punct | print,
1163 punct | print, punct | print,
1164 punct | print, cntrl,
1165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1174 return builtin_table;
1176 #else
1177 const ctype<char>::mask*
1178 ctype<char>::classic_table() noexcept
1180 #if defined(__APPLE__) || defined(__FreeBSD__)
1181 return _DefaultRuneLocale.__runetype;
1182 #elif defined(__NetBSD__)
1183 return _C_ctype_tab_ + 1;
1184 #elif defined(__GLIBC__)
1185 return _LIBCPP_GET_C_LOCALE->__ctype_b;
1186 #elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
1187 return __pctype_func();
1188 #elif defined(__EMSCRIPTEN__)
1189 return *__ctype_b_loc();
1190 #elif defined(_NEWLIB_VERSION)
1191 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1192 return _ctype_ + 1;
1193 #elif defined(_AIX)
1194 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
1195 #elif defined(__MVS__)
1196 # if defined(__NATIVE_ASCII_F)
1197 return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1198 # else
1199 return const_cast<const ctype<char>::mask*> (__ctypec);
1200 # endif
1201 #else
1202 // Platform not supported: abort so the person doing the port knows what to
1203 // fix
1204 # warning ctype<char>::classic_table() is not implemented
1205 printf("ctype<char>::classic_table() is not implemented\n");
1206 abort();
1207 return NULL;
1208 #endif
1210 #endif
1212 #if defined(__GLIBC__)
1213 const int*
1214 ctype<char>::__classic_lower_table() noexcept
1216 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
1219 const int*
1220 ctype<char>::__classic_upper_table() noexcept
1222 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
1224 #elif defined(__NetBSD__)
1225 const short*
1226 ctype<char>::__classic_lower_table() noexcept
1228 return _C_tolower_tab_ + 1;
1231 const short*
1232 ctype<char>::__classic_upper_table() noexcept
1234 return _C_toupper_tab_ + 1;
1237 #elif defined(__EMSCRIPTEN__)
1238 const int*
1239 ctype<char>::__classic_lower_table() noexcept
1241 return *__ctype_tolower_loc();
1244 const int*
1245 ctype<char>::__classic_upper_table() noexcept
1247 return *__ctype_toupper_loc();
1249 #elif defined(__MVS__)
1250 const unsigned short*
1251 ctype<char>::__classic_lower_table() _NOEXCEPT
1253 # if defined(__NATIVE_ASCII_F)
1254 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1255 # else
1256 return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1257 # endif
1259 const unsigned short *
1260 ctype<char>::__classic_upper_table() _NOEXCEPT
1262 # if defined(__NATIVE_ASCII_F)
1263 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1264 # else
1265 return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1266 # endif
1268 #endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
1270 // template <> class ctype_byname<char>
1272 ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1273 : ctype<char>(0, false, refs),
1274 __l_(newlocale(LC_ALL_MASK, name, 0))
1276 if (__l_ == 0)
1277 __throw_runtime_error("ctype_byname<char>::ctype_byname"
1278 " failed to construct for " + string(name));
1281 ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1282 : ctype<char>(0, false, refs),
1283 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1285 if (__l_ == 0)
1286 __throw_runtime_error("ctype_byname<char>::ctype_byname"
1287 " failed to construct for " + name);
1290 ctype_byname<char>::~ctype_byname()
1292 freelocale(__l_);
1295 char
1296 ctype_byname<char>::do_toupper(char_type c) const
1298 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l_));
1301 const char*
1302 ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1304 for (; low != high; ++low)
1305 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l_));
1306 return low;
1309 char
1310 ctype_byname<char>::do_tolower(char_type c) const
1312 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l_));
1315 const char*
1316 ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1318 for (; low != high; ++low)
1319 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l_));
1320 return low;
1323 // template <> class ctype_byname<wchar_t>
1325 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1326 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1327 : ctype<wchar_t>(refs),
1328 __l_(newlocale(LC_ALL_MASK, name, 0))
1330 if (__l_ == 0)
1331 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
1332 " failed to construct for " + string(name));
1335 ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1336 : ctype<wchar_t>(refs),
1337 __l_(newlocale(LC_ALL_MASK, name.c_str(), 0))
1339 if (__l_ == 0)
1340 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
1341 " failed to construct for " + name);
1344 ctype_byname<wchar_t>::~ctype_byname()
1346 freelocale(__l_);
1349 bool
1350 ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1352 #ifdef _LIBCPP_WCTYPE_IS_MASK
1353 return static_cast<bool>(iswctype_l(c, m, __l_));
1354 #else
1355 bool result = false;
1356 wint_t ch = static_cast<wint_t>(c);
1357 if ((m & space) == space) result |= (iswspace_l(ch, __l_) != 0);
1358 if ((m & print) == print) result |= (iswprint_l(ch, __l_) != 0);
1359 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l_) != 0);
1360 if ((m & upper) == upper) result |= (iswupper_l(ch, __l_) != 0);
1361 if ((m & lower) == lower) result |= (iswlower_l(ch, __l_) != 0);
1362 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l_) != 0);
1363 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l_) != 0);
1364 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l_) != 0);
1365 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l_) != 0);
1366 if ((m & blank) == blank) result |= (iswblank_l(ch, __l_) != 0);
1367 return result;
1368 #endif
1371 const wchar_t*
1372 ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1374 for (; low != high; ++low, ++vec)
1376 if (isascii(*low))
1377 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
1378 else
1380 *vec = 0;
1381 wint_t ch = static_cast<wint_t>(*low);
1382 if (iswspace_l(ch, __l_))
1383 *vec |= space;
1384 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
1385 if (iswprint_l(ch, __l_))
1386 *vec |= print;
1387 #endif
1388 if (iswcntrl_l(ch, __l_))
1389 *vec |= cntrl;
1390 if (iswupper_l(ch, __l_))
1391 *vec |= upper;
1392 if (iswlower_l(ch, __l_))
1393 *vec |= lower;
1394 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
1395 if (iswalpha_l(ch, __l_))
1396 *vec |= alpha;
1397 #endif
1398 if (iswdigit_l(ch, __l_))
1399 *vec |= digit;
1400 if (iswpunct_l(ch, __l_))
1401 *vec |= punct;
1402 #ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
1403 if (iswxdigit_l(ch, __l_))
1404 *vec |= xdigit;
1405 #endif
1406 if (iswblank_l(ch, __l_))
1407 *vec |= blank;
1410 return low;
1413 const wchar_t*
1414 ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1416 for (; low != high; ++low)
1418 #ifdef _LIBCPP_WCTYPE_IS_MASK
1419 if (iswctype_l(*low, m, __l_))
1420 break;
1421 #else
1422 wint_t ch = static_cast<wint_t>(*low);
1423 if ((m & space) == space && iswspace_l(ch, __l_)) break;
1424 if ((m & print) == print && iswprint_l(ch, __l_)) break;
1425 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) break;
1426 if ((m & upper) == upper && iswupper_l(ch, __l_)) break;
1427 if ((m & lower) == lower && iswlower_l(ch, __l_)) break;
1428 if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) break;
1429 if ((m & digit) == digit && iswdigit_l(ch, __l_)) break;
1430 if ((m & punct) == punct && iswpunct_l(ch, __l_)) break;
1431 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) break;
1432 if ((m & blank) == blank && iswblank_l(ch, __l_)) break;
1433 #endif
1435 return low;
1438 const wchar_t*
1439 ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1441 for (; low != high; ++low)
1443 #ifdef _LIBCPP_WCTYPE_IS_MASK
1444 if (!iswctype_l(*low, m, __l_))
1445 break;
1446 #else
1447 wint_t ch = static_cast<wint_t>(*low);
1448 if ((m & space) == space && iswspace_l(ch, __l_)) continue;
1449 if ((m & print) == print && iswprint_l(ch, __l_)) continue;
1450 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l_)) continue;
1451 if ((m & upper) == upper && iswupper_l(ch, __l_)) continue;
1452 if ((m & lower) == lower && iswlower_l(ch, __l_)) continue;
1453 if ((m & alpha) == alpha && iswalpha_l(ch, __l_)) continue;
1454 if ((m & digit) == digit && iswdigit_l(ch, __l_)) continue;
1455 if ((m & punct) == punct && iswpunct_l(ch, __l_)) continue;
1456 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l_)) continue;
1457 if ((m & blank) == blank && iswblank_l(ch, __l_)) continue;
1458 break;
1459 #endif
1461 return low;
1464 wchar_t
1465 ctype_byname<wchar_t>::do_toupper(char_type c) const
1467 return towupper_l(c, __l_);
1470 const wchar_t*
1471 ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1473 for (; low != high; ++low)
1474 *low = towupper_l(*low, __l_);
1475 return low;
1478 wchar_t
1479 ctype_byname<wchar_t>::do_tolower(char_type c) const
1481 return towlower_l(c, __l_);
1484 const wchar_t*
1485 ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1487 for (; low != high; ++low)
1488 *low = towlower_l(*low, __l_);
1489 return low;
1492 wchar_t
1493 ctype_byname<wchar_t>::do_widen(char c) const
1495 return __libcpp_btowc_l(c, __l_);
1498 const char*
1499 ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1501 for (; low != high; ++low, ++dest)
1502 *dest = __libcpp_btowc_l(*low, __l_);
1503 return low;
1506 char
1507 ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1509 int r = __libcpp_wctob_l(c, __l_);
1510 return (r != EOF) ? static_cast<char>(r) : dfault;
1513 const wchar_t*
1514 ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1516 for (; low != high; ++low, ++dest)
1518 int r = __libcpp_wctob_l(*low, __l_);
1519 *dest = (r != EOF) ? static_cast<char>(r) : dfault;
1521 return low;
1523 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1525 // template <> class codecvt<char, char, mbstate_t>
1527 locale::id codecvt<char, char, mbstate_t>::id;
1529 codecvt<char, char, mbstate_t>::~codecvt()
1533 codecvt<char, char, mbstate_t>::result
1534 codecvt<char, char, mbstate_t>::do_out(state_type&,
1535 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
1536 extern_type* to, extern_type*, extern_type*& to_nxt) const
1538 frm_nxt = frm;
1539 to_nxt = to;
1540 return noconv;
1543 codecvt<char, char, mbstate_t>::result
1544 codecvt<char, char, mbstate_t>::do_in(state_type&,
1545 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
1546 intern_type* to, intern_type*, intern_type*& to_nxt) const
1548 frm_nxt = frm;
1549 to_nxt = to;
1550 return noconv;
1553 codecvt<char, char, mbstate_t>::result
1554 codecvt<char, char, mbstate_t>::do_unshift(state_type&,
1555 extern_type* to, extern_type*, extern_type*& to_nxt) const
1557 to_nxt = to;
1558 return noconv;
1562 codecvt<char, char, mbstate_t>::do_encoding() const noexcept
1564 return 1;
1567 bool
1568 codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
1570 return true;
1574 codecvt<char, char, mbstate_t>::do_length(state_type&,
1575 const extern_type* frm, const extern_type* end, size_t mx) const
1577 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
1581 codecvt<char, char, mbstate_t>::do_max_length() const noexcept
1583 return 1;
1586 // template <> class codecvt<wchar_t, char, mbstate_t>
1588 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1589 locale::id codecvt<wchar_t, char, mbstate_t>::id;
1591 codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1592 : locale::facet(refs),
1593 __l_(_LIBCPP_GET_C_LOCALE)
1597 codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1598 : locale::facet(refs),
1599 __l_(newlocale(LC_ALL_MASK, nm, 0))
1601 if (__l_ == 0)
1602 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1603 " failed to construct for " + string(nm));
1606 codecvt<wchar_t, char, mbstate_t>::~codecvt()
1608 if (__l_ != _LIBCPP_GET_C_LOCALE)
1609 freelocale(__l_);
1612 codecvt<wchar_t, char, mbstate_t>::result
1613 codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
1614 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1615 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1617 // look for first internal null in frm
1618 const intern_type* fend = frm;
1619 for (; fend != frm_end; ++fend)
1620 if (*fend == 0)
1621 break;
1622 // loop over all null-terminated sequences in frm
1623 to_nxt = to;
1624 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1626 // save state in case it is needed to recover to_nxt on error
1627 mbstate_t save_state = st;
1628 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1629 static_cast<size_t>(to_end-to), &st, __l_);
1630 if (n == size_t(-1))
1632 // need to recover to_nxt
1633 for (to_nxt = to; frm != frm_nxt; ++frm)
1635 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l_);
1636 if (n == size_t(-1))
1637 break;
1638 to_nxt += n;
1640 frm_nxt = frm;
1641 return error;
1643 if (n == 0)
1644 return partial;
1645 to_nxt += n;
1646 if (to_nxt == to_end)
1647 break;
1648 if (fend != frm_end) // set up next null terminated sequence
1650 // Try to write the terminating null
1651 extern_type tmp[MB_LEN_MAX];
1652 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
1653 if (n == size_t(-1)) // on error
1654 return error;
1655 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
1656 return partial;
1657 for (extern_type* p = tmp; n; --n) // write it
1658 *to_nxt++ = *p++;
1659 ++frm_nxt;
1660 // look for next null in frm
1661 for (fend = frm_nxt; fend != frm_end; ++fend)
1662 if (*fend == 0)
1663 break;
1666 return frm_nxt == frm_end ? ok : partial;
1669 codecvt<wchar_t, char, mbstate_t>::result
1670 codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
1671 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1672 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1674 // look for first internal null in frm
1675 const extern_type* fend = frm;
1676 for (; fend != frm_end; ++fend)
1677 if (*fend == 0)
1678 break;
1679 // loop over all null-terminated sequences in frm
1680 to_nxt = to;
1681 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1683 // save state in case it is needed to recover to_nxt on error
1684 mbstate_t save_state = st;
1685 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1686 static_cast<size_t>(to_end-to), &st, __l_);
1687 if (n == size_t(-1))
1689 // need to recover to_nxt
1690 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1692 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1693 &save_state, __l_);
1694 switch (n)
1696 case 0:
1697 ++frm;
1698 break;
1699 case size_t(-1):
1700 frm_nxt = frm;
1701 return error;
1702 case size_t(-2):
1703 frm_nxt = frm;
1704 return partial;
1705 default:
1706 frm += n;
1707 break;
1710 frm_nxt = frm;
1711 return frm_nxt == frm_end ? ok : partial;
1713 if (n == size_t(-1))
1714 return error;
1715 to_nxt += n;
1716 if (to_nxt == to_end)
1717 break;
1718 if (fend != frm_end) // set up next null terminated sequence
1720 // Try to write the terminating null
1721 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l_);
1722 if (n != 0) // on error
1723 return error;
1724 ++to_nxt;
1725 ++frm_nxt;
1726 // look for next null in frm
1727 for (fend = frm_nxt; fend != frm_end; ++fend)
1728 if (*fend == 0)
1729 break;
1732 return frm_nxt == frm_end ? ok : partial;
1735 codecvt<wchar_t, char, mbstate_t>::result
1736 codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1737 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1739 to_nxt = to;
1740 extern_type tmp[MB_LEN_MAX];
1741 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l_);
1742 if (n == size_t(-1) || n == 0) // on error
1743 return error;
1744 --n;
1745 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
1746 return partial;
1747 for (extern_type* p = tmp; n; --n) // write it
1748 *to_nxt++ = *p++;
1749 return ok;
1753 codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
1755 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l_) != 0)
1756 return -1;
1758 // stateless encoding
1759 if (__l_ == 0 || __libcpp_mb_cur_max_l(__l_) == 1) // there are no known constant length encodings
1760 return 1; // which take more than 1 char to form a wchar_t
1761 return 0;
1764 bool
1765 codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
1767 return false;
1771 codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1772 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1774 int nbytes = 0;
1775 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1777 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l_);
1778 switch (n)
1780 case 0:
1781 ++nbytes;
1782 ++frm;
1783 break;
1784 case size_t(-1):
1785 case size_t(-2):
1786 return nbytes;
1787 default:
1788 nbytes += n;
1789 frm += n;
1790 break;
1793 return nbytes;
1797 codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
1799 return __l_ == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l_));
1801 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1803 // Valid UTF ranges
1804 // UTF-32 UTF-16 UTF-8 # of code points
1805 // first second first second third fourth
1806 // 000000 - 00007F 0000 - 007F 00 - 7F 127
1807 // 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1808 // 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1809 // 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1810 // 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1811 // 00D800 - 00DFFF invalid
1812 // 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1813 // 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1814 // 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1815 // 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1817 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
1818 static
1819 codecvt_base::result
1820 utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1821 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1822 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1824 frm_nxt = frm;
1825 to_nxt = to;
1826 if (mode & generate_header)
1828 if (to_end-to_nxt < 3)
1829 return codecvt_base::partial;
1830 *to_nxt++ = static_cast<uint8_t>(0xEF);
1831 *to_nxt++ = static_cast<uint8_t>(0xBB);
1832 *to_nxt++ = static_cast<uint8_t>(0xBF);
1834 for (; frm_nxt < frm_end; ++frm_nxt)
1836 uint16_t wc1 = *frm_nxt;
1837 if (wc1 > Maxcode)
1838 return codecvt_base::error;
1839 if (wc1 < 0x0080)
1841 if (to_end-to_nxt < 1)
1842 return codecvt_base::partial;
1843 *to_nxt++ = static_cast<uint8_t>(wc1);
1845 else if (wc1 < 0x0800)
1847 if (to_end-to_nxt < 2)
1848 return codecvt_base::partial;
1849 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1852 else if (wc1 < 0xD800)
1854 if (to_end-to_nxt < 3)
1855 return codecvt_base::partial;
1856 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1857 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1858 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1860 else if (wc1 < 0xDC00)
1862 if (frm_end-frm_nxt < 2)
1863 return codecvt_base::partial;
1864 uint16_t wc2 = frm_nxt[1];
1865 if ((wc2 & 0xFC00) != 0xDC00)
1866 return codecvt_base::error;
1867 if (to_end-to_nxt < 4)
1868 return codecvt_base::partial;
1869 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1870 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1871 return codecvt_base::error;
1872 ++frm_nxt;
1873 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1874 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1875 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1876 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1877 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1879 else if (wc1 < 0xE000)
1881 return codecvt_base::error;
1883 else
1885 if (to_end-to_nxt < 3)
1886 return codecvt_base::partial;
1887 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1888 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1889 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1892 return codecvt_base::ok;
1895 static
1896 codecvt_base::result
1897 utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1898 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1899 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1901 frm_nxt = frm;
1902 to_nxt = to;
1903 if (mode & generate_header)
1905 if (to_end-to_nxt < 3)
1906 return codecvt_base::partial;
1907 *to_nxt++ = static_cast<uint8_t>(0xEF);
1908 *to_nxt++ = static_cast<uint8_t>(0xBB);
1909 *to_nxt++ = static_cast<uint8_t>(0xBF);
1911 for (; frm_nxt < frm_end; ++frm_nxt)
1913 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1914 if (wc1 > Maxcode)
1915 return codecvt_base::error;
1916 if (wc1 < 0x0080)
1918 if (to_end-to_nxt < 1)
1919 return codecvt_base::partial;
1920 *to_nxt++ = static_cast<uint8_t>(wc1);
1922 else if (wc1 < 0x0800)
1924 if (to_end-to_nxt < 2)
1925 return codecvt_base::partial;
1926 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1927 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1929 else if (wc1 < 0xD800)
1931 if (to_end-to_nxt < 3)
1932 return codecvt_base::partial;
1933 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1934 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1935 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1937 else if (wc1 < 0xDC00)
1939 if (frm_end-frm_nxt < 2)
1940 return codecvt_base::partial;
1941 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1942 if ((wc2 & 0xFC00) != 0xDC00)
1943 return codecvt_base::error;
1944 if (to_end-to_nxt < 4)
1945 return codecvt_base::partial;
1946 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1947 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
1948 return codecvt_base::error;
1949 ++frm_nxt;
1950 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1951 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1952 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1953 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1954 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1956 else if (wc1 < 0xE000)
1958 return codecvt_base::error;
1960 else
1962 if (to_end-to_nxt < 3)
1963 return codecvt_base::partial;
1964 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1965 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1966 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1969 return codecvt_base::ok;
1972 static
1973 codecvt_base::result
1974 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1975 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1976 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1978 frm_nxt = frm;
1979 to_nxt = to;
1980 if (mode & consume_header)
1982 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1983 frm_nxt[2] == 0xBF)
1984 frm_nxt += 3;
1986 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1988 uint8_t c1 = *frm_nxt;
1989 if (c1 > Maxcode)
1990 return codecvt_base::error;
1991 if (c1 < 0x80)
1993 *to_nxt = static_cast<uint16_t>(c1);
1994 ++frm_nxt;
1996 else if (c1 < 0xC2)
1998 return codecvt_base::error;
2000 else if (c1 < 0xE0)
2002 if (frm_end-frm_nxt < 2)
2003 return codecvt_base::partial;
2004 uint8_t c2 = frm_nxt[1];
2005 if ((c2 & 0xC0) != 0x80)
2006 return codecvt_base::error;
2007 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2008 if (t > Maxcode)
2009 return codecvt_base::error;
2010 *to_nxt = t;
2011 frm_nxt += 2;
2013 else if (c1 < 0xF0)
2015 if (frm_end-frm_nxt < 3)
2016 return codecvt_base::partial;
2017 uint8_t c2 = frm_nxt[1];
2018 uint8_t c3 = frm_nxt[2];
2019 switch (c1)
2021 case 0xE0:
2022 if ((c2 & 0xE0) != 0xA0)
2023 return codecvt_base::error;
2024 break;
2025 case 0xED:
2026 if ((c2 & 0xE0) != 0x80)
2027 return codecvt_base::error;
2028 break;
2029 default:
2030 if ((c2 & 0xC0) != 0x80)
2031 return codecvt_base::error;
2032 break;
2034 if ((c3 & 0xC0) != 0x80)
2035 return codecvt_base::error;
2036 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2037 | ((c2 & 0x3F) << 6)
2038 | (c3 & 0x3F));
2039 if (t > Maxcode)
2040 return codecvt_base::error;
2041 *to_nxt = t;
2042 frm_nxt += 3;
2044 else if (c1 < 0xF5)
2046 if (frm_end-frm_nxt < 4)
2047 return codecvt_base::partial;
2048 uint8_t c2 = frm_nxt[1];
2049 uint8_t c3 = frm_nxt[2];
2050 uint8_t c4 = frm_nxt[3];
2051 switch (c1)
2053 case 0xF0:
2054 if (!(0x90 <= c2 && c2 <= 0xBF))
2055 return codecvt_base::error;
2056 break;
2057 case 0xF4:
2058 if ((c2 & 0xF0) != 0x80)
2059 return codecvt_base::error;
2060 break;
2061 default:
2062 if ((c2 & 0xC0) != 0x80)
2063 return codecvt_base::error;
2064 break;
2066 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2067 return codecvt_base::error;
2068 if (to_end-to_nxt < 2)
2069 return codecvt_base::partial;
2070 if ((((c1 & 7UL) << 18) +
2071 ((c2 & 0x3FUL) << 12) +
2072 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2073 return codecvt_base::error;
2074 *to_nxt = static_cast<uint16_t>(
2075 0xD800
2076 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2077 | ((c2 & 0x0F) << 2)
2078 | ((c3 & 0x30) >> 4));
2079 *++to_nxt = static_cast<uint16_t>(
2080 0xDC00
2081 | ((c3 & 0x0F) << 6)
2082 | (c4 & 0x3F));
2083 frm_nxt += 4;
2085 else
2087 return codecvt_base::error;
2090 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2093 static
2094 codecvt_base::result
2095 utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2096 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2097 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2099 frm_nxt = frm;
2100 to_nxt = to;
2101 if (mode & consume_header)
2103 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2104 frm_nxt[2] == 0xBF)
2105 frm_nxt += 3;
2107 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2109 uint8_t c1 = *frm_nxt;
2110 if (c1 > Maxcode)
2111 return codecvt_base::error;
2112 if (c1 < 0x80)
2114 *to_nxt = static_cast<uint32_t>(c1);
2115 ++frm_nxt;
2117 else if (c1 < 0xC2)
2119 return codecvt_base::error;
2121 else if (c1 < 0xE0)
2123 if (frm_end-frm_nxt < 2)
2124 return codecvt_base::partial;
2125 uint8_t c2 = frm_nxt[1];
2126 if ((c2 & 0xC0) != 0x80)
2127 return codecvt_base::error;
2128 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2129 if (t > Maxcode)
2130 return codecvt_base::error;
2131 *to_nxt = static_cast<uint32_t>(t);
2132 frm_nxt += 2;
2134 else if (c1 < 0xF0)
2136 if (frm_end-frm_nxt < 3)
2137 return codecvt_base::partial;
2138 uint8_t c2 = frm_nxt[1];
2139 uint8_t c3 = frm_nxt[2];
2140 switch (c1)
2142 case 0xE0:
2143 if ((c2 & 0xE0) != 0xA0)
2144 return codecvt_base::error;
2145 break;
2146 case 0xED:
2147 if ((c2 & 0xE0) != 0x80)
2148 return codecvt_base::error;
2149 break;
2150 default:
2151 if ((c2 & 0xC0) != 0x80)
2152 return codecvt_base::error;
2153 break;
2155 if ((c3 & 0xC0) != 0x80)
2156 return codecvt_base::error;
2157 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2158 | ((c2 & 0x3F) << 6)
2159 | (c3 & 0x3F));
2160 if (t > Maxcode)
2161 return codecvt_base::error;
2162 *to_nxt = static_cast<uint32_t>(t);
2163 frm_nxt += 3;
2165 else if (c1 < 0xF5)
2167 if (frm_end-frm_nxt < 4)
2168 return codecvt_base::partial;
2169 uint8_t c2 = frm_nxt[1];
2170 uint8_t c3 = frm_nxt[2];
2171 uint8_t c4 = frm_nxt[3];
2172 switch (c1)
2174 case 0xF0:
2175 if (!(0x90 <= c2 && c2 <= 0xBF))
2176 return codecvt_base::error;
2177 break;
2178 case 0xF4:
2179 if ((c2 & 0xF0) != 0x80)
2180 return codecvt_base::error;
2181 break;
2182 default:
2183 if ((c2 & 0xC0) != 0x80)
2184 return codecvt_base::error;
2185 break;
2187 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2188 return codecvt_base::error;
2189 if (to_end-to_nxt < 2)
2190 return codecvt_base::partial;
2191 if ((((c1 & 7UL) << 18) +
2192 ((c2 & 0x3FUL) << 12) +
2193 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2194 return codecvt_base::error;
2195 *to_nxt = static_cast<uint32_t>(
2196 0xD800
2197 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2198 | ((c2 & 0x0F) << 2)
2199 | ((c3 & 0x30) >> 4));
2200 *++to_nxt = static_cast<uint32_t>(
2201 0xDC00
2202 | ((c3 & 0x0F) << 6)
2203 | (c4 & 0x3F));
2204 frm_nxt += 4;
2206 else
2208 return codecvt_base::error;
2211 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2214 static
2216 utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2217 size_t mx, unsigned long Maxcode = 0x10FFFF,
2218 codecvt_mode mode = codecvt_mode(0))
2220 const uint8_t* frm_nxt = frm;
2221 if (mode & consume_header)
2223 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2224 frm_nxt[2] == 0xBF)
2225 frm_nxt += 3;
2227 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2229 uint8_t c1 = *frm_nxt;
2230 if (c1 > Maxcode)
2231 break;
2232 if (c1 < 0x80)
2234 ++frm_nxt;
2236 else if (c1 < 0xC2)
2238 break;
2240 else if (c1 < 0xE0)
2242 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2243 break;
2244 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2245 if (t > Maxcode)
2246 break;
2247 frm_nxt += 2;
2249 else if (c1 < 0xF0)
2251 if (frm_end-frm_nxt < 3)
2252 break;
2253 uint8_t c2 = frm_nxt[1];
2254 uint8_t c3 = frm_nxt[2];
2255 switch (c1)
2257 case 0xE0:
2258 if ((c2 & 0xE0) != 0xA0)
2259 return static_cast<int>(frm_nxt - frm);
2260 break;
2261 case 0xED:
2262 if ((c2 & 0xE0) != 0x80)
2263 return static_cast<int>(frm_nxt - frm);
2264 break;
2265 default:
2266 if ((c2 & 0xC0) != 0x80)
2267 return static_cast<int>(frm_nxt - frm);
2268 break;
2270 if ((c3 & 0xC0) != 0x80)
2271 break;
2272 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2273 break;
2274 frm_nxt += 3;
2276 else if (c1 < 0xF5)
2278 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2279 break;
2280 uint8_t c2 = frm_nxt[1];
2281 uint8_t c3 = frm_nxt[2];
2282 uint8_t c4 = frm_nxt[3];
2283 switch (c1)
2285 case 0xF0:
2286 if (!(0x90 <= c2 && c2 <= 0xBF))
2287 return static_cast<int>(frm_nxt - frm);
2288 break;
2289 case 0xF4:
2290 if ((c2 & 0xF0) != 0x80)
2291 return static_cast<int>(frm_nxt - frm);
2292 break;
2293 default:
2294 if ((c2 & 0xC0) != 0x80)
2295 return static_cast<int>(frm_nxt - frm);
2296 break;
2298 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2299 break;
2300 if ((((c1 & 7UL) << 18) +
2301 ((c2 & 0x3FUL) << 12) +
2302 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
2303 break;
2304 ++nchar16_t;
2305 frm_nxt += 4;
2307 else
2309 break;
2312 return static_cast<int>(frm_nxt - frm);
2315 static
2316 codecvt_base::result
2317 ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2318 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2319 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2321 frm_nxt = frm;
2322 to_nxt = to;
2323 if (mode & generate_header)
2325 if (to_end-to_nxt < 3)
2326 return codecvt_base::partial;
2327 *to_nxt++ = static_cast<uint8_t>(0xEF);
2328 *to_nxt++ = static_cast<uint8_t>(0xBB);
2329 *to_nxt++ = static_cast<uint8_t>(0xBF);
2331 for (; frm_nxt < frm_end; ++frm_nxt)
2333 uint32_t wc = *frm_nxt;
2334 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2335 return codecvt_base::error;
2336 if (wc < 0x000080)
2338 if (to_end-to_nxt < 1)
2339 return codecvt_base::partial;
2340 *to_nxt++ = static_cast<uint8_t>(wc);
2342 else if (wc < 0x000800)
2344 if (to_end-to_nxt < 2)
2345 return codecvt_base::partial;
2346 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2347 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2349 else if (wc < 0x010000)
2351 if (to_end-to_nxt < 3)
2352 return codecvt_base::partial;
2353 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2354 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2355 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2357 else // if (wc < 0x110000)
2359 if (to_end-to_nxt < 4)
2360 return codecvt_base::partial;
2361 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2362 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2363 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2364 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2367 return codecvt_base::ok;
2370 static
2371 codecvt_base::result
2372 utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2373 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2374 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2376 frm_nxt = frm;
2377 to_nxt = to;
2378 if (mode & consume_header)
2380 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2381 frm_nxt[2] == 0xBF)
2382 frm_nxt += 3;
2384 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2386 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2387 if (c1 < 0x80)
2389 if (c1 > Maxcode)
2390 return codecvt_base::error;
2391 *to_nxt = static_cast<uint32_t>(c1);
2392 ++frm_nxt;
2394 else if (c1 < 0xC2)
2396 return codecvt_base::error;
2398 else if (c1 < 0xE0)
2400 if (frm_end-frm_nxt < 2)
2401 return codecvt_base::partial;
2402 uint8_t c2 = frm_nxt[1];
2403 if ((c2 & 0xC0) != 0x80)
2404 return codecvt_base::error;
2405 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2406 | (c2 & 0x3F));
2407 if (t > Maxcode)
2408 return codecvt_base::error;
2409 *to_nxt = t;
2410 frm_nxt += 2;
2412 else if (c1 < 0xF0)
2414 if (frm_end-frm_nxt < 3)
2415 return codecvt_base::partial;
2416 uint8_t c2 = frm_nxt[1];
2417 uint8_t c3 = frm_nxt[2];
2418 switch (c1)
2420 case 0xE0:
2421 if ((c2 & 0xE0) != 0xA0)
2422 return codecvt_base::error;
2423 break;
2424 case 0xED:
2425 if ((c2 & 0xE0) != 0x80)
2426 return codecvt_base::error;
2427 break;
2428 default:
2429 if ((c2 & 0xC0) != 0x80)
2430 return codecvt_base::error;
2431 break;
2433 if ((c3 & 0xC0) != 0x80)
2434 return codecvt_base::error;
2435 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2436 | ((c2 & 0x3F) << 6)
2437 | (c3 & 0x3F));
2438 if (t > Maxcode)
2439 return codecvt_base::error;
2440 *to_nxt = t;
2441 frm_nxt += 3;
2443 else if (c1 < 0xF5)
2445 if (frm_end-frm_nxt < 4)
2446 return codecvt_base::partial;
2447 uint8_t c2 = frm_nxt[1];
2448 uint8_t c3 = frm_nxt[2];
2449 uint8_t c4 = frm_nxt[3];
2450 switch (c1)
2452 case 0xF0:
2453 if (!(0x90 <= c2 && c2 <= 0xBF))
2454 return codecvt_base::error;
2455 break;
2456 case 0xF4:
2457 if ((c2 & 0xF0) != 0x80)
2458 return codecvt_base::error;
2459 break;
2460 default:
2461 if ((c2 & 0xC0) != 0x80)
2462 return codecvt_base::error;
2463 break;
2465 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2466 return codecvt_base::error;
2467 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2468 | ((c2 & 0x3F) << 12)
2469 | ((c3 & 0x3F) << 6)
2470 | (c4 & 0x3F));
2471 if (t > Maxcode)
2472 return codecvt_base::error;
2473 *to_nxt = t;
2474 frm_nxt += 4;
2476 else
2478 return codecvt_base::error;
2481 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2484 static
2486 utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2487 size_t mx, unsigned long Maxcode = 0x10FFFF,
2488 codecvt_mode mode = codecvt_mode(0))
2490 const uint8_t* frm_nxt = frm;
2491 if (mode & consume_header)
2493 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2494 frm_nxt[2] == 0xBF)
2495 frm_nxt += 3;
2497 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2499 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2500 if (c1 < 0x80)
2502 if (c1 > Maxcode)
2503 break;
2504 ++frm_nxt;
2506 else if (c1 < 0xC2)
2508 break;
2510 else if (c1 < 0xE0)
2512 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2513 break;
2514 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2515 break;
2516 frm_nxt += 2;
2518 else if (c1 < 0xF0)
2520 if (frm_end-frm_nxt < 3)
2521 break;
2522 uint8_t c2 = frm_nxt[1];
2523 uint8_t c3 = frm_nxt[2];
2524 switch (c1)
2526 case 0xE0:
2527 if ((c2 & 0xE0) != 0xA0)
2528 return static_cast<int>(frm_nxt - frm);
2529 break;
2530 case 0xED:
2531 if ((c2 & 0xE0) != 0x80)
2532 return static_cast<int>(frm_nxt - frm);
2533 break;
2534 default:
2535 if ((c2 & 0xC0) != 0x80)
2536 return static_cast<int>(frm_nxt - frm);
2537 break;
2539 if ((c3 & 0xC0) != 0x80)
2540 break;
2541 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2542 break;
2543 frm_nxt += 3;
2545 else if (c1 < 0xF5)
2547 if (frm_end-frm_nxt < 4)
2548 break;
2549 uint8_t c2 = frm_nxt[1];
2550 uint8_t c3 = frm_nxt[2];
2551 uint8_t c4 = frm_nxt[3];
2552 switch (c1)
2554 case 0xF0:
2555 if (!(0x90 <= c2 && c2 <= 0xBF))
2556 return static_cast<int>(frm_nxt - frm);
2557 break;
2558 case 0xF4:
2559 if ((c2 & 0xF0) != 0x80)
2560 return static_cast<int>(frm_nxt - frm);
2561 break;
2562 default:
2563 if ((c2 & 0xC0) != 0x80)
2564 return static_cast<int>(frm_nxt - frm);
2565 break;
2567 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2568 break;
2569 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2570 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
2571 break;
2572 frm_nxt += 4;
2574 else
2576 break;
2579 return static_cast<int>(frm_nxt - frm);
2582 static
2583 codecvt_base::result
2584 ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2585 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2586 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2588 frm_nxt = frm;
2589 to_nxt = to;
2590 if (mode & generate_header)
2592 if (to_end-to_nxt < 3)
2593 return codecvt_base::partial;
2594 *to_nxt++ = static_cast<uint8_t>(0xEF);
2595 *to_nxt++ = static_cast<uint8_t>(0xBB);
2596 *to_nxt++ = static_cast<uint8_t>(0xBF);
2598 for (; frm_nxt < frm_end; ++frm_nxt)
2600 uint16_t wc = *frm_nxt;
2601 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2602 return codecvt_base::error;
2603 if (wc < 0x0080)
2605 if (to_end-to_nxt < 1)
2606 return codecvt_base::partial;
2607 *to_nxt++ = static_cast<uint8_t>(wc);
2609 else if (wc < 0x0800)
2611 if (to_end-to_nxt < 2)
2612 return codecvt_base::partial;
2613 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2614 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2616 else // if (wc <= 0xFFFF)
2618 if (to_end-to_nxt < 3)
2619 return codecvt_base::partial;
2620 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2621 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2622 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2625 return codecvt_base::ok;
2628 static
2629 codecvt_base::result
2630 utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2631 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2632 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2634 frm_nxt = frm;
2635 to_nxt = to;
2636 if (mode & consume_header)
2638 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2639 frm_nxt[2] == 0xBF)
2640 frm_nxt += 3;
2642 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2644 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2645 if (c1 < 0x80)
2647 if (c1 > Maxcode)
2648 return codecvt_base::error;
2649 *to_nxt = static_cast<uint16_t>(c1);
2650 ++frm_nxt;
2652 else if (c1 < 0xC2)
2654 return codecvt_base::error;
2656 else if (c1 < 0xE0)
2658 if (frm_end-frm_nxt < 2)
2659 return codecvt_base::partial;
2660 uint8_t c2 = frm_nxt[1];
2661 if ((c2 & 0xC0) != 0x80)
2662 return codecvt_base::error;
2663 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2664 | (c2 & 0x3F));
2665 if (t > Maxcode)
2666 return codecvt_base::error;
2667 *to_nxt = t;
2668 frm_nxt += 2;
2670 else if (c1 < 0xF0)
2672 if (frm_end-frm_nxt < 3)
2673 return codecvt_base::partial;
2674 uint8_t c2 = frm_nxt[1];
2675 uint8_t c3 = frm_nxt[2];
2676 switch (c1)
2678 case 0xE0:
2679 if ((c2 & 0xE0) != 0xA0)
2680 return codecvt_base::error;
2681 break;
2682 case 0xED:
2683 if ((c2 & 0xE0) != 0x80)
2684 return codecvt_base::error;
2685 break;
2686 default:
2687 if ((c2 & 0xC0) != 0x80)
2688 return codecvt_base::error;
2689 break;
2691 if ((c3 & 0xC0) != 0x80)
2692 return codecvt_base::error;
2693 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2694 | ((c2 & 0x3F) << 6)
2695 | (c3 & 0x3F));
2696 if (t > Maxcode)
2697 return codecvt_base::error;
2698 *to_nxt = t;
2699 frm_nxt += 3;
2701 else
2703 return codecvt_base::error;
2706 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2709 static
2711 utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2712 size_t mx, unsigned long Maxcode = 0x10FFFF,
2713 codecvt_mode mode = codecvt_mode(0))
2715 const uint8_t* frm_nxt = frm;
2716 if (mode & consume_header)
2718 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2719 frm_nxt[2] == 0xBF)
2720 frm_nxt += 3;
2722 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2724 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2725 if (c1 < 0x80)
2727 if (c1 > Maxcode)
2728 break;
2729 ++frm_nxt;
2731 else if (c1 < 0xC2)
2733 break;
2735 else if (c1 < 0xE0)
2737 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2738 break;
2739 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
2740 break;
2741 frm_nxt += 2;
2743 else if (c1 < 0xF0)
2745 if (frm_end-frm_nxt < 3)
2746 break;
2747 uint8_t c2 = frm_nxt[1];
2748 uint8_t c3 = frm_nxt[2];
2749 switch (c1)
2751 case 0xE0:
2752 if ((c2 & 0xE0) != 0xA0)
2753 return static_cast<int>(frm_nxt - frm);
2754 break;
2755 case 0xED:
2756 if ((c2 & 0xE0) != 0x80)
2757 return static_cast<int>(frm_nxt - frm);
2758 break;
2759 default:
2760 if ((c2 & 0xC0) != 0x80)
2761 return static_cast<int>(frm_nxt - frm);
2762 break;
2764 if ((c3 & 0xC0) != 0x80)
2765 break;
2766 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
2767 break;
2768 frm_nxt += 3;
2770 else
2772 break;
2775 return static_cast<int>(frm_nxt - frm);
2778 static
2779 codecvt_base::result
2780 ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2781 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2782 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2784 frm_nxt = frm;
2785 to_nxt = to;
2786 if (mode & generate_header)
2788 if (to_end-to_nxt < 2)
2789 return codecvt_base::partial;
2790 *to_nxt++ = static_cast<uint8_t>(0xFE);
2791 *to_nxt++ = static_cast<uint8_t>(0xFF);
2793 for (; frm_nxt < frm_end; ++frm_nxt)
2795 uint32_t wc = *frm_nxt;
2796 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2797 return codecvt_base::error;
2798 if (wc < 0x010000)
2800 if (to_end-to_nxt < 2)
2801 return codecvt_base::partial;
2802 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2803 *to_nxt++ = static_cast<uint8_t>(wc);
2805 else
2807 if (to_end-to_nxt < 4)
2808 return codecvt_base::partial;
2809 uint16_t t = static_cast<uint16_t>(
2810 0xD800
2811 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2812 | ((wc & 0x00FC00) >> 10));
2813 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2814 *to_nxt++ = static_cast<uint8_t>(t);
2815 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2816 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2817 *to_nxt++ = static_cast<uint8_t>(t);
2820 return codecvt_base::ok;
2823 static
2824 codecvt_base::result
2825 utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2826 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2827 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2829 frm_nxt = frm;
2830 to_nxt = to;
2831 if (mode & consume_header)
2833 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2834 frm_nxt += 2;
2836 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2838 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2839 if ((c1 & 0xFC00) == 0xDC00)
2840 return codecvt_base::error;
2841 if ((c1 & 0xFC00) != 0xD800)
2843 if (c1 > Maxcode)
2844 return codecvt_base::error;
2845 *to_nxt = static_cast<uint32_t>(c1);
2846 frm_nxt += 2;
2848 else
2850 if (frm_end-frm_nxt < 4)
2851 return codecvt_base::partial;
2852 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2853 if ((c2 & 0xFC00) != 0xDC00)
2854 return codecvt_base::error;
2855 uint32_t t = static_cast<uint32_t>(
2856 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2857 | ((c1 & 0x003F) << 10)
2858 | (c2 & 0x03FF));
2859 if (t > Maxcode)
2860 return codecvt_base::error;
2861 *to_nxt = t;
2862 frm_nxt += 4;
2865 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2868 static
2870 utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2871 size_t mx, unsigned long Maxcode = 0x10FFFF,
2872 codecvt_mode mode = codecvt_mode(0))
2874 const uint8_t* frm_nxt = frm;
2875 if (mode & consume_header)
2877 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2878 frm_nxt += 2;
2880 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2882 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
2883 if ((c1 & 0xFC00) == 0xDC00)
2884 break;
2885 if ((c1 & 0xFC00) != 0xD800)
2887 if (c1 > Maxcode)
2888 break;
2889 frm_nxt += 2;
2891 else
2893 if (frm_end-frm_nxt < 4)
2894 break;
2895 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
2896 if ((c2 & 0xFC00) != 0xDC00)
2897 break;
2898 uint32_t t = static_cast<uint32_t>(
2899 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2900 | ((c1 & 0x003F) << 10)
2901 | (c2 & 0x03FF));
2902 if (t > Maxcode)
2903 break;
2904 frm_nxt += 4;
2907 return static_cast<int>(frm_nxt - frm);
2910 static
2911 codecvt_base::result
2912 ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2913 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2914 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2916 frm_nxt = frm;
2917 to_nxt = to;
2918 if (mode & generate_header)
2920 if (to_end - to_nxt < 2)
2921 return codecvt_base::partial;
2922 *to_nxt++ = static_cast<uint8_t>(0xFF);
2923 *to_nxt++ = static_cast<uint8_t>(0xFE);
2925 for (; frm_nxt < frm_end; ++frm_nxt)
2927 uint32_t wc = *frm_nxt;
2928 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2929 return codecvt_base::error;
2930 if (wc < 0x010000)
2932 if (to_end-to_nxt < 2)
2933 return codecvt_base::partial;
2934 *to_nxt++ = static_cast<uint8_t>(wc);
2935 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2937 else
2939 if (to_end-to_nxt < 4)
2940 return codecvt_base::partial;
2941 uint16_t t = static_cast<uint16_t>(
2942 0xD800
2943 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2944 | ((wc & 0x00FC00) >> 10));
2945 *to_nxt++ = static_cast<uint8_t>(t);
2946 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2947 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2948 *to_nxt++ = static_cast<uint8_t>(t);
2949 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2952 return codecvt_base::ok;
2955 static
2956 codecvt_base::result
2957 utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2958 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2959 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2961 frm_nxt = frm;
2962 to_nxt = to;
2963 if (mode & consume_header)
2965 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2966 frm_nxt += 2;
2968 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2970 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
2971 if ((c1 & 0xFC00) == 0xDC00)
2972 return codecvt_base::error;
2973 if ((c1 & 0xFC00) != 0xD800)
2975 if (c1 > Maxcode)
2976 return codecvt_base::error;
2977 *to_nxt = static_cast<uint32_t>(c1);
2978 frm_nxt += 2;
2980 else
2982 if (frm_end-frm_nxt < 4)
2983 return codecvt_base::partial;
2984 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
2985 if ((c2 & 0xFC00) != 0xDC00)
2986 return codecvt_base::error;
2987 uint32_t t = static_cast<uint32_t>(
2988 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2989 | ((c1 & 0x003F) << 10)
2990 | (c2 & 0x03FF));
2991 if (t > Maxcode)
2992 return codecvt_base::error;
2993 *to_nxt = t;
2994 frm_nxt += 4;
2997 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3000 static
3002 utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
3003 size_t mx, unsigned long Maxcode = 0x10FFFF,
3004 codecvt_mode mode = codecvt_mode(0))
3006 const uint8_t* frm_nxt = frm;
3007 if (mode & consume_header)
3009 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3010 frm_nxt += 2;
3012 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3014 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3015 if ((c1 & 0xFC00) == 0xDC00)
3016 break;
3017 if ((c1 & 0xFC00) != 0xD800)
3019 if (c1 > Maxcode)
3020 break;
3021 frm_nxt += 2;
3023 else
3025 if (frm_end-frm_nxt < 4)
3026 break;
3027 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
3028 if ((c2 & 0xFC00) != 0xDC00)
3029 break;
3030 uint32_t t = static_cast<uint32_t>(
3031 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3032 | ((c1 & 0x003F) << 10)
3033 | (c2 & 0x03FF));
3034 if (t > Maxcode)
3035 break;
3036 frm_nxt += 4;
3039 return static_cast<int>(frm_nxt - frm);
3042 static
3043 codecvt_base::result
3044 ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3045 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3046 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3048 frm_nxt = frm;
3049 to_nxt = to;
3050 if (mode & generate_header)
3052 if (to_end-to_nxt < 2)
3053 return codecvt_base::partial;
3054 *to_nxt++ = static_cast<uint8_t>(0xFE);
3055 *to_nxt++ = static_cast<uint8_t>(0xFF);
3057 for (; frm_nxt < frm_end; ++frm_nxt)
3059 uint16_t wc = *frm_nxt;
3060 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3061 return codecvt_base::error;
3062 if (to_end-to_nxt < 2)
3063 return codecvt_base::partial;
3064 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3065 *to_nxt++ = static_cast<uint8_t>(wc);
3067 return codecvt_base::ok;
3070 static
3071 codecvt_base::result
3072 utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3073 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3074 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3076 frm_nxt = frm;
3077 to_nxt = to;
3078 if (mode & consume_header)
3080 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3081 frm_nxt += 2;
3083 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3085 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3086 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3087 return codecvt_base::error;
3088 *to_nxt = c1;
3089 frm_nxt += 2;
3091 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3094 static
3096 utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3097 size_t mx, unsigned long Maxcode = 0x10FFFF,
3098 codecvt_mode mode = codecvt_mode(0))
3100 const uint8_t* frm_nxt = frm;
3101 if (mode & consume_header)
3103 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3104 frm_nxt += 2;
3106 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3108 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
3109 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3110 break;
3111 frm_nxt += 2;
3113 return static_cast<int>(frm_nxt - frm);
3116 static
3117 codecvt_base::result
3118 ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3119 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3120 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3122 frm_nxt = frm;
3123 to_nxt = to;
3124 if (mode & generate_header)
3126 if (to_end-to_nxt < 2)
3127 return codecvt_base::partial;
3128 *to_nxt++ = static_cast<uint8_t>(0xFF);
3129 *to_nxt++ = static_cast<uint8_t>(0xFE);
3131 for (; frm_nxt < frm_end; ++frm_nxt)
3133 uint16_t wc = *frm_nxt;
3134 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3135 return codecvt_base::error;
3136 if (to_end-to_nxt < 2)
3137 return codecvt_base::partial;
3138 *to_nxt++ = static_cast<uint8_t>(wc);
3139 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3141 return codecvt_base::ok;
3144 static
3145 codecvt_base::result
3146 utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3147 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3148 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3150 frm_nxt = frm;
3151 to_nxt = to;
3152 if (mode & consume_header)
3154 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3155 frm_nxt += 2;
3157 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3159 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3160 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3161 return codecvt_base::error;
3162 *to_nxt = c1;
3163 frm_nxt += 2;
3165 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3168 static
3170 utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3171 size_t mx, unsigned long Maxcode = 0x10FFFF,
3172 codecvt_mode mode = codecvt_mode(0))
3174 const uint8_t* frm_nxt = frm;
3175 frm_nxt = frm;
3176 if (mode & consume_header)
3178 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3179 frm_nxt += 2;
3181 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3183 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
3184 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3185 break;
3186 frm_nxt += 2;
3188 return static_cast<int>(frm_nxt - frm);
3191 _LIBCPP_SUPPRESS_DEPRECATED_POP
3193 // template <> class codecvt<char16_t, char, mbstate_t>
3195 locale::id codecvt<char16_t, char, mbstate_t>::id;
3197 codecvt<char16_t, char, mbstate_t>::~codecvt()
3201 codecvt<char16_t, char, mbstate_t>::result
3202 codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
3203 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3204 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3206 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3207 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3208 const uint16_t* _frm_nxt = _frm;
3209 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3210 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3211 uint8_t* _to_nxt = _to;
3212 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3213 frm_nxt = frm + (_frm_nxt - _frm);
3214 to_nxt = to + (_to_nxt - _to);
3215 return r;
3218 codecvt<char16_t, char, mbstate_t>::result
3219 codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
3220 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3221 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3223 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3224 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3225 const uint8_t* _frm_nxt = _frm;
3226 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3227 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3228 uint16_t* _to_nxt = _to;
3229 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3230 frm_nxt = frm + (_frm_nxt - _frm);
3231 to_nxt = to + (_to_nxt - _to);
3232 return r;
3235 codecvt<char16_t, char, mbstate_t>::result
3236 codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3237 extern_type* to, extern_type*, extern_type*& to_nxt) const
3239 to_nxt = to;
3240 return noconv;
3244 codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
3246 return 0;
3249 bool
3250 codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
3252 return false;
3256 codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3257 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3259 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3260 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3261 return utf8_to_utf16_length(_frm, _frm_end, mx);
3265 codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
3267 return 4;
3270 #ifndef _LIBCPP_HAS_NO_CHAR8_T
3272 // template <> class codecvt<char16_t, char8_t, mbstate_t>
3274 locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3276 codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3280 codecvt<char16_t, char8_t, mbstate_t>::result
3281 codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3282 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3283 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3285 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3286 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3287 const uint16_t* _frm_nxt = _frm;
3288 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3289 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3290 uint8_t* _to_nxt = _to;
3291 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3292 frm_nxt = frm + (_frm_nxt - _frm);
3293 to_nxt = to + (_to_nxt - _to);
3294 return r;
3297 codecvt<char16_t, char8_t, mbstate_t>::result
3298 codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3299 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3300 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3302 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3303 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3304 const uint8_t* _frm_nxt = _frm;
3305 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3306 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3307 uint16_t* _to_nxt = _to;
3308 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3309 frm_nxt = frm + (_frm_nxt - _frm);
3310 to_nxt = to + (_to_nxt - _to);
3311 return r;
3314 codecvt<char16_t, char8_t, mbstate_t>::result
3315 codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3316 extern_type* to, extern_type*, extern_type*& to_nxt) const
3318 to_nxt = to;
3319 return noconv;
3323 codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
3325 return 0;
3328 bool
3329 codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3331 return false;
3335 codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3336 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3338 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3339 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3340 return utf8_to_utf16_length(_frm, _frm_end, mx);
3344 codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
3346 return 4;
3349 #endif
3351 // template <> class codecvt<char32_t, char, mbstate_t>
3353 locale::id codecvt<char32_t, char, mbstate_t>::id;
3355 codecvt<char32_t, char, mbstate_t>::~codecvt()
3359 codecvt<char32_t, char, mbstate_t>::result
3360 codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
3361 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3362 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3364 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3365 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3366 const uint32_t* _frm_nxt = _frm;
3367 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3368 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3369 uint8_t* _to_nxt = _to;
3370 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3371 frm_nxt = frm + (_frm_nxt - _frm);
3372 to_nxt = to + (_to_nxt - _to);
3373 return r;
3376 codecvt<char32_t, char, mbstate_t>::result
3377 codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
3378 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3379 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3381 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3382 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3383 const uint8_t* _frm_nxt = _frm;
3384 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3385 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3386 uint32_t* _to_nxt = _to;
3387 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3388 frm_nxt = frm + (_frm_nxt - _frm);
3389 to_nxt = to + (_to_nxt - _to);
3390 return r;
3393 codecvt<char32_t, char, mbstate_t>::result
3394 codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3395 extern_type* to, extern_type*, extern_type*& to_nxt) const
3397 to_nxt = to;
3398 return noconv;
3402 codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
3404 return 0;
3407 bool
3408 codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
3410 return false;
3414 codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3415 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3417 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3418 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3419 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3423 codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
3425 return 4;
3428 #ifndef _LIBCPP_HAS_NO_CHAR8_T
3430 // template <> class codecvt<char32_t, char8_t, mbstate_t>
3432 locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3434 codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3438 codecvt<char32_t, char8_t, mbstate_t>::result
3439 codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3440 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3441 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3443 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3444 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3445 const uint32_t* _frm_nxt = _frm;
3446 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3447 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3448 uint8_t* _to_nxt = _to;
3449 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3450 frm_nxt = frm + (_frm_nxt - _frm);
3451 to_nxt = to + (_to_nxt - _to);
3452 return r;
3455 codecvt<char32_t, char8_t, mbstate_t>::result
3456 codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3457 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3458 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3460 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3461 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3462 const uint8_t* _frm_nxt = _frm;
3463 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3464 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3465 uint32_t* _to_nxt = _to;
3466 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3467 frm_nxt = frm + (_frm_nxt - _frm);
3468 to_nxt = to + (_to_nxt - _to);
3469 return r;
3472 codecvt<char32_t, char8_t, mbstate_t>::result
3473 codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3474 extern_type* to, extern_type*, extern_type*& to_nxt) const
3476 to_nxt = to;
3477 return noconv;
3481 codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
3483 return 0;
3486 bool
3487 codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
3489 return false;
3493 codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3494 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3496 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3497 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3498 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3502 codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
3504 return 4;
3507 #endif
3509 // __codecvt_utf8<wchar_t>
3511 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3512 __codecvt_utf8<wchar_t>::result
3513 __codecvt_utf8<wchar_t>::do_out(state_type&,
3514 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3515 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3517 #if defined(_LIBCPP_SHORT_WCHAR)
3518 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3519 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3520 const uint16_t* _frm_nxt = _frm;
3521 #else
3522 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3523 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3524 const uint32_t* _frm_nxt = _frm;
3525 #endif
3526 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3527 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3528 uint8_t* _to_nxt = _to;
3529 #if defined(_LIBCPP_SHORT_WCHAR)
3530 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3531 __maxcode_, __mode_);
3532 #else
3533 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3534 __maxcode_, __mode_);
3535 #endif
3536 frm_nxt = frm + (_frm_nxt - _frm);
3537 to_nxt = to + (_to_nxt - _to);
3538 return r;
3541 __codecvt_utf8<wchar_t>::result
3542 __codecvt_utf8<wchar_t>::do_in(state_type&,
3543 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3544 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3546 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3547 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3548 const uint8_t* _frm_nxt = _frm;
3549 #if defined(_LIBCPP_SHORT_WCHAR)
3550 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3551 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3552 uint16_t* _to_nxt = _to;
3553 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3554 __maxcode_, __mode_);
3555 #else
3556 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3557 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3558 uint32_t* _to_nxt = _to;
3559 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3560 __maxcode_, __mode_);
3561 #endif
3562 frm_nxt = frm + (_frm_nxt - _frm);
3563 to_nxt = to + (_to_nxt - _to);
3564 return r;
3567 __codecvt_utf8<wchar_t>::result
3568 __codecvt_utf8<wchar_t>::do_unshift(state_type&,
3569 extern_type* to, extern_type*, extern_type*& to_nxt) const
3571 to_nxt = to;
3572 return noconv;
3576 __codecvt_utf8<wchar_t>::do_encoding() const noexcept
3578 return 0;
3581 bool
3582 __codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
3584 return false;
3588 __codecvt_utf8<wchar_t>::do_length(state_type&,
3589 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3591 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3592 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3593 #if defined(_LIBCPP_SHORT_WCHAR)
3594 return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3595 #else
3596 return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3597 #endif
3600 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3602 __codecvt_utf8<wchar_t>::do_max_length() const noexcept
3604 #if defined(_LIBCPP_SHORT_WCHAR)
3605 if (__mode_ & consume_header)
3606 return 6;
3607 return 3;
3608 #else
3609 if (__mode_ & consume_header)
3610 return 7;
3611 return 4;
3612 #endif
3614 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3616 // __codecvt_utf8<char16_t>
3618 __codecvt_utf8<char16_t>::result
3619 __codecvt_utf8<char16_t>::do_out(state_type&,
3620 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3621 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3623 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3624 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3625 const uint16_t* _frm_nxt = _frm;
3626 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3627 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3628 uint8_t* _to_nxt = _to;
3629 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3630 __maxcode_, __mode_);
3631 frm_nxt = frm + (_frm_nxt - _frm);
3632 to_nxt = to + (_to_nxt - _to);
3633 return r;
3636 __codecvt_utf8<char16_t>::result
3637 __codecvt_utf8<char16_t>::do_in(state_type&,
3638 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3639 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3641 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3642 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3643 const uint8_t* _frm_nxt = _frm;
3644 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3645 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3646 uint16_t* _to_nxt = _to;
3647 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3648 __maxcode_, __mode_);
3649 frm_nxt = frm + (_frm_nxt - _frm);
3650 to_nxt = to + (_to_nxt - _to);
3651 return r;
3654 __codecvt_utf8<char16_t>::result
3655 __codecvt_utf8<char16_t>::do_unshift(state_type&,
3656 extern_type* to, extern_type*, extern_type*& to_nxt) const
3658 to_nxt = to;
3659 return noconv;
3663 __codecvt_utf8<char16_t>::do_encoding() const noexcept
3665 return 0;
3668 bool
3669 __codecvt_utf8<char16_t>::do_always_noconv() const noexcept
3671 return false;
3675 __codecvt_utf8<char16_t>::do_length(state_type&,
3676 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3678 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3679 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3680 return utf8_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3683 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3685 __codecvt_utf8<char16_t>::do_max_length() const noexcept
3687 if (__mode_ & consume_header)
3688 return 6;
3689 return 3;
3691 _LIBCPP_SUPPRESS_DEPRECATED_POP
3693 // __codecvt_utf8<char32_t>
3695 __codecvt_utf8<char32_t>::result
3696 __codecvt_utf8<char32_t>::do_out(state_type&,
3697 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3698 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3700 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3701 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3702 const uint32_t* _frm_nxt = _frm;
3703 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3704 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3705 uint8_t* _to_nxt = _to;
3706 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3707 __maxcode_, __mode_);
3708 frm_nxt = frm + (_frm_nxt - _frm);
3709 to_nxt = to + (_to_nxt - _to);
3710 return r;
3713 __codecvt_utf8<char32_t>::result
3714 __codecvt_utf8<char32_t>::do_in(state_type&,
3715 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3716 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3718 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3719 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3720 const uint8_t* _frm_nxt = _frm;
3721 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3722 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3723 uint32_t* _to_nxt = _to;
3724 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3725 __maxcode_, __mode_);
3726 frm_nxt = frm + (_frm_nxt - _frm);
3727 to_nxt = to + (_to_nxt - _to);
3728 return r;
3731 __codecvt_utf8<char32_t>::result
3732 __codecvt_utf8<char32_t>::do_unshift(state_type&,
3733 extern_type* to, extern_type*, extern_type*& to_nxt) const
3735 to_nxt = to;
3736 return noconv;
3740 __codecvt_utf8<char32_t>::do_encoding() const noexcept
3742 return 0;
3745 bool
3746 __codecvt_utf8<char32_t>::do_always_noconv() const noexcept
3748 return false;
3752 __codecvt_utf8<char32_t>::do_length(state_type&,
3753 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3755 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3756 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3757 return utf8_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3760 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
3762 __codecvt_utf8<char32_t>::do_max_length() const noexcept
3764 if (__mode_ & consume_header)
3765 return 7;
3766 return 4;
3768 _LIBCPP_SUPPRESS_DEPRECATED_POP
3770 // __codecvt_utf16<wchar_t, false>
3772 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
3773 __codecvt_utf16<wchar_t, false>::result
3774 __codecvt_utf16<wchar_t, false>::do_out(state_type&,
3775 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3776 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3778 #if defined(_LIBCPP_SHORT_WCHAR)
3779 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3780 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3781 const uint16_t* _frm_nxt = _frm;
3782 #else
3783 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3784 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3785 const uint32_t* _frm_nxt = _frm;
3786 #endif
3787 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3788 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3789 uint8_t* _to_nxt = _to;
3790 #if defined(_LIBCPP_SHORT_WCHAR)
3791 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3792 __maxcode_, __mode_);
3793 #else
3794 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3795 __maxcode_, __mode_);
3796 #endif
3797 frm_nxt = frm + (_frm_nxt - _frm);
3798 to_nxt = to + (_to_nxt - _to);
3799 return r;
3802 __codecvt_utf16<wchar_t, false>::result
3803 __codecvt_utf16<wchar_t, false>::do_in(state_type&,
3804 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3805 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3807 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3808 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3809 const uint8_t* _frm_nxt = _frm;
3810 #if defined(_LIBCPP_SHORT_WCHAR)
3811 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3812 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3813 uint16_t* _to_nxt = _to;
3814 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3815 __maxcode_, __mode_);
3816 #else
3817 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3818 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3819 uint32_t* _to_nxt = _to;
3820 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3821 __maxcode_, __mode_);
3822 #endif
3823 frm_nxt = frm + (_frm_nxt - _frm);
3824 to_nxt = to + (_to_nxt - _to);
3825 return r;
3828 __codecvt_utf16<wchar_t, false>::result
3829 __codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3830 extern_type* to, extern_type*, extern_type*& to_nxt) const
3832 to_nxt = to;
3833 return noconv;
3837 __codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
3839 return 0;
3842 bool
3843 __codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
3845 return false;
3849 __codecvt_utf16<wchar_t, false>::do_length(state_type&,
3850 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3852 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3853 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3854 #if defined(_LIBCPP_SHORT_WCHAR)
3855 return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3856 #else
3857 return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3858 #endif
3862 __codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
3864 #if defined(_LIBCPP_SHORT_WCHAR)
3865 if (__mode_ & consume_header)
3866 return 4;
3867 return 2;
3868 #else
3869 if (__mode_ & consume_header)
3870 return 6;
3871 return 4;
3872 #endif
3875 // __codecvt_utf16<wchar_t, true>
3877 __codecvt_utf16<wchar_t, true>::result
3878 __codecvt_utf16<wchar_t, true>::do_out(state_type&,
3879 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3880 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3882 #if defined(_LIBCPP_SHORT_WCHAR)
3883 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3884 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3885 const uint16_t* _frm_nxt = _frm;
3886 #else
3887 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3888 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3889 const uint32_t* _frm_nxt = _frm;
3890 #endif
3891 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3892 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3893 uint8_t* _to_nxt = _to;
3894 #if defined(_LIBCPP_SHORT_WCHAR)
3895 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3896 __maxcode_, __mode_);
3897 #else
3898 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3899 __maxcode_, __mode_);
3900 #endif
3901 frm_nxt = frm + (_frm_nxt - _frm);
3902 to_nxt = to + (_to_nxt - _to);
3903 return r;
3906 __codecvt_utf16<wchar_t, true>::result
3907 __codecvt_utf16<wchar_t, true>::do_in(state_type&,
3908 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3909 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3911 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3912 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3913 const uint8_t* _frm_nxt = _frm;
3914 #if defined(_LIBCPP_SHORT_WCHAR)
3915 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3916 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3917 uint16_t* _to_nxt = _to;
3918 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3919 __maxcode_, __mode_);
3920 #else
3921 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3922 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3923 uint32_t* _to_nxt = _to;
3924 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3925 __maxcode_, __mode_);
3926 #endif
3927 frm_nxt = frm + (_frm_nxt - _frm);
3928 to_nxt = to + (_to_nxt - _to);
3929 return r;
3932 __codecvt_utf16<wchar_t, true>::result
3933 __codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3934 extern_type* to, extern_type*, extern_type*& to_nxt) const
3936 to_nxt = to;
3937 return noconv;
3941 __codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
3943 return 0;
3946 bool
3947 __codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
3949 return false;
3953 __codecvt_utf16<wchar_t, true>::do_length(state_type&,
3954 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3956 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3957 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3958 #if defined(_LIBCPP_SHORT_WCHAR)
3959 return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3960 #else
3961 return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
3962 #endif
3966 __codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
3968 #if defined(_LIBCPP_SHORT_WCHAR)
3969 if (__mode_ & consume_header)
3970 return 4;
3971 return 2;
3972 #else
3973 if (__mode_ & consume_header)
3974 return 6;
3975 return 4;
3976 #endif
3978 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
3980 // __codecvt_utf16<char16_t, false>
3982 __codecvt_utf16<char16_t, false>::result
3983 __codecvt_utf16<char16_t, false>::do_out(state_type&,
3984 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3985 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3987 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3988 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3989 const uint16_t* _frm_nxt = _frm;
3990 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3991 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3992 uint8_t* _to_nxt = _to;
3993 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3994 __maxcode_, __mode_);
3995 frm_nxt = frm + (_frm_nxt - _frm);
3996 to_nxt = to + (_to_nxt - _to);
3997 return r;
4000 __codecvt_utf16<char16_t, false>::result
4001 __codecvt_utf16<char16_t, false>::do_in(state_type&,
4002 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4003 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4005 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4006 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4007 const uint8_t* _frm_nxt = _frm;
4008 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4009 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4010 uint16_t* _to_nxt = _to;
4011 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4012 __maxcode_, __mode_);
4013 frm_nxt = frm + (_frm_nxt - _frm);
4014 to_nxt = to + (_to_nxt - _to);
4015 return r;
4018 __codecvt_utf16<char16_t, false>::result
4019 __codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4020 extern_type* to, extern_type*, extern_type*& to_nxt) const
4022 to_nxt = to;
4023 return noconv;
4027 __codecvt_utf16<char16_t, false>::do_encoding() const noexcept
4029 return 0;
4032 bool
4033 __codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
4035 return false;
4039 __codecvt_utf16<char16_t, false>::do_length(state_type&,
4040 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4042 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4043 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4044 return utf16be_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4047 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4049 __codecvt_utf16<char16_t, false>::do_max_length() const noexcept
4051 if (__mode_ & consume_header)
4052 return 4;
4053 return 2;
4055 _LIBCPP_SUPPRESS_DEPRECATED_POP
4057 // __codecvt_utf16<char16_t, true>
4059 __codecvt_utf16<char16_t, true>::result
4060 __codecvt_utf16<char16_t, true>::do_out(state_type&,
4061 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4062 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4064 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4065 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4066 const uint16_t* _frm_nxt = _frm;
4067 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4068 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4069 uint8_t* _to_nxt = _to;
4070 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4071 __maxcode_, __mode_);
4072 frm_nxt = frm + (_frm_nxt - _frm);
4073 to_nxt = to + (_to_nxt - _to);
4074 return r;
4077 __codecvt_utf16<char16_t, true>::result
4078 __codecvt_utf16<char16_t, true>::do_in(state_type&,
4079 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4080 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4082 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4083 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4084 const uint8_t* _frm_nxt = _frm;
4085 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4086 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4087 uint16_t* _to_nxt = _to;
4088 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4089 __maxcode_, __mode_);
4090 frm_nxt = frm + (_frm_nxt - _frm);
4091 to_nxt = to + (_to_nxt - _to);
4092 return r;
4095 __codecvt_utf16<char16_t, true>::result
4096 __codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4097 extern_type* to, extern_type*, extern_type*& to_nxt) const
4099 to_nxt = to;
4100 return noconv;
4104 __codecvt_utf16<char16_t, true>::do_encoding() const noexcept
4106 return 0;
4109 bool
4110 __codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
4112 return false;
4116 __codecvt_utf16<char16_t, true>::do_length(state_type&,
4117 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4119 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4120 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4121 return utf16le_to_ucs2_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4124 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4126 __codecvt_utf16<char16_t, true>::do_max_length() const noexcept
4128 if (__mode_ & consume_header)
4129 return 4;
4130 return 2;
4132 _LIBCPP_SUPPRESS_DEPRECATED_POP
4134 // __codecvt_utf16<char32_t, false>
4136 __codecvt_utf16<char32_t, false>::result
4137 __codecvt_utf16<char32_t, false>::do_out(state_type&,
4138 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4139 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4141 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4142 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4143 const uint32_t* _frm_nxt = _frm;
4144 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4145 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4146 uint8_t* _to_nxt = _to;
4147 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4148 __maxcode_, __mode_);
4149 frm_nxt = frm + (_frm_nxt - _frm);
4150 to_nxt = to + (_to_nxt - _to);
4151 return r;
4154 __codecvt_utf16<char32_t, false>::result
4155 __codecvt_utf16<char32_t, false>::do_in(state_type&,
4156 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4157 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4159 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4160 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4161 const uint8_t* _frm_nxt = _frm;
4162 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4163 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4164 uint32_t* _to_nxt = _to;
4165 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4166 __maxcode_, __mode_);
4167 frm_nxt = frm + (_frm_nxt - _frm);
4168 to_nxt = to + (_to_nxt - _to);
4169 return r;
4172 __codecvt_utf16<char32_t, false>::result
4173 __codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4174 extern_type* to, extern_type*, extern_type*& to_nxt) const
4176 to_nxt = to;
4177 return noconv;
4181 __codecvt_utf16<char32_t, false>::do_encoding() const noexcept
4183 return 0;
4186 bool
4187 __codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
4189 return false;
4193 __codecvt_utf16<char32_t, false>::do_length(state_type&,
4194 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4196 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4197 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4198 return utf16be_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4201 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4203 __codecvt_utf16<char32_t, false>::do_max_length() const noexcept
4205 if (__mode_ & consume_header)
4206 return 6;
4207 return 4;
4209 _LIBCPP_SUPPRESS_DEPRECATED_POP
4211 // __codecvt_utf16<char32_t, true>
4213 __codecvt_utf16<char32_t, true>::result
4214 __codecvt_utf16<char32_t, true>::do_out(state_type&,
4215 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4216 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4218 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4219 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4220 const uint32_t* _frm_nxt = _frm;
4221 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4222 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4223 uint8_t* _to_nxt = _to;
4224 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4225 __maxcode_, __mode_);
4226 frm_nxt = frm + (_frm_nxt - _frm);
4227 to_nxt = to + (_to_nxt - _to);
4228 return r;
4231 __codecvt_utf16<char32_t, true>::result
4232 __codecvt_utf16<char32_t, true>::do_in(state_type&,
4233 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4234 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4236 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4237 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4238 const uint8_t* _frm_nxt = _frm;
4239 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4240 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4241 uint32_t* _to_nxt = _to;
4242 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4243 __maxcode_, __mode_);
4244 frm_nxt = frm + (_frm_nxt - _frm);
4245 to_nxt = to + (_to_nxt - _to);
4246 return r;
4249 __codecvt_utf16<char32_t, true>::result
4250 __codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4251 extern_type* to, extern_type*, extern_type*& to_nxt) const
4253 to_nxt = to;
4254 return noconv;
4258 __codecvt_utf16<char32_t, true>::do_encoding() const noexcept
4260 return 0;
4263 bool
4264 __codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
4266 return false;
4270 __codecvt_utf16<char32_t, true>::do_length(state_type&,
4271 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4273 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4274 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4275 return utf16le_to_ucs4_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4278 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4280 __codecvt_utf16<char32_t, true>::do_max_length() const noexcept
4282 if (__mode_ & consume_header)
4283 return 6;
4284 return 4;
4286 _LIBCPP_SUPPRESS_DEPRECATED_POP
4288 // __codecvt_utf8_utf16<wchar_t>
4290 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4291 __codecvt_utf8_utf16<wchar_t>::result
4292 __codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4293 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4294 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4296 #if defined(_LIBCPP_SHORT_WCHAR)
4297 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4298 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4299 const uint16_t* _frm_nxt = _frm;
4300 #else
4301 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4302 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4303 const uint32_t* _frm_nxt = _frm;
4304 #endif
4305 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4306 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4307 uint8_t* _to_nxt = _to;
4308 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4309 __maxcode_, __mode_);
4310 frm_nxt = frm + (_frm_nxt - _frm);
4311 to_nxt = to + (_to_nxt - _to);
4312 return r;
4315 __codecvt_utf8_utf16<wchar_t>::result
4316 __codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4317 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4318 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4320 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4321 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4322 const uint8_t* _frm_nxt = _frm;
4323 #if defined(_LIBCPP_SHORT_WCHAR)
4324 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4325 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4326 uint16_t* _to_nxt = _to;
4327 #else
4328 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4329 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4330 uint32_t* _to_nxt = _to;
4331 #endif
4332 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4333 __maxcode_, __mode_);
4334 frm_nxt = frm + (_frm_nxt - _frm);
4335 to_nxt = to + (_to_nxt - _to);
4336 return r;
4339 __codecvt_utf8_utf16<wchar_t>::result
4340 __codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4341 extern_type* to, extern_type*, extern_type*& to_nxt) const
4343 to_nxt = to;
4344 return noconv;
4348 __codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
4350 return 0;
4353 bool
4354 __codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
4356 return false;
4360 __codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4361 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4363 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4364 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4365 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4369 __codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
4371 if (__mode_ & consume_header)
4372 return 7;
4373 return 4;
4375 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4377 // __codecvt_utf8_utf16<char16_t>
4379 __codecvt_utf8_utf16<char16_t>::result
4380 __codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4381 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4382 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4384 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4385 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4386 const uint16_t* _frm_nxt = _frm;
4387 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4388 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4389 uint8_t* _to_nxt = _to;
4390 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4391 __maxcode_, __mode_);
4392 frm_nxt = frm + (_frm_nxt - _frm);
4393 to_nxt = to + (_to_nxt - _to);
4394 return r;
4397 __codecvt_utf8_utf16<char16_t>::result
4398 __codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4399 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4400 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4402 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4403 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4404 const uint8_t* _frm_nxt = _frm;
4405 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4406 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4407 uint16_t* _to_nxt = _to;
4408 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4409 __maxcode_, __mode_);
4410 frm_nxt = frm + (_frm_nxt - _frm);
4411 to_nxt = to + (_to_nxt - _to);
4412 return r;
4415 __codecvt_utf8_utf16<char16_t>::result
4416 __codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4417 extern_type* to, extern_type*, extern_type*& to_nxt) const
4419 to_nxt = to;
4420 return noconv;
4424 __codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
4426 return 0;
4429 bool
4430 __codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
4432 return false;
4436 __codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4437 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4439 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4440 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4441 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4444 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4446 __codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
4448 if (__mode_ & consume_header)
4449 return 7;
4450 return 4;
4452 _LIBCPP_SUPPRESS_DEPRECATED_POP
4454 // __codecvt_utf8_utf16<char32_t>
4456 __codecvt_utf8_utf16<char32_t>::result
4457 __codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4458 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4459 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4461 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4462 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4463 const uint32_t* _frm_nxt = _frm;
4464 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4465 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4466 uint8_t* _to_nxt = _to;
4467 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4468 __maxcode_, __mode_);
4469 frm_nxt = frm + (_frm_nxt - _frm);
4470 to_nxt = to + (_to_nxt - _to);
4471 return r;
4474 __codecvt_utf8_utf16<char32_t>::result
4475 __codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4476 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4477 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4479 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4480 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4481 const uint8_t* _frm_nxt = _frm;
4482 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4483 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4484 uint32_t* _to_nxt = _to;
4485 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4486 __maxcode_, __mode_);
4487 frm_nxt = frm + (_frm_nxt - _frm);
4488 to_nxt = to + (_to_nxt - _to);
4489 return r;
4492 __codecvt_utf8_utf16<char32_t>::result
4493 __codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4494 extern_type* to, extern_type*, extern_type*& to_nxt) const
4496 to_nxt = to;
4497 return noconv;
4501 __codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
4503 return 0;
4506 bool
4507 __codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
4509 return false;
4513 __codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4514 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4516 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4517 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4518 return utf8_to_utf16_length(_frm, _frm_end, mx, __maxcode_, __mode_);
4521 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
4523 __codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
4525 if (__mode_ & consume_header)
4526 return 7;
4527 return 4;
4529 _LIBCPP_SUPPRESS_DEPRECATED_POP
4531 // __narrow_to_utf8<16>
4533 __narrow_to_utf8<16>::~__narrow_to_utf8()
4537 // __narrow_to_utf8<32>
4539 __narrow_to_utf8<32>::~__narrow_to_utf8()
4543 // __widen_from_utf8<16>
4545 __widen_from_utf8<16>::~__widen_from_utf8()
4549 // __widen_from_utf8<32>
4551 __widen_from_utf8<32>::~__widen_from_utf8()
4555 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4556 static bool checked_string_to_wchar_convert(wchar_t& dest,
4557 const char* ptr,
4558 locale_t loc) {
4559 if (*ptr == '\0')
4560 return false;
4561 mbstate_t mb = {};
4562 wchar_t out;
4563 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4564 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4565 return false;
4567 dest = out;
4568 return true;
4570 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4572 #ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4573 static bool is_narrow_non_breaking_space(const char* ptr) {
4574 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4575 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4578 static bool is_non_breaking_space(const char* ptr) {
4579 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4580 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4582 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4584 static bool checked_string_to_char_convert(char& dest,
4585 const char* ptr,
4586 locale_t __loc) {
4587 if (*ptr == '\0')
4588 return false;
4589 if (!ptr[1]) {
4590 dest = *ptr;
4591 return true;
4594 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4595 // First convert the MBS into a wide char then attempt to narrow it using
4596 // wctob_l.
4597 wchar_t wout;
4598 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4599 return false;
4600 int res;
4601 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4602 dest = res;
4603 return true;
4605 // FIXME: Work around specific multibyte sequences that we can reasonably
4606 // translate into a different single byte.
4607 switch (wout) {
4608 case L'\u202F': // narrow non-breaking space
4609 case L'\u00A0': // non-breaking space
4610 dest = ' ';
4611 return true;
4612 default:
4613 return false;
4615 #else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4616 // FIXME: Work around specific multibyte sequences that we can reasonably
4617 // translate into a different single byte.
4618 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4619 dest = ' ';
4620 return true;
4623 return false;
4624 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4625 __libcpp_unreachable();
4629 // numpunct<char> && numpunct<wchar_t>
4631 locale::id numpunct< char >::id;
4632 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4633 locale::id numpunct<wchar_t>::id;
4634 #endif
4636 numpunct<char>::numpunct(size_t refs)
4637 : locale::facet(refs),
4638 __decimal_point_('.'),
4639 __thousands_sep_(',')
4643 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4644 numpunct<wchar_t>::numpunct(size_t refs)
4645 : locale::facet(refs),
4646 __decimal_point_(L'.'),
4647 __thousands_sep_(L',')
4650 #endif
4652 numpunct<char>::~numpunct()
4656 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4657 numpunct<wchar_t>::~numpunct()
4660 #endif
4662 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4663 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4664 wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4665 #endif
4667 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4668 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4669 wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4670 #endif
4672 string numpunct< char >::do_grouping() const {return __grouping_;}
4673 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4674 string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4675 #endif
4677 string numpunct< char >::do_truename() const {return "true";}
4678 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4679 wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4680 #endif
4682 string numpunct< char >::do_falsename() const {return "false";}
4683 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4684 wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4685 #endif
4687 // numpunct_byname<char>
4689 numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4690 : numpunct<char>(refs)
4692 __init(nm);
4695 numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4696 : numpunct<char>(refs)
4698 __init(nm.c_str());
4701 numpunct_byname<char>::~numpunct_byname()
4705 void
4706 numpunct_byname<char>::__init(const char* nm)
4708 typedef numpunct<char> base;
4709 if (strcmp(nm, "C") != 0)
4711 __libcpp_unique_locale loc(nm);
4712 if (!loc)
4713 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
4714 " failed to construct for " + string(nm));
4716 lconv* lc = __libcpp_localeconv_l(loc.get());
4717 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4718 loc.get()))
4719 __decimal_point_ = base::do_decimal_point();
4720 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4721 loc.get()))
4722 __thousands_sep_ = base::do_thousands_sep();
4723 __grouping_ = lc->grouping;
4724 // localization for truename and falsename is not available
4728 // numpunct_byname<wchar_t>
4730 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4731 numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4732 : numpunct<wchar_t>(refs)
4734 __init(nm);
4737 numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4738 : numpunct<wchar_t>(refs)
4740 __init(nm.c_str());
4743 numpunct_byname<wchar_t>::~numpunct_byname()
4747 void
4748 numpunct_byname<wchar_t>::__init(const char* nm)
4750 if (strcmp(nm, "C") != 0)
4752 __libcpp_unique_locale loc(nm);
4753 if (!loc)
4754 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
4755 " failed to construct for " + string(nm));
4757 lconv* lc = __libcpp_localeconv_l(loc.get());
4758 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4759 loc.get());
4760 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4761 loc.get());
4762 __grouping_ = lc->grouping;
4763 // localization for truename and falsename is not available
4766 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4768 // num_get helpers
4771 __num_get_base::__get_base(ios_base& iob)
4773 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4774 if (__basefield == ios_base::oct)
4775 return 8;
4776 else if (__basefield == ios_base::hex)
4777 return 16;
4778 else if (__basefield == 0)
4779 return 0;
4780 return 10;
4783 const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4785 void
4786 __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4787 ios_base::iostate& __err)
4789 // if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4790 // we always have at least a single entry in [__g, __g_end); the end of the input sequence
4791 if (__grouping.size() != 0 && __g_end - __g > 1)
4793 reverse(__g, __g_end);
4794 const char* __ig = __grouping.data();
4795 const char* __eg = __ig + __grouping.size();
4796 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4798 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4800 if (static_cast<unsigned>(*__ig) != *__r)
4802 __err = ios_base::failbit;
4803 return;
4806 if (__eg - __ig > 1)
4807 ++__ig;
4809 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4811 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
4812 __err = ios_base::failbit;
4817 void
4818 __num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4819 ios_base::fmtflags __flags)
4821 if ((__flags & ios_base::showpos) &&
4822 (__flags & ios_base::basefield) != ios_base::oct &&
4823 (__flags & ios_base::basefield) != ios_base::hex &&
4824 __signd)
4825 *__fmtp++ = '+';
4826 if (__flags & ios_base::showbase)
4827 *__fmtp++ = '#';
4828 while(*__len)
4829 *__fmtp++ = *__len++;
4830 if ((__flags & ios_base::basefield) == ios_base::oct)
4831 *__fmtp = 'o';
4832 else if ((__flags & ios_base::basefield) == ios_base::hex)
4834 if (__flags & ios_base::uppercase)
4835 *__fmtp = 'X';
4836 else
4837 *__fmtp = 'x';
4839 else if (__signd)
4840 *__fmtp = 'd';
4841 else
4842 *__fmtp = 'u';
4845 bool
4846 __num_put_base::__format_float(char* __fmtp, const char* __len,
4847 ios_base::fmtflags __flags)
4849 bool specify_precision = true;
4850 if (__flags & ios_base::showpos)
4851 *__fmtp++ = '+';
4852 if (__flags & ios_base::showpoint)
4853 *__fmtp++ = '#';
4854 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4855 bool uppercase = (__flags & ios_base::uppercase) != 0;
4856 if (floatfield == (ios_base::fixed | ios_base::scientific))
4857 specify_precision = false;
4858 else
4860 *__fmtp++ = '.';
4861 *__fmtp++ = '*';
4863 while(*__len)
4864 *__fmtp++ = *__len++;
4865 if (floatfield == ios_base::fixed)
4867 if (uppercase)
4868 *__fmtp = 'F';
4869 else
4870 *__fmtp = 'f';
4872 else if (floatfield == ios_base::scientific)
4874 if (uppercase)
4875 *__fmtp = 'E';
4876 else
4877 *__fmtp = 'e';
4879 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4881 if (uppercase)
4882 *__fmtp = 'A';
4883 else
4884 *__fmtp = 'a';
4886 else
4888 if (uppercase)
4889 *__fmtp = 'G';
4890 else
4891 *__fmtp = 'g';
4893 return specify_precision;
4896 char*
4897 __num_put_base::__identify_padding(char* __nb, char* __ne,
4898 const ios_base& __iob)
4900 switch (__iob.flags() & ios_base::adjustfield)
4902 case ios_base::internal:
4903 if (__nb[0] == '-' || __nb[0] == '+')
4904 return __nb+1;
4905 if (__ne - __nb >= 2 && __nb[0] == '0'
4906 && (__nb[1] == 'x' || __nb[1] == 'X'))
4907 return __nb+2;
4908 break;
4909 case ios_base::left:
4910 return __ne;
4911 case ios_base::right:
4912 default:
4913 break;
4915 return __nb;
4918 // time_get
4920 static
4921 string*
4922 init_weeks()
4924 static string weeks[14];
4925 weeks[0] = "Sunday";
4926 weeks[1] = "Monday";
4927 weeks[2] = "Tuesday";
4928 weeks[3] = "Wednesday";
4929 weeks[4] = "Thursday";
4930 weeks[5] = "Friday";
4931 weeks[6] = "Saturday";
4932 weeks[7] = "Sun";
4933 weeks[8] = "Mon";
4934 weeks[9] = "Tue";
4935 weeks[10] = "Wed";
4936 weeks[11] = "Thu";
4937 weeks[12] = "Fri";
4938 weeks[13] = "Sat";
4939 return weeks;
4942 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4943 static
4944 wstring*
4945 init_wweeks()
4947 static wstring weeks[14];
4948 weeks[0] = L"Sunday";
4949 weeks[1] = L"Monday";
4950 weeks[2] = L"Tuesday";
4951 weeks[3] = L"Wednesday";
4952 weeks[4] = L"Thursday";
4953 weeks[5] = L"Friday";
4954 weeks[6] = L"Saturday";
4955 weeks[7] = L"Sun";
4956 weeks[8] = L"Mon";
4957 weeks[9] = L"Tue";
4958 weeks[10] = L"Wed";
4959 weeks[11] = L"Thu";
4960 weeks[12] = L"Fri";
4961 weeks[13] = L"Sat";
4962 return weeks;
4964 #endif
4966 template <>
4967 const string*
4968 __time_get_c_storage<char>::__weeks() const
4970 static const string* weeks = init_weeks();
4971 return weeks;
4974 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4975 template <>
4976 const wstring*
4977 __time_get_c_storage<wchar_t>::__weeks() const
4979 static const wstring* weeks = init_wweeks();
4980 return weeks;
4982 #endif
4984 static
4985 string*
4986 init_months()
4988 static string months[24];
4989 months[0] = "January";
4990 months[1] = "February";
4991 months[2] = "March";
4992 months[3] = "April";
4993 months[4] = "May";
4994 months[5] = "June";
4995 months[6] = "July";
4996 months[7] = "August";
4997 months[8] = "September";
4998 months[9] = "October";
4999 months[10] = "November";
5000 months[11] = "December";
5001 months[12] = "Jan";
5002 months[13] = "Feb";
5003 months[14] = "Mar";
5004 months[15] = "Apr";
5005 months[16] = "May";
5006 months[17] = "Jun";
5007 months[18] = "Jul";
5008 months[19] = "Aug";
5009 months[20] = "Sep";
5010 months[21] = "Oct";
5011 months[22] = "Nov";
5012 months[23] = "Dec";
5013 return months;
5016 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5017 static
5018 wstring*
5019 init_wmonths()
5021 static wstring months[24];
5022 months[0] = L"January";
5023 months[1] = L"February";
5024 months[2] = L"March";
5025 months[3] = L"April";
5026 months[4] = L"May";
5027 months[5] = L"June";
5028 months[6] = L"July";
5029 months[7] = L"August";
5030 months[8] = L"September";
5031 months[9] = L"October";
5032 months[10] = L"November";
5033 months[11] = L"December";
5034 months[12] = L"Jan";
5035 months[13] = L"Feb";
5036 months[14] = L"Mar";
5037 months[15] = L"Apr";
5038 months[16] = L"May";
5039 months[17] = L"Jun";
5040 months[18] = L"Jul";
5041 months[19] = L"Aug";
5042 months[20] = L"Sep";
5043 months[21] = L"Oct";
5044 months[22] = L"Nov";
5045 months[23] = L"Dec";
5046 return months;
5048 #endif
5050 template <>
5051 const string*
5052 __time_get_c_storage<char>::__months() const
5054 static const string* months = init_months();
5055 return months;
5058 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5059 template <>
5060 const wstring*
5061 __time_get_c_storage<wchar_t>::__months() const
5063 static const wstring* months = init_wmonths();
5064 return months;
5066 #endif
5068 static
5069 string*
5070 init_am_pm()
5072 static string am_pm[2];
5073 am_pm[0] = "AM";
5074 am_pm[1] = "PM";
5075 return am_pm;
5078 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5079 static
5080 wstring*
5081 init_wam_pm()
5083 static wstring am_pm[2];
5084 am_pm[0] = L"AM";
5085 am_pm[1] = L"PM";
5086 return am_pm;
5088 #endif
5090 template <>
5091 const string*
5092 __time_get_c_storage<char>::__am_pm() const
5094 static const string* am_pm = init_am_pm();
5095 return am_pm;
5098 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5099 template <>
5100 const wstring*
5101 __time_get_c_storage<wchar_t>::__am_pm() const
5103 static const wstring* am_pm = init_wam_pm();
5104 return am_pm;
5106 #endif
5108 template <>
5109 const string&
5110 __time_get_c_storage<char>::__x() const
5112 static string s("%m/%d/%y");
5113 return s;
5116 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5117 template <>
5118 const wstring&
5119 __time_get_c_storage<wchar_t>::__x() const
5121 static wstring s(L"%m/%d/%y");
5122 return s;
5124 #endif
5126 template <>
5127 const string&
5128 __time_get_c_storage<char>::__X() const
5130 static string s("%H:%M:%S");
5131 return s;
5134 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5135 template <>
5136 const wstring&
5137 __time_get_c_storage<wchar_t>::__X() const
5139 static wstring s(L"%H:%M:%S");
5140 return s;
5142 #endif
5144 template <>
5145 const string&
5146 __time_get_c_storage<char>::__c() const
5148 static string s("%a %b %d %H:%M:%S %Y");
5149 return s;
5152 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5153 template <>
5154 const wstring&
5155 __time_get_c_storage<wchar_t>::__c() const
5157 static wstring s(L"%a %b %d %H:%M:%S %Y");
5158 return s;
5160 #endif
5162 template <>
5163 const string&
5164 __time_get_c_storage<char>::__r() const
5166 static string s("%I:%M:%S %p");
5167 return s;
5170 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5171 template <>
5172 const wstring&
5173 __time_get_c_storage<wchar_t>::__r() const
5175 static wstring s(L"%I:%M:%S %p");
5176 return s;
5178 #endif
5180 // time_get_byname
5182 __time_get::__time_get(const char* nm)
5183 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5185 if (__loc_ == 0)
5186 __throw_runtime_error("time_get_byname"
5187 " failed to construct for " + string(nm));
5190 __time_get::__time_get(const string& nm)
5191 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5193 if (__loc_ == 0)
5194 __throw_runtime_error("time_get_byname"
5195 " failed to construct for " + nm);
5198 __time_get::~__time_get()
5200 freelocale(__loc_);
5203 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
5205 template <>
5206 string
5207 __time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5209 tm t = {0};
5210 t.tm_sec = 59;
5211 t.tm_min = 55;
5212 t.tm_hour = 23;
5213 t.tm_mday = 31;
5214 t.tm_mon = 11;
5215 t.tm_year = 161;
5216 t.tm_wday = 6;
5217 t.tm_yday = 364;
5218 t.tm_isdst = -1;
5219 char buf[100];
5220 char f[3] = {0};
5221 f[0] = '%';
5222 f[1] = fmt;
5223 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
5224 char* bb = buf;
5225 char* be = buf + n;
5226 string result;
5227 while (bb != be)
5229 if (ct.is(ctype_base::space, *bb))
5231 result.push_back(' ');
5232 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5234 continue;
5236 char* w = bb;
5237 ios_base::iostate err = ios_base::goodbit;
5238 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
5239 ct, err, false)
5240 - this->__weeks_;
5241 if (i < 14)
5243 result.push_back('%');
5244 if (i < 7)
5245 result.push_back('A');
5246 else
5247 result.push_back('a');
5248 bb = w;
5249 continue;
5251 w = bb;
5252 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5253 ct, err, false)
5254 - this->__months_;
5255 if (i < 24)
5257 result.push_back('%');
5258 if (i < 12)
5259 result.push_back('B');
5260 else
5261 result.push_back('b');
5262 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5263 result.back() = 'm';
5264 bb = w;
5265 continue;
5267 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5269 w = bb;
5270 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5271 ct, err, false) - this->__am_pm_;
5272 if (i < 2)
5274 result.push_back('%');
5275 result.push_back('p');
5276 bb = w;
5277 continue;
5280 w = bb;
5281 if (ct.is(ctype_base::digit, *bb))
5283 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5285 case 6:
5286 result.push_back('%');
5287 result.push_back('w');
5288 break;
5289 case 7:
5290 result.push_back('%');
5291 result.push_back('u');
5292 break;
5293 case 11:
5294 result.push_back('%');
5295 result.push_back('I');
5296 break;
5297 case 12:
5298 result.push_back('%');
5299 result.push_back('m');
5300 break;
5301 case 23:
5302 result.push_back('%');
5303 result.push_back('H');
5304 break;
5305 case 31:
5306 result.push_back('%');
5307 result.push_back('d');
5308 break;
5309 case 55:
5310 result.push_back('%');
5311 result.push_back('M');
5312 break;
5313 case 59:
5314 result.push_back('%');
5315 result.push_back('S');
5316 break;
5317 case 61:
5318 result.push_back('%');
5319 result.push_back('y');
5320 break;
5321 case 364:
5322 result.push_back('%');
5323 result.push_back('j');
5324 break;
5325 case 2061:
5326 result.push_back('%');
5327 result.push_back('Y');
5328 break;
5329 default:
5330 for (; w != bb; ++w)
5331 result.push_back(*w);
5332 break;
5334 continue;
5336 if (*bb == '%')
5338 result.push_back('%');
5339 result.push_back('%');
5340 ++bb;
5341 continue;
5343 result.push_back(*bb);
5344 ++bb;
5346 return result;
5349 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces")
5351 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5352 template <>
5353 wstring
5354 __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5356 tm t = {0};
5357 t.tm_sec = 59;
5358 t.tm_min = 55;
5359 t.tm_hour = 23;
5360 t.tm_mday = 31;
5361 t.tm_mon = 11;
5362 t.tm_year = 161;
5363 t.tm_wday = 6;
5364 t.tm_yday = 364;
5365 t.tm_isdst = -1;
5366 char buf[100];
5367 char f[3] = {0};
5368 f[0] = '%';
5369 f[1] = fmt;
5370 strftime_l(buf, countof(buf), f, &t, __loc_);
5371 wchar_t wbuf[100];
5372 wchar_t* wbb = wbuf;
5373 mbstate_t mb = {0};
5374 const char* bb = buf;
5375 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
5376 if (j == size_t(-1))
5377 __throw_runtime_error("locale not supported");
5378 wchar_t* wbe = wbb + j;
5379 wstring result;
5380 while (wbb != wbe)
5382 if (ct.is(ctype_base::space, *wbb))
5384 result.push_back(L' ');
5385 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5387 continue;
5389 wchar_t* w = wbb;
5390 ios_base::iostate err = ios_base::goodbit;
5391 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
5392 ct, err, false)
5393 - this->__weeks_;
5394 if (i < 14)
5396 result.push_back(L'%');
5397 if (i < 7)
5398 result.push_back(L'A');
5399 else
5400 result.push_back(L'a');
5401 wbb = w;
5402 continue;
5404 w = wbb;
5405 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5406 ct, err, false)
5407 - this->__months_;
5408 if (i < 24)
5410 result.push_back(L'%');
5411 if (i < 12)
5412 result.push_back(L'B');
5413 else
5414 result.push_back(L'b');
5415 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5416 result.back() = L'm';
5417 wbb = w;
5418 continue;
5420 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5422 w = wbb;
5423 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5424 ct, err, false) - this->__am_pm_;
5425 if (i < 2)
5427 result.push_back(L'%');
5428 result.push_back(L'p');
5429 wbb = w;
5430 continue;
5433 w = wbb;
5434 if (ct.is(ctype_base::digit, *wbb))
5436 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5438 case 6:
5439 result.push_back(L'%');
5440 result.push_back(L'w');
5441 break;
5442 case 7:
5443 result.push_back(L'%');
5444 result.push_back(L'u');
5445 break;
5446 case 11:
5447 result.push_back(L'%');
5448 result.push_back(L'I');
5449 break;
5450 case 12:
5451 result.push_back(L'%');
5452 result.push_back(L'm');
5453 break;
5454 case 23:
5455 result.push_back(L'%');
5456 result.push_back(L'H');
5457 break;
5458 case 31:
5459 result.push_back(L'%');
5460 result.push_back(L'd');
5461 break;
5462 case 55:
5463 result.push_back(L'%');
5464 result.push_back(L'M');
5465 break;
5466 case 59:
5467 result.push_back(L'%');
5468 result.push_back(L'S');
5469 break;
5470 case 61:
5471 result.push_back(L'%');
5472 result.push_back(L'y');
5473 break;
5474 case 364:
5475 result.push_back(L'%');
5476 result.push_back(L'j');
5477 break;
5478 case 2061:
5479 result.push_back(L'%');
5480 result.push_back(L'Y');
5481 break;
5482 default:
5483 for (; w != wbb; ++w)
5484 result.push_back(*w);
5485 break;
5487 continue;
5489 if (ct.narrow(*wbb, 0) == '%')
5491 result.push_back(L'%');
5492 result.push_back(L'%');
5493 ++wbb;
5494 continue;
5496 result.push_back(*wbb);
5497 ++wbb;
5499 return result;
5501 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5503 template <>
5504 void
5505 __time_get_storage<char>::init(const ctype<char>& ct)
5507 tm t = {0};
5508 char buf[100];
5509 // __weeks_
5510 for (int i = 0; i < 7; ++i)
5512 t.tm_wday = i;
5513 strftime_l(buf, countof(buf), "%A", &t, __loc_);
5514 __weeks_[i] = buf;
5515 strftime_l(buf, countof(buf), "%a", &t, __loc_);
5516 __weeks_[i+7] = buf;
5518 // __months_
5519 for (int i = 0; i < 12; ++i)
5521 t.tm_mon = i;
5522 strftime_l(buf, countof(buf), "%B", &t, __loc_);
5523 __months_[i] = buf;
5524 strftime_l(buf, countof(buf), "%b", &t, __loc_);
5525 __months_[i+12] = buf;
5527 // __am_pm_
5528 t.tm_hour = 1;
5529 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5530 __am_pm_[0] = buf;
5531 t.tm_hour = 13;
5532 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5533 __am_pm_[1] = buf;
5534 __c_ = __analyze('c', ct);
5535 __r_ = __analyze('r', ct);
5536 __x_ = __analyze('x', ct);
5537 __X_ = __analyze('X', ct);
5540 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5541 template <>
5542 void
5543 __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5545 tm t = {0};
5546 char buf[100];
5547 wchar_t wbuf[100];
5548 wchar_t* wbe;
5549 mbstate_t mb = {0};
5550 // __weeks_
5551 for (int i = 0; i < 7; ++i)
5553 t.tm_wday = i;
5554 strftime_l(buf, countof(buf), "%A", &t, __loc_);
5555 mb = mbstate_t();
5556 const char* bb = buf;
5557 size_t 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 __weeks_[i].assign(wbuf, wbe);
5562 strftime_l(buf, countof(buf), "%a", &t, __loc_);
5563 mb = mbstate_t();
5564 bb = buf;
5565 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5566 if (j == size_t(-1) || j == 0)
5567 __throw_runtime_error("locale not supported");
5568 wbe = wbuf + j;
5569 __weeks_[i+7].assign(wbuf, wbe);
5571 // __months_
5572 for (int i = 0; i < 12; ++i)
5574 t.tm_mon = i;
5575 strftime_l(buf, countof(buf), "%B", &t, __loc_);
5576 mb = mbstate_t();
5577 const char* bb = buf;
5578 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5579 if (j == size_t(-1) || j == 0)
5580 __throw_runtime_error("locale not supported");
5581 wbe = wbuf + j;
5582 __months_[i].assign(wbuf, wbe);
5583 strftime_l(buf, countof(buf), "%b", &t, __loc_);
5584 mb = mbstate_t();
5585 bb = buf;
5586 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5587 if (j == size_t(-1) || j == 0)
5588 __throw_runtime_error("locale not supported");
5589 wbe = wbuf + j;
5590 __months_[i+12].assign(wbuf, wbe);
5592 // __am_pm_
5593 t.tm_hour = 1;
5594 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5595 mb = mbstate_t();
5596 const char* bb = buf;
5597 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5598 if (j == size_t(-1))
5599 __throw_runtime_error("locale not supported");
5600 wbe = wbuf + j;
5601 __am_pm_[0].assign(wbuf, wbe);
5602 t.tm_hour = 13;
5603 strftime_l(buf, countof(buf), "%p", &t, __loc_);
5604 mb = mbstate_t();
5605 bb = buf;
5606 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
5607 if (j == size_t(-1))
5608 __throw_runtime_error("locale not supported");
5609 wbe = wbuf + j;
5610 __am_pm_[1].assign(wbuf, wbe);
5611 __c_ = __analyze('c', ct);
5612 __r_ = __analyze('r', ct);
5613 __x_ = __analyze('x', ct);
5614 __X_ = __analyze('X', ct);
5616 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5618 template <class CharT>
5619 struct _LIBCPP_HIDDEN __time_get_temp
5620 : public ctype_byname<CharT>
5622 explicit __time_get_temp(const char* nm)
5623 : ctype_byname<CharT>(nm, 1) {}
5624 explicit __time_get_temp(const string& nm)
5625 : ctype_byname<CharT>(nm, 1) {}
5628 template <>
5629 __time_get_storage<char>::__time_get_storage(const char* __nm)
5630 : __time_get(__nm)
5632 const __time_get_temp<char> ct(__nm);
5633 init(ct);
5636 template <>
5637 __time_get_storage<char>::__time_get_storage(const string& __nm)
5638 : __time_get(__nm)
5640 const __time_get_temp<char> ct(__nm);
5641 init(ct);
5644 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5645 template <>
5646 __time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5647 : __time_get(__nm)
5649 const __time_get_temp<wchar_t> ct(__nm);
5650 init(ct);
5653 template <>
5654 __time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5655 : __time_get(__nm)
5657 const __time_get_temp<wchar_t> ct(__nm);
5658 init(ct);
5660 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5662 template <>
5663 time_base::dateorder
5664 __time_get_storage<char>::__do_date_order() const
5666 unsigned i;
5667 for (i = 0; i < __x_.size(); ++i)
5668 if (__x_[i] == '%')
5669 break;
5670 ++i;
5671 switch (__x_[i])
5673 case 'y':
5674 case 'Y':
5675 for (++i; i < __x_.size(); ++i)
5676 if (__x_[i] == '%')
5677 break;
5678 if (i == __x_.size())
5679 break;
5680 ++i;
5681 switch (__x_[i])
5683 case 'm':
5684 for (++i; i < __x_.size(); ++i)
5685 if (__x_[i] == '%')
5686 break;
5687 if (i == __x_.size())
5688 break;
5689 ++i;
5690 if (__x_[i] == 'd')
5691 return time_base::ymd;
5692 break;
5693 case 'd':
5694 for (++i; i < __x_.size(); ++i)
5695 if (__x_[i] == '%')
5696 break;
5697 if (i == __x_.size())
5698 break;
5699 ++i;
5700 if (__x_[i] == 'm')
5701 return time_base::ydm;
5702 break;
5704 break;
5705 case 'm':
5706 for (++i; i < __x_.size(); ++i)
5707 if (__x_[i] == '%')
5708 break;
5709 if (i == __x_.size())
5710 break;
5711 ++i;
5712 if (__x_[i] == 'd')
5714 for (++i; i < __x_.size(); ++i)
5715 if (__x_[i] == '%')
5716 break;
5717 if (i == __x_.size())
5718 break;
5719 ++i;
5720 if (__x_[i] == 'y' || __x_[i] == 'Y')
5721 return time_base::mdy;
5722 break;
5724 break;
5725 case 'd':
5726 for (++i; i < __x_.size(); ++i)
5727 if (__x_[i] == '%')
5728 break;
5729 if (i == __x_.size())
5730 break;
5731 ++i;
5732 if (__x_[i] == 'm')
5734 for (++i; i < __x_.size(); ++i)
5735 if (__x_[i] == '%')
5736 break;
5737 if (i == __x_.size())
5738 break;
5739 ++i;
5740 if (__x_[i] == 'y' || __x_[i] == 'Y')
5741 return time_base::dmy;
5742 break;
5744 break;
5746 return time_base::no_order;
5749 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5750 template <>
5751 time_base::dateorder
5752 __time_get_storage<wchar_t>::__do_date_order() const
5754 unsigned i;
5755 for (i = 0; i < __x_.size(); ++i)
5756 if (__x_[i] == L'%')
5757 break;
5758 ++i;
5759 switch (__x_[i])
5761 case L'y':
5762 case L'Y':
5763 for (++i; i < __x_.size(); ++i)
5764 if (__x_[i] == L'%')
5765 break;
5766 if (i == __x_.size())
5767 break;
5768 ++i;
5769 switch (__x_[i])
5771 case L'm':
5772 for (++i; i < __x_.size(); ++i)
5773 if (__x_[i] == L'%')
5774 break;
5775 if (i == __x_.size())
5776 break;
5777 ++i;
5778 if (__x_[i] == L'd')
5779 return time_base::ymd;
5780 break;
5781 case L'd':
5782 for (++i; i < __x_.size(); ++i)
5783 if (__x_[i] == L'%')
5784 break;
5785 if (i == __x_.size())
5786 break;
5787 ++i;
5788 if (__x_[i] == L'm')
5789 return time_base::ydm;
5790 break;
5792 break;
5793 case L'm':
5794 for (++i; i < __x_.size(); ++i)
5795 if (__x_[i] == L'%')
5796 break;
5797 if (i == __x_.size())
5798 break;
5799 ++i;
5800 if (__x_[i] == L'd')
5802 for (++i; i < __x_.size(); ++i)
5803 if (__x_[i] == L'%')
5804 break;
5805 if (i == __x_.size())
5806 break;
5807 ++i;
5808 if (__x_[i] == L'y' || __x_[i] == L'Y')
5809 return time_base::mdy;
5810 break;
5812 break;
5813 case L'd':
5814 for (++i; i < __x_.size(); ++i)
5815 if (__x_[i] == L'%')
5816 break;
5817 if (i == __x_.size())
5818 break;
5819 ++i;
5820 if (__x_[i] == L'm')
5822 for (++i; i < __x_.size(); ++i)
5823 if (__x_[i] == L'%')
5824 break;
5825 if (i == __x_.size())
5826 break;
5827 ++i;
5828 if (__x_[i] == L'y' || __x_[i] == L'Y')
5829 return time_base::dmy;
5830 break;
5832 break;
5834 return time_base::no_order;
5836 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5838 // time_put
5840 __time_put::__time_put(const char* nm)
5841 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5843 if (__loc_ == 0)
5844 __throw_runtime_error("time_put_byname"
5845 " failed to construct for " + string(nm));
5848 __time_put::__time_put(const string& nm)
5849 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5851 if (__loc_ == 0)
5852 __throw_runtime_error("time_put_byname"
5853 " failed to construct for " + nm);
5856 __time_put::~__time_put()
5858 if (__loc_ != _LIBCPP_GET_C_LOCALE)
5859 freelocale(__loc_);
5862 void
5863 __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5864 char __fmt, char __mod) const
5866 char fmt[] = {'%', __fmt, __mod, 0};
5867 if (__mod != 0)
5868 swap(fmt[1], fmt[2]);
5869 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
5870 __ne = __nb + n;
5873 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
5874 void
5875 __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5876 char __fmt, char __mod) const
5878 char __nar[100];
5879 char* __ne = __nar + 100;
5880 __do_put(__nar, __ne, __tm, __fmt, __mod);
5881 mbstate_t mb = {0};
5882 const char* __nb = __nar;
5883 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
5884 if (j == size_t(-1))
5885 __throw_runtime_error("locale not supported");
5886 __we = __wb + j;
5888 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
5890 // moneypunct_byname
5892 template <class charT>
5893 static
5894 void
5895 __init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5896 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5897 charT space_char)
5899 const char sign = static_cast<char>(money_base::sign);
5900 const char space = static_cast<char>(money_base::space);
5901 const char none = static_cast<char>(money_base::none);
5902 const char symbol = static_cast<char>(money_base::symbol);
5903 const char value = static_cast<char>(money_base::value);
5904 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5906 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5907 // function'. "Space between sign and symbol or value" means that
5908 // if the sign is adjacent to the symbol, there's a space between
5909 // them, and otherwise there's a space between the sign and value.
5911 // C11's localeconv specifies that the fourth character of an
5912 // international curr_symbol is used to separate the sign and
5913 // value when sep_by_space says to do so. C++ can't represent
5914 // that, so we just use a space. When sep_by_space says to
5915 // separate the symbol and value-or-sign with a space, we rearrange the
5916 // curr_symbol to put its spacing character on the correct side of
5917 // the symbol.
5919 // We also need to avoid adding an extra space between the sign
5920 // and value when the currency symbol is suppressed (by not
5921 // setting showbase). We match glibc's strfmon by interpreting
5922 // sep_by_space==1 as "omit the space when the currency symbol is
5923 // absent".
5925 // Users who want to get this right should use ICU instead.
5927 switch (cs_precedes)
5929 case 0: // value before curr_symbol
5930 if (symbol_contains_sep) {
5931 // Move the separator to before the symbol, to place it
5932 // between the value and symbol.
5933 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5934 __curr_symbol_.end());
5936 switch (sign_posn)
5938 case 0: // Parentheses surround the quantity and currency symbol.
5939 pat.field[0] = sign;
5940 pat.field[1] = value;
5941 pat.field[2] = none; // Any space appears in the symbol.
5942 pat.field[3] = symbol;
5943 switch (sep_by_space)
5945 case 0: // No space separates the currency symbol and value.
5946 // This case may have changed between C99 and C11;
5947 // assume the currency symbol matches the intention.
5948 case 2: // Space between sign and currency or value.
5949 // The "sign" is two parentheses, so no space here either.
5950 return;
5951 case 1: // Space between currency-and-sign or currency and value.
5952 if (!symbol_contains_sep) {
5953 // We insert the space into the symbol instead of
5954 // setting pat.field[2]=space so that when
5955 // showbase is not set, the space goes away too.
5956 __curr_symbol_.insert(0, 1, space_char);
5958 return;
5959 default:
5960 break;
5962 break;
5963 case 1: // The sign string precedes the quantity and currency symbol.
5964 pat.field[0] = sign;
5965 pat.field[3] = symbol;
5966 switch (sep_by_space)
5968 case 0: // No space separates the currency symbol and value.
5969 pat.field[1] = value;
5970 pat.field[2] = none;
5971 return;
5972 case 1: // Space between currency-and-sign or currency and value.
5973 pat.field[1] = value;
5974 pat.field[2] = none;
5975 if (!symbol_contains_sep) {
5976 // We insert the space into the symbol instead of
5977 // setting pat.field[2]=space so that when
5978 // showbase is not set, the space goes away too.
5979 __curr_symbol_.insert(0, 1, space_char);
5981 return;
5982 case 2: // Space between sign and currency or value.
5983 pat.field[1] = space;
5984 pat.field[2] = value;
5985 if (symbol_contains_sep) {
5986 // Remove the separator from the symbol, since it
5987 // has already appeared after the sign.
5988 __curr_symbol_.erase(__curr_symbol_.begin());
5990 return;
5991 default:
5992 break;
5994 break;
5995 case 2: // The sign string succeeds the quantity and currency symbol.
5996 pat.field[0] = value;
5997 pat.field[3] = sign;
5998 switch (sep_by_space)
6000 case 0: // No space separates the currency symbol and value.
6001 pat.field[1] = none;
6002 pat.field[2] = symbol;
6003 return;
6004 case 1: // Space between currency-and-sign or currency and value.
6005 if (!symbol_contains_sep) {
6006 // We insert the space into the symbol instead of
6007 // setting pat.field[1]=space so that when
6008 // showbase is not set, the space goes away too.
6009 __curr_symbol_.insert(0, 1, space_char);
6011 pat.field[1] = none;
6012 pat.field[2] = symbol;
6013 return;
6014 case 2: // Space between sign and currency or value.
6015 pat.field[1] = symbol;
6016 pat.field[2] = space;
6017 if (symbol_contains_sep) {
6018 // Remove the separator from the symbol, since it
6019 // should not be removed if showbase is absent.
6020 __curr_symbol_.erase(__curr_symbol_.begin());
6022 return;
6023 default:
6024 break;
6026 break;
6027 case 3: // The sign string immediately precedes the currency symbol.
6028 pat.field[0] = value;
6029 pat.field[3] = symbol;
6030 switch (sep_by_space)
6032 case 0: // No space separates the currency symbol and value.
6033 pat.field[1] = none;
6034 pat.field[2] = sign;
6035 return;
6036 case 1: // Space between currency-and-sign or currency and value.
6037 pat.field[1] = space;
6038 pat.field[2] = sign;
6039 if (symbol_contains_sep) {
6040 // Remove the separator from the symbol, since it
6041 // has already appeared before the sign.
6042 __curr_symbol_.erase(__curr_symbol_.begin());
6044 return;
6045 case 2: // Space between sign and currency or value.
6046 pat.field[1] = sign;
6047 pat.field[2] = none;
6048 if (!symbol_contains_sep) {
6049 // We insert the space into the symbol instead of
6050 // setting pat.field[2]=space so that when
6051 // showbase is not set, the space goes away too.
6052 __curr_symbol_.insert(0, 1, space_char);
6054 return;
6055 default:
6056 break;
6058 break;
6059 case 4: // The sign string immediately succeeds the currency symbol.
6060 pat.field[0] = value;
6061 pat.field[3] = sign;
6062 switch (sep_by_space)
6064 case 0: // No space separates the currency symbol and value.
6065 pat.field[1] = none;
6066 pat.field[2] = symbol;
6067 return;
6068 case 1: // Space between currency-and-sign or currency and value.
6069 pat.field[1] = none;
6070 pat.field[2] = symbol;
6071 if (!symbol_contains_sep) {
6072 // We insert the space into the symbol instead of
6073 // setting pat.field[1]=space so that when
6074 // showbase is not set, the space goes away too.
6075 __curr_symbol_.insert(0, 1, space_char);
6077 return;
6078 case 2: // Space between sign and currency or value.
6079 pat.field[1] = symbol;
6080 pat.field[2] = space;
6081 if (symbol_contains_sep) {
6082 // Remove the separator from the symbol, since it
6083 // should not disappear when showbase is absent.
6084 __curr_symbol_.erase(__curr_symbol_.begin());
6086 return;
6087 default:
6088 break;
6090 break;
6091 default:
6092 break;
6094 break;
6095 case 1: // curr_symbol before value
6096 switch (sign_posn)
6098 case 0: // Parentheses surround the quantity and currency symbol.
6099 pat.field[0] = sign;
6100 pat.field[1] = symbol;
6101 pat.field[2] = none; // Any space appears in the symbol.
6102 pat.field[3] = value;
6103 switch (sep_by_space)
6105 case 0: // No space separates the currency symbol and value.
6106 // This case may have changed between C99 and C11;
6107 // assume the currency symbol matches the intention.
6108 case 2: // Space between sign and currency or value.
6109 // The "sign" is two parentheses, so no space here either.
6110 return;
6111 case 1: // Space between currency-and-sign or currency and value.
6112 if (!symbol_contains_sep) {
6113 // We insert the space into the symbol instead of
6114 // setting pat.field[2]=space so that when
6115 // showbase is not set, the space goes away too.
6116 __curr_symbol_.insert(0, 1, space_char);
6118 return;
6119 default:
6120 break;
6122 break;
6123 case 1: // The sign string precedes the quantity and currency symbol.
6124 pat.field[0] = sign;
6125 pat.field[3] = value;
6126 switch (sep_by_space)
6128 case 0: // No space separates the currency symbol and value.
6129 pat.field[1] = symbol;
6130 pat.field[2] = none;
6131 return;
6132 case 1: // Space between currency-and-sign or currency and value.
6133 pat.field[1] = symbol;
6134 pat.field[2] = none;
6135 if (!symbol_contains_sep) {
6136 // We insert the space into the symbol instead of
6137 // setting pat.field[2]=space so that when
6138 // showbase is not set, the space goes away too.
6139 __curr_symbol_.push_back(space_char);
6141 return;
6142 case 2: // Space between sign and currency or value.
6143 pat.field[1] = space;
6144 pat.field[2] = symbol;
6145 if (symbol_contains_sep) {
6146 // Remove the separator from the symbol, since it
6147 // has already appeared after the sign.
6148 __curr_symbol_.pop_back();
6150 return;
6151 default:
6152 break;
6154 break;
6155 case 2: // The sign string succeeds the quantity and currency symbol.
6156 pat.field[0] = symbol;
6157 pat.field[3] = sign;
6158 switch (sep_by_space)
6160 case 0: // No space separates the currency symbol and value.
6161 pat.field[1] = none;
6162 pat.field[2] = value;
6163 return;
6164 case 1: // Space between currency-and-sign or currency and value.
6165 pat.field[1] = none;
6166 pat.field[2] = value;
6167 if (!symbol_contains_sep) {
6168 // We insert the space into the symbol instead of
6169 // setting pat.field[1]=space so that when
6170 // showbase is not set, the space goes away too.
6171 __curr_symbol_.push_back(space_char);
6173 return;
6174 case 2: // Space between sign and currency or value.
6175 pat.field[1] = value;
6176 pat.field[2] = space;
6177 if (symbol_contains_sep) {
6178 // Remove the separator from the symbol, since it
6179 // will appear before the sign.
6180 __curr_symbol_.pop_back();
6182 return;
6183 default:
6184 break;
6186 break;
6187 case 3: // The sign string immediately precedes the currency symbol.
6188 pat.field[0] = sign;
6189 pat.field[3] = value;
6190 switch (sep_by_space)
6192 case 0: // No space separates the currency symbol and value.
6193 pat.field[1] = symbol;
6194 pat.field[2] = none;
6195 return;
6196 case 1: // Space between currency-and-sign or currency and value.
6197 pat.field[1] = symbol;
6198 pat.field[2] = none;
6199 if (!symbol_contains_sep) {
6200 // We insert the space into the symbol instead of
6201 // setting pat.field[2]=space so that when
6202 // showbase is not set, the space goes away too.
6203 __curr_symbol_.push_back(space_char);
6205 return;
6206 case 2: // Space between sign and currency or value.
6207 pat.field[1] = space;
6208 pat.field[2] = symbol;
6209 if (symbol_contains_sep) {
6210 // Remove the separator from the symbol, since it
6211 // has already appeared after the sign.
6212 __curr_symbol_.pop_back();
6214 return;
6215 default:
6216 break;
6218 break;
6219 case 4: // The sign string immediately succeeds the currency symbol.
6220 pat.field[0] = symbol;
6221 pat.field[3] = value;
6222 switch (sep_by_space)
6224 case 0: // No space separates the currency symbol and value.
6225 pat.field[1] = sign;
6226 pat.field[2] = none;
6227 return;
6228 case 1: // Space between currency-and-sign or currency and value.
6229 pat.field[1] = sign;
6230 pat.field[2] = space;
6231 if (symbol_contains_sep) {
6232 // Remove the separator from the symbol, since it
6233 // should not disappear when showbase is absent.
6234 __curr_symbol_.pop_back();
6236 return;
6237 case 2: // Space between sign and currency or value.
6238 pat.field[1] = none;
6239 pat.field[2] = sign;
6240 if (!symbol_contains_sep) {
6241 // We insert the space into the symbol instead of
6242 // setting pat.field[1]=space so that when
6243 // showbase is not set, the space goes away too.
6244 __curr_symbol_.push_back(space_char);
6246 return;
6247 default:
6248 break;
6250 break;
6251 default:
6252 break;
6254 break;
6255 default:
6256 break;
6258 pat.field[0] = symbol;
6259 pat.field[1] = sign;
6260 pat.field[2] = none;
6261 pat.field[3] = value;
6264 template<>
6265 void
6266 moneypunct_byname<char, false>::init(const char* nm)
6268 typedef moneypunct<char, false> base;
6269 __libcpp_unique_locale loc(nm);
6270 if (!loc)
6271 __throw_runtime_error("moneypunct_byname"
6272 " failed to construct for " + string(nm));
6274 lconv* lc = __libcpp_localeconv_l(loc.get());
6275 if (!checked_string_to_char_convert(__decimal_point_,
6276 lc->mon_decimal_point,
6277 loc.get()))
6278 __decimal_point_ = base::do_decimal_point();
6279 if (!checked_string_to_char_convert(__thousands_sep_,
6280 lc->mon_thousands_sep,
6281 loc.get()))
6282 __thousands_sep_ = base::do_thousands_sep();
6284 __grouping_ = lc->mon_grouping;
6285 __curr_symbol_ = lc->currency_symbol;
6286 if (lc->frac_digits != CHAR_MAX)
6287 __frac_digits_ = lc->frac_digits;
6288 else
6289 __frac_digits_ = base::do_frac_digits();
6290 if (lc->p_sign_posn == 0)
6291 __positive_sign_ = "()";
6292 else
6293 __positive_sign_ = lc->positive_sign;
6294 if (lc->n_sign_posn == 0)
6295 __negative_sign_ = "()";
6296 else
6297 __negative_sign_ = lc->negative_sign;
6298 // Assume the positive and negative formats will want spaces in
6299 // the same places in curr_symbol since there's no way to
6300 // represent anything else.
6301 string_type __dummy_curr_symbol = __curr_symbol_;
6302 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6303 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6304 __init_pat(__neg_format_, __curr_symbol_, false,
6305 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
6308 template<>
6309 void
6310 moneypunct_byname<char, true>::init(const char* nm)
6312 typedef moneypunct<char, true> base;
6313 __libcpp_unique_locale loc(nm);
6314 if (!loc)
6315 __throw_runtime_error("moneypunct_byname"
6316 " failed to construct for " + string(nm));
6318 lconv* lc = __libcpp_localeconv_l(loc.get());
6319 if (!checked_string_to_char_convert(__decimal_point_,
6320 lc->mon_decimal_point,
6321 loc.get()))
6322 __decimal_point_ = base::do_decimal_point();
6323 if (!checked_string_to_char_convert(__thousands_sep_,
6324 lc->mon_thousands_sep,
6325 loc.get()))
6326 __thousands_sep_ = base::do_thousands_sep();
6327 __grouping_ = lc->mon_grouping;
6328 __curr_symbol_ = lc->int_curr_symbol;
6329 if (lc->int_frac_digits != CHAR_MAX)
6330 __frac_digits_ = lc->int_frac_digits;
6331 else
6332 __frac_digits_ = base::do_frac_digits();
6333 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6334 if (lc->p_sign_posn == 0)
6335 #else // _LIBCPP_MSVCRT
6336 if (lc->int_p_sign_posn == 0)
6337 #endif // !_LIBCPP_MSVCRT
6338 __positive_sign_ = "()";
6339 else
6340 __positive_sign_ = lc->positive_sign;
6341 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6342 if(lc->n_sign_posn == 0)
6343 #else // _LIBCPP_MSVCRT
6344 if (lc->int_n_sign_posn == 0)
6345 #endif // !_LIBCPP_MSVCRT
6346 __negative_sign_ = "()";
6347 else
6348 __negative_sign_ = lc->negative_sign;
6349 // Assume the positive and negative formats will want spaces in
6350 // the same places in curr_symbol since there's no way to
6351 // represent anything else.
6352 string_type __dummy_curr_symbol = __curr_symbol_;
6353 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6354 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6355 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6356 __init_pat(__neg_format_, __curr_symbol_, true,
6357 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
6358 #else // _LIBCPP_MSVCRT
6359 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6360 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6361 lc->int_p_sign_posn, ' ');
6362 __init_pat(__neg_format_, __curr_symbol_, true,
6363 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6364 lc->int_n_sign_posn, ' ');
6365 #endif // !_LIBCPP_MSVCRT
6368 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
6369 template<>
6370 void
6371 moneypunct_byname<wchar_t, false>::init(const char* nm)
6373 typedef moneypunct<wchar_t, false> base;
6374 __libcpp_unique_locale loc(nm);
6375 if (!loc)
6376 __throw_runtime_error("moneypunct_byname"
6377 " failed to construct for " + string(nm));
6378 lconv* lc = __libcpp_localeconv_l(loc.get());
6379 if (!checked_string_to_wchar_convert(__decimal_point_,
6380 lc->mon_decimal_point,
6381 loc.get()))
6382 __decimal_point_ = base::do_decimal_point();
6383 if (!checked_string_to_wchar_convert(__thousands_sep_,
6384 lc->mon_thousands_sep,
6385 loc.get()))
6386 __thousands_sep_ = base::do_thousands_sep();
6387 __grouping_ = lc->mon_grouping;
6388 wchar_t wbuf[100];
6389 mbstate_t mb = {0};
6390 const char* bb = lc->currency_symbol;
6391 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6392 if (j == size_t(-1))
6393 __throw_runtime_error("locale not supported");
6394 wchar_t* wbe = wbuf + j;
6395 __curr_symbol_.assign(wbuf, wbe);
6396 if (lc->frac_digits != CHAR_MAX)
6397 __frac_digits_ = lc->frac_digits;
6398 else
6399 __frac_digits_ = base::do_frac_digits();
6400 if (lc->p_sign_posn == 0)
6401 __positive_sign_ = L"()";
6402 else
6404 mb = mbstate_t();
6405 bb = lc->positive_sign;
6406 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6407 if (j == size_t(-1))
6408 __throw_runtime_error("locale not supported");
6409 wbe = wbuf + j;
6410 __positive_sign_.assign(wbuf, wbe);
6412 if (lc->n_sign_posn == 0)
6413 __negative_sign_ = L"()";
6414 else
6416 mb = mbstate_t();
6417 bb = lc->negative_sign;
6418 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6419 if (j == size_t(-1))
6420 __throw_runtime_error("locale not supported");
6421 wbe = wbuf + j;
6422 __negative_sign_.assign(wbuf, wbe);
6424 // Assume the positive and negative formats will want spaces in
6425 // the same places in curr_symbol since there's no way to
6426 // represent anything else.
6427 string_type __dummy_curr_symbol = __curr_symbol_;
6428 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6429 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6430 __init_pat(__neg_format_, __curr_symbol_, false,
6431 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6434 template<>
6435 void
6436 moneypunct_byname<wchar_t, true>::init(const char* nm)
6438 typedef moneypunct<wchar_t, true> base;
6439 __libcpp_unique_locale loc(nm);
6440 if (!loc)
6441 __throw_runtime_error("moneypunct_byname"
6442 " failed to construct for " + string(nm));
6444 lconv* lc = __libcpp_localeconv_l(loc.get());
6445 if (!checked_string_to_wchar_convert(__decimal_point_,
6446 lc->mon_decimal_point,
6447 loc.get()))
6448 __decimal_point_ = base::do_decimal_point();
6449 if (!checked_string_to_wchar_convert(__thousands_sep_,
6450 lc->mon_thousands_sep,
6451 loc.get()))
6452 __thousands_sep_ = base::do_thousands_sep();
6453 __grouping_ = lc->mon_grouping;
6454 wchar_t wbuf[100];
6455 mbstate_t mb = {0};
6456 const char* bb = lc->int_curr_symbol;
6457 size_t 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 wchar_t* wbe = wbuf + j;
6461 __curr_symbol_.assign(wbuf, wbe);
6462 if (lc->int_frac_digits != CHAR_MAX)
6463 __frac_digits_ = lc->int_frac_digits;
6464 else
6465 __frac_digits_ = base::do_frac_digits();
6466 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6467 if (lc->p_sign_posn == 0)
6468 #else // _LIBCPP_MSVCRT
6469 if (lc->int_p_sign_posn == 0)
6470 #endif // !_LIBCPP_MSVCRT
6471 __positive_sign_ = L"()";
6472 else
6474 mb = mbstate_t();
6475 bb = lc->positive_sign;
6476 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6477 if (j == size_t(-1))
6478 __throw_runtime_error("locale not supported");
6479 wbe = wbuf + j;
6480 __positive_sign_.assign(wbuf, wbe);
6482 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6483 if (lc->n_sign_posn == 0)
6484 #else // _LIBCPP_MSVCRT
6485 if (lc->int_n_sign_posn == 0)
6486 #endif // !_LIBCPP_MSVCRT
6487 __negative_sign_ = L"()";
6488 else
6490 mb = mbstate_t();
6491 bb = lc->negative_sign;
6492 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
6493 if (j == size_t(-1))
6494 __throw_runtime_error("locale not supported");
6495 wbe = wbuf + j;
6496 __negative_sign_.assign(wbuf, wbe);
6498 // Assume the positive and negative formats will want spaces in
6499 // the same places in curr_symbol since there's no way to
6500 // represent anything else.
6501 string_type __dummy_curr_symbol = __curr_symbol_;
6502 #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
6503 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6504 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6505 __init_pat(__neg_format_, __curr_symbol_, true,
6506 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
6507 #else // _LIBCPP_MSVCRT
6508 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6509 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6510 lc->int_p_sign_posn, L' ');
6511 __init_pat(__neg_format_, __curr_symbol_, true,
6512 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6513 lc->int_n_sign_posn, L' ');
6514 #endif // !_LIBCPP_MSVCRT
6516 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
6518 void __do_nothing(void*) {}
6520 void __throw_runtime_error(const char* msg)
6522 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
6523 throw runtime_error(msg);
6524 #else
6525 (void)msg;
6526 _VSTD::abort();
6527 #endif
6530 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6531 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
6533 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6534 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
6536 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6537 _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
6539 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6540 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
6542 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6543 _LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
6545 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6546 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
6548 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6549 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
6551 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6552 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
6554 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6555 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
6557 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6558 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6559 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6560 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
6562 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6563 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6564 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6565 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
6567 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6568 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
6570 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6571 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
6573 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6574 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
6576 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6577 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
6579 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6580 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
6582 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6583 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
6585 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6586 _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;)
6587 template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6588 template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
6589 #ifndef _LIBCPP_HAS_NO_CHAR8_T
6590 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6591 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6592 #endif
6594 _LIBCPP_END_NAMESPACE_STD
6596 _LIBCPP_POP_MACROS