blob: d069b42aed9e74851d04beb6ca474ebe56af4d1d [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// 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
Howard Hinnantc51e1022010-05-11 19:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
David Chisnall8074c342012-02-29 13:05:08 +00009// On Solaris, we need to define something to make the C99 parts of localeconv
10// visible.
11#ifdef __sun__
12#define _LCONV_C99
13#endif
14
Howard Hinnantc51e1022010-05-11 19:42:16 +000015#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000016#include "clocale"
Louis Dionneafc98402021-09-09 13:52:38 -040017#include "codecvt"
18#include "cstdio"
19#include "cstdlib"
Howard Hinnantc51e1022010-05-11 19:42:16 +000020#include "cstring"
Louis Dionneafc98402021-09-09 13:52:38 -040021#include "locale"
22#include "string"
23#include "type_traits"
24#include "typeinfo"
25#include "vector"
26
Louis Dionne89258142021-08-23 15:32:36 -040027#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
28# include "cwctype"
29#endif
30
Louis Dionneafc98402021-09-09 13:52:38 -040031#if defined(_LIBCPP_MSVCRT)
32# define _CTYPE_DISABLE_MACROS
Marshall Clow3477ec92014-07-10 15:20:28 +000033#endif
Louis Dionneafc98402021-09-09 13:52:38 -040034
35#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
36# include "__support/win32/locale_win32.h"
37#elif !defined(__BIONIC__) && !defined(__NuttX__)
38# include <langinfo.h>
39#endif
40
Weiming Zhaob613db72017-09-19 23:18:03 +000041#include "include/atomic_support.h"
Arthur O'Dwyerf5c4bb02021-04-26 09:56:50 -040042#include "include/sso_allocator.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000043#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000044
Marshall Clowab9c1772013-02-07 17:20:56 +000045// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070046// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000047#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000048#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000049#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000050
Howard Hinnantc51e1022010-05-11 19:42:16 +000051_LIBCPP_BEGIN_NAMESPACE_STD
52
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000053struct __libcpp_unique_locale {
54 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
55
56 ~__libcpp_unique_locale() {
57 if (__loc_)
58 freelocale(__loc_);
59 }
60
61 explicit operator bool() const { return __loc_; }
62
63 locale_t& get() { return __loc_; }
64
65 locale_t __loc_;
66private:
67 __libcpp_unique_locale(__libcpp_unique_locale const&);
68 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
69};
70
Howard Hinnantf312e3e2011-09-28 23:39:33 +000071#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000072locale_t __cloc() {
73 // In theory this could create a race condition. In practice
74 // the race condition is non-fatal since it will just create
75 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000076 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
77 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000078}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000079#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000080
Howard Hinnantc51e1022010-05-11 19:42:16 +000081namespace {
82
83struct release
84{
85 void operator()(locale::facet* p) {p->__release_shared();}
86};
87
Louis Dionne6e41a152021-08-09 13:26:04 -040088template <class T, class ...Args>
89T& make(Args ...args)
Howard Hinnantc51e1022010-05-11 19:42:16 +000090{
91 static typename aligned_storage<sizeof(T)>::type buf;
Louis Dionne6e41a152021-08-09 13:26:04 -040092 auto *obj = ::new (&buf) T(args...);
Eric Fiselier4db80032017-05-05 20:32:26 +000093 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000094}
95
Howard Hinnant3d2417c2012-12-27 21:17:53 +000096template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +000097inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +000098_LIBCPP_CONSTEXPR
99size_t
100countof(const T (&)[N])
101{
102 return N;
103}
104
105template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000106inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000107_LIBCPP_CONSTEXPR
108size_t
109countof(const T * const begin, const T * const end)
110{
111 return static_cast<size_t>(end - begin);
112}
113
Marshall Clow8fea1612016-08-25 15:09:01 +0000114_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
115{
116#ifndef _LIBCPP_NO_EXCEPTIONS
117 throw runtime_error(msg);
118#else
119 (void)msg;
120 _VSTD::abort();
121#endif
122}
123
Howard Hinnantc51e1022010-05-11 19:42:16 +0000124}
125
Howard Hinnantdd099492013-08-29 23:37:50 +0000126#if defined(_AIX)
127// Set priority to INT_MIN + 256 + 150
128# pragma priority ( -2147483242 )
129#endif
130
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000131const locale::category locale::none;
132const locale::category locale::collate;
133const locale::category locale::ctype;
134const locale::category locale::monetary;
135const locale::category locale::numeric;
136const locale::category locale::time;
137const locale::category locale::messages;
138const locale::category locale::all;
139
Howard Hinnantc51e1022010-05-11 19:42:16 +0000140class _LIBCPP_HIDDEN locale::__imp
141 : public facet
142{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100143 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000144#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000145// FIXME: MSVC doesn't support aligned parameters by value.
146// I can't get the __sso_allocator to work here
147// for MSVC I think for this reason.
148 vector<facet*> facets_;
149#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000150 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000151#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000152 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000153public:
154 explicit __imp(size_t refs = 0);
155 explicit __imp(const string& name, size_t refs = 0);
156 __imp(const __imp&);
157 __imp(const __imp&, const string&, locale::category c);
158 __imp(const __imp& other, const __imp& one, locale::category c);
159 __imp(const __imp&, facet* f, long id);
160 ~__imp();
161
162 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000163 bool has_facet(long id) const
164 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000165 const locale::facet* use_facet(long id) const;
166
167 static const locale& make_classic();
168 static locale& make_global();
169private:
170 void install(facet* f, long id);
171 template <class F> void install(F* f) {install(f, f->id.__get());}
172 template <class F> void install_from(const __imp& other);
173};
174
175locale::__imp::__imp(size_t refs)
176 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000177 facets_(N),
178 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000179{
180 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000181 install(&make<_VSTD::collate<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400182#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000183 install(&make<_VSTD::collate<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400184#endif
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000185 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Louis Dionne89258142021-08-23 15:32:36 -0400186#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000187 install(&make<_VSTD::ctype<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400188#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000189 install(&make<codecvt<char, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400190#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000191 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400192#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100193_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000194 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
195 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100196_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400197#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100198 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
199 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
200#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000201 install(&make<numpunct<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400202#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000203 install(&make<numpunct<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400204#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000205 install(&make<num_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400206#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000207 install(&make<num_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400208#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000209 install(&make<num_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400210#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000211 install(&make<num_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400212#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000213 install(&make<moneypunct<char, false> >(1u));
214 install(&make<moneypunct<char, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400215#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000216 install(&make<moneypunct<wchar_t, false> >(1u));
217 install(&make<moneypunct<wchar_t, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400218#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000219 install(&make<money_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400220#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000221 install(&make<money_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400222#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000223 install(&make<money_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400224#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000225 install(&make<money_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400226#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000227 install(&make<time_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400228#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000229 install(&make<time_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400230#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000231 install(&make<time_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400232#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000233 install(&make<time_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400234#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000235 install(&make<_VSTD::messages<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400236#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000237 install(&make<_VSTD::messages<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400238#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000239}
240
241locale::__imp::__imp(const string& name, size_t refs)
242 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000243 facets_(N),
244 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000245{
Howard Hinnant72f73582010-08-11 17:04:31 +0000246#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000247 try
248 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400249#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000250 facets_ = locale::classic().__locale_->facets_;
251 for (unsigned i = 0; i < facets_.size(); ++i)
252 if (facets_[i])
253 facets_[i]->__add_shared();
254 install(new collate_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400255#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000256 install(new collate_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400257#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000258 install(new ctype_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400259#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000260 install(new ctype_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400261#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262 install(new codecvt_byname<char, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400263#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000264 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400265#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100266_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000267 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
268 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100269_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400270#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100271 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
272 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
273#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000274 install(new numpunct_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400275#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276 install(new numpunct_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400277#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000278 install(new moneypunct_byname<char, false>(name_));
279 install(new moneypunct_byname<char, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400280#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000281 install(new moneypunct_byname<wchar_t, false>(name_));
282 install(new moneypunct_byname<wchar_t, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400283#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284 install(new time_get_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400285#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000286 install(new time_get_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400287#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288 install(new time_put_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400289#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000290 install(new time_put_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400291#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000292 install(new messages_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400293#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000294 install(new messages_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400295#endif
Howard Hinnant72f73582010-08-11 17:04:31 +0000296#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000297 }
298 catch (...)
299 {
300 for (unsigned i = 0; i < facets_.size(); ++i)
301 if (facets_[i])
302 facets_[i]->__release_shared();
303 throw;
304 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400305#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000306}
307
308locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000309 : facets_(max<size_t>(N, other.facets_.size())),
310 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000311{
312 facets_ = other.facets_;
313 for (unsigned i = 0; i < facets_.size(); ++i)
314 if (facets_[i])
315 facets_[i]->__add_shared();
316}
317
318locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000319 : facets_(N),
320 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000321{
322 facets_ = other.facets_;
323 for (unsigned i = 0; i < facets_.size(); ++i)
324 if (facets_[i])
325 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000326#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000327 try
328 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400329#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000330 if (c & locale::collate)
331 {
332 install(new collate_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400333#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000334 install(new collate_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400335#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000336 }
337 if (c & locale::ctype)
338 {
339 install(new ctype_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400340#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000341 install(new ctype_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400342#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000343 install(new codecvt_byname<char, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400344#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000345 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400346#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100347_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000348 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
349 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100350_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400351#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100352 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
353 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
354#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000355 }
356 if (c & locale::monetary)
357 {
358 install(new moneypunct_byname<char, false>(name));
359 install(new moneypunct_byname<char, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400360#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000361 install(new moneypunct_byname<wchar_t, false>(name));
362 install(new moneypunct_byname<wchar_t, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400363#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000364 }
365 if (c & locale::numeric)
366 {
367 install(new numpunct_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400368#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000369 install(new numpunct_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400370#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000371 }
372 if (c & locale::time)
373 {
374 install(new time_get_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400375#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000376 install(new time_get_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400377#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000378 install(new time_put_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400379#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000380 install(new time_put_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400381#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000382 }
383 if (c & locale::messages)
384 {
385 install(new messages_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400386#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000387 install(new messages_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400388#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000389 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000390#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000391 }
392 catch (...)
393 {
394 for (unsigned i = 0; i < facets_.size(); ++i)
395 if (facets_[i])
396 facets_[i]->__release_shared();
397 throw;
398 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400399#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000400}
401
402template<class F>
403inline
404void
405locale::__imp::install_from(const locale::__imp& one)
406{
407 long id = F::id.__get();
408 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
409}
410
411locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000412 : facets_(N),
413 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000414{
415 facets_ = other.facets_;
416 for (unsigned i = 0; i < facets_.size(); ++i)
417 if (facets_[i])
418 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000419#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000420 try
421 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400422#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000423 if (c & locale::collate)
424 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000425 install_from<_VSTD::collate<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400426#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000427 install_from<_VSTD::collate<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400428#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000429 }
430 if (c & locale::ctype)
431 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000432 install_from<_VSTD::ctype<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400433#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000434 install_from<_VSTD::ctype<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400435#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000436 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100437_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000438 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
439 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100440_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400441#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100442 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
443 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
444#endif
Louis Dionne89258142021-08-23 15:32:36 -0400445#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000446 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400447#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000448 }
449 if (c & locale::monetary)
450 {
451 install_from<moneypunct<char, false> >(one);
452 install_from<moneypunct<char, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400453#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000454 install_from<moneypunct<wchar_t, false> >(one);
455 install_from<moneypunct<wchar_t, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400456#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000457 install_from<money_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400458#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000459 install_from<money_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400460#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000461 install_from<money_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400462#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000463 install_from<money_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400464#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000465 }
466 if (c & locale::numeric)
467 {
468 install_from<numpunct<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400469#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000470 install_from<numpunct<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400471#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000472 install_from<num_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400473#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000474 install_from<num_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400475#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000476 install_from<num_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400477#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000478 install_from<num_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400479#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000480 }
481 if (c & locale::time)
482 {
483 install_from<time_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400484#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000485 install_from<time_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400486#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000487 install_from<time_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400488#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000489 install_from<time_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400490#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000491 }
492 if (c & locale::messages)
493 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000494 install_from<_VSTD::messages<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400495#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000496 install_from<_VSTD::messages<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400497#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000498 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000499#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000500 }
501 catch (...)
502 {
503 for (unsigned i = 0; i < facets_.size(); ++i)
504 if (facets_[i])
505 facets_[i]->__release_shared();
506 throw;
507 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400508#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509}
510
511locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000512 : facets_(max<size_t>(N, other.facets_.size()+1)),
513 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000514{
515 f->__add_shared();
516 unique_ptr<facet, release> hold(f);
517 facets_ = other.facets_;
518 for (unsigned i = 0; i < other.facets_.size(); ++i)
519 if (facets_[i])
520 facets_[i]->__add_shared();
521 install(hold.get(), id);
522}
523
524locale::__imp::~__imp()
525{
526 for (unsigned i = 0; i < facets_.size(); ++i)
527 if (facets_[i])
528 facets_[i]->__release_shared();
529}
530
531void
532locale::__imp::install(facet* f, long id)
533{
534 f->__add_shared();
535 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000536 if (static_cast<size_t>(id) >= facets_.size())
537 facets_.resize(static_cast<size_t>(id+1));
538 if (facets_[static_cast<size_t>(id)])
539 facets_[static_cast<size_t>(id)]->__release_shared();
540 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000541}
542
543const locale::facet*
544locale::__imp::use_facet(long id) const
545{
546 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000547 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000548 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000549}
550
551// locale
552
553const locale&
554locale::__imp::make_classic()
555{
556 // only one thread can get in here and it only gets in once
557 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000558 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000559 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000560 return *c;
561}
562
563const locale&
564locale::classic()
565{
566 static const locale& c = __imp::make_classic();
567 return c;
568}
569
570locale&
571locale::__imp::make_global()
572{
573 // only one thread can get in here and it only gets in once
574 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000575 auto *obj = ::new (&buf) locale(locale::classic());
576 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000577}
578
579locale&
580locale::__global()
581{
582 static locale& g = __imp::make_global();
583 return g;
584}
585
Louis Dionne65358e12021-03-01 12:09:45 -0500586locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000587 : __locale_(__global().__locale_)
588{
589 __locale_->__add_shared();
590}
591
Louis Dionne65358e12021-03-01 12:09:45 -0500592locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000593 : __locale_(l.__locale_)
594{
595 __locale_->__add_shared();
596}
597
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000598locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000599{
600 __locale_->__release_shared();
601}
602
603const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500604locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000605{
606 other.__locale_->__add_shared();
607 __locale_->__release_shared();
608 __locale_ = other.__locale_;
609 return *this;
610}
611
612locale::locale(const char* name)
613 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100614 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000615{
616 __locale_->__add_shared();
617}
618
619locale::locale(const string& name)
620 : __locale_(new __imp(name))
621{
622 __locale_->__add_shared();
623}
624
625locale::locale(const locale& other, const char* name, category c)
626 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100627 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000628{
629 __locale_->__add_shared();
630}
631
632locale::locale(const locale& other, const string& name, category c)
633 : __locale_(new __imp(*other.__locale_, name, c))
634{
635 __locale_->__add_shared();
636}
637
638locale::locale(const locale& other, const locale& one, category c)
639 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
640{
641 __locale_->__add_shared();
642}
643
644string
645locale::name() const
646{
647 return __locale_->name();
648}
649
650void
651locale::__install_ctor(const locale& other, facet* f, long id)
652{
653 if (f)
654 __locale_ = new __imp(*other.__locale_, f, id);
655 else
656 __locale_ = other.__locale_;
657 __locale_->__add_shared();
658}
659
660locale
661locale::global(const locale& loc)
662{
663 locale& g = __global();
664 locale r = g;
665 g = loc;
666 if (g.name() != "*")
667 setlocale(LC_ALL, g.name().c_str());
668 return r;
669}
670
671bool
672locale::has_facet(id& x) const
673{
674 return __locale_->has_facet(x.__get());
675}
676
677const locale::facet*
678locale::use_facet(id& x) const
679{
680 return __locale_->use_facet(x.__get());
681}
682
683bool
684locale::operator==(const locale& y) const
685{
686 return (__locale_ == y.__locale_)
687 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
688}
689
690// locale::facet
691
692locale::facet::~facet()
693{
694}
695
696void
Louis Dionne65358e12021-03-01 12:09:45 -0500697locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000698{
699 delete this;
700}
701
702// locale::id
703
704int32_t locale::id::__next_id = 0;
705
706namespace
707{
708
709class __fake_bind
710{
711 locale::id* id_;
712 void (locale::id::* pmf_)();
713public:
714 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
715 : id_(id), pmf_(pmf) {}
716
717 void operator()() const
718 {
719 (id_->*pmf_)();
720 }
721};
722
723}
724
725long
726locale::id::__get()
727{
728 call_once(__flag_, __fake_bind(&locale::id::__init, this));
729 return __id_ - 1;
730}
731
732void
733locale::id::__init()
734{
Weiming Zhaob613db72017-09-19 23:18:03 +0000735 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000736}
737
738// template <> class collate_byname<char>
739
740collate_byname<char>::collate_byname(const char* n, size_t refs)
741 : collate<char>(refs),
742 __l(newlocale(LC_ALL_MASK, n, 0))
743{
744 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000745 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000746 " failed to construct for " + string(n));
747}
748
749collate_byname<char>::collate_byname(const string& name, size_t refs)
750 : collate<char>(refs),
751 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
752{
753 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000754 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000755 " failed to construct for " + name);
756}
757
758collate_byname<char>::~collate_byname()
759{
760 freelocale(__l);
761}
762
763int
764collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
765 const char_type* __lo2, const char_type* __hi2) const
766{
767 string_type lhs(__lo1, __hi1);
768 string_type rhs(__lo2, __hi2);
769 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
770 if (r < 0)
771 return -1;
772 if (r > 0)
773 return 1;
774 return r;
775}
776
777collate_byname<char>::string_type
778collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
779{
780 const string_type in(lo, hi);
781 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
782 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
783 return out;
784}
785
786// template <> class collate_byname<wchar_t>
787
Louis Dionne89258142021-08-23 15:32:36 -0400788#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000789collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
790 : collate<wchar_t>(refs),
791 __l(newlocale(LC_ALL_MASK, n, 0))
792{
793 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000794 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000795 " failed to construct for " + string(n));
796}
797
798collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
799 : collate<wchar_t>(refs),
800 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
801{
802 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000803 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000804 " failed to construct for " + name);
805}
806
807collate_byname<wchar_t>::~collate_byname()
808{
809 freelocale(__l);
810}
811
812int
813collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
814 const char_type* __lo2, const char_type* __hi2) const
815{
816 string_type lhs(__lo1, __hi1);
817 string_type rhs(__lo2, __hi2);
818 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
819 if (r < 0)
820 return -1;
821 if (r > 0)
822 return 1;
823 return r;
824}
825
826collate_byname<wchar_t>::string_type
827collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
828{
829 const string_type in(lo, hi);
830 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
831 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
832 return out;
833}
Louis Dionne89258142021-08-23 15:32:36 -0400834#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000835
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000836const ctype_base::mask ctype_base::space;
837const ctype_base::mask ctype_base::print;
838const ctype_base::mask ctype_base::cntrl;
839const ctype_base::mask ctype_base::upper;
840const ctype_base::mask ctype_base::lower;
841const ctype_base::mask ctype_base::alpha;
842const ctype_base::mask ctype_base::digit;
843const ctype_base::mask ctype_base::punct;
844const ctype_base::mask ctype_base::xdigit;
845const ctype_base::mask ctype_base::blank;
846const ctype_base::mask ctype_base::alnum;
847const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700848
Louis Dionne945f8682021-09-09 13:29:24 -0400849// template <> class ctype<wchar_t>;
850
Louis Dionne89258142021-08-23 15:32:36 -0400851#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000852locale::id ctype<wchar_t>::id;
853
854ctype<wchar_t>::~ctype()
855{
856}
857
858bool
859ctype<wchar_t>::do_is(mask m, char_type c) const
860{
Marshall Clowd920eea2013-10-21 15:07:28 +0000861 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000862}
863
864const wchar_t*
865ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
866{
867 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000868 *vec = static_cast<mask>(isascii(*low) ?
869 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000870 return low;
871}
872
873const wchar_t*
874ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
875{
876 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000877 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000878 break;
879 return low;
880}
881
882const wchar_t*
883ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
884{
885 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000886 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000887 break;
888 return low;
889}
890
891wchar_t
892ctype<wchar_t>::do_toupper(char_type c) const
893{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000894#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
895 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000896#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000897 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000898 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000899#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000900 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000901#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000902}
903
904const wchar_t*
905ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
906{
907 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000908#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
909 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000910#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000911 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000912 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
913 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000914#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000915 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000916#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000917 return low;
918}
919
920wchar_t
921ctype<wchar_t>::do_tolower(char_type c) const
922{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000923#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
924 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000925#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000926 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000927 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000928#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000929 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000930#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000931}
932
933const wchar_t*
934ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
935{
936 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000937#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
938 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000939#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000940 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000941 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
942 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000943#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000944 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000945#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000946 return low;
947}
948
949wchar_t
950ctype<wchar_t>::do_widen(char c) const
951{
952 return c;
953}
954
955const char*
956ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
957{
958 for (; low != high; ++low, ++dest)
959 *dest = *low;
960 return low;
961}
962
963char
964ctype<wchar_t>::do_narrow(char_type c, char dfault) const
965{
966 if (isascii(c))
967 return static_cast<char>(c);
968 return dfault;
969}
970
971const wchar_t*
972ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
973{
974 for (; low != high; ++low, ++dest)
975 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000976 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000977 else
978 *dest = dfault;
979 return low;
980}
Louis Dionne89258142021-08-23 15:32:36 -0400981#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000982
983// template <> class ctype<char>;
984
985locale::id ctype<char>::id;
986
987ctype<char>::ctype(const mask* tab, bool del, size_t refs)
988 : locale::facet(refs),
989 __tab_(tab),
990 __del_(del)
991{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000992 if (__tab_ == 0)
993 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000994}
995
996ctype<char>::~ctype()
997{
998 if (__tab_ && __del_)
999 delete [] __tab_;
1000}
1001
1002char
1003ctype<char>::do_toupper(char_type c) const
1004{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001005#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001006 return isascii(c) ?
1007 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001008#elif defined(__NetBSD__)
1009 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001010#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +00001011 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001012 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001013#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001014 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001015#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001016}
1017
1018const char*
1019ctype<char>::do_toupper(char_type* low, const char_type* high) const
1020{
1021 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001022#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001023 *low = isascii(*low) ?
1024 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001025#elif defined(__NetBSD__)
1026 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001027#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001028 *low = isascii(*low) ?
1029 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001030#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001031 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001032#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001033 return low;
1034}
1035
1036char
1037ctype<char>::do_tolower(char_type c) const
1038{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001039#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001040 return isascii(c) ?
1041 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001042#elif defined(__NetBSD__)
1043 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001044#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001045 return isascii(c) ?
1046 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001047#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001048 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001049#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001050}
1051
1052const char*
1053ctype<char>::do_tolower(char_type* low, const char_type* high) const
1054{
1055 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001056#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001057 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001058#elif defined(__NetBSD__)
1059 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001060#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001061 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001062#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001063 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001064#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001065 return low;
1066}
1067
1068char
1069ctype<char>::do_widen(char c) const
1070{
1071 return c;
1072}
1073
1074const char*
1075ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1076{
1077 for (; low != high; ++low, ++dest)
1078 *dest = *low;
1079 return low;
1080}
1081
1082char
1083ctype<char>::do_narrow(char_type c, char dfault) const
1084{
1085 if (isascii(c))
1086 return static_cast<char>(c);
1087 return dfault;
1088}
1089
1090const char*
1091ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1092{
1093 for (; low != high; ++low, ++dest)
1094 if (isascii(*low))
1095 *dest = *low;
1096 else
1097 *dest = dfault;
1098 return low;
1099}
1100
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001101#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001102extern "C" const unsigned short ** __ctype_b_loc();
1103extern "C" const int ** __ctype_tolower_loc();
1104extern "C" const int ** __ctype_toupper_loc();
1105#endif
1106
Marshall Clow8f870232015-03-04 16:50:02 +00001107#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001108const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001109ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001110{
1111 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1112 cntrl, cntrl,
1113 cntrl, cntrl,
1114 cntrl, cntrl,
1115 cntrl, cntrl,
1116 cntrl, cntrl | space | blank,
1117 cntrl | space, cntrl | space,
1118 cntrl | space, cntrl | space,
1119 cntrl, cntrl,
1120 cntrl, cntrl,
1121 cntrl, cntrl,
1122 cntrl, cntrl,
1123 cntrl, cntrl,
1124 cntrl, cntrl,
1125 cntrl, cntrl,
1126 cntrl, cntrl,
1127 cntrl, cntrl,
1128 space | blank | print, punct | print,
1129 punct | print, punct | print,
1130 punct | print, punct | print,
1131 punct | print, punct | print,
1132 punct | print, punct | print,
1133 punct | print, punct | print,
1134 punct | print, punct | print,
1135 punct | print, punct | print,
1136 digit | print | xdigit, digit | print | xdigit,
1137 digit | print | xdigit, digit | print | xdigit,
1138 digit | print | xdigit, digit | print | xdigit,
1139 digit | print | xdigit, digit | print | xdigit,
1140 digit | print | xdigit, digit | print | xdigit,
1141 punct | print, punct | print,
1142 punct | print, punct | print,
1143 punct | print, punct | print,
1144 punct | print, upper | xdigit | print | alpha,
1145 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1146 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1147 upper | xdigit | print | alpha, upper | print | alpha,
1148 upper | print | alpha, upper | print | alpha,
1149 upper | print | alpha, upper | print | alpha,
1150 upper | print | alpha, upper | print | alpha,
1151 upper | print | alpha, upper | print | alpha,
1152 upper | print | alpha, upper | print | alpha,
1153 upper | print | alpha, upper | print | alpha,
1154 upper | print | alpha, upper | print | alpha,
1155 upper | print | alpha, upper | print | alpha,
1156 upper | print | alpha, upper | print | alpha,
1157 upper | print | alpha, punct | print,
1158 punct | print, punct | print,
1159 punct | print, punct | print,
1160 punct | print, lower | xdigit | print | alpha,
1161 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1162 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1163 lower | xdigit | print | alpha, lower | print | alpha,
1164 lower | print | alpha, lower | print | alpha,
1165 lower | print | alpha, lower | print | alpha,
1166 lower | print | alpha, lower | print | alpha,
1167 lower | print | alpha, lower | print | alpha,
1168 lower | print | alpha, lower | print | alpha,
1169 lower | print | alpha, lower | print | alpha,
1170 lower | print | alpha, lower | print | alpha,
1171 lower | print | alpha, lower | print | alpha,
1172 lower | print | alpha, lower | print | alpha,
1173 lower | print | alpha, punct | print,
1174 punct | print, punct | print,
1175 punct | print, cntrl,
1176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1184 };
1185 return builtin_table;
1186}
1187#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001188const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001189ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001190{
David Chisnall1d581062011-09-21 08:39:44 +00001191#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001192 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001193#elif defined(__NetBSD__)
1194 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001195#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001196 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001197#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001198 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001199#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001200 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001201#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001202 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001203#elif defined(_NEWLIB_VERSION)
1204 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1205 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001206#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001207 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001208#else
David Chisnall8074c342012-02-29 13:05:08 +00001209 // Platform not supported: abort so the person doing the port knows what to
1210 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001211# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001212 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001213 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001214 return NULL;
1215#endif
1216}
Marshall Clowb3f62842015-03-04 16:10:14 +00001217#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001218
Howard Hinnantd7a78632011-09-29 13:33:15 +00001219#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001220const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001221ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001222{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001223 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001224}
1225
1226const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001227ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001228{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001229 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001230}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001231#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001232const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001233ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001234{
1235 return _C_tolower_tab_ + 1;
1236}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001237
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001238const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001239ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001240{
1241 return _C_toupper_tab_ + 1;
1242}
1243
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001244#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001245const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001246ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001247{
1248 return *__ctype_tolower_loc();
1249}
1250
1251const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001252ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001253{
1254 return *__ctype_toupper_loc();
1255}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001256#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001257
Howard Hinnantc51e1022010-05-11 19:42:16 +00001258// template <> class ctype_byname<char>
1259
1260ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1261 : ctype<char>(0, false, refs),
1262 __l(newlocale(LC_ALL_MASK, name, 0))
1263{
1264 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001265 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001266 " failed to construct for " + string(name));
1267}
1268
1269ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1270 : ctype<char>(0, false, refs),
1271 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1272{
1273 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001274 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001275 " failed to construct for " + name);
1276}
1277
1278ctype_byname<char>::~ctype_byname()
1279{
1280 freelocale(__l);
1281}
1282
1283char
1284ctype_byname<char>::do_toupper(char_type c) const
1285{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001286 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001287}
1288
1289const char*
1290ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1291{
1292 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001293 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001294 return low;
1295}
1296
1297char
1298ctype_byname<char>::do_tolower(char_type c) const
1299{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001300 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301}
1302
1303const char*
1304ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1305{
1306 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001307 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001308 return low;
1309}
1310
1311// template <> class ctype_byname<wchar_t>
1312
Louis Dionne89258142021-08-23 15:32:36 -04001313#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001314ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1315 : ctype<wchar_t>(refs),
1316 __l(newlocale(LC_ALL_MASK, name, 0))
1317{
1318 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001319 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001320 " failed to construct for " + string(name));
1321}
1322
1323ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1324 : ctype<wchar_t>(refs),
1325 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1326{
1327 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001328 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001329 " failed to construct for " + name);
1330}
1331
1332ctype_byname<wchar_t>::~ctype_byname()
1333{
1334 freelocale(__l);
1335}
1336
1337bool
1338ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1339{
Alexis Huntc2017f12011-07-09 03:40:04 +00001340#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001341 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001342#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001343 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001344 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001345 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1346 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1347 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1348 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1349 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1350 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1351 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1352 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1353 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1354 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001355 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001356#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001357}
1358
1359const wchar_t*
1360ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1361{
1362 for (; low != high; ++low, ++vec)
1363 {
1364 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001365 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001366 else
1367 {
1368 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001369 wint_t ch = static_cast<wint_t>(*low);
1370 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001371 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001372#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001373 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001374 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001375#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001376 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001377 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001378 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001379 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001380 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001381 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001382#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001383 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001384 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001385#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001386 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001387 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001388 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001389 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001390#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001391 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001392 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001393#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001394#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001395 if (iswblank_l(ch, __l))
1396 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001397#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001398 }
1399 }
1400 return low;
1401}
1402
1403const wchar_t*
1404ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1405{
1406 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001407 {
1408#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001409 if (iswctype_l(*low, m, __l))
1410 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001411#else
Marshall Clowada0f732013-02-07 14:22:51 +00001412 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001413 if ((m & space) == space && iswspace_l(ch, __l)) break;
1414 if ((m & print) == print && iswprint_l(ch, __l)) break;
1415 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1416 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1417 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1418 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1419 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1420 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1421 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1422 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001423#endif
1424 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001425 return low;
1426}
1427
1428const wchar_t*
1429ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1430{
1431 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001432 {
1433#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001434 if (!iswctype_l(*low, m, __l))
1435 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001436#else
Marshall Clowada0f732013-02-07 14:22:51 +00001437 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001438 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1439 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1440 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1441 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1442 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1443 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1444 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1445 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1446 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1447 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001448 break;
1449#endif
1450 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001451 return low;
1452}
1453
1454wchar_t
1455ctype_byname<wchar_t>::do_toupper(char_type c) const
1456{
1457 return towupper_l(c, __l);
1458}
1459
1460const wchar_t*
1461ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1462{
1463 for (; low != high; ++low)
1464 *low = towupper_l(*low, __l);
1465 return low;
1466}
1467
1468wchar_t
1469ctype_byname<wchar_t>::do_tolower(char_type c) const
1470{
1471 return towlower_l(c, __l);
1472}
1473
1474const wchar_t*
1475ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1476{
1477 for (; low != high; ++low)
1478 *low = towlower_l(*low, __l);
1479 return low;
1480}
1481
1482wchar_t
1483ctype_byname<wchar_t>::do_widen(char c) const
1484{
Ben Craig3756b922016-03-09 15:39:39 +00001485 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001486}
1487
1488const char*
1489ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1490{
1491 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001492 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001493 return low;
1494}
1495
1496char
1497ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1498{
Ben Craig3756b922016-03-09 15:39:39 +00001499 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001500 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001501}
1502
1503const wchar_t*
1504ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1505{
1506 for (; low != high; ++low, ++dest)
1507 {
Ben Craig3756b922016-03-09 15:39:39 +00001508 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001509 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001510 }
1511 return low;
1512}
Louis Dionne89258142021-08-23 15:32:36 -04001513#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001514
1515// template <> class codecvt<char, char, mbstate_t>
1516
Howard Hinnantffb308e2010-08-22 00:03:27 +00001517locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001518
1519codecvt<char, char, mbstate_t>::~codecvt()
1520{
1521}
1522
1523codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001524codecvt<char, char, mbstate_t>::do_out(state_type&,
1525 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526 extern_type* to, extern_type*, extern_type*& to_nxt) const
1527{
1528 frm_nxt = frm;
1529 to_nxt = to;
1530 return noconv;
1531}
1532
1533codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001534codecvt<char, char, mbstate_t>::do_in(state_type&,
1535 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001536 intern_type* to, intern_type*, intern_type*& to_nxt) const
1537{
1538 frm_nxt = frm;
1539 to_nxt = to;
1540 return noconv;
1541}
1542
1543codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001544codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001545 extern_type* to, extern_type*, extern_type*& to_nxt) const
1546{
1547 to_nxt = to;
1548 return noconv;
1549}
1550
1551int
Louis Dionne65358e12021-03-01 12:09:45 -05001552codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001553{
1554 return 1;
1555}
1556
1557bool
Louis Dionne65358e12021-03-01 12:09:45 -05001558codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001559{
1560 return true;
1561}
1562
1563int
1564codecvt<char, char, mbstate_t>::do_length(state_type&,
1565 const extern_type* frm, const extern_type* end, size_t mx) const
1566{
Howard Hinnant28b24882011-12-01 20:21:04 +00001567 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001568}
1569
1570int
Louis Dionne65358e12021-03-01 12:09:45 -05001571codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001572{
1573 return 1;
1574}
1575
1576// template <> class codecvt<wchar_t, char, mbstate_t>
1577
Louis Dionne89258142021-08-23 15:32:36 -04001578#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantffb308e2010-08-22 00:03:27 +00001579locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001580
1581codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1582 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001583 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001584{
1585}
1586
1587codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1588 : locale::facet(refs),
1589 __l(newlocale(LC_ALL_MASK, nm, 0))
1590{
1591 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001592 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001593 " failed to construct for " + string(nm));
1594}
1595
1596codecvt<wchar_t, char, mbstate_t>::~codecvt()
1597{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001598 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001599 freelocale(__l);
1600}
1601
1602codecvt<wchar_t, char, mbstate_t>::result
1603codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001604 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001605 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1606{
1607 // look for first internal null in frm
1608 const intern_type* fend = frm;
1609 for (; fend != frm_end; ++fend)
1610 if (*fend == 0)
1611 break;
1612 // loop over all null-terminated sequences in frm
1613 to_nxt = to;
1614 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1615 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001616 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001617 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001618 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1619 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001620 if (n == size_t(-1))
1621 {
1622 // need to recover to_nxt
1623 for (to_nxt = to; frm != frm_nxt; ++frm)
1624 {
Ben Craig3756b922016-03-09 15:39:39 +00001625 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001626 if (n == size_t(-1))
1627 break;
1628 to_nxt += n;
1629 }
1630 frm_nxt = frm;
1631 return error;
1632 }
1633 if (n == 0)
1634 return partial;
1635 to_nxt += n;
1636 if (to_nxt == to_end)
1637 break;
1638 if (fend != frm_end) // set up next null terminated sequence
1639 {
1640 // Try to write the terminating null
1641 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001642 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001643 if (n == size_t(-1)) // on error
1644 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001645 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001646 return partial;
1647 for (extern_type* p = tmp; n; --n) // write it
1648 *to_nxt++ = *p++;
1649 ++frm_nxt;
1650 // look for next null in frm
1651 for (fend = frm_nxt; fend != frm_end; ++fend)
1652 if (*fend == 0)
1653 break;
1654 }
1655 }
1656 return frm_nxt == frm_end ? ok : partial;
1657}
1658
1659codecvt<wchar_t, char, mbstate_t>::result
1660codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001661 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001662 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1663{
1664 // look for first internal null in frm
1665 const extern_type* fend = frm;
1666 for (; fend != frm_end; ++fend)
1667 if (*fend == 0)
1668 break;
1669 // loop over all null-terminated sequences in frm
1670 to_nxt = to;
1671 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1672 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001673 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001674 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001675 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1676 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001677 if (n == size_t(-1))
1678 {
1679 // need to recover to_nxt
1680 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1681 {
Ben Craig3756b922016-03-09 15:39:39 +00001682 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1683 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001684 switch (n)
1685 {
1686 case 0:
1687 ++frm;
1688 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001689 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001690 frm_nxt = frm;
1691 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001692 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001693 frm_nxt = frm;
1694 return partial;
1695 default:
1696 frm += n;
1697 break;
1698 }
1699 }
1700 frm_nxt = frm;
1701 return frm_nxt == frm_end ? ok : partial;
1702 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001703 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001704 return error;
1705 to_nxt += n;
1706 if (to_nxt == to_end)
1707 break;
1708 if (fend != frm_end) // set up next null terminated sequence
1709 {
1710 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001711 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001712 if (n != 0) // on error
1713 return error;
1714 ++to_nxt;
1715 ++frm_nxt;
1716 // look for next null in frm
1717 for (fend = frm_nxt; fend != frm_end; ++fend)
1718 if (*fend == 0)
1719 break;
1720 }
1721 }
1722 return frm_nxt == frm_end ? ok : partial;
1723}
1724
1725codecvt<wchar_t, char, mbstate_t>::result
1726codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1727 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1728{
1729 to_nxt = to;
1730 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001731 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001732 if (n == size_t(-1) || n == 0) // on error
1733 return error;
1734 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001735 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001736 return partial;
1737 for (extern_type* p = tmp; n; --n) // write it
1738 *to_nxt++ = *p++;
1739 return ok;
1740}
1741
1742int
Louis Dionne65358e12021-03-01 12:09:45 -05001743codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001744{
Ben Craig3756b922016-03-09 15:39:39 +00001745 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001746 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001747
1748 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001749 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001750 return 1; // which take more than 1 char to form a wchar_t
1751 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001752}
1753
1754bool
Louis Dionne65358e12021-03-01 12:09:45 -05001755codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001756{
1757 return false;
1758}
1759
1760int
1761codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1762 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1763{
1764 int nbytes = 0;
1765 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1766 {
Ben Craig3756b922016-03-09 15:39:39 +00001767 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001768 switch (n)
1769 {
1770 case 0:
1771 ++nbytes;
1772 ++frm;
1773 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001774 case size_t(-1):
1775 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001776 return nbytes;
1777 default:
1778 nbytes += n;
1779 frm += n;
1780 break;
1781 }
1782 }
1783 return nbytes;
1784}
1785
1786int
Louis Dionne65358e12021-03-01 12:09:45 -05001787codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001788{
Ben Craig3756b922016-03-09 15:39:39 +00001789 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001790}
Louis Dionne89258142021-08-23 15:32:36 -04001791#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001792
1793// Valid UTF ranges
1794// UTF-32 UTF-16 UTF-8 # of code points
1795// first second first second third fourth
1796// 000000 - 00007F 0000 - 007F 00 - 7F 127
1797// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1798// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1799// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1800// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1801// 00D800 - 00DFFF invalid
1802// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1803// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1804// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1805// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1806
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001807static
1808codecvt_base::result
1809utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1810 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1811 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1812{
1813 frm_nxt = frm;
1814 to_nxt = to;
1815 if (mode & generate_header)
1816 {
1817 if (to_end-to_nxt < 3)
1818 return codecvt_base::partial;
1819 *to_nxt++ = static_cast<uint8_t>(0xEF);
1820 *to_nxt++ = static_cast<uint8_t>(0xBB);
1821 *to_nxt++ = static_cast<uint8_t>(0xBF);
1822 }
1823 for (; frm_nxt < frm_end; ++frm_nxt)
1824 {
1825 uint16_t wc1 = *frm_nxt;
1826 if (wc1 > Maxcode)
1827 return codecvt_base::error;
1828 if (wc1 < 0x0080)
1829 {
1830 if (to_end-to_nxt < 1)
1831 return codecvt_base::partial;
1832 *to_nxt++ = static_cast<uint8_t>(wc1);
1833 }
1834 else if (wc1 < 0x0800)
1835 {
1836 if (to_end-to_nxt < 2)
1837 return codecvt_base::partial;
1838 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1839 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1840 }
1841 else if (wc1 < 0xD800)
1842 {
1843 if (to_end-to_nxt < 3)
1844 return codecvt_base::partial;
1845 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1846 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1847 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1848 }
1849 else if (wc1 < 0xDC00)
1850 {
1851 if (frm_end-frm_nxt < 2)
1852 return codecvt_base::partial;
1853 uint16_t wc2 = frm_nxt[1];
1854 if ((wc2 & 0xFC00) != 0xDC00)
1855 return codecvt_base::error;
1856 if (to_end-to_nxt < 4)
1857 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001858 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1859 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001860 return codecvt_base::error;
1861 ++frm_nxt;
1862 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1863 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1864 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1865 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1866 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1867 }
1868 else if (wc1 < 0xE000)
1869 {
1870 return codecvt_base::error;
1871 }
1872 else
1873 {
1874 if (to_end-to_nxt < 3)
1875 return codecvt_base::partial;
1876 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1877 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1878 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1879 }
1880 }
1881 return codecvt_base::ok;
1882}
1883
1884static
1885codecvt_base::result
1886utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1887 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1888 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1889{
1890 frm_nxt = frm;
1891 to_nxt = to;
1892 if (mode & generate_header)
1893 {
1894 if (to_end-to_nxt < 3)
1895 return codecvt_base::partial;
1896 *to_nxt++ = static_cast<uint8_t>(0xEF);
1897 *to_nxt++ = static_cast<uint8_t>(0xBB);
1898 *to_nxt++ = static_cast<uint8_t>(0xBF);
1899 }
1900 for (; frm_nxt < frm_end; ++frm_nxt)
1901 {
1902 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1903 if (wc1 > Maxcode)
1904 return codecvt_base::error;
1905 if (wc1 < 0x0080)
1906 {
1907 if (to_end-to_nxt < 1)
1908 return codecvt_base::partial;
1909 *to_nxt++ = static_cast<uint8_t>(wc1);
1910 }
1911 else if (wc1 < 0x0800)
1912 {
1913 if (to_end-to_nxt < 2)
1914 return codecvt_base::partial;
1915 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1916 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1917 }
1918 else if (wc1 < 0xD800)
1919 {
1920 if (to_end-to_nxt < 3)
1921 return codecvt_base::partial;
1922 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1923 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1924 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1925 }
1926 else if (wc1 < 0xDC00)
1927 {
1928 if (frm_end-frm_nxt < 2)
1929 return codecvt_base::partial;
1930 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1931 if ((wc2 & 0xFC00) != 0xDC00)
1932 return codecvt_base::error;
1933 if (to_end-to_nxt < 4)
1934 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001935 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1936 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001937 return codecvt_base::error;
1938 ++frm_nxt;
1939 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1940 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1941 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1942 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1943 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1944 }
1945 else if (wc1 < 0xE000)
1946 {
1947 return codecvt_base::error;
1948 }
1949 else
1950 {
1951 if (to_end-to_nxt < 3)
1952 return codecvt_base::partial;
1953 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1954 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1955 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1956 }
1957 }
1958 return codecvt_base::ok;
1959}
1960
1961static
1962codecvt_base::result
1963utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1964 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1965 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1966{
1967 frm_nxt = frm;
1968 to_nxt = to;
1969 if (mode & consume_header)
1970 {
1971 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1972 frm_nxt[2] == 0xBF)
1973 frm_nxt += 3;
1974 }
1975 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1976 {
1977 uint8_t c1 = *frm_nxt;
1978 if (c1 > Maxcode)
1979 return codecvt_base::error;
1980 if (c1 < 0x80)
1981 {
1982 *to_nxt = static_cast<uint16_t>(c1);
1983 ++frm_nxt;
1984 }
1985 else if (c1 < 0xC2)
1986 {
1987 return codecvt_base::error;
1988 }
1989 else if (c1 < 0xE0)
1990 {
1991 if (frm_end-frm_nxt < 2)
1992 return codecvt_base::partial;
1993 uint8_t c2 = frm_nxt[1];
1994 if ((c2 & 0xC0) != 0x80)
1995 return codecvt_base::error;
1996 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1997 if (t > Maxcode)
1998 return codecvt_base::error;
1999 *to_nxt = t;
2000 frm_nxt += 2;
2001 }
2002 else if (c1 < 0xF0)
2003 {
2004 if (frm_end-frm_nxt < 3)
2005 return codecvt_base::partial;
2006 uint8_t c2 = frm_nxt[1];
2007 uint8_t c3 = frm_nxt[2];
2008 switch (c1)
2009 {
2010 case 0xE0:
2011 if ((c2 & 0xE0) != 0xA0)
2012 return codecvt_base::error;
2013 break;
2014 case 0xED:
2015 if ((c2 & 0xE0) != 0x80)
2016 return codecvt_base::error;
2017 break;
2018 default:
2019 if ((c2 & 0xC0) != 0x80)
2020 return codecvt_base::error;
2021 break;
2022 }
2023 if ((c3 & 0xC0) != 0x80)
2024 return codecvt_base::error;
2025 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2026 | ((c2 & 0x3F) << 6)
2027 | (c3 & 0x3F));
2028 if (t > Maxcode)
2029 return codecvt_base::error;
2030 *to_nxt = t;
2031 frm_nxt += 3;
2032 }
2033 else if (c1 < 0xF5)
2034 {
2035 if (frm_end-frm_nxt < 4)
2036 return codecvt_base::partial;
2037 uint8_t c2 = frm_nxt[1];
2038 uint8_t c3 = frm_nxt[2];
2039 uint8_t c4 = frm_nxt[3];
2040 switch (c1)
2041 {
2042 case 0xF0:
2043 if (!(0x90 <= c2 && c2 <= 0xBF))
2044 return codecvt_base::error;
2045 break;
2046 case 0xF4:
2047 if ((c2 & 0xF0) != 0x80)
2048 return codecvt_base::error;
2049 break;
2050 default:
2051 if ((c2 & 0xC0) != 0x80)
2052 return codecvt_base::error;
2053 break;
2054 }
2055 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2056 return codecvt_base::error;
2057 if (to_end-to_nxt < 2)
2058 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002059 if ((((c1 & 7UL) << 18) +
2060 ((c2 & 0x3FUL) << 12) +
2061 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002062 return codecvt_base::error;
2063 *to_nxt = static_cast<uint16_t>(
2064 0xD800
2065 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2066 | ((c2 & 0x0F) << 2)
2067 | ((c3 & 0x30) >> 4));
2068 *++to_nxt = static_cast<uint16_t>(
2069 0xDC00
2070 | ((c3 & 0x0F) << 6)
2071 | (c4 & 0x3F));
2072 frm_nxt += 4;
2073 }
2074 else
2075 {
2076 return codecvt_base::error;
2077 }
2078 }
2079 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2080}
2081
2082static
2083codecvt_base::result
2084utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2085 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2086 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2087{
2088 frm_nxt = frm;
2089 to_nxt = to;
2090 if (mode & consume_header)
2091 {
2092 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2093 frm_nxt[2] == 0xBF)
2094 frm_nxt += 3;
2095 }
2096 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2097 {
2098 uint8_t c1 = *frm_nxt;
2099 if (c1 > Maxcode)
2100 return codecvt_base::error;
2101 if (c1 < 0x80)
2102 {
2103 *to_nxt = static_cast<uint32_t>(c1);
2104 ++frm_nxt;
2105 }
2106 else if (c1 < 0xC2)
2107 {
2108 return codecvt_base::error;
2109 }
2110 else if (c1 < 0xE0)
2111 {
2112 if (frm_end-frm_nxt < 2)
2113 return codecvt_base::partial;
2114 uint8_t c2 = frm_nxt[1];
2115 if ((c2 & 0xC0) != 0x80)
2116 return codecvt_base::error;
2117 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2118 if (t > Maxcode)
2119 return codecvt_base::error;
2120 *to_nxt = static_cast<uint32_t>(t);
2121 frm_nxt += 2;
2122 }
2123 else if (c1 < 0xF0)
2124 {
2125 if (frm_end-frm_nxt < 3)
2126 return codecvt_base::partial;
2127 uint8_t c2 = frm_nxt[1];
2128 uint8_t c3 = frm_nxt[2];
2129 switch (c1)
2130 {
2131 case 0xE0:
2132 if ((c2 & 0xE0) != 0xA0)
2133 return codecvt_base::error;
2134 break;
2135 case 0xED:
2136 if ((c2 & 0xE0) != 0x80)
2137 return codecvt_base::error;
2138 break;
2139 default:
2140 if ((c2 & 0xC0) != 0x80)
2141 return codecvt_base::error;
2142 break;
2143 }
2144 if ((c3 & 0xC0) != 0x80)
2145 return codecvt_base::error;
2146 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2147 | ((c2 & 0x3F) << 6)
2148 | (c3 & 0x3F));
2149 if (t > Maxcode)
2150 return codecvt_base::error;
2151 *to_nxt = static_cast<uint32_t>(t);
2152 frm_nxt += 3;
2153 }
2154 else if (c1 < 0xF5)
2155 {
2156 if (frm_end-frm_nxt < 4)
2157 return codecvt_base::partial;
2158 uint8_t c2 = frm_nxt[1];
2159 uint8_t c3 = frm_nxt[2];
2160 uint8_t c4 = frm_nxt[3];
2161 switch (c1)
2162 {
2163 case 0xF0:
2164 if (!(0x90 <= c2 && c2 <= 0xBF))
2165 return codecvt_base::error;
2166 break;
2167 case 0xF4:
2168 if ((c2 & 0xF0) != 0x80)
2169 return codecvt_base::error;
2170 break;
2171 default:
2172 if ((c2 & 0xC0) != 0x80)
2173 return codecvt_base::error;
2174 break;
2175 }
2176 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2177 return codecvt_base::error;
2178 if (to_end-to_nxt < 2)
2179 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002180 if ((((c1 & 7UL) << 18) +
2181 ((c2 & 0x3FUL) << 12) +
2182 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002183 return codecvt_base::error;
2184 *to_nxt = static_cast<uint32_t>(
2185 0xD800
2186 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2187 | ((c2 & 0x0F) << 2)
2188 | ((c3 & 0x30) >> 4));
2189 *++to_nxt = static_cast<uint32_t>(
2190 0xDC00
2191 | ((c3 & 0x0F) << 6)
2192 | (c4 & 0x3F));
2193 frm_nxt += 4;
2194 }
2195 else
2196 {
2197 return codecvt_base::error;
2198 }
2199 }
2200 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2201}
2202
2203static
2204int
2205utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2206 size_t mx, unsigned long Maxcode = 0x10FFFF,
2207 codecvt_mode mode = codecvt_mode(0))
2208{
2209 const uint8_t* frm_nxt = frm;
2210 if (mode & consume_header)
2211 {
2212 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2213 frm_nxt[2] == 0xBF)
2214 frm_nxt += 3;
2215 }
2216 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2217 {
2218 uint8_t c1 = *frm_nxt;
2219 if (c1 > Maxcode)
2220 break;
2221 if (c1 < 0x80)
2222 {
2223 ++frm_nxt;
2224 }
2225 else if (c1 < 0xC2)
2226 {
2227 break;
2228 }
2229 else if (c1 < 0xE0)
2230 {
2231 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2232 break;
2233 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2234 if (t > Maxcode)
2235 break;
2236 frm_nxt += 2;
2237 }
2238 else if (c1 < 0xF0)
2239 {
2240 if (frm_end-frm_nxt < 3)
2241 break;
2242 uint8_t c2 = frm_nxt[1];
2243 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002244 switch (c1)
2245 {
2246 case 0xE0:
2247 if ((c2 & 0xE0) != 0xA0)
2248 return static_cast<int>(frm_nxt - frm);
2249 break;
2250 case 0xED:
2251 if ((c2 & 0xE0) != 0x80)
2252 return static_cast<int>(frm_nxt - frm);
2253 break;
2254 default:
2255 if ((c2 & 0xC0) != 0x80)
2256 return static_cast<int>(frm_nxt - frm);
2257 break;
2258 }
2259 if ((c3 & 0xC0) != 0x80)
2260 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002261 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002262 break;
2263 frm_nxt += 3;
2264 }
2265 else if (c1 < 0xF5)
2266 {
2267 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2268 break;
2269 uint8_t c2 = frm_nxt[1];
2270 uint8_t c3 = frm_nxt[2];
2271 uint8_t c4 = frm_nxt[3];
2272 switch (c1)
2273 {
2274 case 0xF0:
2275 if (!(0x90 <= c2 && c2 <= 0xBF))
2276 return static_cast<int>(frm_nxt - frm);
2277 break;
2278 case 0xF4:
2279 if ((c2 & 0xF0) != 0x80)
2280 return static_cast<int>(frm_nxt - frm);
2281 break;
2282 default:
2283 if ((c2 & 0xC0) != 0x80)
2284 return static_cast<int>(frm_nxt - frm);
2285 break;
2286 }
2287 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2288 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002289 if ((((c1 & 7UL) << 18) +
2290 ((c2 & 0x3FUL) << 12) +
2291 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002292 break;
2293 ++nchar16_t;
2294 frm_nxt += 4;
2295 }
2296 else
2297 {
2298 break;
2299 }
2300 }
2301 return static_cast<int>(frm_nxt - frm);
2302}
2303
2304static
2305codecvt_base::result
2306ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2307 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2308 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2309{
2310 frm_nxt = frm;
2311 to_nxt = to;
2312 if (mode & generate_header)
2313 {
2314 if (to_end-to_nxt < 3)
2315 return codecvt_base::partial;
2316 *to_nxt++ = static_cast<uint8_t>(0xEF);
2317 *to_nxt++ = static_cast<uint8_t>(0xBB);
2318 *to_nxt++ = static_cast<uint8_t>(0xBF);
2319 }
2320 for (; frm_nxt < frm_end; ++frm_nxt)
2321 {
2322 uint32_t wc = *frm_nxt;
2323 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2324 return codecvt_base::error;
2325 if (wc < 0x000080)
2326 {
2327 if (to_end-to_nxt < 1)
2328 return codecvt_base::partial;
2329 *to_nxt++ = static_cast<uint8_t>(wc);
2330 }
2331 else if (wc < 0x000800)
2332 {
2333 if (to_end-to_nxt < 2)
2334 return codecvt_base::partial;
2335 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2336 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2337 }
2338 else if (wc < 0x010000)
2339 {
2340 if (to_end-to_nxt < 3)
2341 return codecvt_base::partial;
2342 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2343 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2344 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2345 }
2346 else // if (wc < 0x110000)
2347 {
2348 if (to_end-to_nxt < 4)
2349 return codecvt_base::partial;
2350 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2351 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2352 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2353 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2354 }
2355 }
2356 return codecvt_base::ok;
2357}
2358
2359static
2360codecvt_base::result
2361utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2362 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2363 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2364{
2365 frm_nxt = frm;
2366 to_nxt = to;
2367 if (mode & consume_header)
2368 {
2369 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2370 frm_nxt[2] == 0xBF)
2371 frm_nxt += 3;
2372 }
2373 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2374 {
2375 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2376 if (c1 < 0x80)
2377 {
2378 if (c1 > Maxcode)
2379 return codecvt_base::error;
2380 *to_nxt = static_cast<uint32_t>(c1);
2381 ++frm_nxt;
2382 }
2383 else if (c1 < 0xC2)
2384 {
2385 return codecvt_base::error;
2386 }
2387 else if (c1 < 0xE0)
2388 {
2389 if (frm_end-frm_nxt < 2)
2390 return codecvt_base::partial;
2391 uint8_t c2 = frm_nxt[1];
2392 if ((c2 & 0xC0) != 0x80)
2393 return codecvt_base::error;
2394 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2395 | (c2 & 0x3F));
2396 if (t > Maxcode)
2397 return codecvt_base::error;
2398 *to_nxt = t;
2399 frm_nxt += 2;
2400 }
2401 else if (c1 < 0xF0)
2402 {
2403 if (frm_end-frm_nxt < 3)
2404 return codecvt_base::partial;
2405 uint8_t c2 = frm_nxt[1];
2406 uint8_t c3 = frm_nxt[2];
2407 switch (c1)
2408 {
2409 case 0xE0:
2410 if ((c2 & 0xE0) != 0xA0)
2411 return codecvt_base::error;
2412 break;
2413 case 0xED:
2414 if ((c2 & 0xE0) != 0x80)
2415 return codecvt_base::error;
2416 break;
2417 default:
2418 if ((c2 & 0xC0) != 0x80)
2419 return codecvt_base::error;
2420 break;
2421 }
2422 if ((c3 & 0xC0) != 0x80)
2423 return codecvt_base::error;
2424 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2425 | ((c2 & 0x3F) << 6)
2426 | (c3 & 0x3F));
2427 if (t > Maxcode)
2428 return codecvt_base::error;
2429 *to_nxt = t;
2430 frm_nxt += 3;
2431 }
2432 else if (c1 < 0xF5)
2433 {
2434 if (frm_end-frm_nxt < 4)
2435 return codecvt_base::partial;
2436 uint8_t c2 = frm_nxt[1];
2437 uint8_t c3 = frm_nxt[2];
2438 uint8_t c4 = frm_nxt[3];
2439 switch (c1)
2440 {
2441 case 0xF0:
2442 if (!(0x90 <= c2 && c2 <= 0xBF))
2443 return codecvt_base::error;
2444 break;
2445 case 0xF4:
2446 if ((c2 & 0xF0) != 0x80)
2447 return codecvt_base::error;
2448 break;
2449 default:
2450 if ((c2 & 0xC0) != 0x80)
2451 return codecvt_base::error;
2452 break;
2453 }
2454 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2455 return codecvt_base::error;
2456 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2457 | ((c2 & 0x3F) << 12)
2458 | ((c3 & 0x3F) << 6)
2459 | (c4 & 0x3F));
2460 if (t > Maxcode)
2461 return codecvt_base::error;
2462 *to_nxt = t;
2463 frm_nxt += 4;
2464 }
2465 else
2466 {
2467 return codecvt_base::error;
2468 }
2469 }
2470 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2471}
2472
2473static
2474int
2475utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2476 size_t mx, unsigned long Maxcode = 0x10FFFF,
2477 codecvt_mode mode = codecvt_mode(0))
2478{
2479 const uint8_t* frm_nxt = frm;
2480 if (mode & consume_header)
2481 {
2482 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2483 frm_nxt[2] == 0xBF)
2484 frm_nxt += 3;
2485 }
2486 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2487 {
2488 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2489 if (c1 < 0x80)
2490 {
2491 if (c1 > Maxcode)
2492 break;
2493 ++frm_nxt;
2494 }
2495 else if (c1 < 0xC2)
2496 {
2497 break;
2498 }
2499 else if (c1 < 0xE0)
2500 {
2501 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2502 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002503 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002504 break;
2505 frm_nxt += 2;
2506 }
2507 else if (c1 < 0xF0)
2508 {
2509 if (frm_end-frm_nxt < 3)
2510 break;
2511 uint8_t c2 = frm_nxt[1];
2512 uint8_t c3 = frm_nxt[2];
2513 switch (c1)
2514 {
2515 case 0xE0:
2516 if ((c2 & 0xE0) != 0xA0)
2517 return static_cast<int>(frm_nxt - frm);
2518 break;
2519 case 0xED:
2520 if ((c2 & 0xE0) != 0x80)
2521 return static_cast<int>(frm_nxt - frm);
2522 break;
2523 default:
2524 if ((c2 & 0xC0) != 0x80)
2525 return static_cast<int>(frm_nxt - frm);
2526 break;
2527 }
2528 if ((c3 & 0xC0) != 0x80)
2529 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002530 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002531 break;
2532 frm_nxt += 3;
2533 }
2534 else if (c1 < 0xF5)
2535 {
2536 if (frm_end-frm_nxt < 4)
2537 break;
2538 uint8_t c2 = frm_nxt[1];
2539 uint8_t c3 = frm_nxt[2];
2540 uint8_t c4 = frm_nxt[3];
2541 switch (c1)
2542 {
2543 case 0xF0:
2544 if (!(0x90 <= c2 && c2 <= 0xBF))
2545 return static_cast<int>(frm_nxt - frm);
2546 break;
2547 case 0xF4:
2548 if ((c2 & 0xF0) != 0x80)
2549 return static_cast<int>(frm_nxt - frm);
2550 break;
2551 default:
2552 if ((c2 & 0xC0) != 0x80)
2553 return static_cast<int>(frm_nxt - frm);
2554 break;
2555 }
2556 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2557 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002558 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2559 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002560 break;
2561 frm_nxt += 4;
2562 }
2563 else
2564 {
2565 break;
2566 }
2567 }
2568 return static_cast<int>(frm_nxt - frm);
2569}
2570
2571static
2572codecvt_base::result
2573ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2574 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2575 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2576{
2577 frm_nxt = frm;
2578 to_nxt = to;
2579 if (mode & generate_header)
2580 {
2581 if (to_end-to_nxt < 3)
2582 return codecvt_base::partial;
2583 *to_nxt++ = static_cast<uint8_t>(0xEF);
2584 *to_nxt++ = static_cast<uint8_t>(0xBB);
2585 *to_nxt++ = static_cast<uint8_t>(0xBF);
2586 }
2587 for (; frm_nxt < frm_end; ++frm_nxt)
2588 {
2589 uint16_t wc = *frm_nxt;
2590 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2591 return codecvt_base::error;
2592 if (wc < 0x0080)
2593 {
2594 if (to_end-to_nxt < 1)
2595 return codecvt_base::partial;
2596 *to_nxt++ = static_cast<uint8_t>(wc);
2597 }
2598 else if (wc < 0x0800)
2599 {
2600 if (to_end-to_nxt < 2)
2601 return codecvt_base::partial;
2602 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2603 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2604 }
2605 else // if (wc <= 0xFFFF)
2606 {
2607 if (to_end-to_nxt < 3)
2608 return codecvt_base::partial;
2609 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2610 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2611 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2612 }
2613 }
2614 return codecvt_base::ok;
2615}
2616
2617static
2618codecvt_base::result
2619utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2620 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2621 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2622{
2623 frm_nxt = frm;
2624 to_nxt = to;
2625 if (mode & consume_header)
2626 {
2627 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2628 frm_nxt[2] == 0xBF)
2629 frm_nxt += 3;
2630 }
2631 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2632 {
2633 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2634 if (c1 < 0x80)
2635 {
2636 if (c1 > Maxcode)
2637 return codecvt_base::error;
2638 *to_nxt = static_cast<uint16_t>(c1);
2639 ++frm_nxt;
2640 }
2641 else if (c1 < 0xC2)
2642 {
2643 return codecvt_base::error;
2644 }
2645 else if (c1 < 0xE0)
2646 {
2647 if (frm_end-frm_nxt < 2)
2648 return codecvt_base::partial;
2649 uint8_t c2 = frm_nxt[1];
2650 if ((c2 & 0xC0) != 0x80)
2651 return codecvt_base::error;
2652 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2653 | (c2 & 0x3F));
2654 if (t > Maxcode)
2655 return codecvt_base::error;
2656 *to_nxt = t;
2657 frm_nxt += 2;
2658 }
2659 else if (c1 < 0xF0)
2660 {
2661 if (frm_end-frm_nxt < 3)
2662 return codecvt_base::partial;
2663 uint8_t c2 = frm_nxt[1];
2664 uint8_t c3 = frm_nxt[2];
2665 switch (c1)
2666 {
2667 case 0xE0:
2668 if ((c2 & 0xE0) != 0xA0)
2669 return codecvt_base::error;
2670 break;
2671 case 0xED:
2672 if ((c2 & 0xE0) != 0x80)
2673 return codecvt_base::error;
2674 break;
2675 default:
2676 if ((c2 & 0xC0) != 0x80)
2677 return codecvt_base::error;
2678 break;
2679 }
2680 if ((c3 & 0xC0) != 0x80)
2681 return codecvt_base::error;
2682 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2683 | ((c2 & 0x3F) << 6)
2684 | (c3 & 0x3F));
2685 if (t > Maxcode)
2686 return codecvt_base::error;
2687 *to_nxt = t;
2688 frm_nxt += 3;
2689 }
2690 else
2691 {
2692 return codecvt_base::error;
2693 }
2694 }
2695 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2696}
2697
2698static
2699int
2700utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2701 size_t mx, unsigned long Maxcode = 0x10FFFF,
2702 codecvt_mode mode = codecvt_mode(0))
2703{
2704 const uint8_t* frm_nxt = frm;
2705 if (mode & consume_header)
2706 {
2707 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2708 frm_nxt[2] == 0xBF)
2709 frm_nxt += 3;
2710 }
2711 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2712 {
2713 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2714 if (c1 < 0x80)
2715 {
2716 if (c1 > Maxcode)
2717 break;
2718 ++frm_nxt;
2719 }
2720 else if (c1 < 0xC2)
2721 {
2722 break;
2723 }
2724 else if (c1 < 0xE0)
2725 {
2726 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2727 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002728 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002729 break;
2730 frm_nxt += 2;
2731 }
2732 else if (c1 < 0xF0)
2733 {
2734 if (frm_end-frm_nxt < 3)
2735 break;
2736 uint8_t c2 = frm_nxt[1];
2737 uint8_t c3 = frm_nxt[2];
2738 switch (c1)
2739 {
2740 case 0xE0:
2741 if ((c2 & 0xE0) != 0xA0)
2742 return static_cast<int>(frm_nxt - frm);
2743 break;
2744 case 0xED:
2745 if ((c2 & 0xE0) != 0x80)
2746 return static_cast<int>(frm_nxt - frm);
2747 break;
2748 default:
2749 if ((c2 & 0xC0) != 0x80)
2750 return static_cast<int>(frm_nxt - frm);
2751 break;
2752 }
2753 if ((c3 & 0xC0) != 0x80)
2754 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002755 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002756 break;
2757 frm_nxt += 3;
2758 }
2759 else
2760 {
2761 break;
2762 }
2763 }
2764 return static_cast<int>(frm_nxt - frm);
2765}
2766
2767static
2768codecvt_base::result
2769ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2770 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2771 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2772{
2773 frm_nxt = frm;
2774 to_nxt = to;
2775 if (mode & generate_header)
2776 {
2777 if (to_end-to_nxt < 2)
2778 return codecvt_base::partial;
2779 *to_nxt++ = static_cast<uint8_t>(0xFE);
2780 *to_nxt++ = static_cast<uint8_t>(0xFF);
2781 }
2782 for (; frm_nxt < frm_end; ++frm_nxt)
2783 {
2784 uint32_t wc = *frm_nxt;
2785 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2786 return codecvt_base::error;
2787 if (wc < 0x010000)
2788 {
2789 if (to_end-to_nxt < 2)
2790 return codecvt_base::partial;
2791 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2792 *to_nxt++ = static_cast<uint8_t>(wc);
2793 }
2794 else
2795 {
2796 if (to_end-to_nxt < 4)
2797 return codecvt_base::partial;
2798 uint16_t t = static_cast<uint16_t>(
2799 0xD800
2800 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2801 | ((wc & 0x00FC00) >> 10));
2802 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2803 *to_nxt++ = static_cast<uint8_t>(t);
2804 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2805 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2806 *to_nxt++ = static_cast<uint8_t>(t);
2807 }
2808 }
2809 return codecvt_base::ok;
2810}
2811
2812static
2813codecvt_base::result
2814utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2815 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2816 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2817{
2818 frm_nxt = frm;
2819 to_nxt = to;
2820 if (mode & consume_header)
2821 {
2822 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2823 frm_nxt += 2;
2824 }
2825 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2826 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002827 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002828 if ((c1 & 0xFC00) == 0xDC00)
2829 return codecvt_base::error;
2830 if ((c1 & 0xFC00) != 0xD800)
2831 {
2832 if (c1 > Maxcode)
2833 return codecvt_base::error;
2834 *to_nxt = static_cast<uint32_t>(c1);
2835 frm_nxt += 2;
2836 }
2837 else
2838 {
2839 if (frm_end-frm_nxt < 4)
2840 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002841 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002842 if ((c2 & 0xFC00) != 0xDC00)
2843 return codecvt_base::error;
2844 uint32_t t = static_cast<uint32_t>(
2845 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2846 | ((c1 & 0x003F) << 10)
2847 | (c2 & 0x03FF));
2848 if (t > Maxcode)
2849 return codecvt_base::error;
2850 *to_nxt = t;
2851 frm_nxt += 4;
2852 }
2853 }
2854 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2855}
2856
2857static
2858int
2859utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2860 size_t mx, unsigned long Maxcode = 0x10FFFF,
2861 codecvt_mode mode = codecvt_mode(0))
2862{
2863 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002864 if (mode & consume_header)
2865 {
2866 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2867 frm_nxt += 2;
2868 }
2869 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2870 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002871 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002872 if ((c1 & 0xFC00) == 0xDC00)
2873 break;
2874 if ((c1 & 0xFC00) != 0xD800)
2875 {
2876 if (c1 > Maxcode)
2877 break;
2878 frm_nxt += 2;
2879 }
2880 else
2881 {
2882 if (frm_end-frm_nxt < 4)
2883 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002884 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002885 if ((c2 & 0xFC00) != 0xDC00)
2886 break;
2887 uint32_t t = static_cast<uint32_t>(
2888 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2889 | ((c1 & 0x003F) << 10)
2890 | (c2 & 0x03FF));
2891 if (t > Maxcode)
2892 break;
2893 frm_nxt += 4;
2894 }
2895 }
2896 return static_cast<int>(frm_nxt - frm);
2897}
2898
2899static
2900codecvt_base::result
2901ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2902 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2903 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2904{
2905 frm_nxt = frm;
2906 to_nxt = to;
2907 if (mode & generate_header)
2908 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002909 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002910 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002911 *to_nxt++ = static_cast<uint8_t>(0xFF);
2912 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002913 }
2914 for (; frm_nxt < frm_end; ++frm_nxt)
2915 {
2916 uint32_t wc = *frm_nxt;
2917 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2918 return codecvt_base::error;
2919 if (wc < 0x010000)
2920 {
2921 if (to_end-to_nxt < 2)
2922 return codecvt_base::partial;
2923 *to_nxt++ = static_cast<uint8_t>(wc);
2924 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2925 }
2926 else
2927 {
2928 if (to_end-to_nxt < 4)
2929 return codecvt_base::partial;
2930 uint16_t t = static_cast<uint16_t>(
2931 0xD800
2932 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2933 | ((wc & 0x00FC00) >> 10));
2934 *to_nxt++ = static_cast<uint8_t>(t);
2935 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2936 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2937 *to_nxt++ = static_cast<uint8_t>(t);
2938 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2939 }
2940 }
2941 return codecvt_base::ok;
2942}
2943
2944static
2945codecvt_base::result
2946utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2947 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2948 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2949{
2950 frm_nxt = frm;
2951 to_nxt = to;
2952 if (mode & consume_header)
2953 {
2954 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2955 frm_nxt += 2;
2956 }
2957 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2958 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002959 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002960 if ((c1 & 0xFC00) == 0xDC00)
2961 return codecvt_base::error;
2962 if ((c1 & 0xFC00) != 0xD800)
2963 {
2964 if (c1 > Maxcode)
2965 return codecvt_base::error;
2966 *to_nxt = static_cast<uint32_t>(c1);
2967 frm_nxt += 2;
2968 }
2969 else
2970 {
2971 if (frm_end-frm_nxt < 4)
2972 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002973 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002974 if ((c2 & 0xFC00) != 0xDC00)
2975 return codecvt_base::error;
2976 uint32_t t = static_cast<uint32_t>(
2977 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2978 | ((c1 & 0x003F) << 10)
2979 | (c2 & 0x03FF));
2980 if (t > Maxcode)
2981 return codecvt_base::error;
2982 *to_nxt = t;
2983 frm_nxt += 4;
2984 }
2985 }
2986 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2987}
2988
2989static
2990int
2991utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2992 size_t mx, unsigned long Maxcode = 0x10FFFF,
2993 codecvt_mode mode = codecvt_mode(0))
2994{
2995 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002996 if (mode & consume_header)
2997 {
2998 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2999 frm_nxt += 2;
3000 }
3001 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3002 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003003 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003004 if ((c1 & 0xFC00) == 0xDC00)
3005 break;
3006 if ((c1 & 0xFC00) != 0xD800)
3007 {
3008 if (c1 > Maxcode)
3009 break;
3010 frm_nxt += 2;
3011 }
3012 else
3013 {
3014 if (frm_end-frm_nxt < 4)
3015 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00003016 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003017 if ((c2 & 0xFC00) != 0xDC00)
3018 break;
3019 uint32_t t = static_cast<uint32_t>(
3020 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3021 | ((c1 & 0x003F) << 10)
3022 | (c2 & 0x03FF));
3023 if (t > Maxcode)
3024 break;
3025 frm_nxt += 4;
3026 }
3027 }
3028 return static_cast<int>(frm_nxt - frm);
3029}
3030
3031static
3032codecvt_base::result
3033ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3034 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3035 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3036{
3037 frm_nxt = frm;
3038 to_nxt = to;
3039 if (mode & generate_header)
3040 {
3041 if (to_end-to_nxt < 2)
3042 return codecvt_base::partial;
3043 *to_nxt++ = static_cast<uint8_t>(0xFE);
3044 *to_nxt++ = static_cast<uint8_t>(0xFF);
3045 }
3046 for (; frm_nxt < frm_end; ++frm_nxt)
3047 {
3048 uint16_t wc = *frm_nxt;
3049 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3050 return codecvt_base::error;
3051 if (to_end-to_nxt < 2)
3052 return codecvt_base::partial;
3053 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3054 *to_nxt++ = static_cast<uint8_t>(wc);
3055 }
3056 return codecvt_base::ok;
3057}
3058
3059static
3060codecvt_base::result
3061utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3062 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3063 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3064{
3065 frm_nxt = frm;
3066 to_nxt = to;
3067 if (mode & consume_header)
3068 {
3069 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3070 frm_nxt += 2;
3071 }
3072 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3073 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003074 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003075 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3076 return codecvt_base::error;
3077 *to_nxt = c1;
3078 frm_nxt += 2;
3079 }
3080 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3081}
3082
3083static
3084int
3085utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3086 size_t mx, unsigned long Maxcode = 0x10FFFF,
3087 codecvt_mode mode = codecvt_mode(0))
3088{
3089 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003090 if (mode & consume_header)
3091 {
3092 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3093 frm_nxt += 2;
3094 }
3095 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3096 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003097 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003098 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3099 break;
3100 frm_nxt += 2;
3101 }
3102 return static_cast<int>(frm_nxt - frm);
3103}
3104
3105static
3106codecvt_base::result
3107ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3108 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3109 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3110{
3111 frm_nxt = frm;
3112 to_nxt = to;
3113 if (mode & generate_header)
3114 {
3115 if (to_end-to_nxt < 2)
3116 return codecvt_base::partial;
3117 *to_nxt++ = static_cast<uint8_t>(0xFF);
3118 *to_nxt++ = static_cast<uint8_t>(0xFE);
3119 }
3120 for (; frm_nxt < frm_end; ++frm_nxt)
3121 {
3122 uint16_t wc = *frm_nxt;
3123 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3124 return codecvt_base::error;
3125 if (to_end-to_nxt < 2)
3126 return codecvt_base::partial;
3127 *to_nxt++ = static_cast<uint8_t>(wc);
3128 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3129 }
3130 return codecvt_base::ok;
3131}
3132
3133static
3134codecvt_base::result
3135utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3136 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3137 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3138{
3139 frm_nxt = frm;
3140 to_nxt = to;
3141 if (mode & consume_header)
3142 {
3143 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3144 frm_nxt += 2;
3145 }
3146 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3147 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003148 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003149 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3150 return codecvt_base::error;
3151 *to_nxt = c1;
3152 frm_nxt += 2;
3153 }
3154 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3155}
3156
3157static
3158int
3159utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3160 size_t mx, unsigned long Maxcode = 0x10FFFF,
3161 codecvt_mode mode = codecvt_mode(0))
3162{
3163 const uint8_t* frm_nxt = frm;
3164 frm_nxt = frm;
3165 if (mode & consume_header)
3166 {
3167 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3168 frm_nxt += 2;
3169 }
3170 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3171 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003172 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003173 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3174 break;
3175 frm_nxt += 2;
3176 }
3177 return static_cast<int>(frm_nxt - frm);
3178}
3179
Howard Hinnantc51e1022010-05-11 19:42:16 +00003180// template <> class codecvt<char16_t, char, mbstate_t>
3181
Howard Hinnantffb308e2010-08-22 00:03:27 +00003182locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003183
3184codecvt<char16_t, char, mbstate_t>::~codecvt()
3185{
3186}
3187
3188codecvt<char16_t, char, mbstate_t>::result
3189codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003190 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003191 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3192{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003193 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3194 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3195 const uint16_t* _frm_nxt = _frm;
3196 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3197 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3198 uint8_t* _to_nxt = _to;
3199 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3200 frm_nxt = frm + (_frm_nxt - _frm);
3201 to_nxt = to + (_to_nxt - _to);
3202 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003203}
3204
3205codecvt<char16_t, char, mbstate_t>::result
3206codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003207 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003208 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3209{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003210 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3211 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3212 const uint8_t* _frm_nxt = _frm;
3213 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3214 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3215 uint16_t* _to_nxt = _to;
3216 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3217 frm_nxt = frm + (_frm_nxt - _frm);
3218 to_nxt = to + (_to_nxt - _to);
3219 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003220}
3221
3222codecvt<char16_t, char, mbstate_t>::result
3223codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3224 extern_type* to, extern_type*, extern_type*& to_nxt) const
3225{
3226 to_nxt = to;
3227 return noconv;
3228}
3229
3230int
Louis Dionne65358e12021-03-01 12:09:45 -05003231codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003232{
3233 return 0;
3234}
3235
3236bool
Louis Dionne65358e12021-03-01 12:09:45 -05003237codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003238{
3239 return false;
3240}
3241
3242int
3243codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3244 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3245{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003246 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3247 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3248 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003249}
3250
3251int
Louis Dionne65358e12021-03-01 12:09:45 -05003252codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003253{
3254 return 4;
3255}
3256
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003257#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003258
3259// template <> class codecvt<char16_t, char8_t, mbstate_t>
3260
3261locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3262
3263codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3264{
3265}
3266
3267codecvt<char16_t, char8_t, mbstate_t>::result
3268codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3269 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3270 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3271{
3272 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3273 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3274 const uint16_t* _frm_nxt = _frm;
3275 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3276 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3277 uint8_t* _to_nxt = _to;
3278 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3279 frm_nxt = frm + (_frm_nxt - _frm);
3280 to_nxt = to + (_to_nxt - _to);
3281 return r;
3282}
3283
3284codecvt<char16_t, char8_t, mbstate_t>::result
3285codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3286 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3287 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3288{
3289 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3290 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3291 const uint8_t* _frm_nxt = _frm;
3292 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3293 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3294 uint16_t* _to_nxt = _to;
3295 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3296 frm_nxt = frm + (_frm_nxt - _frm);
3297 to_nxt = to + (_to_nxt - _to);
3298 return r;
3299}
3300
3301codecvt<char16_t, char8_t, mbstate_t>::result
3302codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3303 extern_type* to, extern_type*, extern_type*& to_nxt) const
3304{
3305 to_nxt = to;
3306 return noconv;
3307}
3308
3309int
Louis Dionne65358e12021-03-01 12:09:45 -05003310codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003311{
3312 return 0;
3313}
3314
3315bool
Louis Dionne65358e12021-03-01 12:09:45 -05003316codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003317{
3318 return false;
3319}
3320
3321int
3322codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3323 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3324{
3325 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3326 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3327 return utf8_to_utf16_length(_frm, _frm_end, mx);
3328}
3329
3330int
Louis Dionne65358e12021-03-01 12:09:45 -05003331codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003332{
3333 return 4;
3334}
3335
3336#endif
3337
Howard Hinnantc51e1022010-05-11 19:42:16 +00003338// template <> class codecvt<char32_t, char, mbstate_t>
3339
Howard Hinnantffb308e2010-08-22 00:03:27 +00003340locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003341
3342codecvt<char32_t, char, mbstate_t>::~codecvt()
3343{
3344}
3345
3346codecvt<char32_t, char, mbstate_t>::result
3347codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003348 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003349 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3350{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003351 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3352 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3353 const uint32_t* _frm_nxt = _frm;
3354 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3355 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3356 uint8_t* _to_nxt = _to;
3357 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3358 frm_nxt = frm + (_frm_nxt - _frm);
3359 to_nxt = to + (_to_nxt - _to);
3360 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003361}
3362
3363codecvt<char32_t, char, mbstate_t>::result
3364codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003365 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003366 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3367{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003368 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3369 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3370 const uint8_t* _frm_nxt = _frm;
3371 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3372 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3373 uint32_t* _to_nxt = _to;
3374 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3375 frm_nxt = frm + (_frm_nxt - _frm);
3376 to_nxt = to + (_to_nxt - _to);
3377 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003378}
3379
3380codecvt<char32_t, char, mbstate_t>::result
3381codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3382 extern_type* to, extern_type*, extern_type*& to_nxt) const
3383{
3384 to_nxt = to;
3385 return noconv;
3386}
3387
3388int
Louis Dionne65358e12021-03-01 12:09:45 -05003389codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003390{
3391 return 0;
3392}
3393
3394bool
Louis Dionne65358e12021-03-01 12:09:45 -05003395codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003396{
3397 return false;
3398}
3399
3400int
3401codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3402 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3403{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003404 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3405 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3406 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003407}
3408
3409int
Louis Dionne65358e12021-03-01 12:09:45 -05003410codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003411{
3412 return 4;
3413}
3414
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003415#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003416
3417// template <> class codecvt<char32_t, char8_t, mbstate_t>
3418
3419locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3420
3421codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3422{
3423}
3424
3425codecvt<char32_t, char8_t, mbstate_t>::result
3426codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3427 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3428 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3429{
3430 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3431 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3432 const uint32_t* _frm_nxt = _frm;
3433 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3434 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3435 uint8_t* _to_nxt = _to;
3436 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3437 frm_nxt = frm + (_frm_nxt - _frm);
3438 to_nxt = to + (_to_nxt - _to);
3439 return r;
3440}
3441
3442codecvt<char32_t, char8_t, mbstate_t>::result
3443codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3444 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3445 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3446{
3447 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3448 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3449 const uint8_t* _frm_nxt = _frm;
3450 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3451 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3452 uint32_t* _to_nxt = _to;
3453 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3454 frm_nxt = frm + (_frm_nxt - _frm);
3455 to_nxt = to + (_to_nxt - _to);
3456 return r;
3457}
3458
3459codecvt<char32_t, char8_t, mbstate_t>::result
3460codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3461 extern_type* to, extern_type*, extern_type*& to_nxt) const
3462{
3463 to_nxt = to;
3464 return noconv;
3465}
3466
3467int
Louis Dionne65358e12021-03-01 12:09:45 -05003468codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003469{
3470 return 0;
3471}
3472
3473bool
Louis Dionne65358e12021-03-01 12:09:45 -05003474codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003475{
3476 return false;
3477}
3478
3479int
3480codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3481 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3482{
3483 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3484 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3485 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3486}
3487
3488int
Louis Dionne65358e12021-03-01 12:09:45 -05003489codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003490{
3491 return 4;
3492}
3493
3494#endif
3495
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003496// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003497
Louis Dionne89258142021-08-23 15:32:36 -04003498#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003499__codecvt_utf8<wchar_t>::result
3500__codecvt_utf8<wchar_t>::do_out(state_type&,
3501 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003502 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3503{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003504#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003505 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3506 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3507 const uint16_t* _frm_nxt = _frm;
3508#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003509 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3510 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3511 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003512#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003513 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3514 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3515 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003516#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003517 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3518 _Maxcode_, _Mode_);
3519#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003520 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3521 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003522#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003523 frm_nxt = frm + (_frm_nxt - _frm);
3524 to_nxt = to + (_to_nxt - _to);
3525 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003526}
3527
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003528__codecvt_utf8<wchar_t>::result
3529__codecvt_utf8<wchar_t>::do_in(state_type&,
3530 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003531 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3532{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003533 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3534 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3535 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003536#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003537 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3538 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3539 uint16_t* _to_nxt = _to;
3540 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3541 _Maxcode_, _Mode_);
3542#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003543 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3544 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3545 uint32_t* _to_nxt = _to;
3546 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3547 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003548#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003549 frm_nxt = frm + (_frm_nxt - _frm);
3550 to_nxt = to + (_to_nxt - _to);
3551 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003552}
3553
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003554__codecvt_utf8<wchar_t>::result
3555__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003556 extern_type* to, extern_type*, extern_type*& to_nxt) const
3557{
3558 to_nxt = to;
3559 return noconv;
3560}
3561
3562int
Louis Dionne65358e12021-03-01 12:09:45 -05003563__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003564{
3565 return 0;
3566}
3567
3568bool
Louis Dionne65358e12021-03-01 12:09:45 -05003569__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003570{
3571 return false;
3572}
3573
3574int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003575__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003576 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3577{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003578 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3579 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003580#if defined(_LIBCPP_SHORT_WCHAR)
3581 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3582#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003583 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003584#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003585}
3586
3587int
Louis Dionne65358e12021-03-01 12:09:45 -05003588__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003589{
Xing Xue50b0eb42021-09-09 16:20:36 -04003590#if defined(_LIBCPP_SHORT_WCHAR)
3591 if (_Mode_ & consume_header)
3592 return 6;
3593 return 3;
3594#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003595 if (_Mode_ & consume_header)
3596 return 7;
3597 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003598#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003599}
Louis Dionne89258142021-08-23 15:32:36 -04003600#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003601
3602// __codecvt_utf8<char16_t>
3603
3604__codecvt_utf8<char16_t>::result
3605__codecvt_utf8<char16_t>::do_out(state_type&,
3606 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3607 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3608{
3609 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3610 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3611 const uint16_t* _frm_nxt = _frm;
3612 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3613 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3614 uint8_t* _to_nxt = _to;
3615 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3616 _Maxcode_, _Mode_);
3617 frm_nxt = frm + (_frm_nxt - _frm);
3618 to_nxt = to + (_to_nxt - _to);
3619 return r;
3620}
3621
3622__codecvt_utf8<char16_t>::result
3623__codecvt_utf8<char16_t>::do_in(state_type&,
3624 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3625 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3626{
3627 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3628 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3629 const uint8_t* _frm_nxt = _frm;
3630 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3631 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3632 uint16_t* _to_nxt = _to;
3633 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3634 _Maxcode_, _Mode_);
3635 frm_nxt = frm + (_frm_nxt - _frm);
3636 to_nxt = to + (_to_nxt - _to);
3637 return r;
3638}
3639
3640__codecvt_utf8<char16_t>::result
3641__codecvt_utf8<char16_t>::do_unshift(state_type&,
3642 extern_type* to, extern_type*, extern_type*& to_nxt) const
3643{
3644 to_nxt = to;
3645 return noconv;
3646}
3647
3648int
Louis Dionne65358e12021-03-01 12:09:45 -05003649__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003650{
3651 return 0;
3652}
3653
3654bool
Louis Dionne65358e12021-03-01 12:09:45 -05003655__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003656{
3657 return false;
3658}
3659
3660int
3661__codecvt_utf8<char16_t>::do_length(state_type&,
3662 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3663{
3664 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3665 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3666 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3667}
3668
3669int
Louis Dionne65358e12021-03-01 12:09:45 -05003670__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003671{
3672 if (_Mode_ & consume_header)
3673 return 6;
3674 return 3;
3675}
3676
3677// __codecvt_utf8<char32_t>
3678
3679__codecvt_utf8<char32_t>::result
3680__codecvt_utf8<char32_t>::do_out(state_type&,
3681 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3682 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3683{
3684 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3685 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3686 const uint32_t* _frm_nxt = _frm;
3687 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3688 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3689 uint8_t* _to_nxt = _to;
3690 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3691 _Maxcode_, _Mode_);
3692 frm_nxt = frm + (_frm_nxt - _frm);
3693 to_nxt = to + (_to_nxt - _to);
3694 return r;
3695}
3696
3697__codecvt_utf8<char32_t>::result
3698__codecvt_utf8<char32_t>::do_in(state_type&,
3699 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3700 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3701{
3702 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3703 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3704 const uint8_t* _frm_nxt = _frm;
3705 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3706 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3707 uint32_t* _to_nxt = _to;
3708 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3709 _Maxcode_, _Mode_);
3710 frm_nxt = frm + (_frm_nxt - _frm);
3711 to_nxt = to + (_to_nxt - _to);
3712 return r;
3713}
3714
3715__codecvt_utf8<char32_t>::result
3716__codecvt_utf8<char32_t>::do_unshift(state_type&,
3717 extern_type* to, extern_type*, extern_type*& to_nxt) const
3718{
3719 to_nxt = to;
3720 return noconv;
3721}
3722
3723int
Louis Dionne65358e12021-03-01 12:09:45 -05003724__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003725{
3726 return 0;
3727}
3728
3729bool
Louis Dionne65358e12021-03-01 12:09:45 -05003730__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003731{
3732 return false;
3733}
3734
3735int
3736__codecvt_utf8<char32_t>::do_length(state_type&,
3737 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3738{
3739 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3740 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3741 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3742}
3743
3744int
Louis Dionne65358e12021-03-01 12:09:45 -05003745__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003746{
3747 if (_Mode_ & consume_header)
3748 return 7;
3749 return 4;
3750}
3751
3752// __codecvt_utf16<wchar_t, false>
3753
Louis Dionne89258142021-08-23 15:32:36 -04003754#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003755__codecvt_utf16<wchar_t, false>::result
3756__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3757 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3758 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3759{
Xing Xue50b0eb42021-09-09 16:20:36 -04003760#if defined(_LIBCPP_SHORT_WCHAR)
3761 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3762 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3763 const uint16_t* _frm_nxt = _frm;
3764#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003765 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3766 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3767 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003768#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003769 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3770 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3771 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003772#if defined(_LIBCPP_SHORT_WCHAR)
3773 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3774 _Maxcode_, _Mode_);
3775#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003776 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3777 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003778#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003779 frm_nxt = frm + (_frm_nxt - _frm);
3780 to_nxt = to + (_to_nxt - _to);
3781 return r;
3782}
3783
3784__codecvt_utf16<wchar_t, false>::result
3785__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3786 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3787 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3788{
3789 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3790 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3791 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003792#if defined(_LIBCPP_SHORT_WCHAR)
3793 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3794 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3795 uint16_t* _to_nxt = _to;
3796 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3797 _Maxcode_, _Mode_);
3798#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003799 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 = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3803 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003804#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003805 frm_nxt = frm + (_frm_nxt - _frm);
3806 to_nxt = to + (_to_nxt - _to);
3807 return r;
3808}
3809
3810__codecvt_utf16<wchar_t, false>::result
3811__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3812 extern_type* to, extern_type*, extern_type*& to_nxt) const
3813{
3814 to_nxt = to;
3815 return noconv;
3816}
3817
3818int
Louis Dionne65358e12021-03-01 12:09:45 -05003819__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003820{
3821 return 0;
3822}
3823
3824bool
Louis Dionne65358e12021-03-01 12:09:45 -05003825__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003826{
3827 return false;
3828}
3829
3830int
3831__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3832 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3833{
3834 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3835 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003836#if defined(_LIBCPP_SHORT_WCHAR)
3837 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3838#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003839 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003840#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003841}
3842
3843int
Louis Dionne65358e12021-03-01 12:09:45 -05003844__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003845{
Xing Xue50b0eb42021-09-09 16:20:36 -04003846#if defined(_LIBCPP_SHORT_WCHAR)
3847 if (_Mode_ & consume_header)
3848 return 4;
3849 return 2;
3850#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003851 if (_Mode_ & consume_header)
3852 return 6;
3853 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003854#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003855}
3856
3857// __codecvt_utf16<wchar_t, true>
3858
3859__codecvt_utf16<wchar_t, true>::result
3860__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3861 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3862 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3863{
Xing Xue50b0eb42021-09-09 16:20:36 -04003864#if defined(_LIBCPP_SHORT_WCHAR)
3865 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3866 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3867 const uint16_t* _frm_nxt = _frm;
3868#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003869 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3870 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3871 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003872#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003873 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3874 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3875 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003876#if defined(_LIBCPP_SHORT_WCHAR)
3877 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3878 _Maxcode_, _Mode_);
3879#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003880 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3881 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003882#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003883 frm_nxt = frm + (_frm_nxt - _frm);
3884 to_nxt = to + (_to_nxt - _to);
3885 return r;
3886}
3887
3888__codecvt_utf16<wchar_t, true>::result
3889__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3890 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3891 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3892{
3893 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3894 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3895 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003896#if defined(_LIBCPP_SHORT_WCHAR)
3897 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3898 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3899 uint16_t* _to_nxt = _to;
3900 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3901 _Maxcode_, _Mode_);
3902#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003903 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3904 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3905 uint32_t* _to_nxt = _to;
3906 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3907 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003908#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003909 frm_nxt = frm + (_frm_nxt - _frm);
3910 to_nxt = to + (_to_nxt - _to);
3911 return r;
3912}
3913
3914__codecvt_utf16<wchar_t, true>::result
3915__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3916 extern_type* to, extern_type*, extern_type*& to_nxt) const
3917{
3918 to_nxt = to;
3919 return noconv;
3920}
3921
3922int
Louis Dionne65358e12021-03-01 12:09:45 -05003923__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003924{
3925 return 0;
3926}
3927
3928bool
Louis Dionne65358e12021-03-01 12:09:45 -05003929__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003930{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003931 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003932}
3933
3934int
3935__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3936 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3937{
3938 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3939 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003940#if defined(_LIBCPP_SHORT_WCHAR)
3941 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3942#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003943 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003944#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003945}
3946
3947int
Louis Dionne65358e12021-03-01 12:09:45 -05003948__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003949{
Xing Xue50b0eb42021-09-09 16:20:36 -04003950#if defined(_LIBCPP_SHORT_WCHAR)
3951 if (_Mode_ & consume_header)
3952 return 4;
3953 return 2;
3954#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003955 if (_Mode_ & consume_header)
3956 return 6;
3957 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003958#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003959}
Louis Dionne89258142021-08-23 15:32:36 -04003960#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003961
3962// __codecvt_utf16<char16_t, false>
3963
3964__codecvt_utf16<char16_t, false>::result
3965__codecvt_utf16<char16_t, false>::do_out(state_type&,
3966 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3967 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3968{
3969 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3970 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3971 const uint16_t* _frm_nxt = _frm;
3972 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3973 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3974 uint8_t* _to_nxt = _to;
3975 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3976 _Maxcode_, _Mode_);
3977 frm_nxt = frm + (_frm_nxt - _frm);
3978 to_nxt = to + (_to_nxt - _to);
3979 return r;
3980}
3981
3982__codecvt_utf16<char16_t, false>::result
3983__codecvt_utf16<char16_t, false>::do_in(state_type&,
3984 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3985 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3986{
3987 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3988 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3989 const uint8_t* _frm_nxt = _frm;
3990 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3991 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3992 uint16_t* _to_nxt = _to;
3993 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3994 _Maxcode_, _Mode_);
3995 frm_nxt = frm + (_frm_nxt - _frm);
3996 to_nxt = to + (_to_nxt - _to);
3997 return r;
3998}
3999
4000__codecvt_utf16<char16_t, false>::result
4001__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4002 extern_type* to, extern_type*, extern_type*& to_nxt) const
4003{
4004 to_nxt = to;
4005 return noconv;
4006}
4007
4008int
Louis Dionne65358e12021-03-01 12:09:45 -05004009__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004010{
4011 return 0;
4012}
4013
4014bool
Louis Dionne65358e12021-03-01 12:09:45 -05004015__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004016{
4017 return false;
4018}
4019
4020int
4021__codecvt_utf16<char16_t, false>::do_length(state_type&,
4022 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4023{
4024 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4025 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4026 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4027}
4028
4029int
Louis Dionne65358e12021-03-01 12:09:45 -05004030__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004031{
4032 if (_Mode_ & consume_header)
4033 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004034 return 2;
4035}
4036
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004037// __codecvt_utf16<char16_t, true>
4038
4039__codecvt_utf16<char16_t, true>::result
4040__codecvt_utf16<char16_t, true>::do_out(state_type&,
4041 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4042 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4043{
4044 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4045 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4046 const uint16_t* _frm_nxt = _frm;
4047 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4048 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4049 uint8_t* _to_nxt = _to;
4050 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4051 _Maxcode_, _Mode_);
4052 frm_nxt = frm + (_frm_nxt - _frm);
4053 to_nxt = to + (_to_nxt - _to);
4054 return r;
4055}
4056
4057__codecvt_utf16<char16_t, true>::result
4058__codecvt_utf16<char16_t, true>::do_in(state_type&,
4059 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4060 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4061{
4062 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4063 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4064 const uint8_t* _frm_nxt = _frm;
4065 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4066 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4067 uint16_t* _to_nxt = _to;
4068 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4069 _Maxcode_, _Mode_);
4070 frm_nxt = frm + (_frm_nxt - _frm);
4071 to_nxt = to + (_to_nxt - _to);
4072 return r;
4073}
4074
4075__codecvt_utf16<char16_t, true>::result
4076__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4077 extern_type* to, extern_type*, extern_type*& to_nxt) const
4078{
4079 to_nxt = to;
4080 return noconv;
4081}
4082
4083int
Louis Dionne65358e12021-03-01 12:09:45 -05004084__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004085{
4086 return 0;
4087}
4088
4089bool
Louis Dionne65358e12021-03-01 12:09:45 -05004090__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004091{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004092 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004093}
4094
4095int
4096__codecvt_utf16<char16_t, true>::do_length(state_type&,
4097 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4098{
4099 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4100 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4101 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4102}
4103
4104int
Louis Dionne65358e12021-03-01 12:09:45 -05004105__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004106{
4107 if (_Mode_ & consume_header)
4108 return 4;
4109 return 2;
4110}
4111
4112// __codecvt_utf16<char32_t, false>
4113
4114__codecvt_utf16<char32_t, false>::result
4115__codecvt_utf16<char32_t, false>::do_out(state_type&,
4116 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4117 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4118{
4119 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4120 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4121 const uint32_t* _frm_nxt = _frm;
4122 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4123 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4124 uint8_t* _to_nxt = _to;
4125 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4126 _Maxcode_, _Mode_);
4127 frm_nxt = frm + (_frm_nxt - _frm);
4128 to_nxt = to + (_to_nxt - _to);
4129 return r;
4130}
4131
4132__codecvt_utf16<char32_t, false>::result
4133__codecvt_utf16<char32_t, false>::do_in(state_type&,
4134 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4135 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4136{
4137 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4138 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4139 const uint8_t* _frm_nxt = _frm;
4140 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4141 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4142 uint32_t* _to_nxt = _to;
4143 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4144 _Maxcode_, _Mode_);
4145 frm_nxt = frm + (_frm_nxt - _frm);
4146 to_nxt = to + (_to_nxt - _to);
4147 return r;
4148}
4149
4150__codecvt_utf16<char32_t, false>::result
4151__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4152 extern_type* to, extern_type*, extern_type*& to_nxt) const
4153{
4154 to_nxt = to;
4155 return noconv;
4156}
4157
4158int
Louis Dionne65358e12021-03-01 12:09:45 -05004159__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004160{
4161 return 0;
4162}
4163
4164bool
Louis Dionne65358e12021-03-01 12:09:45 -05004165__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004166{
4167 return false;
4168}
4169
4170int
4171__codecvt_utf16<char32_t, false>::do_length(state_type&,
4172 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4173{
4174 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4175 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4176 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4177}
4178
4179int
Louis Dionne65358e12021-03-01 12:09:45 -05004180__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004181{
4182 if (_Mode_ & consume_header)
4183 return 6;
4184 return 4;
4185}
4186
4187// __codecvt_utf16<char32_t, true>
4188
4189__codecvt_utf16<char32_t, true>::result
4190__codecvt_utf16<char32_t, true>::do_out(state_type&,
4191 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4192 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4193{
4194 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4195 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4196 const uint32_t* _frm_nxt = _frm;
4197 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4198 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4199 uint8_t* _to_nxt = _to;
4200 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4201 _Maxcode_, _Mode_);
4202 frm_nxt = frm + (_frm_nxt - _frm);
4203 to_nxt = to + (_to_nxt - _to);
4204 return r;
4205}
4206
4207__codecvt_utf16<char32_t, true>::result
4208__codecvt_utf16<char32_t, true>::do_in(state_type&,
4209 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4210 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4211{
4212 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4213 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4214 const uint8_t* _frm_nxt = _frm;
4215 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4216 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4217 uint32_t* _to_nxt = _to;
4218 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4219 _Maxcode_, _Mode_);
4220 frm_nxt = frm + (_frm_nxt - _frm);
4221 to_nxt = to + (_to_nxt - _to);
4222 return r;
4223}
4224
4225__codecvt_utf16<char32_t, true>::result
4226__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4227 extern_type* to, extern_type*, extern_type*& to_nxt) const
4228{
4229 to_nxt = to;
4230 return noconv;
4231}
4232
4233int
Louis Dionne65358e12021-03-01 12:09:45 -05004234__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004235{
4236 return 0;
4237}
4238
4239bool
Louis Dionne65358e12021-03-01 12:09:45 -05004240__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004241{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004242 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004243}
4244
4245int
4246__codecvt_utf16<char32_t, true>::do_length(state_type&,
4247 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4248{
4249 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4250 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4251 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4252}
4253
4254int
Louis Dionne65358e12021-03-01 12:09:45 -05004255__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004256{
4257 if (_Mode_ & consume_header)
4258 return 6;
4259 return 4;
4260}
4261
4262// __codecvt_utf8_utf16<wchar_t>
4263
Louis Dionne89258142021-08-23 15:32:36 -04004264#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004265__codecvt_utf8_utf16<wchar_t>::result
4266__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4267 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4268 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4269{
Xing Xue50b0eb42021-09-09 16:20:36 -04004270#if defined(_LIBCPP_SHORT_WCHAR)
4271 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4272 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4273 const uint16_t* _frm_nxt = _frm;
4274#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004275 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4276 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4277 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004278#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004279 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4280 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4281 uint8_t* _to_nxt = _to;
4282 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4283 _Maxcode_, _Mode_);
4284 frm_nxt = frm + (_frm_nxt - _frm);
4285 to_nxt = to + (_to_nxt - _to);
4286 return r;
4287}
4288
4289__codecvt_utf8_utf16<wchar_t>::result
4290__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4291 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4292 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4293{
4294 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4295 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4296 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004297#if defined(_LIBCPP_SHORT_WCHAR)
4298 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4299 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4300 uint16_t* _to_nxt = _to;
4301#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004302 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4303 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4304 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004305#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004306 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4307 _Maxcode_, _Mode_);
4308 frm_nxt = frm + (_frm_nxt - _frm);
4309 to_nxt = to + (_to_nxt - _to);
4310 return r;
4311}
4312
4313__codecvt_utf8_utf16<wchar_t>::result
4314__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4315 extern_type* to, extern_type*, extern_type*& to_nxt) const
4316{
4317 to_nxt = to;
4318 return noconv;
4319}
4320
4321int
Louis Dionne65358e12021-03-01 12:09:45 -05004322__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004323{
4324 return 0;
4325}
4326
4327bool
Louis Dionne65358e12021-03-01 12:09:45 -05004328__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004329{
4330 return false;
4331}
4332
4333int
4334__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4335 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4336{
4337 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4338 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4339 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4340}
4341
4342int
Louis Dionne65358e12021-03-01 12:09:45 -05004343__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004344{
4345 if (_Mode_ & consume_header)
4346 return 7;
4347 return 4;
4348}
Louis Dionne89258142021-08-23 15:32:36 -04004349#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004350
4351// __codecvt_utf8_utf16<char16_t>
4352
4353__codecvt_utf8_utf16<char16_t>::result
4354__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4355 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4356 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4357{
4358 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4359 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4360 const uint16_t* _frm_nxt = _frm;
4361 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4362 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4363 uint8_t* _to_nxt = _to;
4364 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4365 _Maxcode_, _Mode_);
4366 frm_nxt = frm + (_frm_nxt - _frm);
4367 to_nxt = to + (_to_nxt - _to);
4368 return r;
4369}
4370
4371__codecvt_utf8_utf16<char16_t>::result
4372__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4373 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4374 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4375{
4376 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4377 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4378 const uint8_t* _frm_nxt = _frm;
4379 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4380 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4381 uint16_t* _to_nxt = _to;
4382 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4383 _Maxcode_, _Mode_);
4384 frm_nxt = frm + (_frm_nxt - _frm);
4385 to_nxt = to + (_to_nxt - _to);
4386 return r;
4387}
4388
4389__codecvt_utf8_utf16<char16_t>::result
4390__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4391 extern_type* to, extern_type*, extern_type*& to_nxt) const
4392{
4393 to_nxt = to;
4394 return noconv;
4395}
4396
4397int
Louis Dionne65358e12021-03-01 12:09:45 -05004398__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004399{
4400 return 0;
4401}
4402
4403bool
Louis Dionne65358e12021-03-01 12:09:45 -05004404__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004405{
4406 return false;
4407}
4408
4409int
4410__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4411 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4412{
4413 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4414 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4415 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4416}
4417
4418int
Louis Dionne65358e12021-03-01 12:09:45 -05004419__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004420{
4421 if (_Mode_ & consume_header)
4422 return 7;
4423 return 4;
4424}
4425
4426// __codecvt_utf8_utf16<char32_t>
4427
4428__codecvt_utf8_utf16<char32_t>::result
4429__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4430 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4431 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4432{
4433 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4434 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4435 const uint32_t* _frm_nxt = _frm;
4436 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4437 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4438 uint8_t* _to_nxt = _to;
4439 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4440 _Maxcode_, _Mode_);
4441 frm_nxt = frm + (_frm_nxt - _frm);
4442 to_nxt = to + (_to_nxt - _to);
4443 return r;
4444}
4445
4446__codecvt_utf8_utf16<char32_t>::result
4447__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4448 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4449 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4450{
4451 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4452 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4453 const uint8_t* _frm_nxt = _frm;
4454 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4455 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4456 uint32_t* _to_nxt = _to;
4457 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4458 _Maxcode_, _Mode_);
4459 frm_nxt = frm + (_frm_nxt - _frm);
4460 to_nxt = to + (_to_nxt - _to);
4461 return r;
4462}
4463
4464__codecvt_utf8_utf16<char32_t>::result
4465__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4466 extern_type* to, extern_type*, extern_type*& to_nxt) const
4467{
4468 to_nxt = to;
4469 return noconv;
4470}
4471
4472int
Louis Dionne65358e12021-03-01 12:09:45 -05004473__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004474{
4475 return 0;
4476}
4477
4478bool
Louis Dionne65358e12021-03-01 12:09:45 -05004479__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004480{
4481 return false;
4482}
4483
4484int
4485__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4486 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4487{
4488 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4489 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4490 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4491}
4492
4493int
Louis Dionne65358e12021-03-01 12:09:45 -05004494__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004495{
4496 if (_Mode_ & consume_header)
4497 return 7;
4498 return 4;
4499}
4500
Howard Hinnantc51e1022010-05-11 19:42:16 +00004501// __narrow_to_utf8<16>
4502
4503__narrow_to_utf8<16>::~__narrow_to_utf8()
4504{
4505}
4506
4507// __narrow_to_utf8<32>
4508
4509__narrow_to_utf8<32>::~__narrow_to_utf8()
4510{
4511}
4512
4513// __widen_from_utf8<16>
4514
4515__widen_from_utf8<16>::~__widen_from_utf8()
4516{
4517}
4518
4519// __widen_from_utf8<32>
4520
4521__widen_from_utf8<32>::~__widen_from_utf8()
4522{
4523}
4524
Louis Dionne89258142021-08-23 15:32:36 -04004525#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004526static bool checked_string_to_wchar_convert(wchar_t& dest,
4527 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004528 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004529 if (*ptr == '\0')
4530 return false;
4531 mbstate_t mb = {};
4532 wchar_t out;
4533 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4534 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4535 return false;
4536 }
4537 dest = out;
4538 return true;
4539}
Louis Dionne89258142021-08-23 15:32:36 -04004540#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004541
4542static bool checked_string_to_char_convert(char& dest,
4543 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004544 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004545 if (*ptr == '\0')
4546 return false;
4547 if (!ptr[1]) {
4548 dest = *ptr;
4549 return true;
4550 }
Louis Dionne89258142021-08-23 15:32:36 -04004551
4552#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004553 // First convert the MBS into a wide char then attempt to narrow it using
4554 // wctob_l.
4555 wchar_t wout;
4556 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4557 return false;
4558 int res;
4559 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4560 dest = res;
4561 return true;
4562 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004563 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004564 // translate into a different single byte.
4565 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004566 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004567 case L'\u00A0': // non-breaking space
4568 dest = ' ';
4569 return true;
4570 default:
4571 return false;
4572 }
Louis Dionne89258142021-08-23 15:32:36 -04004573#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4574 return false;
4575#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004576 _LIBCPP_UNREACHABLE();
4577}
4578
4579
Howard Hinnantc51e1022010-05-11 19:42:16 +00004580// numpunct<char> && numpunct<wchar_t>
4581
4582locale::id numpunct< char >::id;
Louis Dionne89258142021-08-23 15:32:36 -04004583#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004584locale::id numpunct<wchar_t>::id;
Louis Dionne89258142021-08-23 15:32:36 -04004585#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004586
4587numpunct<char>::numpunct(size_t refs)
4588 : locale::facet(refs),
4589 __decimal_point_('.'),
4590 __thousands_sep_(',')
4591{
4592}
4593
Louis Dionne89258142021-08-23 15:32:36 -04004594#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004595numpunct<wchar_t>::numpunct(size_t refs)
4596 : locale::facet(refs),
4597 __decimal_point_(L'.'),
4598 __thousands_sep_(L',')
4599{
4600}
Louis Dionne89258142021-08-23 15:32:36 -04004601#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004602
4603numpunct<char>::~numpunct()
4604{
4605}
4606
Louis Dionne89258142021-08-23 15:32:36 -04004607#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004608numpunct<wchar_t>::~numpunct()
4609{
4610}
Louis Dionne89258142021-08-23 15:32:36 -04004611#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004612
4613 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004614#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004615wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004616#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004617
4618 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004619#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004620wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004621#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004622
4623string numpunct< char >::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004624#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004625string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004626#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004627
4628 string numpunct< char >::do_truename() const {return "true";}
Louis Dionne89258142021-08-23 15:32:36 -04004629#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004630wstring numpunct<wchar_t>::do_truename() const {return L"true";}
Louis Dionne89258142021-08-23 15:32:36 -04004631#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004632
4633 string numpunct< char >::do_falsename() const {return "false";}
Louis Dionne89258142021-08-23 15:32:36 -04004634#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004635wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
Louis Dionne89258142021-08-23 15:32:36 -04004636#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004637
4638// numpunct_byname<char>
4639
4640numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4641 : numpunct<char>(refs)
4642{
4643 __init(nm);
4644}
4645
4646numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4647 : numpunct<char>(refs)
4648{
4649 __init(nm.c_str());
4650}
4651
4652numpunct_byname<char>::~numpunct_byname()
4653{
4654}
4655
4656void
4657numpunct_byname<char>::__init(const char* nm)
4658{
Louis Dionne89258142021-08-23 15:32:36 -04004659 typedef numpunct<char> base;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004660 if (strcmp(nm, "C") != 0)
4661 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004662 __libcpp_unique_locale loc(nm);
4663 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004664 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004665 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004666
Ben Craig3756b922016-03-09 15:39:39 +00004667 lconv* lc = __libcpp_localeconv_l(loc.get());
Louis Dionne89258142021-08-23 15:32:36 -04004668 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4669 loc.get()))
4670 __decimal_point_ = base::do_decimal_point();
4671 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4672 loc.get()))
4673 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00004674 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004675 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004676 }
4677}
4678
4679// numpunct_byname<wchar_t>
4680
Louis Dionne89258142021-08-23 15:32:36 -04004681#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004682numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4683 : numpunct<wchar_t>(refs)
4684{
4685 __init(nm);
4686}
4687
4688numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4689 : numpunct<wchar_t>(refs)
4690{
4691 __init(nm.c_str());
4692}
4693
4694numpunct_byname<wchar_t>::~numpunct_byname()
4695{
4696}
4697
4698void
4699numpunct_byname<wchar_t>::__init(const char* nm)
4700{
4701 if (strcmp(nm, "C") != 0)
4702 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004703 __libcpp_unique_locale loc(nm);
4704 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004705 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004706 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004707
Ben Craig3756b922016-03-09 15:39:39 +00004708 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004709 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4710 loc.get());
4711 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4712 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004713 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004714 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004715 }
4716}
Louis Dionne89258142021-08-23 15:32:36 -04004717#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004718
4719// num_get helpers
4720
4721int
4722__num_get_base::__get_base(ios_base& iob)
4723{
4724 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4725 if (__basefield == ios_base::oct)
4726 return 8;
4727 else if (__basefield == ios_base::hex)
4728 return 16;
4729 else if (__basefield == 0)
4730 return 0;
4731 return 10;
4732}
4733
4734const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4735
4736void
4737__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4738 ios_base::iostate& __err)
4739{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004740// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4741// we always have at least a single entry in [__g, __g_end); the end of the input sequence
Marshall Clow3ec1c362019-06-17 13:41:14 +00004742 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004743 {
4744 reverse(__g, __g_end);
4745 const char* __ig = __grouping.data();
4746 const char* __eg = __ig + __grouping.size();
4747 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4748 {
4749 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4750 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004751 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004752 {
4753 __err = ios_base::failbit;
4754 return;
4755 }
4756 }
4757 if (__eg - __ig > 1)
4758 ++__ig;
4759 }
4760 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4761 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004762 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004763 __err = ios_base::failbit;
4764 }
4765 }
4766}
4767
4768void
4769__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4770 ios_base::fmtflags __flags)
4771{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004772 if ((__flags & ios_base::showpos) &&
4773 (__flags & ios_base::basefield) != ios_base::oct &&
4774 (__flags & ios_base::basefield) != ios_base::hex &&
4775 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004776 *__fmtp++ = '+';
4777 if (__flags & ios_base::showbase)
4778 *__fmtp++ = '#';
4779 while(*__len)
4780 *__fmtp++ = *__len++;
4781 if ((__flags & ios_base::basefield) == ios_base::oct)
4782 *__fmtp = 'o';
4783 else if ((__flags & ios_base::basefield) == ios_base::hex)
4784 {
4785 if (__flags & ios_base::uppercase)
4786 *__fmtp = 'X';
4787 else
4788 *__fmtp = 'x';
4789 }
4790 else if (__signd)
4791 *__fmtp = 'd';
4792 else
4793 *__fmtp = 'u';
4794}
4795
4796bool
4797__num_put_base::__format_float(char* __fmtp, const char* __len,
4798 ios_base::fmtflags __flags)
4799{
4800 bool specify_precision = true;
4801 if (__flags & ios_base::showpos)
4802 *__fmtp++ = '+';
4803 if (__flags & ios_base::showpoint)
4804 *__fmtp++ = '#';
4805 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004806 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004807 if (floatfield == (ios_base::fixed | ios_base::scientific))
4808 specify_precision = false;
4809 else
4810 {
4811 *__fmtp++ = '.';
4812 *__fmtp++ = '*';
4813 }
4814 while(*__len)
4815 *__fmtp++ = *__len++;
4816 if (floatfield == ios_base::fixed)
4817 {
4818 if (uppercase)
4819 *__fmtp = 'F';
4820 else
4821 *__fmtp = 'f';
4822 }
4823 else if (floatfield == ios_base::scientific)
4824 {
4825 if (uppercase)
4826 *__fmtp = 'E';
4827 else
4828 *__fmtp = 'e';
4829 }
4830 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4831 {
4832 if (uppercase)
4833 *__fmtp = 'A';
4834 else
4835 *__fmtp = 'a';
4836 }
4837 else
4838 {
4839 if (uppercase)
4840 *__fmtp = 'G';
4841 else
4842 *__fmtp = 'g';
4843 }
4844 return specify_precision;
4845}
4846
4847char*
4848__num_put_base::__identify_padding(char* __nb, char* __ne,
4849 const ios_base& __iob)
4850{
4851 switch (__iob.flags() & ios_base::adjustfield)
4852 {
4853 case ios_base::internal:
4854 if (__nb[0] == '-' || __nb[0] == '+')
4855 return __nb+1;
4856 if (__ne - __nb >= 2 && __nb[0] == '0'
4857 && (__nb[1] == 'x' || __nb[1] == 'X'))
4858 return __nb+2;
4859 break;
4860 case ios_base::left:
4861 return __ne;
4862 case ios_base::right:
4863 default:
4864 break;
4865 }
4866 return __nb;
4867}
4868
4869// time_get
4870
4871static
4872string*
4873init_weeks()
4874{
4875 static string weeks[14];
4876 weeks[0] = "Sunday";
4877 weeks[1] = "Monday";
4878 weeks[2] = "Tuesday";
4879 weeks[3] = "Wednesday";
4880 weeks[4] = "Thursday";
4881 weeks[5] = "Friday";
4882 weeks[6] = "Saturday";
4883 weeks[7] = "Sun";
4884 weeks[8] = "Mon";
4885 weeks[9] = "Tue";
4886 weeks[10] = "Wed";
4887 weeks[11] = "Thu";
4888 weeks[12] = "Fri";
4889 weeks[13] = "Sat";
4890 return weeks;
4891}
4892
Louis Dionne89258142021-08-23 15:32:36 -04004893#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004894static
4895wstring*
4896init_wweeks()
4897{
4898 static wstring weeks[14];
4899 weeks[0] = L"Sunday";
4900 weeks[1] = L"Monday";
4901 weeks[2] = L"Tuesday";
4902 weeks[3] = L"Wednesday";
4903 weeks[4] = L"Thursday";
4904 weeks[5] = L"Friday";
4905 weeks[6] = L"Saturday";
4906 weeks[7] = L"Sun";
4907 weeks[8] = L"Mon";
4908 weeks[9] = L"Tue";
4909 weeks[10] = L"Wed";
4910 weeks[11] = L"Thu";
4911 weeks[12] = L"Fri";
4912 weeks[13] = L"Sat";
4913 return weeks;
4914}
Louis Dionne89258142021-08-23 15:32:36 -04004915#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004916
4917template <>
4918const string*
4919__time_get_c_storage<char>::__weeks() const
4920{
4921 static const string* weeks = init_weeks();
4922 return weeks;
4923}
4924
Louis Dionne89258142021-08-23 15:32:36 -04004925#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004926template <>
4927const wstring*
4928__time_get_c_storage<wchar_t>::__weeks() const
4929{
4930 static const wstring* weeks = init_wweeks();
4931 return weeks;
4932}
Louis Dionne89258142021-08-23 15:32:36 -04004933#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004934
4935static
4936string*
4937init_months()
4938{
4939 static string months[24];
4940 months[0] = "January";
4941 months[1] = "February";
4942 months[2] = "March";
4943 months[3] = "April";
4944 months[4] = "May";
4945 months[5] = "June";
4946 months[6] = "July";
4947 months[7] = "August";
4948 months[8] = "September";
4949 months[9] = "October";
4950 months[10] = "November";
4951 months[11] = "December";
4952 months[12] = "Jan";
4953 months[13] = "Feb";
4954 months[14] = "Mar";
4955 months[15] = "Apr";
4956 months[16] = "May";
4957 months[17] = "Jun";
4958 months[18] = "Jul";
4959 months[19] = "Aug";
4960 months[20] = "Sep";
4961 months[21] = "Oct";
4962 months[22] = "Nov";
4963 months[23] = "Dec";
4964 return months;
4965}
4966
Louis Dionne89258142021-08-23 15:32:36 -04004967#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004968static
4969wstring*
4970init_wmonths()
4971{
4972 static wstring months[24];
4973 months[0] = L"January";
4974 months[1] = L"February";
4975 months[2] = L"March";
4976 months[3] = L"April";
4977 months[4] = L"May";
4978 months[5] = L"June";
4979 months[6] = L"July";
4980 months[7] = L"August";
4981 months[8] = L"September";
4982 months[9] = L"October";
4983 months[10] = L"November";
4984 months[11] = L"December";
4985 months[12] = L"Jan";
4986 months[13] = L"Feb";
4987 months[14] = L"Mar";
4988 months[15] = L"Apr";
4989 months[16] = L"May";
4990 months[17] = L"Jun";
4991 months[18] = L"Jul";
4992 months[19] = L"Aug";
4993 months[20] = L"Sep";
4994 months[21] = L"Oct";
4995 months[22] = L"Nov";
4996 months[23] = L"Dec";
4997 return months;
4998}
Louis Dionne89258142021-08-23 15:32:36 -04004999#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005000
5001template <>
5002const string*
5003__time_get_c_storage<char>::__months() const
5004{
5005 static const string* months = init_months();
5006 return months;
5007}
5008
Louis Dionne89258142021-08-23 15:32:36 -04005009#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005010template <>
5011const wstring*
5012__time_get_c_storage<wchar_t>::__months() const
5013{
5014 static const wstring* months = init_wmonths();
5015 return months;
5016}
Louis Dionne89258142021-08-23 15:32:36 -04005017#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005018
5019static
5020string*
5021init_am_pm()
5022{
Marshall Clow5cc04922018-01-11 17:16:52 +00005023 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005024 am_pm[0] = "AM";
5025 am_pm[1] = "PM";
5026 return am_pm;
5027}
5028
Louis Dionne89258142021-08-23 15:32:36 -04005029#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005030static
5031wstring*
5032init_wam_pm()
5033{
Marshall Clow5cc04922018-01-11 17:16:52 +00005034 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005035 am_pm[0] = L"AM";
5036 am_pm[1] = L"PM";
5037 return am_pm;
5038}
Louis Dionne89258142021-08-23 15:32:36 -04005039#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005040
5041template <>
5042const string*
5043__time_get_c_storage<char>::__am_pm() const
5044{
5045 static const string* am_pm = init_am_pm();
5046 return am_pm;
5047}
5048
Louis Dionne89258142021-08-23 15:32:36 -04005049#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005050template <>
5051const wstring*
5052__time_get_c_storage<wchar_t>::__am_pm() const
5053{
5054 static const wstring* am_pm = init_wam_pm();
5055 return am_pm;
5056}
Louis Dionne89258142021-08-23 15:32:36 -04005057#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005058
5059template <>
5060const string&
5061__time_get_c_storage<char>::__x() const
5062{
5063 static string s("%m/%d/%y");
5064 return s;
5065}
5066
Louis Dionne89258142021-08-23 15:32:36 -04005067#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005068template <>
5069const wstring&
5070__time_get_c_storage<wchar_t>::__x() const
5071{
5072 static wstring s(L"%m/%d/%y");
5073 return s;
5074}
Louis Dionne89258142021-08-23 15:32:36 -04005075#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005076
5077template <>
5078const string&
5079__time_get_c_storage<char>::__X() const
5080{
5081 static string s("%H:%M:%S");
5082 return s;
5083}
5084
Louis Dionne89258142021-08-23 15:32:36 -04005085#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005086template <>
5087const wstring&
5088__time_get_c_storage<wchar_t>::__X() const
5089{
5090 static wstring s(L"%H:%M:%S");
5091 return s;
5092}
Louis Dionne89258142021-08-23 15:32:36 -04005093#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005094
5095template <>
5096const string&
5097__time_get_c_storage<char>::__c() const
5098{
5099 static string s("%a %b %d %H:%M:%S %Y");
5100 return s;
5101}
5102
Louis Dionne89258142021-08-23 15:32:36 -04005103#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005104template <>
5105const wstring&
5106__time_get_c_storage<wchar_t>::__c() const
5107{
5108 static wstring s(L"%a %b %d %H:%M:%S %Y");
5109 return s;
5110}
Louis Dionne89258142021-08-23 15:32:36 -04005111#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005112
5113template <>
5114const string&
5115__time_get_c_storage<char>::__r() const
5116{
5117 static string s("%I:%M:%S %p");
5118 return s;
5119}
5120
Louis Dionne89258142021-08-23 15:32:36 -04005121#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005122template <>
5123const wstring&
5124__time_get_c_storage<wchar_t>::__r() const
5125{
5126 static wstring s(L"%I:%M:%S %p");
5127 return s;
5128}
Louis Dionne89258142021-08-23 15:32:36 -04005129#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005130
5131// time_get_byname
5132
5133__time_get::__time_get(const char* nm)
5134 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5135{
5136 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005137 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005138 " failed to construct for " + string(nm));
5139}
5140
5141__time_get::__time_get(const string& nm)
5142 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5143{
5144 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005145 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005146 " failed to construct for " + nm);
5147}
5148
5149__time_get::~__time_get()
5150{
5151 freelocale(__loc_);
5152}
Marshall Clowd920eea2013-10-21 15:07:28 +00005153#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005154#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005155#endif
5156#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00005157#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005158#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005159
Howard Hinnantc51e1022010-05-11 19:42:16 +00005160template <>
5161string
5162__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5163{
Howard Hinnant990207c2012-02-19 14:55:32 +00005164 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005165 t.tm_sec = 59;
5166 t.tm_min = 55;
5167 t.tm_hour = 23;
5168 t.tm_mday = 31;
5169 t.tm_mon = 11;
5170 t.tm_year = 161;
5171 t.tm_wday = 6;
5172 t.tm_yday = 364;
5173 t.tm_isdst = -1;
5174 char buf[100];
5175 char f[3] = {0};
5176 f[0] = '%';
5177 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005178 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005179 char* bb = buf;
5180 char* be = buf + n;
5181 string result;
5182 while (bb != be)
5183 {
5184 if (ct.is(ctype_base::space, *bb))
5185 {
5186 result.push_back(' ');
5187 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5188 ;
5189 continue;
5190 }
5191 char* w = bb;
5192 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005193 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005194 ct, err, false)
5195 - this->__weeks_;
5196 if (i < 14)
5197 {
5198 result.push_back('%');
5199 if (i < 7)
5200 result.push_back('A');
5201 else
5202 result.push_back('a');
5203 bb = w;
5204 continue;
5205 }
5206 w = bb;
5207 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5208 ct, err, false)
5209 - this->__months_;
5210 if (i < 24)
5211 {
5212 result.push_back('%');
5213 if (i < 12)
5214 result.push_back('B');
5215 else
5216 result.push_back('b');
5217 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5218 result.back() = 'm';
5219 bb = w;
5220 continue;
5221 }
5222 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5223 {
5224 w = bb;
5225 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5226 ct, err, false) - this->__am_pm_;
5227 if (i < 2)
5228 {
5229 result.push_back('%');
5230 result.push_back('p');
5231 bb = w;
5232 continue;
5233 }
5234 }
5235 w = bb;
5236 if (ct.is(ctype_base::digit, *bb))
5237 {
5238 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5239 {
5240 case 6:
5241 result.push_back('%');
5242 result.push_back('w');
5243 break;
5244 case 7:
5245 result.push_back('%');
5246 result.push_back('u');
5247 break;
5248 case 11:
5249 result.push_back('%');
5250 result.push_back('I');
5251 break;
5252 case 12:
5253 result.push_back('%');
5254 result.push_back('m');
5255 break;
5256 case 23:
5257 result.push_back('%');
5258 result.push_back('H');
5259 break;
5260 case 31:
5261 result.push_back('%');
5262 result.push_back('d');
5263 break;
5264 case 55:
5265 result.push_back('%');
5266 result.push_back('M');
5267 break;
5268 case 59:
5269 result.push_back('%');
5270 result.push_back('S');
5271 break;
5272 case 61:
5273 result.push_back('%');
5274 result.push_back('y');
5275 break;
5276 case 364:
5277 result.push_back('%');
5278 result.push_back('j');
5279 break;
5280 case 2061:
5281 result.push_back('%');
5282 result.push_back('Y');
5283 break;
5284 default:
5285 for (; w != bb; ++w)
5286 result.push_back(*w);
5287 break;
5288 }
5289 continue;
5290 }
5291 if (*bb == '%')
5292 {
5293 result.push_back('%');
5294 result.push_back('%');
5295 ++bb;
5296 continue;
5297 }
5298 result.push_back(*bb);
5299 ++bb;
5300 }
5301 return result;
5302}
5303
Marshall Clowd920eea2013-10-21 15:07:28 +00005304#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005305#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005306#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005307
Louis Dionne89258142021-08-23 15:32:36 -04005308#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005309template <>
5310wstring
5311__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5312{
Howard Hinnant990207c2012-02-19 14:55:32 +00005313 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005314 t.tm_sec = 59;
5315 t.tm_min = 55;
5316 t.tm_hour = 23;
5317 t.tm_mday = 31;
5318 t.tm_mon = 11;
5319 t.tm_year = 161;
5320 t.tm_wday = 6;
5321 t.tm_yday = 364;
5322 t.tm_isdst = -1;
5323 char buf[100];
5324 char f[3] = {0};
5325 f[0] = '%';
5326 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005327 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005328 wchar_t wbuf[100];
5329 wchar_t* wbb = wbuf;
5330 mbstate_t mb = {0};
5331 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005332 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005333 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005334 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005335 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005336 wstring result;
5337 while (wbb != wbe)
5338 {
5339 if (ct.is(ctype_base::space, *wbb))
5340 {
5341 result.push_back(L' ');
5342 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5343 ;
5344 continue;
5345 }
5346 wchar_t* w = wbb;
5347 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005348 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005349 ct, err, false)
5350 - this->__weeks_;
5351 if (i < 14)
5352 {
5353 result.push_back(L'%');
5354 if (i < 7)
5355 result.push_back(L'A');
5356 else
5357 result.push_back(L'a');
5358 wbb = w;
5359 continue;
5360 }
5361 w = wbb;
5362 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5363 ct, err, false)
5364 - this->__months_;
5365 if (i < 24)
5366 {
5367 result.push_back(L'%');
5368 if (i < 12)
5369 result.push_back(L'B');
5370 else
5371 result.push_back(L'b');
5372 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5373 result.back() = L'm';
5374 wbb = w;
5375 continue;
5376 }
5377 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5378 {
5379 w = wbb;
5380 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5381 ct, err, false) - this->__am_pm_;
5382 if (i < 2)
5383 {
5384 result.push_back(L'%');
5385 result.push_back(L'p');
5386 wbb = w;
5387 continue;
5388 }
5389 }
5390 w = wbb;
5391 if (ct.is(ctype_base::digit, *wbb))
5392 {
5393 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5394 {
5395 case 6:
5396 result.push_back(L'%');
5397 result.push_back(L'w');
5398 break;
5399 case 7:
5400 result.push_back(L'%');
5401 result.push_back(L'u');
5402 break;
5403 case 11:
5404 result.push_back(L'%');
5405 result.push_back(L'I');
5406 break;
5407 case 12:
5408 result.push_back(L'%');
5409 result.push_back(L'm');
5410 break;
5411 case 23:
5412 result.push_back(L'%');
5413 result.push_back(L'H');
5414 break;
5415 case 31:
5416 result.push_back(L'%');
5417 result.push_back(L'd');
5418 break;
5419 case 55:
5420 result.push_back(L'%');
5421 result.push_back(L'M');
5422 break;
5423 case 59:
5424 result.push_back(L'%');
5425 result.push_back(L'S');
5426 break;
5427 case 61:
5428 result.push_back(L'%');
5429 result.push_back(L'y');
5430 break;
5431 case 364:
5432 result.push_back(L'%');
5433 result.push_back(L'j');
5434 break;
5435 case 2061:
5436 result.push_back(L'%');
5437 result.push_back(L'Y');
5438 break;
5439 default:
5440 for (; w != wbb; ++w)
5441 result.push_back(*w);
5442 break;
5443 }
5444 continue;
5445 }
5446 if (ct.narrow(*wbb, 0) == '%')
5447 {
5448 result.push_back(L'%');
5449 result.push_back(L'%');
5450 ++wbb;
5451 continue;
5452 }
5453 result.push_back(*wbb);
5454 ++wbb;
5455 }
5456 return result;
5457}
Louis Dionne89258142021-08-23 15:32:36 -04005458#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005459
5460template <>
5461void
5462__time_get_storage<char>::init(const ctype<char>& ct)
5463{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005464 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005465 char buf[100];
5466 // __weeks_
5467 for (int i = 0; i < 7; ++i)
5468 {
5469 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005470 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005471 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005472 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005473 __weeks_[i+7] = buf;
5474 }
5475 // __months_
5476 for (int i = 0; i < 12; ++i)
5477 {
5478 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005479 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005480 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005481 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005482 __months_[i+12] = buf;
5483 }
5484 // __am_pm_
5485 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005486 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005487 __am_pm_[0] = buf;
5488 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005489 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005490 __am_pm_[1] = buf;
5491 __c_ = __analyze('c', ct);
5492 __r_ = __analyze('r', ct);
5493 __x_ = __analyze('x', ct);
5494 __X_ = __analyze('X', ct);
5495}
5496
Louis Dionne89258142021-08-23 15:32:36 -04005497#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005498template <>
5499void
5500__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5501{
5502 tm t = {0};
5503 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005504 wchar_t wbuf[100];
5505 wchar_t* wbe;
5506 mbstate_t mb = {0};
5507 // __weeks_
5508 for (int i = 0; i < 7; ++i)
5509 {
5510 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005511 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005512 mb = mbstate_t();
5513 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005514 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005515 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005516 __throw_runtime_error("locale not supported");
5517 wbe = wbuf + j;
5518 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005519 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005520 mb = mbstate_t();
5521 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005522 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005523 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005524 __throw_runtime_error("locale not supported");
5525 wbe = wbuf + j;
5526 __weeks_[i+7].assign(wbuf, wbe);
5527 }
5528 // __months_
5529 for (int i = 0; i < 12; ++i)
5530 {
5531 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005532 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005533 mb = mbstate_t();
5534 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005535 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005536 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005537 __throw_runtime_error("locale not supported");
5538 wbe = wbuf + j;
5539 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005540 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005541 mb = mbstate_t();
5542 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005543 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005544 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005545 __throw_runtime_error("locale not supported");
5546 wbe = wbuf + j;
5547 __months_[i+12].assign(wbuf, wbe);
5548 }
5549 // __am_pm_
5550 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005551 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005552 mb = mbstate_t();
5553 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005554 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005555 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005556 __throw_runtime_error("locale not supported");
5557 wbe = wbuf + j;
5558 __am_pm_[0].assign(wbuf, wbe);
5559 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005560 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005561 mb = mbstate_t();
5562 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005563 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005564 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005565 __throw_runtime_error("locale not supported");
5566 wbe = wbuf + j;
5567 __am_pm_[1].assign(wbuf, wbe);
5568 __c_ = __analyze('c', ct);
5569 __r_ = __analyze('r', ct);
5570 __x_ = __analyze('x', ct);
5571 __X_ = __analyze('X', ct);
5572}
Louis Dionne89258142021-08-23 15:32:36 -04005573#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005574
5575template <class CharT>
5576struct _LIBCPP_HIDDEN __time_get_temp
5577 : public ctype_byname<CharT>
5578{
5579 explicit __time_get_temp(const char* nm)
5580 : ctype_byname<CharT>(nm, 1) {}
5581 explicit __time_get_temp(const string& nm)
5582 : ctype_byname<CharT>(nm, 1) {}
5583};
5584
5585template <>
5586__time_get_storage<char>::__time_get_storage(const char* __nm)
5587 : __time_get(__nm)
5588{
5589 const __time_get_temp<char> ct(__nm);
5590 init(ct);
5591}
5592
5593template <>
5594__time_get_storage<char>::__time_get_storage(const string& __nm)
5595 : __time_get(__nm)
5596{
5597 const __time_get_temp<char> ct(__nm);
5598 init(ct);
5599}
5600
Louis Dionne89258142021-08-23 15:32:36 -04005601#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602template <>
5603__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5604 : __time_get(__nm)
5605{
5606 const __time_get_temp<wchar_t> ct(__nm);
5607 init(ct);
5608}
5609
5610template <>
5611__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5612 : __time_get(__nm)
5613{
5614 const __time_get_temp<wchar_t> ct(__nm);
5615 init(ct);
5616}
Louis Dionne89258142021-08-23 15:32:36 -04005617#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005618
5619template <>
5620time_base::dateorder
5621__time_get_storage<char>::__do_date_order() const
5622{
5623 unsigned i;
5624 for (i = 0; i < __x_.size(); ++i)
5625 if (__x_[i] == '%')
5626 break;
5627 ++i;
5628 switch (__x_[i])
5629 {
5630 case 'y':
5631 case 'Y':
5632 for (++i; i < __x_.size(); ++i)
5633 if (__x_[i] == '%')
5634 break;
5635 if (i == __x_.size())
5636 break;
5637 ++i;
5638 switch (__x_[i])
5639 {
5640 case 'm':
5641 for (++i; i < __x_.size(); ++i)
5642 if (__x_[i] == '%')
5643 break;
5644 if (i == __x_.size())
5645 break;
5646 ++i;
5647 if (__x_[i] == 'd')
5648 return time_base::ymd;
5649 break;
5650 case 'd':
5651 for (++i; i < __x_.size(); ++i)
5652 if (__x_[i] == '%')
5653 break;
5654 if (i == __x_.size())
5655 break;
5656 ++i;
5657 if (__x_[i] == 'm')
5658 return time_base::ydm;
5659 break;
5660 }
5661 break;
5662 case 'm':
5663 for (++i; i < __x_.size(); ++i)
5664 if (__x_[i] == '%')
5665 break;
5666 if (i == __x_.size())
5667 break;
5668 ++i;
5669 if (__x_[i] == 'd')
5670 {
5671 for (++i; i < __x_.size(); ++i)
5672 if (__x_[i] == '%')
5673 break;
5674 if (i == __x_.size())
5675 break;
5676 ++i;
5677 if (__x_[i] == 'y' || __x_[i] == 'Y')
5678 return time_base::mdy;
5679 break;
5680 }
5681 break;
5682 case 'd':
5683 for (++i; i < __x_.size(); ++i)
5684 if (__x_[i] == '%')
5685 break;
5686 if (i == __x_.size())
5687 break;
5688 ++i;
5689 if (__x_[i] == 'm')
5690 {
5691 for (++i; i < __x_.size(); ++i)
5692 if (__x_[i] == '%')
5693 break;
5694 if (i == __x_.size())
5695 break;
5696 ++i;
5697 if (__x_[i] == 'y' || __x_[i] == 'Y')
5698 return time_base::dmy;
5699 break;
5700 }
5701 break;
5702 }
5703 return time_base::no_order;
5704}
5705
Louis Dionne89258142021-08-23 15:32:36 -04005706#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005707template <>
5708time_base::dateorder
5709__time_get_storage<wchar_t>::__do_date_order() const
5710{
5711 unsigned i;
5712 for (i = 0; i < __x_.size(); ++i)
5713 if (__x_[i] == L'%')
5714 break;
5715 ++i;
5716 switch (__x_[i])
5717 {
5718 case L'y':
5719 case L'Y':
5720 for (++i; i < __x_.size(); ++i)
5721 if (__x_[i] == L'%')
5722 break;
5723 if (i == __x_.size())
5724 break;
5725 ++i;
5726 switch (__x_[i])
5727 {
5728 case L'm':
5729 for (++i; i < __x_.size(); ++i)
5730 if (__x_[i] == L'%')
5731 break;
5732 if (i == __x_.size())
5733 break;
5734 ++i;
5735 if (__x_[i] == L'd')
5736 return time_base::ymd;
5737 break;
5738 case L'd':
5739 for (++i; i < __x_.size(); ++i)
5740 if (__x_[i] == L'%')
5741 break;
5742 if (i == __x_.size())
5743 break;
5744 ++i;
5745 if (__x_[i] == L'm')
5746 return time_base::ydm;
5747 break;
5748 }
5749 break;
5750 case L'm':
5751 for (++i; i < __x_.size(); ++i)
5752 if (__x_[i] == L'%')
5753 break;
5754 if (i == __x_.size())
5755 break;
5756 ++i;
5757 if (__x_[i] == L'd')
5758 {
5759 for (++i; i < __x_.size(); ++i)
5760 if (__x_[i] == L'%')
5761 break;
5762 if (i == __x_.size())
5763 break;
5764 ++i;
5765 if (__x_[i] == L'y' || __x_[i] == L'Y')
5766 return time_base::mdy;
5767 break;
5768 }
5769 break;
5770 case L'd':
5771 for (++i; i < __x_.size(); ++i)
5772 if (__x_[i] == L'%')
5773 break;
5774 if (i == __x_.size())
5775 break;
5776 ++i;
5777 if (__x_[i] == L'm')
5778 {
5779 for (++i; i < __x_.size(); ++i)
5780 if (__x_[i] == L'%')
5781 break;
5782 if (i == __x_.size())
5783 break;
5784 ++i;
5785 if (__x_[i] == L'y' || __x_[i] == L'Y')
5786 return time_base::dmy;
5787 break;
5788 }
5789 break;
5790 }
5791 return time_base::no_order;
5792}
Louis Dionne89258142021-08-23 15:32:36 -04005793#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005794
5795// time_put
5796
5797__time_put::__time_put(const char* nm)
5798 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5799{
5800 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005801 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005802 " failed to construct for " + string(nm));
5803}
5804
5805__time_put::__time_put(const string& nm)
5806 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5807{
5808 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005809 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005810 " failed to construct for " + nm);
5811}
5812
5813__time_put::~__time_put()
5814{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005815 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005816 freelocale(__loc_);
5817}
5818
5819void
5820__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5821 char __fmt, char __mod) const
5822{
5823 char fmt[] = {'%', __fmt, __mod, 0};
5824 if (__mod != 0)
5825 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005826 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005827 __ne = __nb + n;
5828}
5829
Louis Dionne89258142021-08-23 15:32:36 -04005830#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005831void
5832__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5833 char __fmt, char __mod) const
5834{
5835 char __nar[100];
5836 char* __ne = __nar + 100;
5837 __do_put(__nar, __ne, __tm, __fmt, __mod);
5838 mbstate_t mb = {0};
5839 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005840 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005841 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005842 __throw_runtime_error("locale not supported");
5843 __we = __wb + j;
5844}
Louis Dionne89258142021-08-23 15:32:36 -04005845#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005846
5847// moneypunct_byname
5848
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005849template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005850static
5851void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005852__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5853 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5854 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005855{
5856 const char sign = static_cast<char>(money_base::sign);
5857 const char space = static_cast<char>(money_base::space);
5858 const char none = static_cast<char>(money_base::none);
5859 const char symbol = static_cast<char>(money_base::symbol);
5860 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005861 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5862
5863 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5864 // function'. "Space between sign and symbol or value" means that
5865 // if the sign is adjacent to the symbol, there's a space between
5866 // them, and otherwise there's a space between the sign and value.
5867 //
5868 // C11's localeconv specifies that the fourth character of an
5869 // international curr_symbol is used to separate the sign and
5870 // value when sep_by_space says to do so. C++ can't represent
5871 // that, so we just use a space. When sep_by_space says to
5872 // separate the symbol and value-or-sign with a space, we rearrange the
5873 // curr_symbol to put its spacing character on the correct side of
5874 // the symbol.
5875 //
5876 // We also need to avoid adding an extra space between the sign
5877 // and value when the currency symbol is suppressed (by not
5878 // setting showbase). We match glibc's strfmon by interpreting
5879 // sep_by_space==1 as "omit the space when the currency symbol is
5880 // absent".
5881 //
5882 // Users who want to get this right should use ICU instead.
5883
Howard Hinnantc51e1022010-05-11 19:42:16 +00005884 switch (cs_precedes)
5885 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005886 case 0: // value before curr_symbol
5887 if (symbol_contains_sep) {
5888 // Move the separator to before the symbol, to place it
5889 // between the value and symbol.
5890 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5891 __curr_symbol_.end());
5892 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005893 switch (sign_posn)
5894 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005895 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005896 pat.field[0] = sign;
5897 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005898 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005899 pat.field[3] = symbol;
5900 switch (sep_by_space)
5901 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005902 case 0: // No space separates the currency symbol and value.
5903 // This case may have changed between C99 and C11;
5904 // assume the currency symbol matches the intention.
5905 case 2: // Space between sign and currency or value.
5906 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005907 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005908 case 1: // Space between currency-and-sign or currency and value.
5909 if (!symbol_contains_sep) {
5910 // We insert the space into the symbol instead of
5911 // setting pat.field[2]=space so that when
5912 // showbase is not set, the space goes away too.
5913 __curr_symbol_.insert(0, 1, space_char);
5914 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005915 return;
5916 default:
5917 break;
5918 }
5919 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005920 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005921 pat.field[0] = sign;
5922 pat.field[3] = symbol;
5923 switch (sep_by_space)
5924 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005925 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005926 pat.field[1] = value;
5927 pat.field[2] = none;
5928 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005930 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005931 pat.field[2] = none;
5932 if (!symbol_contains_sep) {
5933 // We insert the space into the symbol instead of
5934 // setting pat.field[2]=space so that when
5935 // showbase is not set, the space goes away too.
5936 __curr_symbol_.insert(0, 1, space_char);
5937 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005938 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005939 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005940 pat.field[1] = space;
5941 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005942 if (symbol_contains_sep) {
5943 // Remove the separator from the symbol, since it
5944 // has already appeared after the sign.
5945 __curr_symbol_.erase(__curr_symbol_.begin());
5946 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 return;
5948 default:
5949 break;
5950 }
5951 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005952 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005953 pat.field[0] = value;
5954 pat.field[3] = sign;
5955 switch (sep_by_space)
5956 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005957 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005958 pat.field[1] = none;
5959 pat.field[2] = symbol;
5960 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005961 case 1: // Space between currency-and-sign or currency and value.
5962 if (!symbol_contains_sep) {
5963 // We insert the space into the symbol instead of
5964 // setting pat.field[1]=space so that when
5965 // showbase is not set, the space goes away too.
5966 __curr_symbol_.insert(0, 1, space_char);
5967 }
5968 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 pat.field[2] = symbol;
5970 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005971 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005972 pat.field[1] = symbol;
5973 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005974 if (symbol_contains_sep) {
5975 // Remove the separator from the symbol, since it
5976 // should not be removed if showbase is absent.
5977 __curr_symbol_.erase(__curr_symbol_.begin());
5978 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005979 return;
5980 default:
5981 break;
5982 }
5983 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005984 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005985 pat.field[0] = value;
5986 pat.field[3] = symbol;
5987 switch (sep_by_space)
5988 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005989 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005990 pat.field[1] = none;
5991 pat.field[2] = sign;
5992 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005993 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005994 pat.field[1] = space;
5995 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005996 if (symbol_contains_sep) {
5997 // Remove the separator from the symbol, since it
5998 // has already appeared before the sign.
5999 __curr_symbol_.erase(__curr_symbol_.begin());
6000 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006001 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006002 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006003 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006004 pat.field[2] = none;
6005 if (!symbol_contains_sep) {
6006 // We insert the space into the symbol instead of
6007 // setting pat.field[2]=space so that when
6008 // showbase is not set, the space goes away too.
6009 __curr_symbol_.insert(0, 1, space_char);
6010 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006011 return;
6012 default:
6013 break;
6014 }
6015 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006016 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006017 pat.field[0] = value;
6018 pat.field[3] = sign;
6019 switch (sep_by_space)
6020 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006021 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006022 pat.field[1] = none;
6023 pat.field[2] = symbol;
6024 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006025 case 1: // Space between currency-and-sign or currency and value.
6026 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006027 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006028 if (!symbol_contains_sep) {
6029 // We insert the space into the symbol instead of
6030 // setting pat.field[1]=space so that when
6031 // showbase is not set, the space goes away too.
6032 __curr_symbol_.insert(0, 1, space_char);
6033 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006034 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006035 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006036 pat.field[1] = symbol;
6037 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006038 if (symbol_contains_sep) {
6039 // Remove the separator from the symbol, since it
6040 // should not disappear when showbase is absent.
6041 __curr_symbol_.erase(__curr_symbol_.begin());
6042 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006043 return;
6044 default:
6045 break;
6046 }
6047 break;
6048 default:
6049 break;
6050 }
6051 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006052 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00006053 switch (sign_posn)
6054 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006055 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006056 pat.field[0] = sign;
6057 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006058 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006059 pat.field[3] = value;
6060 switch (sep_by_space)
6061 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006062 case 0: // No space separates the currency symbol and value.
6063 // This case may have changed between C99 and C11;
6064 // assume the currency symbol matches the intention.
6065 case 2: // Space between sign and currency or value.
6066 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006067 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006068 case 1: // Space between currency-and-sign or currency and value.
6069 if (!symbol_contains_sep) {
6070 // We insert the space into the symbol instead of
6071 // setting pat.field[2]=space so that when
6072 // showbase is not set, the space goes away too.
6073 __curr_symbol_.insert(0, 1, space_char);
6074 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006075 return;
6076 default:
6077 break;
6078 }
6079 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006080 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006081 pat.field[0] = sign;
6082 pat.field[3] = value;
6083 switch (sep_by_space)
6084 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006085 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006086 pat.field[1] = symbol;
6087 pat.field[2] = none;
6088 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006089 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006090 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006091 pat.field[2] = none;
6092 if (!symbol_contains_sep) {
6093 // We insert the space into the symbol instead of
6094 // setting pat.field[2]=space so that when
6095 // showbase is not set, the space goes away too.
6096 __curr_symbol_.push_back(space_char);
6097 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006098 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006099 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006100 pat.field[1] = space;
6101 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006102 if (symbol_contains_sep) {
6103 // Remove the separator from the symbol, since it
6104 // has already appeared after the sign.
6105 __curr_symbol_.pop_back();
6106 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006107 return;
6108 default:
6109 break;
6110 }
6111 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006112 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006113 pat.field[0] = symbol;
6114 pat.field[3] = sign;
6115 switch (sep_by_space)
6116 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006117 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006118 pat.field[1] = none;
6119 pat.field[2] = value;
6120 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006121 case 1: // Space between currency-and-sign or currency and value.
6122 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006123 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006124 if (!symbol_contains_sep) {
6125 // We insert the space into the symbol instead of
6126 // setting pat.field[1]=space so that when
6127 // showbase is not set, the space goes away too.
6128 __curr_symbol_.push_back(space_char);
6129 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006130 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006131 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006132 pat.field[1] = value;
6133 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006134 if (symbol_contains_sep) {
6135 // Remove the separator from the symbol, since it
6136 // will appear before the sign.
6137 __curr_symbol_.pop_back();
6138 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006139 return;
6140 default:
6141 break;
6142 }
6143 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006144 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006145 pat.field[0] = sign;
6146 pat.field[3] = value;
6147 switch (sep_by_space)
6148 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006149 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006150 pat.field[1] = symbol;
6151 pat.field[2] = none;
6152 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006153 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006154 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006155 pat.field[2] = none;
6156 if (!symbol_contains_sep) {
6157 // We insert the space into the symbol instead of
6158 // setting pat.field[2]=space so that when
6159 // showbase is not set, the space goes away too.
6160 __curr_symbol_.push_back(space_char);
6161 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006162 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006163 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006164 pat.field[1] = space;
6165 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006166 if (symbol_contains_sep) {
6167 // Remove the separator from the symbol, since it
6168 // has already appeared after the sign.
6169 __curr_symbol_.pop_back();
6170 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006171 return;
6172 default:
6173 break;
6174 }
6175 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006176 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006177 pat.field[0] = symbol;
6178 pat.field[3] = value;
6179 switch (sep_by_space)
6180 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006181 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006182 pat.field[1] = sign;
6183 pat.field[2] = none;
6184 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006185 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006186 pat.field[1] = sign;
6187 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006188 if (symbol_contains_sep) {
6189 // Remove the separator from the symbol, since it
6190 // should not disappear when showbase is absent.
6191 __curr_symbol_.pop_back();
6192 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006193 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006194 case 2: // Space between sign and currency or value.
6195 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006196 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006197 if (!symbol_contains_sep) {
6198 // We insert the space into the symbol instead of
6199 // setting pat.field[1]=space so that when
6200 // showbase is not set, the space goes away too.
6201 __curr_symbol_.push_back(space_char);
6202 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006203 return;
6204 default:
6205 break;
6206 }
6207 break;
6208 default:
6209 break;
6210 }
6211 break;
6212 default:
6213 break;
6214 }
6215 pat.field[0] = symbol;
6216 pat.field[1] = sign;
6217 pat.field[2] = none;
6218 pat.field[3] = value;
6219}
6220
6221template<>
6222void
6223moneypunct_byname<char, false>::init(const char* nm)
6224{
6225 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006226 __libcpp_unique_locale loc(nm);
6227 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006228 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006229 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006230
Ben Craig3756b922016-03-09 15:39:39 +00006231 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006232 if (!checked_string_to_char_convert(__decimal_point_,
6233 lc->mon_decimal_point,
6234 loc.get()))
6235 __decimal_point_ = base::do_decimal_point();
6236 if (!checked_string_to_char_convert(__thousands_sep_,
6237 lc->mon_thousands_sep,
6238 loc.get()))
6239 __thousands_sep_ = base::do_thousands_sep();
6240
Howard Hinnantc51e1022010-05-11 19:42:16 +00006241 __grouping_ = lc->mon_grouping;
6242 __curr_symbol_ = lc->currency_symbol;
6243 if (lc->frac_digits != CHAR_MAX)
6244 __frac_digits_ = lc->frac_digits;
6245 else
6246 __frac_digits_ = base::do_frac_digits();
6247 if (lc->p_sign_posn == 0)
6248 __positive_sign_ = "()";
6249 else
6250 __positive_sign_ = lc->positive_sign;
6251 if (lc->n_sign_posn == 0)
6252 __negative_sign_ = "()";
6253 else
6254 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006255 // Assume the positive and negative formats will want spaces in
6256 // the same places in curr_symbol since there's no way to
6257 // represent anything else.
6258 string_type __dummy_curr_symbol = __curr_symbol_;
6259 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6260 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6261 __init_pat(__neg_format_, __curr_symbol_, false,
6262 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006263}
6264
6265template<>
6266void
6267moneypunct_byname<char, true>::init(const char* nm)
6268{
6269 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006270 __libcpp_unique_locale loc(nm);
6271 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006272 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006273 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006274
Ben Craig3756b922016-03-09 15:39:39 +00006275 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006276 if (!checked_string_to_char_convert(__decimal_point_,
6277 lc->mon_decimal_point,
6278 loc.get()))
6279 __decimal_point_ = base::do_decimal_point();
6280 if (!checked_string_to_char_convert(__thousands_sep_,
6281 lc->mon_thousands_sep,
6282 loc.get()))
6283 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006284 __grouping_ = lc->mon_grouping;
6285 __curr_symbol_ = lc->int_curr_symbol;
6286 if (lc->int_frac_digits != CHAR_MAX)
6287 __frac_digits_ = lc->int_frac_digits;
6288 else
6289 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006290#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006291 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006292#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006293 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006294#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006295 __positive_sign_ = "()";
6296 else
6297 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006298#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006299 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006300#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006301 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006302#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006303 __negative_sign_ = "()";
6304 else
6305 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006306 // Assume the positive and negative formats will want spaces in
6307 // the same places in curr_symbol since there's no way to
6308 // represent anything else.
6309 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006310#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006311 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6312 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6313 __init_pat(__neg_format_, __curr_symbol_, true,
6314 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006315#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006316 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6317 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6318 lc->int_p_sign_posn, ' ');
6319 __init_pat(__neg_format_, __curr_symbol_, true,
6320 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6321 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006322#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006323}
6324
Louis Dionne89258142021-08-23 15:32:36 -04006325#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006326template<>
6327void
6328moneypunct_byname<wchar_t, false>::init(const char* nm)
6329{
6330 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006331 __libcpp_unique_locale loc(nm);
6332 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006333 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006334 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006335 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006336 if (!checked_string_to_wchar_convert(__decimal_point_,
6337 lc->mon_decimal_point,
6338 loc.get()))
6339 __decimal_point_ = base::do_decimal_point();
6340 if (!checked_string_to_wchar_convert(__thousands_sep_,
6341 lc->mon_thousands_sep,
6342 loc.get()))
6343 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006344 __grouping_ = lc->mon_grouping;
6345 wchar_t wbuf[100];
6346 mbstate_t mb = {0};
6347 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006348 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006349 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006350 __throw_runtime_error("locale not supported");
6351 wchar_t* wbe = wbuf + j;
6352 __curr_symbol_.assign(wbuf, wbe);
6353 if (lc->frac_digits != CHAR_MAX)
6354 __frac_digits_ = lc->frac_digits;
6355 else
6356 __frac_digits_ = base::do_frac_digits();
6357 if (lc->p_sign_posn == 0)
6358 __positive_sign_ = L"()";
6359 else
6360 {
6361 mb = mbstate_t();
6362 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006363 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006364 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006365 __throw_runtime_error("locale not supported");
6366 wbe = wbuf + j;
6367 __positive_sign_.assign(wbuf, wbe);
6368 }
6369 if (lc->n_sign_posn == 0)
6370 __negative_sign_ = L"()";
6371 else
6372 {
6373 mb = mbstate_t();
6374 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006375 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006376 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006377 __throw_runtime_error("locale not supported");
6378 wbe = wbuf + j;
6379 __negative_sign_.assign(wbuf, wbe);
6380 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006381 // Assume the positive and negative formats will want spaces in
6382 // the same places in curr_symbol since there's no way to
6383 // represent anything else.
6384 string_type __dummy_curr_symbol = __curr_symbol_;
6385 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6386 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6387 __init_pat(__neg_format_, __curr_symbol_, false,
6388 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006389}
6390
6391template<>
6392void
6393moneypunct_byname<wchar_t, true>::init(const char* nm)
6394{
6395 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006396 __libcpp_unique_locale loc(nm);
6397 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006398 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006399 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006400
Ben Craig3756b922016-03-09 15:39:39 +00006401 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006402 if (!checked_string_to_wchar_convert(__decimal_point_,
6403 lc->mon_decimal_point,
6404 loc.get()))
6405 __decimal_point_ = base::do_decimal_point();
6406 if (!checked_string_to_wchar_convert(__thousands_sep_,
6407 lc->mon_thousands_sep,
6408 loc.get()))
6409 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006410 __grouping_ = lc->mon_grouping;
6411 wchar_t wbuf[100];
6412 mbstate_t mb = {0};
6413 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006414 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006415 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006416 __throw_runtime_error("locale not supported");
6417 wchar_t* wbe = wbuf + j;
6418 __curr_symbol_.assign(wbuf, wbe);
6419 if (lc->int_frac_digits != CHAR_MAX)
6420 __frac_digits_ = lc->int_frac_digits;
6421 else
6422 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006423#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006424 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006425#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006426 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006427#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006428 __positive_sign_ = L"()";
6429 else
6430 {
6431 mb = mbstate_t();
6432 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006433 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006434 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006435 __throw_runtime_error("locale not supported");
6436 wbe = wbuf + j;
6437 __positive_sign_.assign(wbuf, wbe);
6438 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006439#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006440 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006441#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006442 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006443#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006444 __negative_sign_ = L"()";
6445 else
6446 {
6447 mb = mbstate_t();
6448 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006449 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006450 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006451 __throw_runtime_error("locale not supported");
6452 wbe = wbuf + j;
6453 __negative_sign_.assign(wbuf, wbe);
6454 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006455 // Assume the positive and negative formats will want spaces in
6456 // the same places in curr_symbol since there's no way to
6457 // represent anything else.
6458 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006459#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006460 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6461 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6462 __init_pat(__neg_format_, __curr_symbol_, true,
6463 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006464#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006465 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6466 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6467 lc->int_p_sign_posn, L' ');
6468 __init_pat(__neg_format_, __curr_symbol_, true,
6469 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6470 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006471#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006472}
Louis Dionne89258142021-08-23 15:32:36 -04006473#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006474
6475void __do_nothing(void*) {}
6476
6477void __throw_runtime_error(const char* msg)
6478{
Howard Hinnant72f73582010-08-11 17:04:31 +00006479#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006480 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006481#else
6482 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006483 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006484#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006485}
6486
Louis Dionne89258142021-08-23 15:32:36 -04006487 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6488_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006489
Louis Dionne89258142021-08-23 15:32:36 -04006490 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6491_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006492
Louis Dionne89258142021-08-23 15:32:36 -04006493 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6494_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006495
Louis Dionne89258142021-08-23 15:32:36 -04006496 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6497_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006498
Louis Dionne89258142021-08-23 15:32:36 -04006499 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6500_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006501
Louis Dionne89258142021-08-23 15:32:36 -04006502 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6503_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006504
Louis Dionne89258142021-08-23 15:32:36 -04006505 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6506_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006507
Louis Dionne89258142021-08-23 15:32:36 -04006508 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6509_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006510
Louis Dionne89258142021-08-23 15:32:36 -04006511 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6512_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006513
Louis Dionne89258142021-08-23 15:32:36 -04006514 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6515 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6516_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6517_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006518
Louis Dionne89258142021-08-23 15:32:36 -04006519 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6520 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6521_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6522_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006523
Louis Dionne89258142021-08-23 15:32:36 -04006524 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6525_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006526
Louis Dionne89258142021-08-23 15:32:36 -04006527 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6528_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006529
Louis Dionne89258142021-08-23 15:32:36 -04006530 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6531_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006532
Louis Dionne89258142021-08-23 15:32:36 -04006533 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6534_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006535
Louis Dionne89258142021-08-23 15:32:36 -04006536 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6537_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006538
Louis Dionne89258142021-08-23 15:32:36 -04006539 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6540_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006541
Louis Dionne89258142021-08-23 15:32:36 -04006542 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6543_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;)
Reid Klecknerbc2a2ce2021-01-15 08:56:34 -08006544template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6545template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04006546#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006547template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6548template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6549#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006550
Howard Hinnantc51e1022010-05-11 19:42:16 +00006551_LIBCPP_END_NAMESPACE_STD