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