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