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