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