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

source code of libcxx/src/locale.cpp