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