blob: 009ee1e4e2f4c519ad179b208c73e56cce71a5d5 [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
David Tenty725f16e2021-10-12 11:53:12 -040031#if defined(_AIX)
32# include <sys/localedef.h> // for __lc_ctype_ptr
33#endif
34
Louis Dionneafc98402021-09-09 13:52:38 -040035#if defined(_LIBCPP_MSVCRT)
36# define _CTYPE_DISABLE_MACROS
Marshall Clow3477ec92014-07-10 15:20:28 +000037#endif
Louis Dionneafc98402021-09-09 13:52:38 -040038
39#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
40# include "__support/win32/locale_win32.h"
41#elif !defined(__BIONIC__) && !defined(__NuttX__)
42# include <langinfo.h>
43#endif
44
Weiming Zhaob613db72017-09-19 23:18:03 +000045#include "include/atomic_support.h"
Arthur O'Dwyerf5c4bb02021-04-26 09:56:50 -040046#include "include/sso_allocator.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000047#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000048
Marshall Clowab9c1772013-02-07 17:20:56 +000049// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070050// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000051#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000052#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000053#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000054
Howard Hinnantc51e1022010-05-11 19:42:16 +000055_LIBCPP_BEGIN_NAMESPACE_STD
56
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000057struct __libcpp_unique_locale {
58 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
59
60 ~__libcpp_unique_locale() {
61 if (__loc_)
62 freelocale(__loc_);
63 }
64
65 explicit operator bool() const { return __loc_; }
66
67 locale_t& get() { return __loc_; }
68
69 locale_t __loc_;
70private:
71 __libcpp_unique_locale(__libcpp_unique_locale const&);
72 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
73};
74
Howard Hinnantf312e3e2011-09-28 23:39:33 +000075#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000076locale_t __cloc() {
77 // In theory this could create a race condition. In practice
78 // the race condition is non-fatal since it will just create
79 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000080 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
81 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000082}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000083#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000084
Howard Hinnantc51e1022010-05-11 19:42:16 +000085namespace {
86
87struct release
88{
89 void operator()(locale::facet* p) {p->__release_shared();}
90};
91
Louis Dionne6e41a152021-08-09 13:26:04 -040092template <class T, class ...Args>
93T& make(Args ...args)
Howard Hinnantc51e1022010-05-11 19:42:16 +000094{
95 static typename aligned_storage<sizeof(T)>::type buf;
Louis Dionne6e41a152021-08-09 13:26:04 -040096 auto *obj = ::new (&buf) T(args...);
Eric Fiselier4db80032017-05-05 20:32:26 +000097 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000098}
99
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000100template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000101inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000102_LIBCPP_CONSTEXPR
103size_t
104countof(const T (&)[N])
105{
106 return N;
107}
108
109template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000110inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000111_LIBCPP_CONSTEXPR
112size_t
113countof(const T * const begin, const T * const end)
114{
115 return static_cast<size_t>(end - begin);
116}
117
Marshall Clow8fea1612016-08-25 15:09:01 +0000118_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
119{
120#ifndef _LIBCPP_NO_EXCEPTIONS
121 throw runtime_error(msg);
122#else
123 (void)msg;
124 _VSTD::abort();
125#endif
126}
127
Howard Hinnantc51e1022010-05-11 19:42:16 +0000128}
129
Howard Hinnantdd099492013-08-29 23:37:50 +0000130#if defined(_AIX)
131// Set priority to INT_MIN + 256 + 150
132# pragma priority ( -2147483242 )
133#endif
134
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000135const locale::category locale::none;
136const locale::category locale::collate;
137const locale::category locale::ctype;
138const locale::category locale::monetary;
139const locale::category locale::numeric;
140const locale::category locale::time;
141const locale::category locale::messages;
142const locale::category locale::all;
143
Howard Hinnantc51e1022010-05-11 19:42:16 +0000144class _LIBCPP_HIDDEN locale::__imp
145 : public facet
146{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100147 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000148#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000149// FIXME: MSVC doesn't support aligned parameters by value.
150// I can't get the __sso_allocator to work here
151// for MSVC I think for this reason.
152 vector<facet*> facets_;
153#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000154 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000155#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000156 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000157public:
158 explicit __imp(size_t refs = 0);
159 explicit __imp(const string& name, size_t refs = 0);
160 __imp(const __imp&);
161 __imp(const __imp&, const string&, locale::category c);
162 __imp(const __imp& other, const __imp& one, locale::category c);
163 __imp(const __imp&, facet* f, long id);
164 ~__imp();
165
166 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000167 bool has_facet(long id) const
168 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000169 const locale::facet* use_facet(long id) const;
170
171 static const locale& make_classic();
172 static locale& make_global();
173private:
174 void install(facet* f, long id);
175 template <class F> void install(F* f) {install(f, f->id.__get());}
176 template <class F> void install_from(const __imp& other);
177};
178
179locale::__imp::__imp(size_t refs)
180 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000181 facets_(N),
182 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000183{
184 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000185 install(&make<_VSTD::collate<char> >(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::collate<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400188#endif
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000189 install(&make<_VSTD::ctype<char> >(nullptr, false, 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<_VSTD::ctype<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400192#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000193 install(&make<codecvt<char, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400194#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000195 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400196#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100197_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000198 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
199 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100200_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400201#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100202 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
203 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
204#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000205 install(&make<numpunct<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<numpunct<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400208#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000209 install(&make<num_get<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_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400212#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000213 install(&make<num_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400214#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000215 install(&make<num_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400216#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000217 install(&make<moneypunct<char, false> >(1u));
218 install(&make<moneypunct<char, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400219#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000220 install(&make<moneypunct<wchar_t, false> >(1u));
221 install(&make<moneypunct<wchar_t, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400222#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000223 install(&make<money_get<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_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400226#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000227 install(&make<money_put<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<money_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400230#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000231 install(&make<time_get<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_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400234#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000235 install(&make<time_put<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<time_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400238#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000239 install(&make<_VSTD::messages<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400240#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000241 install(&make<_VSTD::messages<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400242#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000243}
244
245locale::__imp::__imp(const string& name, size_t refs)
246 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000247 facets_(N),
248 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000249{
Howard Hinnant72f73582010-08-11 17:04:31 +0000250#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000251 try
252 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400253#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000254 facets_ = locale::classic().__locale_->facets_;
255 for (unsigned i = 0; i < facets_.size(); ++i)
256 if (facets_[i])
257 facets_[i]->__add_shared();
258 install(new collate_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400259#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000260 install(new collate_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400261#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262 install(new ctype_byname<char>(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 ctype_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400265#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000266 install(new codecvt_byname<char, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400267#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000268 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400269#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100270_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000271 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
272 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100273_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400274#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100275 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
276 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
277#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000278 install(new numpunct_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400279#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000280 install(new numpunct_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400281#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000282 install(new moneypunct_byname<char, false>(name_));
283 install(new moneypunct_byname<char, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400284#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000285 install(new moneypunct_byname<wchar_t, false>(name_));
286 install(new moneypunct_byname<wchar_t, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400287#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288 install(new time_get_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_get_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400291#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000292 install(new time_put_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 time_put_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400295#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000296 install(new messages_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400297#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000298 install(new messages_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400299#endif
Howard Hinnant72f73582010-08-11 17:04:31 +0000300#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000301 }
302 catch (...)
303 {
304 for (unsigned i = 0; i < facets_.size(); ++i)
305 if (facets_[i])
306 facets_[i]->__release_shared();
307 throw;
308 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400309#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000310}
311
312locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000313 : facets_(max<size_t>(N, other.facets_.size())),
314 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000315{
316 facets_ = other.facets_;
317 for (unsigned i = 0; i < facets_.size(); ++i)
318 if (facets_[i])
319 facets_[i]->__add_shared();
320}
321
322locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000323 : facets_(N),
324 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000325{
326 facets_ = other.facets_;
327 for (unsigned i = 0; i < facets_.size(); ++i)
328 if (facets_[i])
329 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000330#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000331 try
332 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400333#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000334 if (c & locale::collate)
335 {
336 install(new collate_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400337#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000338 install(new collate_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400339#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000340 }
341 if (c & locale::ctype)
342 {
343 install(new ctype_byname<char>(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 ctype_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400346#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000347 install(new codecvt_byname<char, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400348#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000349 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400350#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100351_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000352 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
353 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100354_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400355#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100356 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
357 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
358#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000359 }
360 if (c & locale::monetary)
361 {
362 install(new moneypunct_byname<char, false>(name));
363 install(new moneypunct_byname<char, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400364#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000365 install(new moneypunct_byname<wchar_t, false>(name));
366 install(new moneypunct_byname<wchar_t, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400367#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000368 }
369 if (c & locale::numeric)
370 {
371 install(new numpunct_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400372#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000373 install(new numpunct_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400374#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000375 }
376 if (c & locale::time)
377 {
378 install(new time_get_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_get_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400381#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000382 install(new time_put_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400383#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000384 install(new time_put_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400385#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000386 }
387 if (c & locale::messages)
388 {
389 install(new messages_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400390#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000391 install(new messages_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400392#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000393 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000394#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000395 }
396 catch (...)
397 {
398 for (unsigned i = 0; i < facets_.size(); ++i)
399 if (facets_[i])
400 facets_[i]->__release_shared();
401 throw;
402 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400403#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000404}
405
406template<class F>
407inline
408void
409locale::__imp::install_from(const locale::__imp& one)
410{
411 long id = F::id.__get();
412 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
413}
414
415locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000416 : facets_(N),
417 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000418{
419 facets_ = other.facets_;
420 for (unsigned i = 0; i < facets_.size(); ++i)
421 if (facets_[i])
422 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000423#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000424 try
425 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400426#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000427 if (c & locale::collate)
428 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000429 install_from<_VSTD::collate<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400430#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000431 install_from<_VSTD::collate<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400432#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000433 }
434 if (c & locale::ctype)
435 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000436 install_from<_VSTD::ctype<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400437#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000438 install_from<_VSTD::ctype<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400439#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000440 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100441_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000442 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
443 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100444_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400445#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100446 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
447 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
448#endif
Louis Dionne89258142021-08-23 15:32:36 -0400449#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000450 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400451#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000452 }
453 if (c & locale::monetary)
454 {
455 install_from<moneypunct<char, false> >(one);
456 install_from<moneypunct<char, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400457#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000458 install_from<moneypunct<wchar_t, false> >(one);
459 install_from<moneypunct<wchar_t, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400460#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000461 install_from<money_get<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_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400464#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000465 install_from<money_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400466#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000467 install_from<money_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400468#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000469 }
470 if (c & locale::numeric)
471 {
472 install_from<numpunct<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<numpunct<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400475#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000476 install_from<num_get<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_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400479#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000480 install_from<num_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400481#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000482 install_from<num_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400483#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000484 }
485 if (c & locale::time)
486 {
487 install_from<time_get<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_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400490#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000491 install_from<time_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400492#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000493 install_from<time_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400494#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000495 }
496 if (c & locale::messages)
497 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000498 install_from<_VSTD::messages<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400499#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000500 install_from<_VSTD::messages<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400501#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000502 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000503#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000504 }
505 catch (...)
506 {
507 for (unsigned i = 0; i < facets_.size(); ++i)
508 if (facets_[i])
509 facets_[i]->__release_shared();
510 throw;
511 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400512#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000513}
514
515locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000516 : facets_(max<size_t>(N, other.facets_.size()+1)),
517 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000518{
519 f->__add_shared();
520 unique_ptr<facet, release> hold(f);
521 facets_ = other.facets_;
522 for (unsigned i = 0; i < other.facets_.size(); ++i)
523 if (facets_[i])
524 facets_[i]->__add_shared();
525 install(hold.get(), id);
526}
527
528locale::__imp::~__imp()
529{
530 for (unsigned i = 0; i < facets_.size(); ++i)
531 if (facets_[i])
532 facets_[i]->__release_shared();
533}
534
535void
536locale::__imp::install(facet* f, long id)
537{
538 f->__add_shared();
539 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000540 if (static_cast<size_t>(id) >= facets_.size())
541 facets_.resize(static_cast<size_t>(id+1));
542 if (facets_[static_cast<size_t>(id)])
543 facets_[static_cast<size_t>(id)]->__release_shared();
544 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000545}
546
547const locale::facet*
548locale::__imp::use_facet(long id) const
549{
550 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000551 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000552 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000553}
554
555// locale
556
557const locale&
558locale::__imp::make_classic()
559{
560 // only one thread can get in here and it only gets in once
561 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000562 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000563 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000564 return *c;
565}
566
567const locale&
568locale::classic()
569{
570 static const locale& c = __imp::make_classic();
571 return c;
572}
573
574locale&
575locale::__imp::make_global()
576{
577 // only one thread can get in here and it only gets in once
578 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000579 auto *obj = ::new (&buf) locale(locale::classic());
580 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000581}
582
583locale&
584locale::__global()
585{
586 static locale& g = __imp::make_global();
587 return g;
588}
589
Louis Dionne65358e12021-03-01 12:09:45 -0500590locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000591 : __locale_(__global().__locale_)
592{
593 __locale_->__add_shared();
594}
595
Louis Dionne65358e12021-03-01 12:09:45 -0500596locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000597 : __locale_(l.__locale_)
598{
599 __locale_->__add_shared();
600}
601
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000602locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000603{
604 __locale_->__release_shared();
605}
606
607const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500608locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000609{
610 other.__locale_->__add_shared();
611 __locale_->__release_shared();
612 __locale_ = other.__locale_;
613 return *this;
614}
615
616locale::locale(const char* name)
617 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100618 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000619{
620 __locale_->__add_shared();
621}
622
623locale::locale(const string& name)
624 : __locale_(new __imp(name))
625{
626 __locale_->__add_shared();
627}
628
629locale::locale(const locale& other, const char* name, category c)
630 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100631 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000632{
633 __locale_->__add_shared();
634}
635
636locale::locale(const locale& other, const string& name, category c)
637 : __locale_(new __imp(*other.__locale_, name, c))
638{
639 __locale_->__add_shared();
640}
641
642locale::locale(const locale& other, const locale& one, category c)
643 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
644{
645 __locale_->__add_shared();
646}
647
648string
649locale::name() const
650{
651 return __locale_->name();
652}
653
654void
655locale::__install_ctor(const locale& other, facet* f, long id)
656{
657 if (f)
658 __locale_ = new __imp(*other.__locale_, f, id);
659 else
660 __locale_ = other.__locale_;
661 __locale_->__add_shared();
662}
663
664locale
665locale::global(const locale& loc)
666{
667 locale& g = __global();
668 locale r = g;
669 g = loc;
670 if (g.name() != "*")
671 setlocale(LC_ALL, g.name().c_str());
672 return r;
673}
674
675bool
676locale::has_facet(id& x) const
677{
678 return __locale_->has_facet(x.__get());
679}
680
681const locale::facet*
682locale::use_facet(id& x) const
683{
684 return __locale_->use_facet(x.__get());
685}
686
687bool
688locale::operator==(const locale& y) const
689{
690 return (__locale_ == y.__locale_)
691 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
692}
693
694// locale::facet
695
696locale::facet::~facet()
697{
698}
699
700void
Louis Dionne65358e12021-03-01 12:09:45 -0500701locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000702{
703 delete this;
704}
705
706// locale::id
707
708int32_t locale::id::__next_id = 0;
709
710namespace
711{
712
713class __fake_bind
714{
715 locale::id* id_;
716 void (locale::id::* pmf_)();
717public:
718 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
719 : id_(id), pmf_(pmf) {}
720
721 void operator()() const
722 {
723 (id_->*pmf_)();
724 }
725};
726
727}
728
729long
730locale::id::__get()
731{
732 call_once(__flag_, __fake_bind(&locale::id::__init, this));
733 return __id_ - 1;
734}
735
736void
737locale::id::__init()
738{
Weiming Zhaob613db72017-09-19 23:18:03 +0000739 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000740}
741
742// template <> class collate_byname<char>
743
744collate_byname<char>::collate_byname(const char* n, size_t refs)
745 : collate<char>(refs),
746 __l(newlocale(LC_ALL_MASK, n, 0))
747{
748 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000749 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000750 " failed to construct for " + string(n));
751}
752
753collate_byname<char>::collate_byname(const string& name, size_t refs)
754 : collate<char>(refs),
755 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
756{
757 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000758 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000759 " failed to construct for " + name);
760}
761
762collate_byname<char>::~collate_byname()
763{
764 freelocale(__l);
765}
766
767int
768collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
769 const char_type* __lo2, const char_type* __hi2) const
770{
771 string_type lhs(__lo1, __hi1);
772 string_type rhs(__lo2, __hi2);
773 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
774 if (r < 0)
775 return -1;
776 if (r > 0)
777 return 1;
778 return r;
779}
780
781collate_byname<char>::string_type
782collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
783{
784 const string_type in(lo, hi);
785 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
786 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
787 return out;
788}
789
790// template <> class collate_byname<wchar_t>
791
Louis Dionne89258142021-08-23 15:32:36 -0400792#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000793collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
794 : collate<wchar_t>(refs),
795 __l(newlocale(LC_ALL_MASK, n, 0))
796{
797 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000798 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000799 " failed to construct for " + string(n));
800}
801
802collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
803 : collate<wchar_t>(refs),
804 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
805{
806 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000807 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000808 " failed to construct for " + name);
809}
810
811collate_byname<wchar_t>::~collate_byname()
812{
813 freelocale(__l);
814}
815
816int
817collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
818 const char_type* __lo2, const char_type* __hi2) const
819{
820 string_type lhs(__lo1, __hi1);
821 string_type rhs(__lo2, __hi2);
822 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
823 if (r < 0)
824 return -1;
825 if (r > 0)
826 return 1;
827 return r;
828}
829
830collate_byname<wchar_t>::string_type
831collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
832{
833 const string_type in(lo, hi);
834 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
835 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
836 return out;
837}
Louis Dionne89258142021-08-23 15:32:36 -0400838#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000839
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000840const ctype_base::mask ctype_base::space;
841const ctype_base::mask ctype_base::print;
842const ctype_base::mask ctype_base::cntrl;
843const ctype_base::mask ctype_base::upper;
844const ctype_base::mask ctype_base::lower;
845const ctype_base::mask ctype_base::alpha;
846const ctype_base::mask ctype_base::digit;
847const ctype_base::mask ctype_base::punct;
848const ctype_base::mask ctype_base::xdigit;
849const ctype_base::mask ctype_base::blank;
850const ctype_base::mask ctype_base::alnum;
851const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700852
Louis Dionne945f8682021-09-09 13:29:24 -0400853// template <> class ctype<wchar_t>;
854
Louis Dionne89258142021-08-23 15:32:36 -0400855#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000856locale::id ctype<wchar_t>::id;
857
858ctype<wchar_t>::~ctype()
859{
860}
861
862bool
863ctype<wchar_t>::do_is(mask m, char_type c) const
864{
Marshall Clowd920eea2013-10-21 15:07:28 +0000865 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000866}
867
868const wchar_t*
869ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
870{
871 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000872 *vec = static_cast<mask>(isascii(*low) ?
873 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000874 return low;
875}
876
877const wchar_t*
878ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
879{
880 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000881 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000882 break;
883 return low;
884}
885
886const wchar_t*
887ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
888{
889 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000890 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000891 break;
892 return low;
893}
894
895wchar_t
896ctype<wchar_t>::do_toupper(char_type c) const
897{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000898#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
899 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000900#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000901 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000902 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000903#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000904 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000905#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000906}
907
908const wchar_t*
909ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
910{
911 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000912#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
913 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000914#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000915 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000916 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
917 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000918#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000919 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000920#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000921 return low;
922}
923
924wchar_t
925ctype<wchar_t>::do_tolower(char_type c) const
926{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000927#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
928 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000929#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000930 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000931 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000932#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000933 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000934#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000935}
936
937const wchar_t*
938ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
939{
940 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000941#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
942 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000943#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000944 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000945 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
946 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000947#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000948 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000949#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000950 return low;
951}
952
953wchar_t
954ctype<wchar_t>::do_widen(char c) const
955{
956 return c;
957}
958
959const char*
960ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
961{
962 for (; low != high; ++low, ++dest)
963 *dest = *low;
964 return low;
965}
966
967char
968ctype<wchar_t>::do_narrow(char_type c, char dfault) const
969{
970 if (isascii(c))
971 return static_cast<char>(c);
972 return dfault;
973}
974
975const wchar_t*
976ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
977{
978 for (; low != high; ++low, ++dest)
979 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000980 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000981 else
982 *dest = dfault;
983 return low;
984}
Louis Dionne89258142021-08-23 15:32:36 -0400985#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000986
987// template <> class ctype<char>;
988
989locale::id ctype<char>::id;
990
991ctype<char>::ctype(const mask* tab, bool del, size_t refs)
992 : locale::facet(refs),
993 __tab_(tab),
994 __del_(del)
995{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000996 if (__tab_ == 0)
997 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000998}
999
1000ctype<char>::~ctype()
1001{
1002 if (__tab_ && __del_)
1003 delete [] __tab_;
1004}
1005
1006char
1007ctype<char>::do_toupper(char_type c) const
1008{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001009#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001010 return isascii(c) ?
1011 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001012#elif defined(__NetBSD__)
1013 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001014#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +00001015 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001016 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001017#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001018 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001019#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001020}
1021
1022const char*
1023ctype<char>::do_toupper(char_type* low, const char_type* high) const
1024{
1025 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001026#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001027 *low = isascii(*low) ?
1028 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001029#elif defined(__NetBSD__)
1030 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001031#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001032 *low = isascii(*low) ?
1033 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001034#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001035 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001036#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001037 return low;
1038}
1039
1040char
1041ctype<char>::do_tolower(char_type c) const
1042{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001043#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001044 return isascii(c) ?
1045 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001046#elif defined(__NetBSD__)
1047 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001048#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001049 return isascii(c) ?
1050 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001051#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001052 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001053#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001054}
1055
1056const char*
1057ctype<char>::do_tolower(char_type* low, const char_type* high) const
1058{
1059 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001060#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001061 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001062#elif defined(__NetBSD__)
1063 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001064#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001065 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001066#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001067 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001068#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001069 return low;
1070}
1071
1072char
1073ctype<char>::do_widen(char c) const
1074{
1075 return c;
1076}
1077
1078const char*
1079ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1080{
1081 for (; low != high; ++low, ++dest)
1082 *dest = *low;
1083 return low;
1084}
1085
1086char
1087ctype<char>::do_narrow(char_type c, char dfault) const
1088{
1089 if (isascii(c))
1090 return static_cast<char>(c);
1091 return dfault;
1092}
1093
1094const char*
1095ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1096{
1097 for (; low != high; ++low, ++dest)
1098 if (isascii(*low))
1099 *dest = *low;
1100 else
1101 *dest = dfault;
1102 return low;
1103}
1104
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001105#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001106extern "C" const unsigned short ** __ctype_b_loc();
1107extern "C" const int ** __ctype_tolower_loc();
1108extern "C" const int ** __ctype_toupper_loc();
1109#endif
1110
Marshall Clow8f870232015-03-04 16:50:02 +00001111#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001112const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001113ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001114{
1115 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1116 cntrl, cntrl,
1117 cntrl, cntrl,
1118 cntrl, cntrl,
1119 cntrl, cntrl,
1120 cntrl, cntrl | space | blank,
1121 cntrl | space, cntrl | space,
1122 cntrl | space, cntrl | space,
1123 cntrl, cntrl,
1124 cntrl, cntrl,
1125 cntrl, cntrl,
1126 cntrl, cntrl,
1127 cntrl, cntrl,
1128 cntrl, cntrl,
1129 cntrl, cntrl,
1130 cntrl, cntrl,
1131 cntrl, cntrl,
1132 space | blank | print, punct | print,
1133 punct | print, punct | print,
1134 punct | print, punct | print,
1135 punct | print, punct | print,
1136 punct | print, punct | print,
1137 punct | print, punct | print,
1138 punct | print, punct | print,
1139 punct | print, punct | print,
1140 digit | print | xdigit, digit | print | xdigit,
1141 digit | print | xdigit, digit | print | xdigit,
1142 digit | print | xdigit, digit | print | xdigit,
1143 digit | print | xdigit, digit | print | xdigit,
1144 digit | print | xdigit, digit | print | xdigit,
1145 punct | print, punct | print,
1146 punct | print, punct | print,
1147 punct | print, punct | print,
1148 punct | print, upper | xdigit | print | alpha,
1149 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1150 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1151 upper | xdigit | print | alpha, upper | print | alpha,
1152 upper | print | alpha, upper | print | alpha,
1153 upper | print | alpha, upper | print | alpha,
1154 upper | print | alpha, upper | print | alpha,
1155 upper | print | alpha, upper | print | alpha,
1156 upper | print | alpha, upper | print | alpha,
1157 upper | print | alpha, upper | print | alpha,
1158 upper | print | alpha, upper | print | alpha,
1159 upper | print | alpha, upper | print | alpha,
1160 upper | print | alpha, upper | print | alpha,
1161 upper | print | alpha, punct | print,
1162 punct | print, punct | print,
1163 punct | print, punct | print,
1164 punct | print, lower | xdigit | print | alpha,
1165 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1166 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1167 lower | xdigit | print | alpha, lower | print | alpha,
1168 lower | print | alpha, lower | print | alpha,
1169 lower | print | alpha, lower | print | alpha,
1170 lower | print | alpha, lower | print | alpha,
1171 lower | print | alpha, lower | print | alpha,
1172 lower | print | alpha, lower | print | alpha,
1173 lower | print | alpha, lower | print | alpha,
1174 lower | print | alpha, lower | print | alpha,
1175 lower | print | alpha, lower | print | alpha,
1176 lower | print | alpha, lower | print | alpha,
1177 lower | print | alpha, punct | print,
1178 punct | print, punct | print,
1179 punct | print, cntrl,
1180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1188 };
1189 return builtin_table;
1190}
1191#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001192const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001193ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001194{
David Chisnall1d581062011-09-21 08:39:44 +00001195#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001196 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001197#elif defined(__NetBSD__)
1198 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001199#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001200 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001201#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001202 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001203#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001204 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001205#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001206 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001207#elif defined(_NEWLIB_VERSION)
1208 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1209 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001210#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001211 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001212#else
David Chisnall8074c342012-02-29 13:05:08 +00001213 // Platform not supported: abort so the person doing the port knows what to
1214 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001215# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001216 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001217 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001218 return NULL;
1219#endif
1220}
Marshall Clowb3f62842015-03-04 16:10:14 +00001221#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001222
Howard Hinnantd7a78632011-09-29 13:33:15 +00001223#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001224const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001225ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001226{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001227 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001228}
1229
1230const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001231ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001232{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001233 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001234}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001235#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001236const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001237ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001238{
1239 return _C_tolower_tab_ + 1;
1240}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001241
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001242const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001243ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001244{
1245 return _C_toupper_tab_ + 1;
1246}
1247
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001248#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001249const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001250ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001251{
1252 return *__ctype_tolower_loc();
1253}
1254
1255const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001256ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001257{
1258 return *__ctype_toupper_loc();
1259}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001260#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001261
Howard Hinnantc51e1022010-05-11 19:42:16 +00001262// template <> class ctype_byname<char>
1263
1264ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1265 : ctype<char>(0, false, refs),
1266 __l(newlocale(LC_ALL_MASK, name, 0))
1267{
1268 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001269 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001270 " failed to construct for " + string(name));
1271}
1272
1273ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1274 : ctype<char>(0, false, refs),
1275 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1276{
1277 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001278 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001279 " failed to construct for " + name);
1280}
1281
1282ctype_byname<char>::~ctype_byname()
1283{
1284 freelocale(__l);
1285}
1286
1287char
1288ctype_byname<char>::do_toupper(char_type c) const
1289{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001290 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001291}
1292
1293const char*
1294ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1295{
1296 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001297 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001298 return low;
1299}
1300
1301char
1302ctype_byname<char>::do_tolower(char_type c) const
1303{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001304 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001305}
1306
1307const char*
1308ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1309{
1310 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001311 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001312 return low;
1313}
1314
1315// template <> class ctype_byname<wchar_t>
1316
Louis Dionne89258142021-08-23 15:32:36 -04001317#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001318ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1319 : ctype<wchar_t>(refs),
1320 __l(newlocale(LC_ALL_MASK, name, 0))
1321{
1322 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001323 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001324 " failed to construct for " + string(name));
1325}
1326
1327ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1328 : ctype<wchar_t>(refs),
1329 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1330{
1331 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001332 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001333 " failed to construct for " + name);
1334}
1335
1336ctype_byname<wchar_t>::~ctype_byname()
1337{
1338 freelocale(__l);
1339}
1340
1341bool
1342ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1343{
Alexis Huntc2017f12011-07-09 03:40:04 +00001344#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001346#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001347 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001348 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001349 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1350 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1351 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1352 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1353 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1354 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1355 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1356 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1357 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1358 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001359 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001360#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001361}
1362
1363const wchar_t*
1364ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1365{
1366 for (; low != high; ++low, ++vec)
1367 {
1368 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001369 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001370 else
1371 {
1372 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001373 wint_t ch = static_cast<wint_t>(*low);
1374 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001375 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001376#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001377 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001378 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001379#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001380 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001381 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001382 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001383 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001384 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001385 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001386#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001387 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001388 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001389#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001390 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001391 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001392 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001393 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001394#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001395 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001396 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001397#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001398#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001399 if (iswblank_l(ch, __l))
1400 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001401#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001402 }
1403 }
1404 return low;
1405}
1406
1407const wchar_t*
1408ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1409{
1410 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001411 {
1412#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001413 if (iswctype_l(*low, m, __l))
1414 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001415#else
Marshall Clowada0f732013-02-07 14:22:51 +00001416 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001417 if ((m & space) == space && iswspace_l(ch, __l)) break;
1418 if ((m & print) == print && iswprint_l(ch, __l)) break;
1419 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1420 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1421 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1422 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1423 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1424 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1425 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1426 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001427#endif
1428 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001429 return low;
1430}
1431
1432const wchar_t*
1433ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1434{
1435 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001436 {
1437#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001438 if (!iswctype_l(*low, m, __l))
1439 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001440#else
Marshall Clowada0f732013-02-07 14:22:51 +00001441 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001442 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1443 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1444 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1445 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1446 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1447 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1448 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1449 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1450 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1451 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001452 break;
1453#endif
1454 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001455 return low;
1456}
1457
1458wchar_t
1459ctype_byname<wchar_t>::do_toupper(char_type c) const
1460{
1461 return towupper_l(c, __l);
1462}
1463
1464const wchar_t*
1465ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1466{
1467 for (; low != high; ++low)
1468 *low = towupper_l(*low, __l);
1469 return low;
1470}
1471
1472wchar_t
1473ctype_byname<wchar_t>::do_tolower(char_type c) const
1474{
1475 return towlower_l(c, __l);
1476}
1477
1478const wchar_t*
1479ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1480{
1481 for (; low != high; ++low)
1482 *low = towlower_l(*low, __l);
1483 return low;
1484}
1485
1486wchar_t
1487ctype_byname<wchar_t>::do_widen(char c) const
1488{
Ben Craig3756b922016-03-09 15:39:39 +00001489 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001490}
1491
1492const char*
1493ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1494{
1495 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001496 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001497 return low;
1498}
1499
1500char
1501ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1502{
Ben Craig3756b922016-03-09 15:39:39 +00001503 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001504 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001505}
1506
1507const wchar_t*
1508ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1509{
1510 for (; low != high; ++low, ++dest)
1511 {
Ben Craig3756b922016-03-09 15:39:39 +00001512 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001513 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001514 }
1515 return low;
1516}
Louis Dionne89258142021-08-23 15:32:36 -04001517#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001518
1519// template <> class codecvt<char, char, mbstate_t>
1520
Howard Hinnantffb308e2010-08-22 00:03:27 +00001521locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001522
1523codecvt<char, char, mbstate_t>::~codecvt()
1524{
1525}
1526
1527codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001528codecvt<char, char, mbstate_t>::do_out(state_type&,
1529 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001530 extern_type* to, extern_type*, extern_type*& to_nxt) const
1531{
1532 frm_nxt = frm;
1533 to_nxt = to;
1534 return noconv;
1535}
1536
1537codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001538codecvt<char, char, mbstate_t>::do_in(state_type&,
1539 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001540 intern_type* to, intern_type*, intern_type*& to_nxt) const
1541{
1542 frm_nxt = frm;
1543 to_nxt = to;
1544 return noconv;
1545}
1546
1547codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001548codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001549 extern_type* to, extern_type*, extern_type*& to_nxt) const
1550{
1551 to_nxt = to;
1552 return noconv;
1553}
1554
1555int
Louis Dionne65358e12021-03-01 12:09:45 -05001556codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001557{
1558 return 1;
1559}
1560
1561bool
Louis Dionne65358e12021-03-01 12:09:45 -05001562codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001563{
1564 return true;
1565}
1566
1567int
1568codecvt<char, char, mbstate_t>::do_length(state_type&,
1569 const extern_type* frm, const extern_type* end, size_t mx) const
1570{
Howard Hinnant28b24882011-12-01 20:21:04 +00001571 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001572}
1573
1574int
Louis Dionne65358e12021-03-01 12:09:45 -05001575codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001576{
1577 return 1;
1578}
1579
1580// template <> class codecvt<wchar_t, char, mbstate_t>
1581
Louis Dionne89258142021-08-23 15:32:36 -04001582#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantffb308e2010-08-22 00:03:27 +00001583locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001584
1585codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1586 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001587 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001588{
1589}
1590
1591codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1592 : locale::facet(refs),
1593 __l(newlocale(LC_ALL_MASK, nm, 0))
1594{
1595 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001596 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001597 " failed to construct for " + string(nm));
1598}
1599
1600codecvt<wchar_t, char, mbstate_t>::~codecvt()
1601{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001602 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001603 freelocale(__l);
1604}
1605
1606codecvt<wchar_t, char, mbstate_t>::result
1607codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001608 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001609 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1610{
1611 // look for first internal null in frm
1612 const intern_type* fend = frm;
1613 for (; fend != frm_end; ++fend)
1614 if (*fend == 0)
1615 break;
1616 // loop over all null-terminated sequences in frm
1617 to_nxt = to;
1618 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1619 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001620 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001621 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001622 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1623 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001624 if (n == size_t(-1))
1625 {
1626 // need to recover to_nxt
1627 for (to_nxt = to; frm != frm_nxt; ++frm)
1628 {
Ben Craig3756b922016-03-09 15:39:39 +00001629 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001630 if (n == size_t(-1))
1631 break;
1632 to_nxt += n;
1633 }
1634 frm_nxt = frm;
1635 return error;
1636 }
1637 if (n == 0)
1638 return partial;
1639 to_nxt += n;
1640 if (to_nxt == to_end)
1641 break;
1642 if (fend != frm_end) // set up next null terminated sequence
1643 {
1644 // Try to write the terminating null
1645 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001646 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001647 if (n == size_t(-1)) // on error
1648 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001649 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001650 return partial;
1651 for (extern_type* p = tmp; n; --n) // write it
1652 *to_nxt++ = *p++;
1653 ++frm_nxt;
1654 // look for next null in frm
1655 for (fend = frm_nxt; fend != frm_end; ++fend)
1656 if (*fend == 0)
1657 break;
1658 }
1659 }
1660 return frm_nxt == frm_end ? ok : partial;
1661}
1662
1663codecvt<wchar_t, char, mbstate_t>::result
1664codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001665 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001666 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1667{
1668 // look for first internal null in frm
1669 const extern_type* fend = frm;
1670 for (; fend != frm_end; ++fend)
1671 if (*fend == 0)
1672 break;
1673 // loop over all null-terminated sequences in frm
1674 to_nxt = to;
1675 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1676 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001677 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001678 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001679 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1680 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001681 if (n == size_t(-1))
1682 {
1683 // need to recover to_nxt
1684 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1685 {
Ben Craig3756b922016-03-09 15:39:39 +00001686 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1687 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001688 switch (n)
1689 {
1690 case 0:
1691 ++frm;
1692 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001693 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001694 frm_nxt = frm;
1695 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001696 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001697 frm_nxt = frm;
1698 return partial;
1699 default:
1700 frm += n;
1701 break;
1702 }
1703 }
1704 frm_nxt = frm;
1705 return frm_nxt == frm_end ? ok : partial;
1706 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001707 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001708 return error;
1709 to_nxt += n;
1710 if (to_nxt == to_end)
1711 break;
1712 if (fend != frm_end) // set up next null terminated sequence
1713 {
1714 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001715 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001716 if (n != 0) // on error
1717 return error;
1718 ++to_nxt;
1719 ++frm_nxt;
1720 // look for next null in frm
1721 for (fend = frm_nxt; fend != frm_end; ++fend)
1722 if (*fend == 0)
1723 break;
1724 }
1725 }
1726 return frm_nxt == frm_end ? ok : partial;
1727}
1728
1729codecvt<wchar_t, char, mbstate_t>::result
1730codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1731 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1732{
1733 to_nxt = to;
1734 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001735 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001736 if (n == size_t(-1) || n == 0) // on error
1737 return error;
1738 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001739 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001740 return partial;
1741 for (extern_type* p = tmp; n; --n) // write it
1742 *to_nxt++ = *p++;
1743 return ok;
1744}
1745
1746int
Louis Dionne65358e12021-03-01 12:09:45 -05001747codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001748{
Ben Craig3756b922016-03-09 15:39:39 +00001749 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001750 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001751
1752 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001753 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001754 return 1; // which take more than 1 char to form a wchar_t
1755 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001756}
1757
1758bool
Louis Dionne65358e12021-03-01 12:09:45 -05001759codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001760{
1761 return false;
1762}
1763
1764int
1765codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1766 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1767{
1768 int nbytes = 0;
1769 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1770 {
Ben Craig3756b922016-03-09 15:39:39 +00001771 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001772 switch (n)
1773 {
1774 case 0:
1775 ++nbytes;
1776 ++frm;
1777 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001778 case size_t(-1):
1779 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001780 return nbytes;
1781 default:
1782 nbytes += n;
1783 frm += n;
1784 break;
1785 }
1786 }
1787 return nbytes;
1788}
1789
1790int
Louis Dionne65358e12021-03-01 12:09:45 -05001791codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001792{
Ben Craig3756b922016-03-09 15:39:39 +00001793 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001794}
Louis Dionne89258142021-08-23 15:32:36 -04001795#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001796
1797// Valid UTF ranges
1798// UTF-32 UTF-16 UTF-8 # of code points
1799// first second first second third fourth
1800// 000000 - 00007F 0000 - 007F 00 - 7F 127
1801// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1802// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1803// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1804// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1805// 00D800 - 00DFFF invalid
1806// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1807// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1808// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1809// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1810
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001811static
1812codecvt_base::result
1813utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1814 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1815 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1816{
1817 frm_nxt = frm;
1818 to_nxt = to;
1819 if (mode & generate_header)
1820 {
1821 if (to_end-to_nxt < 3)
1822 return codecvt_base::partial;
1823 *to_nxt++ = static_cast<uint8_t>(0xEF);
1824 *to_nxt++ = static_cast<uint8_t>(0xBB);
1825 *to_nxt++ = static_cast<uint8_t>(0xBF);
1826 }
1827 for (; frm_nxt < frm_end; ++frm_nxt)
1828 {
1829 uint16_t wc1 = *frm_nxt;
1830 if (wc1 > Maxcode)
1831 return codecvt_base::error;
1832 if (wc1 < 0x0080)
1833 {
1834 if (to_end-to_nxt < 1)
1835 return codecvt_base::partial;
1836 *to_nxt++ = static_cast<uint8_t>(wc1);
1837 }
1838 else if (wc1 < 0x0800)
1839 {
1840 if (to_end-to_nxt < 2)
1841 return codecvt_base::partial;
1842 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1843 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1844 }
1845 else if (wc1 < 0xD800)
1846 {
1847 if (to_end-to_nxt < 3)
1848 return codecvt_base::partial;
1849 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1852 }
1853 else if (wc1 < 0xDC00)
1854 {
1855 if (frm_end-frm_nxt < 2)
1856 return codecvt_base::partial;
1857 uint16_t wc2 = frm_nxt[1];
1858 if ((wc2 & 0xFC00) != 0xDC00)
1859 return codecvt_base::error;
1860 if (to_end-to_nxt < 4)
1861 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001862 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1863 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001864 return codecvt_base::error;
1865 ++frm_nxt;
1866 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1867 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1868 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1869 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1870 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1871 }
1872 else if (wc1 < 0xE000)
1873 {
1874 return codecvt_base::error;
1875 }
1876 else
1877 {
1878 if (to_end-to_nxt < 3)
1879 return codecvt_base::partial;
1880 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1881 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1882 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1883 }
1884 }
1885 return codecvt_base::ok;
1886}
1887
1888static
1889codecvt_base::result
1890utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1891 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1892 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1893{
1894 frm_nxt = frm;
1895 to_nxt = to;
1896 if (mode & generate_header)
1897 {
1898 if (to_end-to_nxt < 3)
1899 return codecvt_base::partial;
1900 *to_nxt++ = static_cast<uint8_t>(0xEF);
1901 *to_nxt++ = static_cast<uint8_t>(0xBB);
1902 *to_nxt++ = static_cast<uint8_t>(0xBF);
1903 }
1904 for (; frm_nxt < frm_end; ++frm_nxt)
1905 {
1906 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1907 if (wc1 > Maxcode)
1908 return codecvt_base::error;
1909 if (wc1 < 0x0080)
1910 {
1911 if (to_end-to_nxt < 1)
1912 return codecvt_base::partial;
1913 *to_nxt++ = static_cast<uint8_t>(wc1);
1914 }
1915 else if (wc1 < 0x0800)
1916 {
1917 if (to_end-to_nxt < 2)
1918 return codecvt_base::partial;
1919 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1920 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1921 }
1922 else if (wc1 < 0xD800)
1923 {
1924 if (to_end-to_nxt < 3)
1925 return codecvt_base::partial;
1926 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1927 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1928 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1929 }
1930 else if (wc1 < 0xDC00)
1931 {
1932 if (frm_end-frm_nxt < 2)
1933 return codecvt_base::partial;
1934 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1935 if ((wc2 & 0xFC00) != 0xDC00)
1936 return codecvt_base::error;
1937 if (to_end-to_nxt < 4)
1938 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001939 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1940 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001941 return codecvt_base::error;
1942 ++frm_nxt;
1943 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1944 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1945 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1946 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1947 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1948 }
1949 else if (wc1 < 0xE000)
1950 {
1951 return codecvt_base::error;
1952 }
1953 else
1954 {
1955 if (to_end-to_nxt < 3)
1956 return codecvt_base::partial;
1957 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1958 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1959 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1960 }
1961 }
1962 return codecvt_base::ok;
1963}
1964
1965static
1966codecvt_base::result
1967utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1968 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1969 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1970{
1971 frm_nxt = frm;
1972 to_nxt = to;
1973 if (mode & consume_header)
1974 {
1975 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1976 frm_nxt[2] == 0xBF)
1977 frm_nxt += 3;
1978 }
1979 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1980 {
1981 uint8_t c1 = *frm_nxt;
1982 if (c1 > Maxcode)
1983 return codecvt_base::error;
1984 if (c1 < 0x80)
1985 {
1986 *to_nxt = static_cast<uint16_t>(c1);
1987 ++frm_nxt;
1988 }
1989 else if (c1 < 0xC2)
1990 {
1991 return codecvt_base::error;
1992 }
1993 else if (c1 < 0xE0)
1994 {
1995 if (frm_end-frm_nxt < 2)
1996 return codecvt_base::partial;
1997 uint8_t c2 = frm_nxt[1];
1998 if ((c2 & 0xC0) != 0x80)
1999 return codecvt_base::error;
2000 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2001 if (t > Maxcode)
2002 return codecvt_base::error;
2003 *to_nxt = t;
2004 frm_nxt += 2;
2005 }
2006 else if (c1 < 0xF0)
2007 {
2008 if (frm_end-frm_nxt < 3)
2009 return codecvt_base::partial;
2010 uint8_t c2 = frm_nxt[1];
2011 uint8_t c3 = frm_nxt[2];
2012 switch (c1)
2013 {
2014 case 0xE0:
2015 if ((c2 & 0xE0) != 0xA0)
2016 return codecvt_base::error;
2017 break;
2018 case 0xED:
2019 if ((c2 & 0xE0) != 0x80)
2020 return codecvt_base::error;
2021 break;
2022 default:
2023 if ((c2 & 0xC0) != 0x80)
2024 return codecvt_base::error;
2025 break;
2026 }
2027 if ((c3 & 0xC0) != 0x80)
2028 return codecvt_base::error;
2029 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2030 | ((c2 & 0x3F) << 6)
2031 | (c3 & 0x3F));
2032 if (t > Maxcode)
2033 return codecvt_base::error;
2034 *to_nxt = t;
2035 frm_nxt += 3;
2036 }
2037 else if (c1 < 0xF5)
2038 {
2039 if (frm_end-frm_nxt < 4)
2040 return codecvt_base::partial;
2041 uint8_t c2 = frm_nxt[1];
2042 uint8_t c3 = frm_nxt[2];
2043 uint8_t c4 = frm_nxt[3];
2044 switch (c1)
2045 {
2046 case 0xF0:
2047 if (!(0x90 <= c2 && c2 <= 0xBF))
2048 return codecvt_base::error;
2049 break;
2050 case 0xF4:
2051 if ((c2 & 0xF0) != 0x80)
2052 return codecvt_base::error;
2053 break;
2054 default:
2055 if ((c2 & 0xC0) != 0x80)
2056 return codecvt_base::error;
2057 break;
2058 }
2059 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2060 return codecvt_base::error;
2061 if (to_end-to_nxt < 2)
2062 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002063 if ((((c1 & 7UL) << 18) +
2064 ((c2 & 0x3FUL) << 12) +
2065 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002066 return codecvt_base::error;
2067 *to_nxt = static_cast<uint16_t>(
2068 0xD800
2069 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2070 | ((c2 & 0x0F) << 2)
2071 | ((c3 & 0x30) >> 4));
2072 *++to_nxt = static_cast<uint16_t>(
2073 0xDC00
2074 | ((c3 & 0x0F) << 6)
2075 | (c4 & 0x3F));
2076 frm_nxt += 4;
2077 }
2078 else
2079 {
2080 return codecvt_base::error;
2081 }
2082 }
2083 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2084}
2085
2086static
2087codecvt_base::result
2088utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2089 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2090 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2091{
2092 frm_nxt = frm;
2093 to_nxt = to;
2094 if (mode & consume_header)
2095 {
2096 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2097 frm_nxt[2] == 0xBF)
2098 frm_nxt += 3;
2099 }
2100 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2101 {
2102 uint8_t c1 = *frm_nxt;
2103 if (c1 > Maxcode)
2104 return codecvt_base::error;
2105 if (c1 < 0x80)
2106 {
2107 *to_nxt = static_cast<uint32_t>(c1);
2108 ++frm_nxt;
2109 }
2110 else if (c1 < 0xC2)
2111 {
2112 return codecvt_base::error;
2113 }
2114 else if (c1 < 0xE0)
2115 {
2116 if (frm_end-frm_nxt < 2)
2117 return codecvt_base::partial;
2118 uint8_t c2 = frm_nxt[1];
2119 if ((c2 & 0xC0) != 0x80)
2120 return codecvt_base::error;
2121 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2122 if (t > Maxcode)
2123 return codecvt_base::error;
2124 *to_nxt = static_cast<uint32_t>(t);
2125 frm_nxt += 2;
2126 }
2127 else if (c1 < 0xF0)
2128 {
2129 if (frm_end-frm_nxt < 3)
2130 return codecvt_base::partial;
2131 uint8_t c2 = frm_nxt[1];
2132 uint8_t c3 = frm_nxt[2];
2133 switch (c1)
2134 {
2135 case 0xE0:
2136 if ((c2 & 0xE0) != 0xA0)
2137 return codecvt_base::error;
2138 break;
2139 case 0xED:
2140 if ((c2 & 0xE0) != 0x80)
2141 return codecvt_base::error;
2142 break;
2143 default:
2144 if ((c2 & 0xC0) != 0x80)
2145 return codecvt_base::error;
2146 break;
2147 }
2148 if ((c3 & 0xC0) != 0x80)
2149 return codecvt_base::error;
2150 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2151 | ((c2 & 0x3F) << 6)
2152 | (c3 & 0x3F));
2153 if (t > Maxcode)
2154 return codecvt_base::error;
2155 *to_nxt = static_cast<uint32_t>(t);
2156 frm_nxt += 3;
2157 }
2158 else if (c1 < 0xF5)
2159 {
2160 if (frm_end-frm_nxt < 4)
2161 return codecvt_base::partial;
2162 uint8_t c2 = frm_nxt[1];
2163 uint8_t c3 = frm_nxt[2];
2164 uint8_t c4 = frm_nxt[3];
2165 switch (c1)
2166 {
2167 case 0xF0:
2168 if (!(0x90 <= c2 && c2 <= 0xBF))
2169 return codecvt_base::error;
2170 break;
2171 case 0xF4:
2172 if ((c2 & 0xF0) != 0x80)
2173 return codecvt_base::error;
2174 break;
2175 default:
2176 if ((c2 & 0xC0) != 0x80)
2177 return codecvt_base::error;
2178 break;
2179 }
2180 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2181 return codecvt_base::error;
2182 if (to_end-to_nxt < 2)
2183 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002184 if ((((c1 & 7UL) << 18) +
2185 ((c2 & 0x3FUL) << 12) +
2186 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002187 return codecvt_base::error;
2188 *to_nxt = static_cast<uint32_t>(
2189 0xD800
2190 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2191 | ((c2 & 0x0F) << 2)
2192 | ((c3 & 0x30) >> 4));
2193 *++to_nxt = static_cast<uint32_t>(
2194 0xDC00
2195 | ((c3 & 0x0F) << 6)
2196 | (c4 & 0x3F));
2197 frm_nxt += 4;
2198 }
2199 else
2200 {
2201 return codecvt_base::error;
2202 }
2203 }
2204 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2205}
2206
2207static
2208int
2209utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2210 size_t mx, unsigned long Maxcode = 0x10FFFF,
2211 codecvt_mode mode = codecvt_mode(0))
2212{
2213 const uint8_t* frm_nxt = frm;
2214 if (mode & consume_header)
2215 {
2216 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2217 frm_nxt[2] == 0xBF)
2218 frm_nxt += 3;
2219 }
2220 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2221 {
2222 uint8_t c1 = *frm_nxt;
2223 if (c1 > Maxcode)
2224 break;
2225 if (c1 < 0x80)
2226 {
2227 ++frm_nxt;
2228 }
2229 else if (c1 < 0xC2)
2230 {
2231 break;
2232 }
2233 else if (c1 < 0xE0)
2234 {
2235 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2236 break;
2237 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2238 if (t > Maxcode)
2239 break;
2240 frm_nxt += 2;
2241 }
2242 else if (c1 < 0xF0)
2243 {
2244 if (frm_end-frm_nxt < 3)
2245 break;
2246 uint8_t c2 = frm_nxt[1];
2247 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002248 switch (c1)
2249 {
2250 case 0xE0:
2251 if ((c2 & 0xE0) != 0xA0)
2252 return static_cast<int>(frm_nxt - frm);
2253 break;
2254 case 0xED:
2255 if ((c2 & 0xE0) != 0x80)
2256 return static_cast<int>(frm_nxt - frm);
2257 break;
2258 default:
2259 if ((c2 & 0xC0) != 0x80)
2260 return static_cast<int>(frm_nxt - frm);
2261 break;
2262 }
2263 if ((c3 & 0xC0) != 0x80)
2264 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002265 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002266 break;
2267 frm_nxt += 3;
2268 }
2269 else if (c1 < 0xF5)
2270 {
2271 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2272 break;
2273 uint8_t c2 = frm_nxt[1];
2274 uint8_t c3 = frm_nxt[2];
2275 uint8_t c4 = frm_nxt[3];
2276 switch (c1)
2277 {
2278 case 0xF0:
2279 if (!(0x90 <= c2 && c2 <= 0xBF))
2280 return static_cast<int>(frm_nxt - frm);
2281 break;
2282 case 0xF4:
2283 if ((c2 & 0xF0) != 0x80)
2284 return static_cast<int>(frm_nxt - frm);
2285 break;
2286 default:
2287 if ((c2 & 0xC0) != 0x80)
2288 return static_cast<int>(frm_nxt - frm);
2289 break;
2290 }
2291 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2292 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002293 if ((((c1 & 7UL) << 18) +
2294 ((c2 & 0x3FUL) << 12) +
2295 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002296 break;
2297 ++nchar16_t;
2298 frm_nxt += 4;
2299 }
2300 else
2301 {
2302 break;
2303 }
2304 }
2305 return static_cast<int>(frm_nxt - frm);
2306}
2307
2308static
2309codecvt_base::result
2310ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2311 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2312 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2313{
2314 frm_nxt = frm;
2315 to_nxt = to;
2316 if (mode & generate_header)
2317 {
2318 if (to_end-to_nxt < 3)
2319 return codecvt_base::partial;
2320 *to_nxt++ = static_cast<uint8_t>(0xEF);
2321 *to_nxt++ = static_cast<uint8_t>(0xBB);
2322 *to_nxt++ = static_cast<uint8_t>(0xBF);
2323 }
2324 for (; frm_nxt < frm_end; ++frm_nxt)
2325 {
2326 uint32_t wc = *frm_nxt;
2327 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2328 return codecvt_base::error;
2329 if (wc < 0x000080)
2330 {
2331 if (to_end-to_nxt < 1)
2332 return codecvt_base::partial;
2333 *to_nxt++ = static_cast<uint8_t>(wc);
2334 }
2335 else if (wc < 0x000800)
2336 {
2337 if (to_end-to_nxt < 2)
2338 return codecvt_base::partial;
2339 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2340 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2341 }
2342 else if (wc < 0x010000)
2343 {
2344 if (to_end-to_nxt < 3)
2345 return codecvt_base::partial;
2346 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2347 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2348 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2349 }
2350 else // if (wc < 0x110000)
2351 {
2352 if (to_end-to_nxt < 4)
2353 return codecvt_base::partial;
2354 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2355 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2356 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2357 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2358 }
2359 }
2360 return codecvt_base::ok;
2361}
2362
2363static
2364codecvt_base::result
2365utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2366 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2367 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2368{
2369 frm_nxt = frm;
2370 to_nxt = to;
2371 if (mode & consume_header)
2372 {
2373 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2374 frm_nxt[2] == 0xBF)
2375 frm_nxt += 3;
2376 }
2377 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2378 {
2379 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2380 if (c1 < 0x80)
2381 {
2382 if (c1 > Maxcode)
2383 return codecvt_base::error;
2384 *to_nxt = static_cast<uint32_t>(c1);
2385 ++frm_nxt;
2386 }
2387 else if (c1 < 0xC2)
2388 {
2389 return codecvt_base::error;
2390 }
2391 else if (c1 < 0xE0)
2392 {
2393 if (frm_end-frm_nxt < 2)
2394 return codecvt_base::partial;
2395 uint8_t c2 = frm_nxt[1];
2396 if ((c2 & 0xC0) != 0x80)
2397 return codecvt_base::error;
2398 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2399 | (c2 & 0x3F));
2400 if (t > Maxcode)
2401 return codecvt_base::error;
2402 *to_nxt = t;
2403 frm_nxt += 2;
2404 }
2405 else if (c1 < 0xF0)
2406 {
2407 if (frm_end-frm_nxt < 3)
2408 return codecvt_base::partial;
2409 uint8_t c2 = frm_nxt[1];
2410 uint8_t c3 = frm_nxt[2];
2411 switch (c1)
2412 {
2413 case 0xE0:
2414 if ((c2 & 0xE0) != 0xA0)
2415 return codecvt_base::error;
2416 break;
2417 case 0xED:
2418 if ((c2 & 0xE0) != 0x80)
2419 return codecvt_base::error;
2420 break;
2421 default:
2422 if ((c2 & 0xC0) != 0x80)
2423 return codecvt_base::error;
2424 break;
2425 }
2426 if ((c3 & 0xC0) != 0x80)
2427 return codecvt_base::error;
2428 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2429 | ((c2 & 0x3F) << 6)
2430 | (c3 & 0x3F));
2431 if (t > Maxcode)
2432 return codecvt_base::error;
2433 *to_nxt = t;
2434 frm_nxt += 3;
2435 }
2436 else if (c1 < 0xF5)
2437 {
2438 if (frm_end-frm_nxt < 4)
2439 return codecvt_base::partial;
2440 uint8_t c2 = frm_nxt[1];
2441 uint8_t c3 = frm_nxt[2];
2442 uint8_t c4 = frm_nxt[3];
2443 switch (c1)
2444 {
2445 case 0xF0:
2446 if (!(0x90 <= c2 && c2 <= 0xBF))
2447 return codecvt_base::error;
2448 break;
2449 case 0xF4:
2450 if ((c2 & 0xF0) != 0x80)
2451 return codecvt_base::error;
2452 break;
2453 default:
2454 if ((c2 & 0xC0) != 0x80)
2455 return codecvt_base::error;
2456 break;
2457 }
2458 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2459 return codecvt_base::error;
2460 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2461 | ((c2 & 0x3F) << 12)
2462 | ((c3 & 0x3F) << 6)
2463 | (c4 & 0x3F));
2464 if (t > Maxcode)
2465 return codecvt_base::error;
2466 *to_nxt = t;
2467 frm_nxt += 4;
2468 }
2469 else
2470 {
2471 return codecvt_base::error;
2472 }
2473 }
2474 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2475}
2476
2477static
2478int
2479utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2480 size_t mx, unsigned long Maxcode = 0x10FFFF,
2481 codecvt_mode mode = codecvt_mode(0))
2482{
2483 const uint8_t* frm_nxt = frm;
2484 if (mode & consume_header)
2485 {
2486 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2487 frm_nxt[2] == 0xBF)
2488 frm_nxt += 3;
2489 }
2490 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2491 {
2492 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2493 if (c1 < 0x80)
2494 {
2495 if (c1 > Maxcode)
2496 break;
2497 ++frm_nxt;
2498 }
2499 else if (c1 < 0xC2)
2500 {
2501 break;
2502 }
2503 else if (c1 < 0xE0)
2504 {
2505 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2506 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002507 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002508 break;
2509 frm_nxt += 2;
2510 }
2511 else if (c1 < 0xF0)
2512 {
2513 if (frm_end-frm_nxt < 3)
2514 break;
2515 uint8_t c2 = frm_nxt[1];
2516 uint8_t c3 = frm_nxt[2];
2517 switch (c1)
2518 {
2519 case 0xE0:
2520 if ((c2 & 0xE0) != 0xA0)
2521 return static_cast<int>(frm_nxt - frm);
2522 break;
2523 case 0xED:
2524 if ((c2 & 0xE0) != 0x80)
2525 return static_cast<int>(frm_nxt - frm);
2526 break;
2527 default:
2528 if ((c2 & 0xC0) != 0x80)
2529 return static_cast<int>(frm_nxt - frm);
2530 break;
2531 }
2532 if ((c3 & 0xC0) != 0x80)
2533 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002534 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002535 break;
2536 frm_nxt += 3;
2537 }
2538 else if (c1 < 0xF5)
2539 {
2540 if (frm_end-frm_nxt < 4)
2541 break;
2542 uint8_t c2 = frm_nxt[1];
2543 uint8_t c3 = frm_nxt[2];
2544 uint8_t c4 = frm_nxt[3];
2545 switch (c1)
2546 {
2547 case 0xF0:
2548 if (!(0x90 <= c2 && c2 <= 0xBF))
2549 return static_cast<int>(frm_nxt - frm);
2550 break;
2551 case 0xF4:
2552 if ((c2 & 0xF0) != 0x80)
2553 return static_cast<int>(frm_nxt - frm);
2554 break;
2555 default:
2556 if ((c2 & 0xC0) != 0x80)
2557 return static_cast<int>(frm_nxt - frm);
2558 break;
2559 }
2560 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2561 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002562 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2563 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002564 break;
2565 frm_nxt += 4;
2566 }
2567 else
2568 {
2569 break;
2570 }
2571 }
2572 return static_cast<int>(frm_nxt - frm);
2573}
2574
2575static
2576codecvt_base::result
2577ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2578 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2579 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2580{
2581 frm_nxt = frm;
2582 to_nxt = to;
2583 if (mode & generate_header)
2584 {
2585 if (to_end-to_nxt < 3)
2586 return codecvt_base::partial;
2587 *to_nxt++ = static_cast<uint8_t>(0xEF);
2588 *to_nxt++ = static_cast<uint8_t>(0xBB);
2589 *to_nxt++ = static_cast<uint8_t>(0xBF);
2590 }
2591 for (; frm_nxt < frm_end; ++frm_nxt)
2592 {
2593 uint16_t wc = *frm_nxt;
2594 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2595 return codecvt_base::error;
2596 if (wc < 0x0080)
2597 {
2598 if (to_end-to_nxt < 1)
2599 return codecvt_base::partial;
2600 *to_nxt++ = static_cast<uint8_t>(wc);
2601 }
2602 else if (wc < 0x0800)
2603 {
2604 if (to_end-to_nxt < 2)
2605 return codecvt_base::partial;
2606 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2607 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2608 }
2609 else // if (wc <= 0xFFFF)
2610 {
2611 if (to_end-to_nxt < 3)
2612 return codecvt_base::partial;
2613 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2614 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2615 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2616 }
2617 }
2618 return codecvt_base::ok;
2619}
2620
2621static
2622codecvt_base::result
2623utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2624 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2625 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2626{
2627 frm_nxt = frm;
2628 to_nxt = to;
2629 if (mode & consume_header)
2630 {
2631 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2632 frm_nxt[2] == 0xBF)
2633 frm_nxt += 3;
2634 }
2635 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2636 {
2637 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2638 if (c1 < 0x80)
2639 {
2640 if (c1 > Maxcode)
2641 return codecvt_base::error;
2642 *to_nxt = static_cast<uint16_t>(c1);
2643 ++frm_nxt;
2644 }
2645 else if (c1 < 0xC2)
2646 {
2647 return codecvt_base::error;
2648 }
2649 else if (c1 < 0xE0)
2650 {
2651 if (frm_end-frm_nxt < 2)
2652 return codecvt_base::partial;
2653 uint8_t c2 = frm_nxt[1];
2654 if ((c2 & 0xC0) != 0x80)
2655 return codecvt_base::error;
2656 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2657 | (c2 & 0x3F));
2658 if (t > Maxcode)
2659 return codecvt_base::error;
2660 *to_nxt = t;
2661 frm_nxt += 2;
2662 }
2663 else if (c1 < 0xF0)
2664 {
2665 if (frm_end-frm_nxt < 3)
2666 return codecvt_base::partial;
2667 uint8_t c2 = frm_nxt[1];
2668 uint8_t c3 = frm_nxt[2];
2669 switch (c1)
2670 {
2671 case 0xE0:
2672 if ((c2 & 0xE0) != 0xA0)
2673 return codecvt_base::error;
2674 break;
2675 case 0xED:
2676 if ((c2 & 0xE0) != 0x80)
2677 return codecvt_base::error;
2678 break;
2679 default:
2680 if ((c2 & 0xC0) != 0x80)
2681 return codecvt_base::error;
2682 break;
2683 }
2684 if ((c3 & 0xC0) != 0x80)
2685 return codecvt_base::error;
2686 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2687 | ((c2 & 0x3F) << 6)
2688 | (c3 & 0x3F));
2689 if (t > Maxcode)
2690 return codecvt_base::error;
2691 *to_nxt = t;
2692 frm_nxt += 3;
2693 }
2694 else
2695 {
2696 return codecvt_base::error;
2697 }
2698 }
2699 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2700}
2701
2702static
2703int
2704utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2705 size_t mx, unsigned long Maxcode = 0x10FFFF,
2706 codecvt_mode mode = codecvt_mode(0))
2707{
2708 const uint8_t* frm_nxt = frm;
2709 if (mode & consume_header)
2710 {
2711 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2712 frm_nxt[2] == 0xBF)
2713 frm_nxt += 3;
2714 }
2715 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2716 {
2717 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2718 if (c1 < 0x80)
2719 {
2720 if (c1 > Maxcode)
2721 break;
2722 ++frm_nxt;
2723 }
2724 else if (c1 < 0xC2)
2725 {
2726 break;
2727 }
2728 else if (c1 < 0xE0)
2729 {
2730 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2731 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002732 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002733 break;
2734 frm_nxt += 2;
2735 }
2736 else if (c1 < 0xF0)
2737 {
2738 if (frm_end-frm_nxt < 3)
2739 break;
2740 uint8_t c2 = frm_nxt[1];
2741 uint8_t c3 = frm_nxt[2];
2742 switch (c1)
2743 {
2744 case 0xE0:
2745 if ((c2 & 0xE0) != 0xA0)
2746 return static_cast<int>(frm_nxt - frm);
2747 break;
2748 case 0xED:
2749 if ((c2 & 0xE0) != 0x80)
2750 return static_cast<int>(frm_nxt - frm);
2751 break;
2752 default:
2753 if ((c2 & 0xC0) != 0x80)
2754 return static_cast<int>(frm_nxt - frm);
2755 break;
2756 }
2757 if ((c3 & 0xC0) != 0x80)
2758 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002759 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002760 break;
2761 frm_nxt += 3;
2762 }
2763 else
2764 {
2765 break;
2766 }
2767 }
2768 return static_cast<int>(frm_nxt - frm);
2769}
2770
2771static
2772codecvt_base::result
2773ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2774 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2775 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2776{
2777 frm_nxt = frm;
2778 to_nxt = to;
2779 if (mode & generate_header)
2780 {
2781 if (to_end-to_nxt < 2)
2782 return codecvt_base::partial;
2783 *to_nxt++ = static_cast<uint8_t>(0xFE);
2784 *to_nxt++ = static_cast<uint8_t>(0xFF);
2785 }
2786 for (; frm_nxt < frm_end; ++frm_nxt)
2787 {
2788 uint32_t wc = *frm_nxt;
2789 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2790 return codecvt_base::error;
2791 if (wc < 0x010000)
2792 {
2793 if (to_end-to_nxt < 2)
2794 return codecvt_base::partial;
2795 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2796 *to_nxt++ = static_cast<uint8_t>(wc);
2797 }
2798 else
2799 {
2800 if (to_end-to_nxt < 4)
2801 return codecvt_base::partial;
2802 uint16_t t = static_cast<uint16_t>(
2803 0xD800
2804 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2805 | ((wc & 0x00FC00) >> 10));
2806 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2807 *to_nxt++ = static_cast<uint8_t>(t);
2808 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2809 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2810 *to_nxt++ = static_cast<uint8_t>(t);
2811 }
2812 }
2813 return codecvt_base::ok;
2814}
2815
2816static
2817codecvt_base::result
2818utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2819 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2820 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2821{
2822 frm_nxt = frm;
2823 to_nxt = to;
2824 if (mode & consume_header)
2825 {
2826 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2827 frm_nxt += 2;
2828 }
2829 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2830 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002831 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002832 if ((c1 & 0xFC00) == 0xDC00)
2833 return codecvt_base::error;
2834 if ((c1 & 0xFC00) != 0xD800)
2835 {
2836 if (c1 > Maxcode)
2837 return codecvt_base::error;
2838 *to_nxt = static_cast<uint32_t>(c1);
2839 frm_nxt += 2;
2840 }
2841 else
2842 {
2843 if (frm_end-frm_nxt < 4)
2844 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002845 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002846 if ((c2 & 0xFC00) != 0xDC00)
2847 return codecvt_base::error;
2848 uint32_t t = static_cast<uint32_t>(
2849 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2850 | ((c1 & 0x003F) << 10)
2851 | (c2 & 0x03FF));
2852 if (t > Maxcode)
2853 return codecvt_base::error;
2854 *to_nxt = t;
2855 frm_nxt += 4;
2856 }
2857 }
2858 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2859}
2860
2861static
2862int
2863utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2864 size_t mx, unsigned long Maxcode = 0x10FFFF,
2865 codecvt_mode mode = codecvt_mode(0))
2866{
2867 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002868 if (mode & consume_header)
2869 {
2870 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2871 frm_nxt += 2;
2872 }
2873 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2874 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002875 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002876 if ((c1 & 0xFC00) == 0xDC00)
2877 break;
2878 if ((c1 & 0xFC00) != 0xD800)
2879 {
2880 if (c1 > Maxcode)
2881 break;
2882 frm_nxt += 2;
2883 }
2884 else
2885 {
2886 if (frm_end-frm_nxt < 4)
2887 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002888 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002889 if ((c2 & 0xFC00) != 0xDC00)
2890 break;
2891 uint32_t t = static_cast<uint32_t>(
2892 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2893 | ((c1 & 0x003F) << 10)
2894 | (c2 & 0x03FF));
2895 if (t > Maxcode)
2896 break;
2897 frm_nxt += 4;
2898 }
2899 }
2900 return static_cast<int>(frm_nxt - frm);
2901}
2902
2903static
2904codecvt_base::result
2905ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2906 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2907 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2908{
2909 frm_nxt = frm;
2910 to_nxt = to;
2911 if (mode & generate_header)
2912 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002913 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002914 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002915 *to_nxt++ = static_cast<uint8_t>(0xFF);
2916 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002917 }
2918 for (; frm_nxt < frm_end; ++frm_nxt)
2919 {
2920 uint32_t wc = *frm_nxt;
2921 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2922 return codecvt_base::error;
2923 if (wc < 0x010000)
2924 {
2925 if (to_end-to_nxt < 2)
2926 return codecvt_base::partial;
2927 *to_nxt++ = static_cast<uint8_t>(wc);
2928 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2929 }
2930 else
2931 {
2932 if (to_end-to_nxt < 4)
2933 return codecvt_base::partial;
2934 uint16_t t = static_cast<uint16_t>(
2935 0xD800
2936 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2937 | ((wc & 0x00FC00) >> 10));
2938 *to_nxt++ = static_cast<uint8_t>(t);
2939 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2940 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2941 *to_nxt++ = static_cast<uint8_t>(t);
2942 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2943 }
2944 }
2945 return codecvt_base::ok;
2946}
2947
2948static
2949codecvt_base::result
2950utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2951 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2952 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2953{
2954 frm_nxt = frm;
2955 to_nxt = to;
2956 if (mode & consume_header)
2957 {
2958 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2959 frm_nxt += 2;
2960 }
2961 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2962 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002963 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002964 if ((c1 & 0xFC00) == 0xDC00)
2965 return codecvt_base::error;
2966 if ((c1 & 0xFC00) != 0xD800)
2967 {
2968 if (c1 > Maxcode)
2969 return codecvt_base::error;
2970 *to_nxt = static_cast<uint32_t>(c1);
2971 frm_nxt += 2;
2972 }
2973 else
2974 {
2975 if (frm_end-frm_nxt < 4)
2976 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002977 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002978 if ((c2 & 0xFC00) != 0xDC00)
2979 return codecvt_base::error;
2980 uint32_t t = static_cast<uint32_t>(
2981 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2982 | ((c1 & 0x003F) << 10)
2983 | (c2 & 0x03FF));
2984 if (t > Maxcode)
2985 return codecvt_base::error;
2986 *to_nxt = t;
2987 frm_nxt += 4;
2988 }
2989 }
2990 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2991}
2992
2993static
2994int
2995utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2996 size_t mx, unsigned long Maxcode = 0x10FFFF,
2997 codecvt_mode mode = codecvt_mode(0))
2998{
2999 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003000 if (mode & consume_header)
3001 {
3002 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3003 frm_nxt += 2;
3004 }
3005 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3006 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003007 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003008 if ((c1 & 0xFC00) == 0xDC00)
3009 break;
3010 if ((c1 & 0xFC00) != 0xD800)
3011 {
3012 if (c1 > Maxcode)
3013 break;
3014 frm_nxt += 2;
3015 }
3016 else
3017 {
3018 if (frm_end-frm_nxt < 4)
3019 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00003020 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003021 if ((c2 & 0xFC00) != 0xDC00)
3022 break;
3023 uint32_t t = static_cast<uint32_t>(
3024 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3025 | ((c1 & 0x003F) << 10)
3026 | (c2 & 0x03FF));
3027 if (t > Maxcode)
3028 break;
3029 frm_nxt += 4;
3030 }
3031 }
3032 return static_cast<int>(frm_nxt - frm);
3033}
3034
3035static
3036codecvt_base::result
3037ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3038 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3039 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3040{
3041 frm_nxt = frm;
3042 to_nxt = to;
3043 if (mode & generate_header)
3044 {
3045 if (to_end-to_nxt < 2)
3046 return codecvt_base::partial;
3047 *to_nxt++ = static_cast<uint8_t>(0xFE);
3048 *to_nxt++ = static_cast<uint8_t>(0xFF);
3049 }
3050 for (; frm_nxt < frm_end; ++frm_nxt)
3051 {
3052 uint16_t wc = *frm_nxt;
3053 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3054 return codecvt_base::error;
3055 if (to_end-to_nxt < 2)
3056 return codecvt_base::partial;
3057 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3058 *to_nxt++ = static_cast<uint8_t>(wc);
3059 }
3060 return codecvt_base::ok;
3061}
3062
3063static
3064codecvt_base::result
3065utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3066 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3067 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3068{
3069 frm_nxt = frm;
3070 to_nxt = to;
3071 if (mode & consume_header)
3072 {
3073 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3074 frm_nxt += 2;
3075 }
3076 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3077 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003078 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003079 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3080 return codecvt_base::error;
3081 *to_nxt = c1;
3082 frm_nxt += 2;
3083 }
3084 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3085}
3086
3087static
3088int
3089utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3090 size_t mx, unsigned long Maxcode = 0x10FFFF,
3091 codecvt_mode mode = codecvt_mode(0))
3092{
3093 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003094 if (mode & consume_header)
3095 {
3096 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3097 frm_nxt += 2;
3098 }
3099 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3100 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003101 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003102 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3103 break;
3104 frm_nxt += 2;
3105 }
3106 return static_cast<int>(frm_nxt - frm);
3107}
3108
3109static
3110codecvt_base::result
3111ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3112 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3113 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3114{
3115 frm_nxt = frm;
3116 to_nxt = to;
3117 if (mode & generate_header)
3118 {
3119 if (to_end-to_nxt < 2)
3120 return codecvt_base::partial;
3121 *to_nxt++ = static_cast<uint8_t>(0xFF);
3122 *to_nxt++ = static_cast<uint8_t>(0xFE);
3123 }
3124 for (; frm_nxt < frm_end; ++frm_nxt)
3125 {
3126 uint16_t wc = *frm_nxt;
3127 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3128 return codecvt_base::error;
3129 if (to_end-to_nxt < 2)
3130 return codecvt_base::partial;
3131 *to_nxt++ = static_cast<uint8_t>(wc);
3132 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3133 }
3134 return codecvt_base::ok;
3135}
3136
3137static
3138codecvt_base::result
3139utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3140 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3141 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3142{
3143 frm_nxt = frm;
3144 to_nxt = to;
3145 if (mode & consume_header)
3146 {
3147 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3148 frm_nxt += 2;
3149 }
3150 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3151 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003152 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003153 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3154 return codecvt_base::error;
3155 *to_nxt = c1;
3156 frm_nxt += 2;
3157 }
3158 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3159}
3160
3161static
3162int
3163utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3164 size_t mx, unsigned long Maxcode = 0x10FFFF,
3165 codecvt_mode mode = codecvt_mode(0))
3166{
3167 const uint8_t* frm_nxt = frm;
3168 frm_nxt = frm;
3169 if (mode & consume_header)
3170 {
3171 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3172 frm_nxt += 2;
3173 }
3174 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3175 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003176 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003177 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3178 break;
3179 frm_nxt += 2;
3180 }
3181 return static_cast<int>(frm_nxt - frm);
3182}
3183
Howard Hinnantc51e1022010-05-11 19:42:16 +00003184// template <> class codecvt<char16_t, char, mbstate_t>
3185
Howard Hinnantffb308e2010-08-22 00:03:27 +00003186locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003187
3188codecvt<char16_t, char, mbstate_t>::~codecvt()
3189{
3190}
3191
3192codecvt<char16_t, char, mbstate_t>::result
3193codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003194 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003195 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3196{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003197 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3198 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3199 const uint16_t* _frm_nxt = _frm;
3200 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3201 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3202 uint8_t* _to_nxt = _to;
3203 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3204 frm_nxt = frm + (_frm_nxt - _frm);
3205 to_nxt = to + (_to_nxt - _to);
3206 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003207}
3208
3209codecvt<char16_t, char, mbstate_t>::result
3210codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003211 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003212 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3213{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003214 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3215 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3216 const uint8_t* _frm_nxt = _frm;
3217 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3218 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3219 uint16_t* _to_nxt = _to;
3220 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3221 frm_nxt = frm + (_frm_nxt - _frm);
3222 to_nxt = to + (_to_nxt - _to);
3223 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003224}
3225
3226codecvt<char16_t, char, mbstate_t>::result
3227codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3228 extern_type* to, extern_type*, extern_type*& to_nxt) const
3229{
3230 to_nxt = to;
3231 return noconv;
3232}
3233
3234int
Louis Dionne65358e12021-03-01 12:09:45 -05003235codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003236{
3237 return 0;
3238}
3239
3240bool
Louis Dionne65358e12021-03-01 12:09:45 -05003241codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003242{
3243 return false;
3244}
3245
3246int
3247codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3248 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3249{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003250 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3251 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3252 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003253}
3254
3255int
Louis Dionne65358e12021-03-01 12:09:45 -05003256codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003257{
3258 return 4;
3259}
3260
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003261#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003262
3263// template <> class codecvt<char16_t, char8_t, mbstate_t>
3264
3265locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3266
3267codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3268{
3269}
3270
3271codecvt<char16_t, char8_t, mbstate_t>::result
3272codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3273 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3274 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3275{
3276 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3277 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3278 const uint16_t* _frm_nxt = _frm;
3279 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3280 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3281 uint8_t* _to_nxt = _to;
3282 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3283 frm_nxt = frm + (_frm_nxt - _frm);
3284 to_nxt = to + (_to_nxt - _to);
3285 return r;
3286}
3287
3288codecvt<char16_t, char8_t, mbstate_t>::result
3289codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3290 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3291 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3292{
3293 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3294 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3295 const uint8_t* _frm_nxt = _frm;
3296 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3297 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3298 uint16_t* _to_nxt = _to;
3299 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3300 frm_nxt = frm + (_frm_nxt - _frm);
3301 to_nxt = to + (_to_nxt - _to);
3302 return r;
3303}
3304
3305codecvt<char16_t, char8_t, mbstate_t>::result
3306codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3307 extern_type* to, extern_type*, extern_type*& to_nxt) const
3308{
3309 to_nxt = to;
3310 return noconv;
3311}
3312
3313int
Louis Dionne65358e12021-03-01 12:09:45 -05003314codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003315{
3316 return 0;
3317}
3318
3319bool
Louis Dionne65358e12021-03-01 12:09:45 -05003320codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003321{
3322 return false;
3323}
3324
3325int
3326codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3327 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3328{
3329 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3330 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3331 return utf8_to_utf16_length(_frm, _frm_end, mx);
3332}
3333
3334int
Louis Dionne65358e12021-03-01 12:09:45 -05003335codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003336{
3337 return 4;
3338}
3339
3340#endif
3341
Howard Hinnantc51e1022010-05-11 19:42:16 +00003342// template <> class codecvt<char32_t, char, mbstate_t>
3343
Howard Hinnantffb308e2010-08-22 00:03:27 +00003344locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003345
3346codecvt<char32_t, char, mbstate_t>::~codecvt()
3347{
3348}
3349
3350codecvt<char32_t, char, mbstate_t>::result
3351codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003352 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003353 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3354{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003355 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3356 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3357 const uint32_t* _frm_nxt = _frm;
3358 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3359 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3360 uint8_t* _to_nxt = _to;
3361 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3362 frm_nxt = frm + (_frm_nxt - _frm);
3363 to_nxt = to + (_to_nxt - _to);
3364 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003365}
3366
3367codecvt<char32_t, char, mbstate_t>::result
3368codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003369 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003370 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3371{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003372 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3373 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3374 const uint8_t* _frm_nxt = _frm;
3375 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3376 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3377 uint32_t* _to_nxt = _to;
3378 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3379 frm_nxt = frm + (_frm_nxt - _frm);
3380 to_nxt = to + (_to_nxt - _to);
3381 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003382}
3383
3384codecvt<char32_t, char, mbstate_t>::result
3385codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3386 extern_type* to, extern_type*, extern_type*& to_nxt) const
3387{
3388 to_nxt = to;
3389 return noconv;
3390}
3391
3392int
Louis Dionne65358e12021-03-01 12:09:45 -05003393codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003394{
3395 return 0;
3396}
3397
3398bool
Louis Dionne65358e12021-03-01 12:09:45 -05003399codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003400{
3401 return false;
3402}
3403
3404int
3405codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3406 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3407{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003408 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3409 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3410 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003411}
3412
3413int
Louis Dionne65358e12021-03-01 12:09:45 -05003414codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003415{
3416 return 4;
3417}
3418
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003419#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003420
3421// template <> class codecvt<char32_t, char8_t, mbstate_t>
3422
3423locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3424
3425codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3426{
3427}
3428
3429codecvt<char32_t, char8_t, mbstate_t>::result
3430codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3431 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3432 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3433{
3434 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3435 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3436 const uint32_t* _frm_nxt = _frm;
3437 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3438 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3439 uint8_t* _to_nxt = _to;
3440 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3441 frm_nxt = frm + (_frm_nxt - _frm);
3442 to_nxt = to + (_to_nxt - _to);
3443 return r;
3444}
3445
3446codecvt<char32_t, char8_t, mbstate_t>::result
3447codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3448 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3449 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3450{
3451 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3452 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3453 const uint8_t* _frm_nxt = _frm;
3454 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3455 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3456 uint32_t* _to_nxt = _to;
3457 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3458 frm_nxt = frm + (_frm_nxt - _frm);
3459 to_nxt = to + (_to_nxt - _to);
3460 return r;
3461}
3462
3463codecvt<char32_t, char8_t, mbstate_t>::result
3464codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3465 extern_type* to, extern_type*, extern_type*& to_nxt) const
3466{
3467 to_nxt = to;
3468 return noconv;
3469}
3470
3471int
Louis Dionne65358e12021-03-01 12:09:45 -05003472codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003473{
3474 return 0;
3475}
3476
3477bool
Louis Dionne65358e12021-03-01 12:09:45 -05003478codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003479{
3480 return false;
3481}
3482
3483int
3484codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3485 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3486{
3487 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3488 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3489 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3490}
3491
3492int
Louis Dionne65358e12021-03-01 12:09:45 -05003493codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003494{
3495 return 4;
3496}
3497
3498#endif
3499
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003500// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003501
Louis Dionne89258142021-08-23 15:32:36 -04003502#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003503__codecvt_utf8<wchar_t>::result
3504__codecvt_utf8<wchar_t>::do_out(state_type&,
3505 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003506 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3507{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003508#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003509 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3510 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3511 const uint16_t* _frm_nxt = _frm;
3512#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003513 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3514 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3515 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003516#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003517 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3518 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3519 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003520#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003521 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3522 _Maxcode_, _Mode_);
3523#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003524 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3525 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003526#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003527 frm_nxt = frm + (_frm_nxt - _frm);
3528 to_nxt = to + (_to_nxt - _to);
3529 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003530}
3531
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003532__codecvt_utf8<wchar_t>::result
3533__codecvt_utf8<wchar_t>::do_in(state_type&,
3534 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003535 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3536{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003537 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3538 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3539 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003540#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003541 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3542 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3543 uint16_t* _to_nxt = _to;
3544 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3545 _Maxcode_, _Mode_);
3546#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003547 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3548 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3549 uint32_t* _to_nxt = _to;
3550 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3551 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003552#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003553 frm_nxt = frm + (_frm_nxt - _frm);
3554 to_nxt = to + (_to_nxt - _to);
3555 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003556}
3557
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003558__codecvt_utf8<wchar_t>::result
3559__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003560 extern_type* to, extern_type*, extern_type*& to_nxt) const
3561{
3562 to_nxt = to;
3563 return noconv;
3564}
3565
3566int
Louis Dionne65358e12021-03-01 12:09:45 -05003567__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003568{
3569 return 0;
3570}
3571
3572bool
Louis Dionne65358e12021-03-01 12:09:45 -05003573__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003574{
3575 return false;
3576}
3577
3578int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003579__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003580 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3581{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003582 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3583 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003584#if defined(_LIBCPP_SHORT_WCHAR)
3585 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3586#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003587 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003588#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003589}
3590
3591int
Louis Dionne65358e12021-03-01 12:09:45 -05003592__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003593{
Xing Xue50b0eb42021-09-09 16:20:36 -04003594#if defined(_LIBCPP_SHORT_WCHAR)
3595 if (_Mode_ & consume_header)
3596 return 6;
3597 return 3;
3598#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003599 if (_Mode_ & consume_header)
3600 return 7;
3601 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003602#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003603}
Louis Dionne89258142021-08-23 15:32:36 -04003604#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003605
3606// __codecvt_utf8<char16_t>
3607
3608__codecvt_utf8<char16_t>::result
3609__codecvt_utf8<char16_t>::do_out(state_type&,
3610 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3611 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3612{
3613 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3614 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3615 const uint16_t* _frm_nxt = _frm;
3616 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3617 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3618 uint8_t* _to_nxt = _to;
3619 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3620 _Maxcode_, _Mode_);
3621 frm_nxt = frm + (_frm_nxt - _frm);
3622 to_nxt = to + (_to_nxt - _to);
3623 return r;
3624}
3625
3626__codecvt_utf8<char16_t>::result
3627__codecvt_utf8<char16_t>::do_in(state_type&,
3628 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3629 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3630{
3631 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3632 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3633 const uint8_t* _frm_nxt = _frm;
3634 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3635 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3636 uint16_t* _to_nxt = _to;
3637 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3638 _Maxcode_, _Mode_);
3639 frm_nxt = frm + (_frm_nxt - _frm);
3640 to_nxt = to + (_to_nxt - _to);
3641 return r;
3642}
3643
3644__codecvt_utf8<char16_t>::result
3645__codecvt_utf8<char16_t>::do_unshift(state_type&,
3646 extern_type* to, extern_type*, extern_type*& to_nxt) const
3647{
3648 to_nxt = to;
3649 return noconv;
3650}
3651
3652int
Louis Dionne65358e12021-03-01 12:09:45 -05003653__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003654{
3655 return 0;
3656}
3657
3658bool
Louis Dionne65358e12021-03-01 12:09:45 -05003659__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003660{
3661 return false;
3662}
3663
3664int
3665__codecvt_utf8<char16_t>::do_length(state_type&,
3666 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3667{
3668 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3669 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3670 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3671}
3672
3673int
Louis Dionne65358e12021-03-01 12:09:45 -05003674__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003675{
3676 if (_Mode_ & consume_header)
3677 return 6;
3678 return 3;
3679}
3680
3681// __codecvt_utf8<char32_t>
3682
3683__codecvt_utf8<char32_t>::result
3684__codecvt_utf8<char32_t>::do_out(state_type&,
3685 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3686 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3687{
3688 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3689 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3690 const uint32_t* _frm_nxt = _frm;
3691 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3692 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3693 uint8_t* _to_nxt = _to;
3694 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3695 _Maxcode_, _Mode_);
3696 frm_nxt = frm + (_frm_nxt - _frm);
3697 to_nxt = to + (_to_nxt - _to);
3698 return r;
3699}
3700
3701__codecvt_utf8<char32_t>::result
3702__codecvt_utf8<char32_t>::do_in(state_type&,
3703 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3704 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3705{
3706 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3707 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3708 const uint8_t* _frm_nxt = _frm;
3709 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3710 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3711 uint32_t* _to_nxt = _to;
3712 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3713 _Maxcode_, _Mode_);
3714 frm_nxt = frm + (_frm_nxt - _frm);
3715 to_nxt = to + (_to_nxt - _to);
3716 return r;
3717}
3718
3719__codecvt_utf8<char32_t>::result
3720__codecvt_utf8<char32_t>::do_unshift(state_type&,
3721 extern_type* to, extern_type*, extern_type*& to_nxt) const
3722{
3723 to_nxt = to;
3724 return noconv;
3725}
3726
3727int
Louis Dionne65358e12021-03-01 12:09:45 -05003728__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003729{
3730 return 0;
3731}
3732
3733bool
Louis Dionne65358e12021-03-01 12:09:45 -05003734__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003735{
3736 return false;
3737}
3738
3739int
3740__codecvt_utf8<char32_t>::do_length(state_type&,
3741 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3742{
3743 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3744 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3745 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3746}
3747
3748int
Louis Dionne65358e12021-03-01 12:09:45 -05003749__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003750{
3751 if (_Mode_ & consume_header)
3752 return 7;
3753 return 4;
3754}
3755
3756// __codecvt_utf16<wchar_t, false>
3757
Louis Dionne89258142021-08-23 15:32:36 -04003758#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003759__codecvt_utf16<wchar_t, false>::result
3760__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3761 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3762 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3763{
Xing Xue50b0eb42021-09-09 16:20:36 -04003764#if defined(_LIBCPP_SHORT_WCHAR)
3765 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3766 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3767 const uint16_t* _frm_nxt = _frm;
3768#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003769 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3770 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3771 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003772#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003773 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3774 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3775 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003776#if defined(_LIBCPP_SHORT_WCHAR)
3777 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3778 _Maxcode_, _Mode_);
3779#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003780 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3781 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003782#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003783 frm_nxt = frm + (_frm_nxt - _frm);
3784 to_nxt = to + (_to_nxt - _to);
3785 return r;
3786}
3787
3788__codecvt_utf16<wchar_t, false>::result
3789__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3790 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3791 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3792{
3793 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3794 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3795 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003796#if defined(_LIBCPP_SHORT_WCHAR)
3797 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3798 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3799 uint16_t* _to_nxt = _to;
3800 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3801 _Maxcode_, _Mode_);
3802#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003803 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3804 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3805 uint32_t* _to_nxt = _to;
3806 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3807 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003808#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003809 frm_nxt = frm + (_frm_nxt - _frm);
3810 to_nxt = to + (_to_nxt - _to);
3811 return r;
3812}
3813
3814__codecvt_utf16<wchar_t, false>::result
3815__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3816 extern_type* to, extern_type*, extern_type*& to_nxt) const
3817{
3818 to_nxt = to;
3819 return noconv;
3820}
3821
3822int
Louis Dionne65358e12021-03-01 12:09:45 -05003823__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003824{
3825 return 0;
3826}
3827
3828bool
Louis Dionne65358e12021-03-01 12:09:45 -05003829__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003830{
3831 return false;
3832}
3833
3834int
3835__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3836 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3837{
3838 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3839 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003840#if defined(_LIBCPP_SHORT_WCHAR)
3841 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3842#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003843 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003844#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003845}
3846
3847int
Louis Dionne65358e12021-03-01 12:09:45 -05003848__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003849{
Xing Xue50b0eb42021-09-09 16:20:36 -04003850#if defined(_LIBCPP_SHORT_WCHAR)
3851 if (_Mode_ & consume_header)
3852 return 4;
3853 return 2;
3854#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003855 if (_Mode_ & consume_header)
3856 return 6;
3857 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003858#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003859}
3860
3861// __codecvt_utf16<wchar_t, true>
3862
3863__codecvt_utf16<wchar_t, true>::result
3864__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3865 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3866 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3867{
Xing Xue50b0eb42021-09-09 16:20:36 -04003868#if defined(_LIBCPP_SHORT_WCHAR)
3869 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3870 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3871 const uint16_t* _frm_nxt = _frm;
3872#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003873 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3874 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3875 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003876#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003877 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3878 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3879 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003880#if defined(_LIBCPP_SHORT_WCHAR)
3881 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3882 _Maxcode_, _Mode_);
3883#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003884 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3885 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003886#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003887 frm_nxt = frm + (_frm_nxt - _frm);
3888 to_nxt = to + (_to_nxt - _to);
3889 return r;
3890}
3891
3892__codecvt_utf16<wchar_t, true>::result
3893__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3894 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3895 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3896{
3897 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3898 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3899 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003900#if defined(_LIBCPP_SHORT_WCHAR)
3901 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3902 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3903 uint16_t* _to_nxt = _to;
3904 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3905 _Maxcode_, _Mode_);
3906#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003907 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3908 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3909 uint32_t* _to_nxt = _to;
3910 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3911 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003912#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003913 frm_nxt = frm + (_frm_nxt - _frm);
3914 to_nxt = to + (_to_nxt - _to);
3915 return r;
3916}
3917
3918__codecvt_utf16<wchar_t, true>::result
3919__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3920 extern_type* to, extern_type*, extern_type*& to_nxt) const
3921{
3922 to_nxt = to;
3923 return noconv;
3924}
3925
3926int
Louis Dionne65358e12021-03-01 12:09:45 -05003927__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003928{
3929 return 0;
3930}
3931
3932bool
Louis Dionne65358e12021-03-01 12:09:45 -05003933__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003934{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003935 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003936}
3937
3938int
3939__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3940 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3941{
3942 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3943 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003944#if defined(_LIBCPP_SHORT_WCHAR)
3945 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3946#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003947 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003948#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003949}
3950
3951int
Louis Dionne65358e12021-03-01 12:09:45 -05003952__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003953{
Xing Xue50b0eb42021-09-09 16:20:36 -04003954#if defined(_LIBCPP_SHORT_WCHAR)
3955 if (_Mode_ & consume_header)
3956 return 4;
3957 return 2;
3958#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003959 if (_Mode_ & consume_header)
3960 return 6;
3961 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003962#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003963}
Louis Dionne89258142021-08-23 15:32:36 -04003964#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003965
3966// __codecvt_utf16<char16_t, false>
3967
3968__codecvt_utf16<char16_t, false>::result
3969__codecvt_utf16<char16_t, false>::do_out(state_type&,
3970 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3971 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3972{
3973 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3974 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3975 const uint16_t* _frm_nxt = _frm;
3976 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3977 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3978 uint8_t* _to_nxt = _to;
3979 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3980 _Maxcode_, _Mode_);
3981 frm_nxt = frm + (_frm_nxt - _frm);
3982 to_nxt = to + (_to_nxt - _to);
3983 return r;
3984}
3985
3986__codecvt_utf16<char16_t, false>::result
3987__codecvt_utf16<char16_t, false>::do_in(state_type&,
3988 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3989 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3990{
3991 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3992 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3993 const uint8_t* _frm_nxt = _frm;
3994 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3995 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3996 uint16_t* _to_nxt = _to;
3997 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3998 _Maxcode_, _Mode_);
3999 frm_nxt = frm + (_frm_nxt - _frm);
4000 to_nxt = to + (_to_nxt - _to);
4001 return r;
4002}
4003
4004__codecvt_utf16<char16_t, false>::result
4005__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4006 extern_type* to, extern_type*, extern_type*& to_nxt) const
4007{
4008 to_nxt = to;
4009 return noconv;
4010}
4011
4012int
Louis Dionne65358e12021-03-01 12:09:45 -05004013__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004014{
4015 return 0;
4016}
4017
4018bool
Louis Dionne65358e12021-03-01 12:09:45 -05004019__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004020{
4021 return false;
4022}
4023
4024int
4025__codecvt_utf16<char16_t, false>::do_length(state_type&,
4026 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4027{
4028 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4029 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4030 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4031}
4032
4033int
Louis Dionne65358e12021-03-01 12:09:45 -05004034__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004035{
4036 if (_Mode_ & consume_header)
4037 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004038 return 2;
4039}
4040
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004041// __codecvt_utf16<char16_t, true>
4042
4043__codecvt_utf16<char16_t, true>::result
4044__codecvt_utf16<char16_t, true>::do_out(state_type&,
4045 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4046 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4047{
4048 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4049 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4050 const uint16_t* _frm_nxt = _frm;
4051 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4052 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4053 uint8_t* _to_nxt = _to;
4054 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4055 _Maxcode_, _Mode_);
4056 frm_nxt = frm + (_frm_nxt - _frm);
4057 to_nxt = to + (_to_nxt - _to);
4058 return r;
4059}
4060
4061__codecvt_utf16<char16_t, true>::result
4062__codecvt_utf16<char16_t, true>::do_in(state_type&,
4063 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4064 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4065{
4066 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4067 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4068 const uint8_t* _frm_nxt = _frm;
4069 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4070 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4071 uint16_t* _to_nxt = _to;
4072 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4073 _Maxcode_, _Mode_);
4074 frm_nxt = frm + (_frm_nxt - _frm);
4075 to_nxt = to + (_to_nxt - _to);
4076 return r;
4077}
4078
4079__codecvt_utf16<char16_t, true>::result
4080__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4081 extern_type* to, extern_type*, extern_type*& to_nxt) const
4082{
4083 to_nxt = to;
4084 return noconv;
4085}
4086
4087int
Louis Dionne65358e12021-03-01 12:09:45 -05004088__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004089{
4090 return 0;
4091}
4092
4093bool
Louis Dionne65358e12021-03-01 12:09:45 -05004094__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004095{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004096 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004097}
4098
4099int
4100__codecvt_utf16<char16_t, true>::do_length(state_type&,
4101 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4102{
4103 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4104 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4105 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4106}
4107
4108int
Louis Dionne65358e12021-03-01 12:09:45 -05004109__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004110{
4111 if (_Mode_ & consume_header)
4112 return 4;
4113 return 2;
4114}
4115
4116// __codecvt_utf16<char32_t, false>
4117
4118__codecvt_utf16<char32_t, false>::result
4119__codecvt_utf16<char32_t, false>::do_out(state_type&,
4120 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4121 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4122{
4123 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4124 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4125 const uint32_t* _frm_nxt = _frm;
4126 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4127 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4128 uint8_t* _to_nxt = _to;
4129 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4130 _Maxcode_, _Mode_);
4131 frm_nxt = frm + (_frm_nxt - _frm);
4132 to_nxt = to + (_to_nxt - _to);
4133 return r;
4134}
4135
4136__codecvt_utf16<char32_t, false>::result
4137__codecvt_utf16<char32_t, false>::do_in(state_type&,
4138 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4139 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4140{
4141 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4142 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4143 const uint8_t* _frm_nxt = _frm;
4144 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4145 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4146 uint32_t* _to_nxt = _to;
4147 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4148 _Maxcode_, _Mode_);
4149 frm_nxt = frm + (_frm_nxt - _frm);
4150 to_nxt = to + (_to_nxt - _to);
4151 return r;
4152}
4153
4154__codecvt_utf16<char32_t, false>::result
4155__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4156 extern_type* to, extern_type*, extern_type*& to_nxt) const
4157{
4158 to_nxt = to;
4159 return noconv;
4160}
4161
4162int
Louis Dionne65358e12021-03-01 12:09:45 -05004163__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004164{
4165 return 0;
4166}
4167
4168bool
Louis Dionne65358e12021-03-01 12:09:45 -05004169__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004170{
4171 return false;
4172}
4173
4174int
4175__codecvt_utf16<char32_t, false>::do_length(state_type&,
4176 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4177{
4178 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4179 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4180 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4181}
4182
4183int
Louis Dionne65358e12021-03-01 12:09:45 -05004184__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004185{
4186 if (_Mode_ & consume_header)
4187 return 6;
4188 return 4;
4189}
4190
4191// __codecvt_utf16<char32_t, true>
4192
4193__codecvt_utf16<char32_t, true>::result
4194__codecvt_utf16<char32_t, true>::do_out(state_type&,
4195 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4196 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4197{
4198 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4199 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4200 const uint32_t* _frm_nxt = _frm;
4201 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4202 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4203 uint8_t* _to_nxt = _to;
4204 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4205 _Maxcode_, _Mode_);
4206 frm_nxt = frm + (_frm_nxt - _frm);
4207 to_nxt = to + (_to_nxt - _to);
4208 return r;
4209}
4210
4211__codecvt_utf16<char32_t, true>::result
4212__codecvt_utf16<char32_t, true>::do_in(state_type&,
4213 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4214 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4215{
4216 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4217 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4218 const uint8_t* _frm_nxt = _frm;
4219 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4220 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4221 uint32_t* _to_nxt = _to;
4222 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4223 _Maxcode_, _Mode_);
4224 frm_nxt = frm + (_frm_nxt - _frm);
4225 to_nxt = to + (_to_nxt - _to);
4226 return r;
4227}
4228
4229__codecvt_utf16<char32_t, true>::result
4230__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4231 extern_type* to, extern_type*, extern_type*& to_nxt) const
4232{
4233 to_nxt = to;
4234 return noconv;
4235}
4236
4237int
Louis Dionne65358e12021-03-01 12:09:45 -05004238__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004239{
4240 return 0;
4241}
4242
4243bool
Louis Dionne65358e12021-03-01 12:09:45 -05004244__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004245{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004246 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004247}
4248
4249int
4250__codecvt_utf16<char32_t, true>::do_length(state_type&,
4251 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4252{
4253 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4254 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4255 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4256}
4257
4258int
Louis Dionne65358e12021-03-01 12:09:45 -05004259__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004260{
4261 if (_Mode_ & consume_header)
4262 return 6;
4263 return 4;
4264}
4265
4266// __codecvt_utf8_utf16<wchar_t>
4267
Louis Dionne89258142021-08-23 15:32:36 -04004268#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004269__codecvt_utf8_utf16<wchar_t>::result
4270__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4271 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4272 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4273{
Xing Xue50b0eb42021-09-09 16:20:36 -04004274#if defined(_LIBCPP_SHORT_WCHAR)
4275 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4276 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4277 const uint16_t* _frm_nxt = _frm;
4278#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004279 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4280 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4281 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004282#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004283 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4284 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4285 uint8_t* _to_nxt = _to;
4286 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4287 _Maxcode_, _Mode_);
4288 frm_nxt = frm + (_frm_nxt - _frm);
4289 to_nxt = to + (_to_nxt - _to);
4290 return r;
4291}
4292
4293__codecvt_utf8_utf16<wchar_t>::result
4294__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4295 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4296 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4297{
4298 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4299 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4300 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004301#if defined(_LIBCPP_SHORT_WCHAR)
4302 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4303 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4304 uint16_t* _to_nxt = _to;
4305#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004306 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4307 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4308 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004309#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004310 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4311 _Maxcode_, _Mode_);
4312 frm_nxt = frm + (_frm_nxt - _frm);
4313 to_nxt = to + (_to_nxt - _to);
4314 return r;
4315}
4316
4317__codecvt_utf8_utf16<wchar_t>::result
4318__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4319 extern_type* to, extern_type*, extern_type*& to_nxt) const
4320{
4321 to_nxt = to;
4322 return noconv;
4323}
4324
4325int
Louis Dionne65358e12021-03-01 12:09:45 -05004326__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004327{
4328 return 0;
4329}
4330
4331bool
Louis Dionne65358e12021-03-01 12:09:45 -05004332__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004333{
4334 return false;
4335}
4336
4337int
4338__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4339 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4340{
4341 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4342 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4343 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4344}
4345
4346int
Louis Dionne65358e12021-03-01 12:09:45 -05004347__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004348{
4349 if (_Mode_ & consume_header)
4350 return 7;
4351 return 4;
4352}
Louis Dionne89258142021-08-23 15:32:36 -04004353#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004354
4355// __codecvt_utf8_utf16<char16_t>
4356
4357__codecvt_utf8_utf16<char16_t>::result
4358__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4359 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4360 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4361{
4362 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4363 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4364 const uint16_t* _frm_nxt = _frm;
4365 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4366 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4367 uint8_t* _to_nxt = _to;
4368 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4369 _Maxcode_, _Mode_);
4370 frm_nxt = frm + (_frm_nxt - _frm);
4371 to_nxt = to + (_to_nxt - _to);
4372 return r;
4373}
4374
4375__codecvt_utf8_utf16<char16_t>::result
4376__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4377 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4378 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4379{
4380 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4381 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4382 const uint8_t* _frm_nxt = _frm;
4383 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4384 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4385 uint16_t* _to_nxt = _to;
4386 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4387 _Maxcode_, _Mode_);
4388 frm_nxt = frm + (_frm_nxt - _frm);
4389 to_nxt = to + (_to_nxt - _to);
4390 return r;
4391}
4392
4393__codecvt_utf8_utf16<char16_t>::result
4394__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4395 extern_type* to, extern_type*, extern_type*& to_nxt) const
4396{
4397 to_nxt = to;
4398 return noconv;
4399}
4400
4401int
Louis Dionne65358e12021-03-01 12:09:45 -05004402__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004403{
4404 return 0;
4405}
4406
4407bool
Louis Dionne65358e12021-03-01 12:09:45 -05004408__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004409{
4410 return false;
4411}
4412
4413int
4414__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4415 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4416{
4417 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4418 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4419 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4420}
4421
4422int
Louis Dionne65358e12021-03-01 12:09:45 -05004423__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004424{
4425 if (_Mode_ & consume_header)
4426 return 7;
4427 return 4;
4428}
4429
4430// __codecvt_utf8_utf16<char32_t>
4431
4432__codecvt_utf8_utf16<char32_t>::result
4433__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4434 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4435 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4436{
4437 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4438 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4439 const uint32_t* _frm_nxt = _frm;
4440 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4441 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4442 uint8_t* _to_nxt = _to;
4443 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4444 _Maxcode_, _Mode_);
4445 frm_nxt = frm + (_frm_nxt - _frm);
4446 to_nxt = to + (_to_nxt - _to);
4447 return r;
4448}
4449
4450__codecvt_utf8_utf16<char32_t>::result
4451__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4452 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4453 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4454{
4455 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4456 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4457 const uint8_t* _frm_nxt = _frm;
4458 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4459 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4460 uint32_t* _to_nxt = _to;
4461 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4462 _Maxcode_, _Mode_);
4463 frm_nxt = frm + (_frm_nxt - _frm);
4464 to_nxt = to + (_to_nxt - _to);
4465 return r;
4466}
4467
4468__codecvt_utf8_utf16<char32_t>::result
4469__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4470 extern_type* to, extern_type*, extern_type*& to_nxt) const
4471{
4472 to_nxt = to;
4473 return noconv;
4474}
4475
4476int
Louis Dionne65358e12021-03-01 12:09:45 -05004477__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004478{
4479 return 0;
4480}
4481
4482bool
Louis Dionne65358e12021-03-01 12:09:45 -05004483__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004484{
4485 return false;
4486}
4487
4488int
4489__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4490 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4491{
4492 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4493 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4494 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4495}
4496
4497int
Louis Dionne65358e12021-03-01 12:09:45 -05004498__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004499{
4500 if (_Mode_ & consume_header)
4501 return 7;
4502 return 4;
4503}
4504
Howard Hinnantc51e1022010-05-11 19:42:16 +00004505// __narrow_to_utf8<16>
4506
4507__narrow_to_utf8<16>::~__narrow_to_utf8()
4508{
4509}
4510
4511// __narrow_to_utf8<32>
4512
4513__narrow_to_utf8<32>::~__narrow_to_utf8()
4514{
4515}
4516
4517// __widen_from_utf8<16>
4518
4519__widen_from_utf8<16>::~__widen_from_utf8()
4520{
4521}
4522
4523// __widen_from_utf8<32>
4524
4525__widen_from_utf8<32>::~__widen_from_utf8()
4526{
4527}
4528
Louis Dionne89258142021-08-23 15:32:36 -04004529#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004530static bool checked_string_to_wchar_convert(wchar_t& dest,
4531 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004532 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004533 if (*ptr == '\0')
4534 return false;
4535 mbstate_t mb = {};
4536 wchar_t out;
4537 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4538 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4539 return false;
4540 }
4541 dest = out;
4542 return true;
4543}
Louis Dionne89258142021-08-23 15:32:36 -04004544#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004545
Mark de Weverffed1402021-11-03 19:25:20 +01004546#ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4547static bool is_narrow_non_breaking_space(const char* ptr) {
4548 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4549 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4550}
4551
4552static bool is_non_breaking_space(const char* ptr) {
4553 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4554 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4555}
4556#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4557
Eric Fiselierbf945a22016-12-11 00:20:59 +00004558static bool checked_string_to_char_convert(char& dest,
4559 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004560 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004561 if (*ptr == '\0')
4562 return false;
4563 if (!ptr[1]) {
4564 dest = *ptr;
4565 return true;
4566 }
Louis Dionne89258142021-08-23 15:32:36 -04004567
4568#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004569 // First convert the MBS into a wide char then attempt to narrow it using
4570 // wctob_l.
4571 wchar_t wout;
4572 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4573 return false;
4574 int res;
4575 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4576 dest = res;
4577 return true;
4578 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004579 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004580 // translate into a different single byte.
4581 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004582 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004583 case L'\u00A0': // non-breaking space
4584 dest = ' ';
4585 return true;
4586 default:
4587 return false;
4588 }
Louis Dionne89258142021-08-23 15:32:36 -04004589#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverffed1402021-11-03 19:25:20 +01004590 // FIXME: Work around specific multibyte sequences that we can reasonably
4591 // translate into a different single byte.
4592 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4593 dest = ' ';
4594 return true;
4595 }
4596
Louis Dionne89258142021-08-23 15:32:36 -04004597 return false;
4598#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004599 _LIBCPP_UNREACHABLE();
4600}
4601
4602
Howard Hinnantc51e1022010-05-11 19:42:16 +00004603// numpunct<char> && numpunct<wchar_t>
4604
4605locale::id numpunct< char >::id;
Louis Dionne89258142021-08-23 15:32:36 -04004606#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004607locale::id numpunct<wchar_t>::id;
Louis Dionne89258142021-08-23 15:32:36 -04004608#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004609
4610numpunct<char>::numpunct(size_t refs)
4611 : locale::facet(refs),
4612 __decimal_point_('.'),
4613 __thousands_sep_(',')
4614{
4615}
4616
Louis Dionne89258142021-08-23 15:32:36 -04004617#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004618numpunct<wchar_t>::numpunct(size_t refs)
4619 : locale::facet(refs),
4620 __decimal_point_(L'.'),
4621 __thousands_sep_(L',')
4622{
4623}
Louis Dionne89258142021-08-23 15:32:36 -04004624#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004625
4626numpunct<char>::~numpunct()
4627{
4628}
4629
Louis Dionne89258142021-08-23 15:32:36 -04004630#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004631numpunct<wchar_t>::~numpunct()
4632{
4633}
Louis Dionne89258142021-08-23 15:32:36 -04004634#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004635
4636 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004637#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004638wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004639#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004640
4641 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004642#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004643wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004644#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004645
4646string numpunct< char >::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004647#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004648string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004649#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004650
4651 string numpunct< char >::do_truename() const {return "true";}
Louis Dionne89258142021-08-23 15:32:36 -04004652#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004653wstring numpunct<wchar_t>::do_truename() const {return L"true";}
Louis Dionne89258142021-08-23 15:32:36 -04004654#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004655
4656 string numpunct< char >::do_falsename() const {return "false";}
Louis Dionne89258142021-08-23 15:32:36 -04004657#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004658wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
Louis Dionne89258142021-08-23 15:32:36 -04004659#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004660
4661// numpunct_byname<char>
4662
4663numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4664 : numpunct<char>(refs)
4665{
4666 __init(nm);
4667}
4668
4669numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4670 : numpunct<char>(refs)
4671{
4672 __init(nm.c_str());
4673}
4674
4675numpunct_byname<char>::~numpunct_byname()
4676{
4677}
4678
4679void
4680numpunct_byname<char>::__init(const char* nm)
4681{
Louis Dionne89258142021-08-23 15:32:36 -04004682 typedef numpunct<char> base;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004683 if (strcmp(nm, "C") != 0)
4684 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004685 __libcpp_unique_locale loc(nm);
4686 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004687 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004688 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004689
Ben Craig3756b922016-03-09 15:39:39 +00004690 lconv* lc = __libcpp_localeconv_l(loc.get());
Louis Dionne89258142021-08-23 15:32:36 -04004691 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4692 loc.get()))
4693 __decimal_point_ = base::do_decimal_point();
4694 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4695 loc.get()))
4696 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00004697 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004698 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004699 }
4700}
4701
4702// numpunct_byname<wchar_t>
4703
Louis Dionne89258142021-08-23 15:32:36 -04004704#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004705numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4706 : numpunct<wchar_t>(refs)
4707{
4708 __init(nm);
4709}
4710
4711numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4712 : numpunct<wchar_t>(refs)
4713{
4714 __init(nm.c_str());
4715}
4716
4717numpunct_byname<wchar_t>::~numpunct_byname()
4718{
4719}
4720
4721void
4722numpunct_byname<wchar_t>::__init(const char* nm)
4723{
4724 if (strcmp(nm, "C") != 0)
4725 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004726 __libcpp_unique_locale loc(nm);
4727 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004728 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004729 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004730
Ben Craig3756b922016-03-09 15:39:39 +00004731 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004732 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4733 loc.get());
4734 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4735 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004736 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004737 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004738 }
4739}
Louis Dionne89258142021-08-23 15:32:36 -04004740#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004741
4742// num_get helpers
4743
4744int
4745__num_get_base::__get_base(ios_base& iob)
4746{
4747 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4748 if (__basefield == ios_base::oct)
4749 return 8;
4750 else if (__basefield == ios_base::hex)
4751 return 16;
4752 else if (__basefield == 0)
4753 return 0;
4754 return 10;
4755}
4756
4757const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4758
4759void
4760__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4761 ios_base::iostate& __err)
4762{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004763// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4764// 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 +00004765 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004766 {
4767 reverse(__g, __g_end);
4768 const char* __ig = __grouping.data();
4769 const char* __eg = __ig + __grouping.size();
4770 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4771 {
4772 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4773 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004774 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004775 {
4776 __err = ios_base::failbit;
4777 return;
4778 }
4779 }
4780 if (__eg - __ig > 1)
4781 ++__ig;
4782 }
4783 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4784 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004785 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004786 __err = ios_base::failbit;
4787 }
4788 }
4789}
4790
4791void
4792__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4793 ios_base::fmtflags __flags)
4794{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004795 if ((__flags & ios_base::showpos) &&
4796 (__flags & ios_base::basefield) != ios_base::oct &&
4797 (__flags & ios_base::basefield) != ios_base::hex &&
4798 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004799 *__fmtp++ = '+';
4800 if (__flags & ios_base::showbase)
4801 *__fmtp++ = '#';
4802 while(*__len)
4803 *__fmtp++ = *__len++;
4804 if ((__flags & ios_base::basefield) == ios_base::oct)
4805 *__fmtp = 'o';
4806 else if ((__flags & ios_base::basefield) == ios_base::hex)
4807 {
4808 if (__flags & ios_base::uppercase)
4809 *__fmtp = 'X';
4810 else
4811 *__fmtp = 'x';
4812 }
4813 else if (__signd)
4814 *__fmtp = 'd';
4815 else
4816 *__fmtp = 'u';
4817}
4818
4819bool
4820__num_put_base::__format_float(char* __fmtp, const char* __len,
4821 ios_base::fmtflags __flags)
4822{
4823 bool specify_precision = true;
4824 if (__flags & ios_base::showpos)
4825 *__fmtp++ = '+';
4826 if (__flags & ios_base::showpoint)
4827 *__fmtp++ = '#';
4828 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004829 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004830 if (floatfield == (ios_base::fixed | ios_base::scientific))
4831 specify_precision = false;
4832 else
4833 {
4834 *__fmtp++ = '.';
4835 *__fmtp++ = '*';
4836 }
4837 while(*__len)
4838 *__fmtp++ = *__len++;
4839 if (floatfield == ios_base::fixed)
4840 {
4841 if (uppercase)
4842 *__fmtp = 'F';
4843 else
4844 *__fmtp = 'f';
4845 }
4846 else if (floatfield == ios_base::scientific)
4847 {
4848 if (uppercase)
4849 *__fmtp = 'E';
4850 else
4851 *__fmtp = 'e';
4852 }
4853 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4854 {
4855 if (uppercase)
4856 *__fmtp = 'A';
4857 else
4858 *__fmtp = 'a';
4859 }
4860 else
4861 {
4862 if (uppercase)
4863 *__fmtp = 'G';
4864 else
4865 *__fmtp = 'g';
4866 }
4867 return specify_precision;
4868}
4869
4870char*
4871__num_put_base::__identify_padding(char* __nb, char* __ne,
4872 const ios_base& __iob)
4873{
4874 switch (__iob.flags() & ios_base::adjustfield)
4875 {
4876 case ios_base::internal:
4877 if (__nb[0] == '-' || __nb[0] == '+')
4878 return __nb+1;
4879 if (__ne - __nb >= 2 && __nb[0] == '0'
4880 && (__nb[1] == 'x' || __nb[1] == 'X'))
4881 return __nb+2;
4882 break;
4883 case ios_base::left:
4884 return __ne;
4885 case ios_base::right:
4886 default:
4887 break;
4888 }
4889 return __nb;
4890}
4891
4892// time_get
4893
4894static
4895string*
4896init_weeks()
4897{
4898 static string weeks[14];
4899 weeks[0] = "Sunday";
4900 weeks[1] = "Monday";
4901 weeks[2] = "Tuesday";
4902 weeks[3] = "Wednesday";
4903 weeks[4] = "Thursday";
4904 weeks[5] = "Friday";
4905 weeks[6] = "Saturday";
4906 weeks[7] = "Sun";
4907 weeks[8] = "Mon";
4908 weeks[9] = "Tue";
4909 weeks[10] = "Wed";
4910 weeks[11] = "Thu";
4911 weeks[12] = "Fri";
4912 weeks[13] = "Sat";
4913 return weeks;
4914}
4915
Louis Dionne89258142021-08-23 15:32:36 -04004916#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004917static
4918wstring*
4919init_wweeks()
4920{
4921 static wstring weeks[14];
4922 weeks[0] = L"Sunday";
4923 weeks[1] = L"Monday";
4924 weeks[2] = L"Tuesday";
4925 weeks[3] = L"Wednesday";
4926 weeks[4] = L"Thursday";
4927 weeks[5] = L"Friday";
4928 weeks[6] = L"Saturday";
4929 weeks[7] = L"Sun";
4930 weeks[8] = L"Mon";
4931 weeks[9] = L"Tue";
4932 weeks[10] = L"Wed";
4933 weeks[11] = L"Thu";
4934 weeks[12] = L"Fri";
4935 weeks[13] = L"Sat";
4936 return weeks;
4937}
Louis Dionne89258142021-08-23 15:32:36 -04004938#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004939
4940template <>
4941const string*
4942__time_get_c_storage<char>::__weeks() const
4943{
4944 static const string* weeks = init_weeks();
4945 return weeks;
4946}
4947
Louis Dionne89258142021-08-23 15:32:36 -04004948#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004949template <>
4950const wstring*
4951__time_get_c_storage<wchar_t>::__weeks() const
4952{
4953 static const wstring* weeks = init_wweeks();
4954 return weeks;
4955}
Louis Dionne89258142021-08-23 15:32:36 -04004956#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004957
4958static
4959string*
4960init_months()
4961{
4962 static string months[24];
4963 months[0] = "January";
4964 months[1] = "February";
4965 months[2] = "March";
4966 months[3] = "April";
4967 months[4] = "May";
4968 months[5] = "June";
4969 months[6] = "July";
4970 months[7] = "August";
4971 months[8] = "September";
4972 months[9] = "October";
4973 months[10] = "November";
4974 months[11] = "December";
4975 months[12] = "Jan";
4976 months[13] = "Feb";
4977 months[14] = "Mar";
4978 months[15] = "Apr";
4979 months[16] = "May";
4980 months[17] = "Jun";
4981 months[18] = "Jul";
4982 months[19] = "Aug";
4983 months[20] = "Sep";
4984 months[21] = "Oct";
4985 months[22] = "Nov";
4986 months[23] = "Dec";
4987 return months;
4988}
4989
Louis Dionne89258142021-08-23 15:32:36 -04004990#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004991static
4992wstring*
4993init_wmonths()
4994{
4995 static wstring months[24];
4996 months[0] = L"January";
4997 months[1] = L"February";
4998 months[2] = L"March";
4999 months[3] = L"April";
5000 months[4] = L"May";
5001 months[5] = L"June";
5002 months[6] = L"July";
5003 months[7] = L"August";
5004 months[8] = L"September";
5005 months[9] = L"October";
5006 months[10] = L"November";
5007 months[11] = L"December";
5008 months[12] = L"Jan";
5009 months[13] = L"Feb";
5010 months[14] = L"Mar";
5011 months[15] = L"Apr";
5012 months[16] = L"May";
5013 months[17] = L"Jun";
5014 months[18] = L"Jul";
5015 months[19] = L"Aug";
5016 months[20] = L"Sep";
5017 months[21] = L"Oct";
5018 months[22] = L"Nov";
5019 months[23] = L"Dec";
5020 return months;
5021}
Louis Dionne89258142021-08-23 15:32:36 -04005022#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005023
5024template <>
5025const string*
5026__time_get_c_storage<char>::__months() const
5027{
5028 static const string* months = init_months();
5029 return months;
5030}
5031
Louis Dionne89258142021-08-23 15:32:36 -04005032#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005033template <>
5034const wstring*
5035__time_get_c_storage<wchar_t>::__months() const
5036{
5037 static const wstring* months = init_wmonths();
5038 return months;
5039}
Louis Dionne89258142021-08-23 15:32:36 -04005040#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005041
5042static
5043string*
5044init_am_pm()
5045{
Marshall Clow5cc04922018-01-11 17:16:52 +00005046 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005047 am_pm[0] = "AM";
5048 am_pm[1] = "PM";
5049 return am_pm;
5050}
5051
Louis Dionne89258142021-08-23 15:32:36 -04005052#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005053static
5054wstring*
5055init_wam_pm()
5056{
Marshall Clow5cc04922018-01-11 17:16:52 +00005057 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005058 am_pm[0] = L"AM";
5059 am_pm[1] = L"PM";
5060 return am_pm;
5061}
Louis Dionne89258142021-08-23 15:32:36 -04005062#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005063
5064template <>
5065const string*
5066__time_get_c_storage<char>::__am_pm() const
5067{
5068 static const string* am_pm = init_am_pm();
5069 return am_pm;
5070}
5071
Louis Dionne89258142021-08-23 15:32:36 -04005072#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005073template <>
5074const wstring*
5075__time_get_c_storage<wchar_t>::__am_pm() const
5076{
5077 static const wstring* am_pm = init_wam_pm();
5078 return am_pm;
5079}
Louis Dionne89258142021-08-23 15:32:36 -04005080#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005081
5082template <>
5083const string&
5084__time_get_c_storage<char>::__x() const
5085{
5086 static string s("%m/%d/%y");
5087 return s;
5088}
5089
Louis Dionne89258142021-08-23 15:32:36 -04005090#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005091template <>
5092const wstring&
5093__time_get_c_storage<wchar_t>::__x() const
5094{
5095 static wstring s(L"%m/%d/%y");
5096 return s;
5097}
Louis Dionne89258142021-08-23 15:32:36 -04005098#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005099
5100template <>
5101const string&
5102__time_get_c_storage<char>::__X() const
5103{
5104 static string s("%H:%M:%S");
5105 return s;
5106}
5107
Louis Dionne89258142021-08-23 15:32:36 -04005108#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005109template <>
5110const wstring&
5111__time_get_c_storage<wchar_t>::__X() const
5112{
5113 static wstring s(L"%H:%M:%S");
5114 return s;
5115}
Louis Dionne89258142021-08-23 15:32:36 -04005116#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005117
5118template <>
5119const string&
5120__time_get_c_storage<char>::__c() const
5121{
5122 static string s("%a %b %d %H:%M:%S %Y");
5123 return s;
5124}
5125
Louis Dionne89258142021-08-23 15:32:36 -04005126#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005127template <>
5128const wstring&
5129__time_get_c_storage<wchar_t>::__c() const
5130{
5131 static wstring s(L"%a %b %d %H:%M:%S %Y");
5132 return s;
5133}
Louis Dionne89258142021-08-23 15:32:36 -04005134#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005135
5136template <>
5137const string&
5138__time_get_c_storage<char>::__r() const
5139{
5140 static string s("%I:%M:%S %p");
5141 return s;
5142}
5143
Louis Dionne89258142021-08-23 15:32:36 -04005144#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005145template <>
5146const wstring&
5147__time_get_c_storage<wchar_t>::__r() const
5148{
5149 static wstring s(L"%I:%M:%S %p");
5150 return s;
5151}
Louis Dionne89258142021-08-23 15:32:36 -04005152#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005153
5154// time_get_byname
5155
5156__time_get::__time_get(const char* nm)
5157 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5158{
5159 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005160 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005161 " failed to construct for " + string(nm));
5162}
5163
5164__time_get::__time_get(const string& nm)
5165 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5166{
5167 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005168 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005169 " failed to construct for " + nm);
5170}
5171
5172__time_get::~__time_get()
5173{
5174 freelocale(__loc_);
5175}
Marshall Clowd920eea2013-10-21 15:07:28 +00005176#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005177#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005178#endif
5179#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00005180#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005181#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005182
Howard Hinnantc51e1022010-05-11 19:42:16 +00005183template <>
5184string
5185__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5186{
Howard Hinnant990207c2012-02-19 14:55:32 +00005187 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005188 t.tm_sec = 59;
5189 t.tm_min = 55;
5190 t.tm_hour = 23;
5191 t.tm_mday = 31;
5192 t.tm_mon = 11;
5193 t.tm_year = 161;
5194 t.tm_wday = 6;
5195 t.tm_yday = 364;
5196 t.tm_isdst = -1;
5197 char buf[100];
5198 char f[3] = {0};
5199 f[0] = '%';
5200 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005201 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005202 char* bb = buf;
5203 char* be = buf + n;
5204 string result;
5205 while (bb != be)
5206 {
5207 if (ct.is(ctype_base::space, *bb))
5208 {
5209 result.push_back(' ');
5210 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5211 ;
5212 continue;
5213 }
5214 char* w = bb;
5215 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005216 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005217 ct, err, false)
5218 - this->__weeks_;
5219 if (i < 14)
5220 {
5221 result.push_back('%');
5222 if (i < 7)
5223 result.push_back('A');
5224 else
5225 result.push_back('a');
5226 bb = w;
5227 continue;
5228 }
5229 w = bb;
5230 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5231 ct, err, false)
5232 - this->__months_;
5233 if (i < 24)
5234 {
5235 result.push_back('%');
5236 if (i < 12)
5237 result.push_back('B');
5238 else
5239 result.push_back('b');
5240 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5241 result.back() = 'm';
5242 bb = w;
5243 continue;
5244 }
5245 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5246 {
5247 w = bb;
5248 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5249 ct, err, false) - this->__am_pm_;
5250 if (i < 2)
5251 {
5252 result.push_back('%');
5253 result.push_back('p');
5254 bb = w;
5255 continue;
5256 }
5257 }
5258 w = bb;
5259 if (ct.is(ctype_base::digit, *bb))
5260 {
5261 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5262 {
5263 case 6:
5264 result.push_back('%');
5265 result.push_back('w');
5266 break;
5267 case 7:
5268 result.push_back('%');
5269 result.push_back('u');
5270 break;
5271 case 11:
5272 result.push_back('%');
5273 result.push_back('I');
5274 break;
5275 case 12:
5276 result.push_back('%');
5277 result.push_back('m');
5278 break;
5279 case 23:
5280 result.push_back('%');
5281 result.push_back('H');
5282 break;
5283 case 31:
5284 result.push_back('%');
5285 result.push_back('d');
5286 break;
5287 case 55:
5288 result.push_back('%');
5289 result.push_back('M');
5290 break;
5291 case 59:
5292 result.push_back('%');
5293 result.push_back('S');
5294 break;
5295 case 61:
5296 result.push_back('%');
5297 result.push_back('y');
5298 break;
5299 case 364:
5300 result.push_back('%');
5301 result.push_back('j');
5302 break;
5303 case 2061:
5304 result.push_back('%');
5305 result.push_back('Y');
5306 break;
5307 default:
5308 for (; w != bb; ++w)
5309 result.push_back(*w);
5310 break;
5311 }
5312 continue;
5313 }
5314 if (*bb == '%')
5315 {
5316 result.push_back('%');
5317 result.push_back('%');
5318 ++bb;
5319 continue;
5320 }
5321 result.push_back(*bb);
5322 ++bb;
5323 }
5324 return result;
5325}
5326
Marshall Clowd920eea2013-10-21 15:07:28 +00005327#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005328#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005329#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005330
Louis Dionne89258142021-08-23 15:32:36 -04005331#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005332template <>
5333wstring
5334__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5335{
Howard Hinnant990207c2012-02-19 14:55:32 +00005336 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005337 t.tm_sec = 59;
5338 t.tm_min = 55;
5339 t.tm_hour = 23;
5340 t.tm_mday = 31;
5341 t.tm_mon = 11;
5342 t.tm_year = 161;
5343 t.tm_wday = 6;
5344 t.tm_yday = 364;
5345 t.tm_isdst = -1;
5346 char buf[100];
5347 char f[3] = {0};
5348 f[0] = '%';
5349 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005350 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005351 wchar_t wbuf[100];
5352 wchar_t* wbb = wbuf;
5353 mbstate_t mb = {0};
5354 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005355 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005356 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005357 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005358 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005359 wstring result;
5360 while (wbb != wbe)
5361 {
5362 if (ct.is(ctype_base::space, *wbb))
5363 {
5364 result.push_back(L' ');
5365 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5366 ;
5367 continue;
5368 }
5369 wchar_t* w = wbb;
5370 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005371 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005372 ct, err, false)
5373 - this->__weeks_;
5374 if (i < 14)
5375 {
5376 result.push_back(L'%');
5377 if (i < 7)
5378 result.push_back(L'A');
5379 else
5380 result.push_back(L'a');
5381 wbb = w;
5382 continue;
5383 }
5384 w = wbb;
5385 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5386 ct, err, false)
5387 - this->__months_;
5388 if (i < 24)
5389 {
5390 result.push_back(L'%');
5391 if (i < 12)
5392 result.push_back(L'B');
5393 else
5394 result.push_back(L'b');
5395 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5396 result.back() = L'm';
5397 wbb = w;
5398 continue;
5399 }
5400 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5401 {
5402 w = wbb;
5403 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5404 ct, err, false) - this->__am_pm_;
5405 if (i < 2)
5406 {
5407 result.push_back(L'%');
5408 result.push_back(L'p');
5409 wbb = w;
5410 continue;
5411 }
5412 }
5413 w = wbb;
5414 if (ct.is(ctype_base::digit, *wbb))
5415 {
5416 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5417 {
5418 case 6:
5419 result.push_back(L'%');
5420 result.push_back(L'w');
5421 break;
5422 case 7:
5423 result.push_back(L'%');
5424 result.push_back(L'u');
5425 break;
5426 case 11:
5427 result.push_back(L'%');
5428 result.push_back(L'I');
5429 break;
5430 case 12:
5431 result.push_back(L'%');
5432 result.push_back(L'm');
5433 break;
5434 case 23:
5435 result.push_back(L'%');
5436 result.push_back(L'H');
5437 break;
5438 case 31:
5439 result.push_back(L'%');
5440 result.push_back(L'd');
5441 break;
5442 case 55:
5443 result.push_back(L'%');
5444 result.push_back(L'M');
5445 break;
5446 case 59:
5447 result.push_back(L'%');
5448 result.push_back(L'S');
5449 break;
5450 case 61:
5451 result.push_back(L'%');
5452 result.push_back(L'y');
5453 break;
5454 case 364:
5455 result.push_back(L'%');
5456 result.push_back(L'j');
5457 break;
5458 case 2061:
5459 result.push_back(L'%');
5460 result.push_back(L'Y');
5461 break;
5462 default:
5463 for (; w != wbb; ++w)
5464 result.push_back(*w);
5465 break;
5466 }
5467 continue;
5468 }
5469 if (ct.narrow(*wbb, 0) == '%')
5470 {
5471 result.push_back(L'%');
5472 result.push_back(L'%');
5473 ++wbb;
5474 continue;
5475 }
5476 result.push_back(*wbb);
5477 ++wbb;
5478 }
5479 return result;
5480}
Louis Dionne89258142021-08-23 15:32:36 -04005481#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005482
5483template <>
5484void
5485__time_get_storage<char>::init(const ctype<char>& ct)
5486{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005487 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005488 char buf[100];
5489 // __weeks_
5490 for (int i = 0; i < 7; ++i)
5491 {
5492 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005493 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005494 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005495 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005496 __weeks_[i+7] = buf;
5497 }
5498 // __months_
5499 for (int i = 0; i < 12; ++i)
5500 {
5501 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005502 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005503 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005504 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005505 __months_[i+12] = buf;
5506 }
5507 // __am_pm_
5508 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005509 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005510 __am_pm_[0] = buf;
5511 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005512 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005513 __am_pm_[1] = buf;
5514 __c_ = __analyze('c', ct);
5515 __r_ = __analyze('r', ct);
5516 __x_ = __analyze('x', ct);
5517 __X_ = __analyze('X', ct);
5518}
5519
Louis Dionne89258142021-08-23 15:32:36 -04005520#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005521template <>
5522void
5523__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5524{
5525 tm t = {0};
5526 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005527 wchar_t wbuf[100];
5528 wchar_t* wbe;
5529 mbstate_t mb = {0};
5530 // __weeks_
5531 for (int i = 0; i < 7; ++i)
5532 {
5533 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005534 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005535 mb = mbstate_t();
5536 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005537 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005538 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005539 __throw_runtime_error("locale not supported");
5540 wbe = wbuf + j;
5541 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005542 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005543 mb = mbstate_t();
5544 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005545 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005546 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005547 __throw_runtime_error("locale not supported");
5548 wbe = wbuf + j;
5549 __weeks_[i+7].assign(wbuf, wbe);
5550 }
5551 // __months_
5552 for (int i = 0; i < 12; ++i)
5553 {
5554 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005555 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005556 mb = mbstate_t();
5557 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005558 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005559 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005560 __throw_runtime_error("locale not supported");
5561 wbe = wbuf + j;
5562 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005563 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005564 mb = mbstate_t();
5565 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005566 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005567 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005568 __throw_runtime_error("locale not supported");
5569 wbe = wbuf + j;
5570 __months_[i+12].assign(wbuf, wbe);
5571 }
5572 // __am_pm_
5573 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005574 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005575 mb = mbstate_t();
5576 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005577 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005578 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005579 __throw_runtime_error("locale not supported");
5580 wbe = wbuf + j;
5581 __am_pm_[0].assign(wbuf, wbe);
5582 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005583 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005584 mb = mbstate_t();
5585 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005586 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005587 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005588 __throw_runtime_error("locale not supported");
5589 wbe = wbuf + j;
5590 __am_pm_[1].assign(wbuf, wbe);
5591 __c_ = __analyze('c', ct);
5592 __r_ = __analyze('r', ct);
5593 __x_ = __analyze('x', ct);
5594 __X_ = __analyze('X', ct);
5595}
Louis Dionne89258142021-08-23 15:32:36 -04005596#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005597
5598template <class CharT>
5599struct _LIBCPP_HIDDEN __time_get_temp
5600 : public ctype_byname<CharT>
5601{
5602 explicit __time_get_temp(const char* nm)
5603 : ctype_byname<CharT>(nm, 1) {}
5604 explicit __time_get_temp(const string& nm)
5605 : ctype_byname<CharT>(nm, 1) {}
5606};
5607
5608template <>
5609__time_get_storage<char>::__time_get_storage(const char* __nm)
5610 : __time_get(__nm)
5611{
5612 const __time_get_temp<char> ct(__nm);
5613 init(ct);
5614}
5615
5616template <>
5617__time_get_storage<char>::__time_get_storage(const string& __nm)
5618 : __time_get(__nm)
5619{
5620 const __time_get_temp<char> ct(__nm);
5621 init(ct);
5622}
5623
Louis Dionne89258142021-08-23 15:32:36 -04005624#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005625template <>
5626__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5627 : __time_get(__nm)
5628{
5629 const __time_get_temp<wchar_t> ct(__nm);
5630 init(ct);
5631}
5632
5633template <>
5634__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5635 : __time_get(__nm)
5636{
5637 const __time_get_temp<wchar_t> ct(__nm);
5638 init(ct);
5639}
Louis Dionne89258142021-08-23 15:32:36 -04005640#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005641
5642template <>
5643time_base::dateorder
5644__time_get_storage<char>::__do_date_order() const
5645{
5646 unsigned i;
5647 for (i = 0; i < __x_.size(); ++i)
5648 if (__x_[i] == '%')
5649 break;
5650 ++i;
5651 switch (__x_[i])
5652 {
5653 case 'y':
5654 case 'Y':
5655 for (++i; i < __x_.size(); ++i)
5656 if (__x_[i] == '%')
5657 break;
5658 if (i == __x_.size())
5659 break;
5660 ++i;
5661 switch (__x_[i])
5662 {
5663 case 'm':
5664 for (++i; i < __x_.size(); ++i)
5665 if (__x_[i] == '%')
5666 break;
5667 if (i == __x_.size())
5668 break;
5669 ++i;
5670 if (__x_[i] == 'd')
5671 return time_base::ymd;
5672 break;
5673 case 'd':
5674 for (++i; i < __x_.size(); ++i)
5675 if (__x_[i] == '%')
5676 break;
5677 if (i == __x_.size())
5678 break;
5679 ++i;
5680 if (__x_[i] == 'm')
5681 return time_base::ydm;
5682 break;
5683 }
5684 break;
5685 case 'm':
5686 for (++i; i < __x_.size(); ++i)
5687 if (__x_[i] == '%')
5688 break;
5689 if (i == __x_.size())
5690 break;
5691 ++i;
5692 if (__x_[i] == 'd')
5693 {
5694 for (++i; i < __x_.size(); ++i)
5695 if (__x_[i] == '%')
5696 break;
5697 if (i == __x_.size())
5698 break;
5699 ++i;
5700 if (__x_[i] == 'y' || __x_[i] == 'Y')
5701 return time_base::mdy;
5702 break;
5703 }
5704 break;
5705 case 'd':
5706 for (++i; i < __x_.size(); ++i)
5707 if (__x_[i] == '%')
5708 break;
5709 if (i == __x_.size())
5710 break;
5711 ++i;
5712 if (__x_[i] == 'm')
5713 {
5714 for (++i; i < __x_.size(); ++i)
5715 if (__x_[i] == '%')
5716 break;
5717 if (i == __x_.size())
5718 break;
5719 ++i;
5720 if (__x_[i] == 'y' || __x_[i] == 'Y')
5721 return time_base::dmy;
5722 break;
5723 }
5724 break;
5725 }
5726 return time_base::no_order;
5727}
5728
Louis Dionne89258142021-08-23 15:32:36 -04005729#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005730template <>
5731time_base::dateorder
5732__time_get_storage<wchar_t>::__do_date_order() const
5733{
5734 unsigned i;
5735 for (i = 0; i < __x_.size(); ++i)
5736 if (__x_[i] == L'%')
5737 break;
5738 ++i;
5739 switch (__x_[i])
5740 {
5741 case L'y':
5742 case L'Y':
5743 for (++i; i < __x_.size(); ++i)
5744 if (__x_[i] == L'%')
5745 break;
5746 if (i == __x_.size())
5747 break;
5748 ++i;
5749 switch (__x_[i])
5750 {
5751 case L'm':
5752 for (++i; i < __x_.size(); ++i)
5753 if (__x_[i] == L'%')
5754 break;
5755 if (i == __x_.size())
5756 break;
5757 ++i;
5758 if (__x_[i] == L'd')
5759 return time_base::ymd;
5760 break;
5761 case L'd':
5762 for (++i; i < __x_.size(); ++i)
5763 if (__x_[i] == L'%')
5764 break;
5765 if (i == __x_.size())
5766 break;
5767 ++i;
5768 if (__x_[i] == L'm')
5769 return time_base::ydm;
5770 break;
5771 }
5772 break;
5773 case L'm':
5774 for (++i; i < __x_.size(); ++i)
5775 if (__x_[i] == L'%')
5776 break;
5777 if (i == __x_.size())
5778 break;
5779 ++i;
5780 if (__x_[i] == L'd')
5781 {
5782 for (++i; i < __x_.size(); ++i)
5783 if (__x_[i] == L'%')
5784 break;
5785 if (i == __x_.size())
5786 break;
5787 ++i;
5788 if (__x_[i] == L'y' || __x_[i] == L'Y')
5789 return time_base::mdy;
5790 break;
5791 }
5792 break;
5793 case L'd':
5794 for (++i; i < __x_.size(); ++i)
5795 if (__x_[i] == L'%')
5796 break;
5797 if (i == __x_.size())
5798 break;
5799 ++i;
5800 if (__x_[i] == L'm')
5801 {
5802 for (++i; i < __x_.size(); ++i)
5803 if (__x_[i] == L'%')
5804 break;
5805 if (i == __x_.size())
5806 break;
5807 ++i;
5808 if (__x_[i] == L'y' || __x_[i] == L'Y')
5809 return time_base::dmy;
5810 break;
5811 }
5812 break;
5813 }
5814 return time_base::no_order;
5815}
Louis Dionne89258142021-08-23 15:32:36 -04005816#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005817
5818// time_put
5819
5820__time_put::__time_put(const char* nm)
5821 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5822{
5823 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005824 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005825 " failed to construct for " + string(nm));
5826}
5827
5828__time_put::__time_put(const string& nm)
5829 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5830{
5831 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005832 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005833 " failed to construct for " + nm);
5834}
5835
5836__time_put::~__time_put()
5837{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005838 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005839 freelocale(__loc_);
5840}
5841
5842void
5843__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5844 char __fmt, char __mod) const
5845{
5846 char fmt[] = {'%', __fmt, __mod, 0};
5847 if (__mod != 0)
5848 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005849 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005850 __ne = __nb + n;
5851}
5852
Louis Dionne89258142021-08-23 15:32:36 -04005853#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005854void
5855__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5856 char __fmt, char __mod) const
5857{
5858 char __nar[100];
5859 char* __ne = __nar + 100;
5860 __do_put(__nar, __ne, __tm, __fmt, __mod);
5861 mbstate_t mb = {0};
5862 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005863 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005864 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005865 __throw_runtime_error("locale not supported");
5866 __we = __wb + j;
5867}
Louis Dionne89258142021-08-23 15:32:36 -04005868#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005869
5870// moneypunct_byname
5871
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005872template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005873static
5874void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005875__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5876 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5877 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005878{
5879 const char sign = static_cast<char>(money_base::sign);
5880 const char space = static_cast<char>(money_base::space);
5881 const char none = static_cast<char>(money_base::none);
5882 const char symbol = static_cast<char>(money_base::symbol);
5883 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005884 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5885
5886 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5887 // function'. "Space between sign and symbol or value" means that
5888 // if the sign is adjacent to the symbol, there's a space between
5889 // them, and otherwise there's a space between the sign and value.
5890 //
5891 // C11's localeconv specifies that the fourth character of an
5892 // international curr_symbol is used to separate the sign and
5893 // value when sep_by_space says to do so. C++ can't represent
5894 // that, so we just use a space. When sep_by_space says to
5895 // separate the symbol and value-or-sign with a space, we rearrange the
5896 // curr_symbol to put its spacing character on the correct side of
5897 // the symbol.
5898 //
5899 // We also need to avoid adding an extra space between the sign
5900 // and value when the currency symbol is suppressed (by not
5901 // setting showbase). We match glibc's strfmon by interpreting
5902 // sep_by_space==1 as "omit the space when the currency symbol is
5903 // absent".
5904 //
5905 // Users who want to get this right should use ICU instead.
5906
Howard Hinnantc51e1022010-05-11 19:42:16 +00005907 switch (cs_precedes)
5908 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005909 case 0: // value before curr_symbol
5910 if (symbol_contains_sep) {
5911 // Move the separator to before the symbol, to place it
5912 // between the value and symbol.
5913 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5914 __curr_symbol_.end());
5915 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005916 switch (sign_posn)
5917 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005918 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005919 pat.field[0] = sign;
5920 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005921 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005922 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.
5926 // This case may have changed between C99 and C11;
5927 // assume the currency symbol matches the intention.
5928 case 2: // Space between sign and currency or value.
5929 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005930 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005931 case 1: // Space between currency-and-sign or currency and value.
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;
5939 default:
5940 break;
5941 }
5942 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005943 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005944 pat.field[0] = sign;
5945 pat.field[3] = symbol;
5946 switch (sep_by_space)
5947 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005948 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005949 pat.field[1] = value;
5950 pat.field[2] = none;
5951 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005952 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005953 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005954 pat.field[2] = none;
5955 if (!symbol_contains_sep) {
5956 // We insert the space into the symbol instead of
5957 // setting pat.field[2]=space so that when
5958 // showbase is not set, the space goes away too.
5959 __curr_symbol_.insert(0, 1, space_char);
5960 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005961 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005962 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005963 pat.field[1] = space;
5964 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005965 if (symbol_contains_sep) {
5966 // Remove the separator from the symbol, since it
5967 // has already appeared after the sign.
5968 __curr_symbol_.erase(__curr_symbol_.begin());
5969 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005970 return;
5971 default:
5972 break;
5973 }
5974 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005975 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005976 pat.field[0] = value;
5977 pat.field[3] = sign;
5978 switch (sep_by_space)
5979 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005980 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005981 pat.field[1] = none;
5982 pat.field[2] = symbol;
5983 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005984 case 1: // Space between currency-and-sign or currency and value.
5985 if (!symbol_contains_sep) {
5986 // We insert the space into the symbol instead of
5987 // setting pat.field[1]=space so that when
5988 // showbase is not set, the space goes away too.
5989 __curr_symbol_.insert(0, 1, space_char);
5990 }
5991 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005992 pat.field[2] = symbol;
5993 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005994 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005995 pat.field[1] = symbol;
5996 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005997 if (symbol_contains_sep) {
5998 // Remove the separator from the symbol, since it
5999 // should not be removed if showbase is absent.
6000 __curr_symbol_.erase(__curr_symbol_.begin());
6001 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006002 return;
6003 default:
6004 break;
6005 }
6006 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006007 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006008 pat.field[0] = value;
6009 pat.field[3] = symbol;
6010 switch (sep_by_space)
6011 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006012 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006013 pat.field[1] = none;
6014 pat.field[2] = sign;
6015 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006016 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006017 pat.field[1] = space;
6018 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006019 if (symbol_contains_sep) {
6020 // Remove the separator from the symbol, since it
6021 // has already appeared before the sign.
6022 __curr_symbol_.erase(__curr_symbol_.begin());
6023 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006024 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006025 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006026 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006027 pat.field[2] = none;
6028 if (!symbol_contains_sep) {
6029 // We insert the space into the symbol instead of
6030 // setting pat.field[2]=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;
6035 default:
6036 break;
6037 }
6038 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006039 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006040 pat.field[0] = value;
6041 pat.field[3] = sign;
6042 switch (sep_by_space)
6043 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006044 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006045 pat.field[1] = none;
6046 pat.field[2] = symbol;
6047 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006048 case 1: // Space between currency-and-sign or currency and value.
6049 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006050 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006051 if (!symbol_contains_sep) {
6052 // We insert the space into the symbol instead of
6053 // setting pat.field[1]=space so that when
6054 // showbase is not set, the space goes away too.
6055 __curr_symbol_.insert(0, 1, space_char);
6056 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006057 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006058 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006059 pat.field[1] = symbol;
6060 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006061 if (symbol_contains_sep) {
6062 // Remove the separator from the symbol, since it
6063 // should not disappear when showbase is absent.
6064 __curr_symbol_.erase(__curr_symbol_.begin());
6065 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006066 return;
6067 default:
6068 break;
6069 }
6070 break;
6071 default:
6072 break;
6073 }
6074 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006075 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00006076 switch (sign_posn)
6077 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006078 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006079 pat.field[0] = sign;
6080 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006081 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006082 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.
6086 // This case may have changed between C99 and C11;
6087 // assume the currency symbol matches the intention.
6088 case 2: // Space between sign and currency or value.
6089 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006090 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006091 case 1: // Space between currency-and-sign or currency and value.
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_.insert(0, 1, space_char);
6097 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006098 return;
6099 default:
6100 break;
6101 }
6102 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006103 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006104 pat.field[0] = sign;
6105 pat.field[3] = value;
6106 switch (sep_by_space)
6107 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006108 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006109 pat.field[1] = symbol;
6110 pat.field[2] = none;
6111 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006112 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006113 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006114 pat.field[2] = none;
6115 if (!symbol_contains_sep) {
6116 // We insert the space into the symbol instead of
6117 // setting pat.field[2]=space so that when
6118 // showbase is not set, the space goes away too.
6119 __curr_symbol_.push_back(space_char);
6120 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006121 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006122 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006123 pat.field[1] = space;
6124 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006125 if (symbol_contains_sep) {
6126 // Remove the separator from the symbol, since it
6127 // has already appeared after the sign.
6128 __curr_symbol_.pop_back();
6129 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006130 return;
6131 default:
6132 break;
6133 }
6134 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006135 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006136 pat.field[0] = symbol;
6137 pat.field[3] = sign;
6138 switch (sep_by_space)
6139 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006140 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141 pat.field[1] = none;
6142 pat.field[2] = value;
6143 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006144 case 1: // Space between currency-and-sign or currency and value.
6145 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006146 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006147 if (!symbol_contains_sep) {
6148 // We insert the space into the symbol instead of
6149 // setting pat.field[1]=space so that when
6150 // showbase is not set, the space goes away too.
6151 __curr_symbol_.push_back(space_char);
6152 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006153 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006154 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006155 pat.field[1] = value;
6156 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006157 if (symbol_contains_sep) {
6158 // Remove the separator from the symbol, since it
6159 // will appear before the sign.
6160 __curr_symbol_.pop_back();
6161 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006162 return;
6163 default:
6164 break;
6165 }
6166 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006167 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006168 pat.field[0] = sign;
6169 pat.field[3] = value;
6170 switch (sep_by_space)
6171 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006172 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006173 pat.field[1] = symbol;
6174 pat.field[2] = none;
6175 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006176 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006177 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006178 pat.field[2] = none;
6179 if (!symbol_contains_sep) {
6180 // We insert the space into the symbol instead of
6181 // setting pat.field[2]=space so that when
6182 // showbase is not set, the space goes away too.
6183 __curr_symbol_.push_back(space_char);
6184 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006185 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006186 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006187 pat.field[1] = space;
6188 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006189 if (symbol_contains_sep) {
6190 // Remove the separator from the symbol, since it
6191 // has already appeared after the sign.
6192 __curr_symbol_.pop_back();
6193 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006194 return;
6195 default:
6196 break;
6197 }
6198 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006199 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006200 pat.field[0] = symbol;
6201 pat.field[3] = value;
6202 switch (sep_by_space)
6203 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006204 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006205 pat.field[1] = sign;
6206 pat.field[2] = none;
6207 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006208 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006209 pat.field[1] = sign;
6210 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006211 if (symbol_contains_sep) {
6212 // Remove the separator from the symbol, since it
6213 // should not disappear when showbase is absent.
6214 __curr_symbol_.pop_back();
6215 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006216 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006217 case 2: // Space between sign and currency or value.
6218 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006219 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006220 if (!symbol_contains_sep) {
6221 // We insert the space into the symbol instead of
6222 // setting pat.field[1]=space so that when
6223 // showbase is not set, the space goes away too.
6224 __curr_symbol_.push_back(space_char);
6225 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006226 return;
6227 default:
6228 break;
6229 }
6230 break;
6231 default:
6232 break;
6233 }
6234 break;
6235 default:
6236 break;
6237 }
6238 pat.field[0] = symbol;
6239 pat.field[1] = sign;
6240 pat.field[2] = none;
6241 pat.field[3] = value;
6242}
6243
6244template<>
6245void
6246moneypunct_byname<char, false>::init(const char* nm)
6247{
6248 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006249 __libcpp_unique_locale loc(nm);
6250 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006251 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006252 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006253
Ben Craig3756b922016-03-09 15:39:39 +00006254 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006255 if (!checked_string_to_char_convert(__decimal_point_,
6256 lc->mon_decimal_point,
6257 loc.get()))
6258 __decimal_point_ = base::do_decimal_point();
6259 if (!checked_string_to_char_convert(__thousands_sep_,
6260 lc->mon_thousands_sep,
6261 loc.get()))
6262 __thousands_sep_ = base::do_thousands_sep();
6263
Howard Hinnantc51e1022010-05-11 19:42:16 +00006264 __grouping_ = lc->mon_grouping;
6265 __curr_symbol_ = lc->currency_symbol;
6266 if (lc->frac_digits != CHAR_MAX)
6267 __frac_digits_ = lc->frac_digits;
6268 else
6269 __frac_digits_ = base::do_frac_digits();
6270 if (lc->p_sign_posn == 0)
6271 __positive_sign_ = "()";
6272 else
6273 __positive_sign_ = lc->positive_sign;
6274 if (lc->n_sign_posn == 0)
6275 __negative_sign_ = "()";
6276 else
6277 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006278 // Assume the positive and negative formats will want spaces in
6279 // the same places in curr_symbol since there's no way to
6280 // represent anything else.
6281 string_type __dummy_curr_symbol = __curr_symbol_;
6282 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6283 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6284 __init_pat(__neg_format_, __curr_symbol_, false,
6285 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006286}
6287
6288template<>
6289void
6290moneypunct_byname<char, true>::init(const char* nm)
6291{
6292 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006293 __libcpp_unique_locale loc(nm);
6294 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006295 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006296 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006297
Ben Craig3756b922016-03-09 15:39:39 +00006298 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006299 if (!checked_string_to_char_convert(__decimal_point_,
6300 lc->mon_decimal_point,
6301 loc.get()))
6302 __decimal_point_ = base::do_decimal_point();
6303 if (!checked_string_to_char_convert(__thousands_sep_,
6304 lc->mon_thousands_sep,
6305 loc.get()))
6306 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006307 __grouping_ = lc->mon_grouping;
6308 __curr_symbol_ = lc->int_curr_symbol;
6309 if (lc->int_frac_digits != CHAR_MAX)
6310 __frac_digits_ = lc->int_frac_digits;
6311 else
6312 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006313#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006314 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006315#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006316 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006317#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006318 __positive_sign_ = "()";
6319 else
6320 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006321#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006322 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006323#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006324 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006325#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006326 __negative_sign_ = "()";
6327 else
6328 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006329 // Assume the positive and negative formats will want spaces in
6330 // the same places in curr_symbol since there's no way to
6331 // represent anything else.
6332 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006333#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006334 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6335 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6336 __init_pat(__neg_format_, __curr_symbol_, true,
6337 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006338#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006339 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6340 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6341 lc->int_p_sign_posn, ' ');
6342 __init_pat(__neg_format_, __curr_symbol_, true,
6343 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6344 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006345#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006346}
6347
Louis Dionne89258142021-08-23 15:32:36 -04006348#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006349template<>
6350void
6351moneypunct_byname<wchar_t, false>::init(const char* nm)
6352{
6353 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006354 __libcpp_unique_locale loc(nm);
6355 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006356 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006357 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006358 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006359 if (!checked_string_to_wchar_convert(__decimal_point_,
6360 lc->mon_decimal_point,
6361 loc.get()))
6362 __decimal_point_ = base::do_decimal_point();
6363 if (!checked_string_to_wchar_convert(__thousands_sep_,
6364 lc->mon_thousands_sep,
6365 loc.get()))
6366 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006367 __grouping_ = lc->mon_grouping;
6368 wchar_t wbuf[100];
6369 mbstate_t mb = {0};
6370 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006371 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006372 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006373 __throw_runtime_error("locale not supported");
6374 wchar_t* wbe = wbuf + j;
6375 __curr_symbol_.assign(wbuf, wbe);
6376 if (lc->frac_digits != CHAR_MAX)
6377 __frac_digits_ = lc->frac_digits;
6378 else
6379 __frac_digits_ = base::do_frac_digits();
6380 if (lc->p_sign_posn == 0)
6381 __positive_sign_ = L"()";
6382 else
6383 {
6384 mb = mbstate_t();
6385 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006386 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006387 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006388 __throw_runtime_error("locale not supported");
6389 wbe = wbuf + j;
6390 __positive_sign_.assign(wbuf, wbe);
6391 }
6392 if (lc->n_sign_posn == 0)
6393 __negative_sign_ = L"()";
6394 else
6395 {
6396 mb = mbstate_t();
6397 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006398 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006399 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006400 __throw_runtime_error("locale not supported");
6401 wbe = wbuf + j;
6402 __negative_sign_.assign(wbuf, wbe);
6403 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006404 // Assume the positive and negative formats will want spaces in
6405 // the same places in curr_symbol since there's no way to
6406 // represent anything else.
6407 string_type __dummy_curr_symbol = __curr_symbol_;
6408 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6409 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6410 __init_pat(__neg_format_, __curr_symbol_, false,
6411 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006412}
6413
6414template<>
6415void
6416moneypunct_byname<wchar_t, true>::init(const char* nm)
6417{
6418 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006419 __libcpp_unique_locale loc(nm);
6420 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006421 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006422 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006423
Ben Craig3756b922016-03-09 15:39:39 +00006424 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006425 if (!checked_string_to_wchar_convert(__decimal_point_,
6426 lc->mon_decimal_point,
6427 loc.get()))
6428 __decimal_point_ = base::do_decimal_point();
6429 if (!checked_string_to_wchar_convert(__thousands_sep_,
6430 lc->mon_thousands_sep,
6431 loc.get()))
6432 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006433 __grouping_ = lc->mon_grouping;
6434 wchar_t wbuf[100];
6435 mbstate_t mb = {0};
6436 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006437 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006438 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006439 __throw_runtime_error("locale not supported");
6440 wchar_t* wbe = wbuf + j;
6441 __curr_symbol_.assign(wbuf, wbe);
6442 if (lc->int_frac_digits != CHAR_MAX)
6443 __frac_digits_ = lc->int_frac_digits;
6444 else
6445 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006446#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006447 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006448#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006449 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006450#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006451 __positive_sign_ = L"()";
6452 else
6453 {
6454 mb = mbstate_t();
6455 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006456 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006457 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006458 __throw_runtime_error("locale not supported");
6459 wbe = wbuf + j;
6460 __positive_sign_.assign(wbuf, wbe);
6461 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006462#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006463 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006464#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006465 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006466#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006467 __negative_sign_ = L"()";
6468 else
6469 {
6470 mb = mbstate_t();
6471 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006472 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006473 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006474 __throw_runtime_error("locale not supported");
6475 wbe = wbuf + j;
6476 __negative_sign_.assign(wbuf, wbe);
6477 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006478 // Assume the positive and negative formats will want spaces in
6479 // the same places in curr_symbol since there's no way to
6480 // represent anything else.
6481 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006482#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006483 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6484 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6485 __init_pat(__neg_format_, __curr_symbol_, true,
6486 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006487#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006488 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6489 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6490 lc->int_p_sign_posn, L' ');
6491 __init_pat(__neg_format_, __curr_symbol_, true,
6492 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6493 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006494#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006495}
Louis Dionne89258142021-08-23 15:32:36 -04006496#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006497
6498void __do_nothing(void*) {}
6499
6500void __throw_runtime_error(const char* msg)
6501{
Howard Hinnant72f73582010-08-11 17:04:31 +00006502#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006503 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006504#else
6505 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006506 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006507#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006508}
6509
Louis Dionne89258142021-08-23 15:32:36 -04006510 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6511_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006512
Louis Dionne89258142021-08-23 15:32:36 -04006513 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6514_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006515
Louis Dionne89258142021-08-23 15:32:36 -04006516 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6517_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006518
Louis Dionne89258142021-08-23 15:32:36 -04006519 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6520_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006521
Louis Dionne89258142021-08-23 15:32:36 -04006522 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6523_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006524
Louis Dionne89258142021-08-23 15:32:36 -04006525 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6526_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006527
Louis Dionne89258142021-08-23 15:32:36 -04006528 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6529_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006530
Louis Dionne89258142021-08-23 15:32:36 -04006531 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6532_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006533
Louis Dionne89258142021-08-23 15:32:36 -04006534 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6535_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006536
Louis Dionne89258142021-08-23 15:32:36 -04006537 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6538 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6539_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6540_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006541
Louis Dionne89258142021-08-23 15:32:36 -04006542 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6543 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6544_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6545_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006546
Louis Dionne89258142021-08-23 15:32:36 -04006547 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6548_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006549
Louis Dionne89258142021-08-23 15:32:36 -04006550 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6551_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006552
Louis Dionne89258142021-08-23 15:32:36 -04006553 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6554_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006555
Louis Dionne89258142021-08-23 15:32:36 -04006556 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6557_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006558
Louis Dionne89258142021-08-23 15:32:36 -04006559 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6560_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006561
Louis Dionne89258142021-08-23 15:32:36 -04006562 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6563_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006564
Louis Dionne89258142021-08-23 15:32:36 -04006565 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6566_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 -08006567template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6568template 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 -04006569#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006570template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6571template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6572#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006573
Howard Hinnantc51e1022010-05-11 19:42:16 +00006574_LIBCPP_END_NAMESPACE_STD