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