blob: 79f03b85fab3db445fa2398764b1bfb7af73dff7 [file] [log] [blame]
Louis Dionne9bd93882021-11-17 16:25:01 -05001//===----------------------------------------------------------------------===//
Howard Hinnantc51e1022010-05-11 19:42:16 +00002//
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
Muiez Ahmedc98adb12021-11-18 15:49:45 -0500991const size_t ctype<char>::table_size;
992
Howard Hinnantc51e1022010-05-11 19:42:16 +0000993ctype<char>::ctype(const mask* tab, bool del, size_t refs)
994 : locale::facet(refs),
995 __tab_(tab),
996 __del_(del)
997{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000998 if (__tab_ == 0)
999 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +00001000}
1001
1002ctype<char>::~ctype()
1003{
1004 if (__tab_ && __del_)
1005 delete [] __tab_;
1006}
1007
1008char
1009ctype<char>::do_toupper(char_type c) const
1010{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001011#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001012 return isascii(c) ?
1013 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001014#elif defined(__NetBSD__)
1015 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001016#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +00001017 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001018 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001019#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001020 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001021#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001022}
1023
1024const char*
1025ctype<char>::do_toupper(char_type* low, const char_type* high) const
1026{
1027 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001028#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001029 *low = isascii(*low) ?
1030 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001031#elif defined(__NetBSD__)
1032 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001033#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001034 *low = isascii(*low) ?
1035 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001036#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001037 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001038#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001039 return low;
1040}
1041
1042char
1043ctype<char>::do_tolower(char_type c) const
1044{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001045#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001046 return isascii(c) ?
1047 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001048#elif defined(__NetBSD__)
1049 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001050#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001051 return isascii(c) ?
1052 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001053#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001054 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001055#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001056}
1057
1058const char*
1059ctype<char>::do_tolower(char_type* low, const char_type* high) const
1060{
1061 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001062#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001063 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001064#elif defined(__NetBSD__)
1065 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001066#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001067 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001068#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001069 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001070#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001071 return low;
1072}
1073
1074char
1075ctype<char>::do_widen(char c) const
1076{
1077 return c;
1078}
1079
1080const char*
1081ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1082{
1083 for (; low != high; ++low, ++dest)
1084 *dest = *low;
1085 return low;
1086}
1087
1088char
1089ctype<char>::do_narrow(char_type c, char dfault) const
1090{
1091 if (isascii(c))
1092 return static_cast<char>(c);
1093 return dfault;
1094}
1095
1096const char*
1097ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1098{
1099 for (; low != high; ++low, ++dest)
1100 if (isascii(*low))
1101 *dest = *low;
1102 else
1103 *dest = dfault;
1104 return low;
1105}
1106
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001107#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001108extern "C" const unsigned short ** __ctype_b_loc();
1109extern "C" const int ** __ctype_tolower_loc();
1110extern "C" const int ** __ctype_toupper_loc();
1111#endif
1112
Marshall Clow8f870232015-03-04 16:50:02 +00001113#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001114const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001115ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001116{
1117 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1118 cntrl, cntrl,
1119 cntrl, cntrl,
1120 cntrl, cntrl,
1121 cntrl, cntrl,
1122 cntrl, cntrl | space | blank,
1123 cntrl | space, cntrl | space,
1124 cntrl | space, cntrl | space,
1125 cntrl, cntrl,
1126 cntrl, cntrl,
1127 cntrl, cntrl,
1128 cntrl, cntrl,
1129 cntrl, cntrl,
1130 cntrl, cntrl,
1131 cntrl, cntrl,
1132 cntrl, cntrl,
1133 cntrl, cntrl,
1134 space | blank | 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 punct | print, punct | print,
1141 punct | print, punct | print,
1142 digit | print | xdigit, digit | print | xdigit,
1143 digit | print | xdigit, digit | print | xdigit,
1144 digit | print | xdigit, digit | print | xdigit,
1145 digit | print | xdigit, digit | print | xdigit,
1146 digit | print | xdigit, digit | print | xdigit,
1147 punct | print, punct | print,
1148 punct | print, punct | print,
1149 punct | print, punct | print,
1150 punct | print, upper | xdigit | print | alpha,
1151 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1152 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1153 upper | xdigit | 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, upper | print | alpha,
1162 upper | print | alpha, upper | print | alpha,
1163 upper | print | alpha, punct | print,
1164 punct | print, punct | print,
1165 punct | print, punct | print,
1166 punct | print, lower | xdigit | print | alpha,
1167 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1168 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1169 lower | xdigit | 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, lower | print | alpha,
1178 lower | print | alpha, lower | print | alpha,
1179 lower | print | alpha, punct | print,
1180 punct | print, punct | print,
1181 punct | print, cntrl,
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1190 };
1191 return builtin_table;
1192}
1193#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001194const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001195ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001196{
David Chisnall1d581062011-09-21 08:39:44 +00001197#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001198 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001199#elif defined(__NetBSD__)
1200 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001201#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001202 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001203#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001204 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001205#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001206 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001207#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001208 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001209#elif defined(_NEWLIB_VERSION)
1210 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1211 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001212#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001213 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001214#else
David Chisnall8074c342012-02-29 13:05:08 +00001215 // Platform not supported: abort so the person doing the port knows what to
1216 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001217# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001218 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001219 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001220 return NULL;
1221#endif
1222}
Marshall Clowb3f62842015-03-04 16:10:14 +00001223#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001224
Howard Hinnantd7a78632011-09-29 13:33:15 +00001225#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001226const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001227ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001228{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001229 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001230}
1231
1232const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001233ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001234{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001235 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001236}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001237#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001238const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001239ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001240{
1241 return _C_tolower_tab_ + 1;
1242}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001243
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001244const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001245ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001246{
1247 return _C_toupper_tab_ + 1;
1248}
1249
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001250#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001251const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001252ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001253{
1254 return *__ctype_tolower_loc();
1255}
1256
1257const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001258ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001259{
1260 return *__ctype_toupper_loc();
1261}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001262#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001263
Howard Hinnantc51e1022010-05-11 19:42:16 +00001264// template <> class ctype_byname<char>
1265
1266ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1267 : ctype<char>(0, false, refs),
1268 __l(newlocale(LC_ALL_MASK, name, 0))
1269{
1270 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001271 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001272 " failed to construct for " + string(name));
1273}
1274
1275ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1276 : ctype<char>(0, false, refs),
1277 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1278{
1279 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001280 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001281 " failed to construct for " + name);
1282}
1283
1284ctype_byname<char>::~ctype_byname()
1285{
1286 freelocale(__l);
1287}
1288
1289char
1290ctype_byname<char>::do_toupper(char_type c) const
1291{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001292 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001293}
1294
1295const char*
1296ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1297{
1298 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001299 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 return low;
1301}
1302
1303char
1304ctype_byname<char>::do_tolower(char_type c) const
1305{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001306 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001307}
1308
1309const char*
1310ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1311{
1312 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001313 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001314 return low;
1315}
1316
1317// template <> class ctype_byname<wchar_t>
1318
Louis Dionne89258142021-08-23 15:32:36 -04001319#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001320ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1321 : ctype<wchar_t>(refs),
1322 __l(newlocale(LC_ALL_MASK, name, 0))
1323{
1324 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001325 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001326 " failed to construct for " + string(name));
1327}
1328
1329ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1330 : ctype<wchar_t>(refs),
1331 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1332{
1333 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001334 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001335 " failed to construct for " + name);
1336}
1337
1338ctype_byname<wchar_t>::~ctype_byname()
1339{
1340 freelocale(__l);
1341}
1342
1343bool
1344ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1345{
Alexis Huntc2017f12011-07-09 03:40:04 +00001346#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001347 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001348#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001349 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001350 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001351 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1352 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1353 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1354 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1355 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1356 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1357 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1358 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1359 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1360 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001361 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001362#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001363}
1364
1365const wchar_t*
1366ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1367{
1368 for (; low != high; ++low, ++vec)
1369 {
1370 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001371 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001372 else
1373 {
1374 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001375 wint_t ch = static_cast<wint_t>(*low);
1376 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001377 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001378#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001379 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001380 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001381#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001382 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001383 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001384 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001385 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001386 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001387 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001388#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001389 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001390 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001391#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001392 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001393 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001394 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001395 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001396#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001397 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001398 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001399#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001400#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001401 if (iswblank_l(ch, __l))
1402 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001403#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404 }
1405 }
1406 return low;
1407}
1408
1409const wchar_t*
1410ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1411{
1412 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001413 {
1414#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001415 if (iswctype_l(*low, m, __l))
1416 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001417#else
Marshall Clowada0f732013-02-07 14:22:51 +00001418 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001419 if ((m & space) == space && iswspace_l(ch, __l)) break;
1420 if ((m & print) == print && iswprint_l(ch, __l)) break;
1421 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1422 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1423 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1424 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1425 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1426 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1427 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1428 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001429#endif
1430 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001431 return low;
1432}
1433
1434const wchar_t*
1435ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1436{
1437 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001438 {
1439#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001440 if (!iswctype_l(*low, m, __l))
1441 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001442#else
Marshall Clowada0f732013-02-07 14:22:51 +00001443 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001444 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1445 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1446 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1447 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1448 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1449 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1450 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1451 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1452 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1453 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001454 break;
1455#endif
1456 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001457 return low;
1458}
1459
1460wchar_t
1461ctype_byname<wchar_t>::do_toupper(char_type c) const
1462{
1463 return towupper_l(c, __l);
1464}
1465
1466const wchar_t*
1467ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1468{
1469 for (; low != high; ++low)
1470 *low = towupper_l(*low, __l);
1471 return low;
1472}
1473
1474wchar_t
1475ctype_byname<wchar_t>::do_tolower(char_type c) const
1476{
1477 return towlower_l(c, __l);
1478}
1479
1480const wchar_t*
1481ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1482{
1483 for (; low != high; ++low)
1484 *low = towlower_l(*low, __l);
1485 return low;
1486}
1487
1488wchar_t
1489ctype_byname<wchar_t>::do_widen(char c) const
1490{
Ben Craig3756b922016-03-09 15:39:39 +00001491 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001492}
1493
1494const char*
1495ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1496{
1497 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001498 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001499 return low;
1500}
1501
1502char
1503ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1504{
Ben Craig3756b922016-03-09 15:39:39 +00001505 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001506 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001507}
1508
1509const wchar_t*
1510ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1511{
1512 for (; low != high; ++low, ++dest)
1513 {
Ben Craig3756b922016-03-09 15:39:39 +00001514 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001515 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001516 }
1517 return low;
1518}
Louis Dionne89258142021-08-23 15:32:36 -04001519#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001520
1521// template <> class codecvt<char, char, mbstate_t>
1522
Howard Hinnantffb308e2010-08-22 00:03:27 +00001523locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001524
1525codecvt<char, char, mbstate_t>::~codecvt()
1526{
1527}
1528
1529codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001530codecvt<char, char, mbstate_t>::do_out(state_type&,
1531 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001532 extern_type* to, extern_type*, extern_type*& to_nxt) const
1533{
1534 frm_nxt = frm;
1535 to_nxt = to;
1536 return noconv;
1537}
1538
1539codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001540codecvt<char, char, mbstate_t>::do_in(state_type&,
1541 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001542 intern_type* to, intern_type*, intern_type*& to_nxt) const
1543{
1544 frm_nxt = frm;
1545 to_nxt = to;
1546 return noconv;
1547}
1548
1549codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001550codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001551 extern_type* to, extern_type*, extern_type*& to_nxt) const
1552{
1553 to_nxt = to;
1554 return noconv;
1555}
1556
1557int
Louis Dionne65358e12021-03-01 12:09:45 -05001558codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001559{
1560 return 1;
1561}
1562
1563bool
Louis Dionne65358e12021-03-01 12:09:45 -05001564codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001565{
1566 return true;
1567}
1568
1569int
1570codecvt<char, char, mbstate_t>::do_length(state_type&,
1571 const extern_type* frm, const extern_type* end, size_t mx) const
1572{
Howard Hinnant28b24882011-12-01 20:21:04 +00001573 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001574}
1575
1576int
Louis Dionne65358e12021-03-01 12:09:45 -05001577codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001578{
1579 return 1;
1580}
1581
1582// template <> class codecvt<wchar_t, char, mbstate_t>
1583
Louis Dionne89258142021-08-23 15:32:36 -04001584#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantffb308e2010-08-22 00:03:27 +00001585locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001586
1587codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1588 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001589 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001590{
1591}
1592
1593codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1594 : locale::facet(refs),
1595 __l(newlocale(LC_ALL_MASK, nm, 0))
1596{
1597 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001598 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001599 " failed to construct for " + string(nm));
1600}
1601
1602codecvt<wchar_t, char, mbstate_t>::~codecvt()
1603{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001604 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001605 freelocale(__l);
1606}
1607
1608codecvt<wchar_t, char, mbstate_t>::result
1609codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001610 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1612{
1613 // look for first internal null in frm
1614 const intern_type* fend = frm;
1615 for (; fend != frm_end; ++fend)
1616 if (*fend == 0)
1617 break;
1618 // loop over all null-terminated sequences in frm
1619 to_nxt = to;
1620 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1621 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001622 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001623 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001624 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1625 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001626 if (n == size_t(-1))
1627 {
1628 // need to recover to_nxt
1629 for (to_nxt = to; frm != frm_nxt; ++frm)
1630 {
Ben Craig3756b922016-03-09 15:39:39 +00001631 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001632 if (n == size_t(-1))
1633 break;
1634 to_nxt += n;
1635 }
1636 frm_nxt = frm;
1637 return error;
1638 }
1639 if (n == 0)
1640 return partial;
1641 to_nxt += n;
1642 if (to_nxt == to_end)
1643 break;
1644 if (fend != frm_end) // set up next null terminated sequence
1645 {
1646 // Try to write the terminating null
1647 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001648 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001649 if (n == size_t(-1)) // on error
1650 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001651 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001652 return partial;
1653 for (extern_type* p = tmp; n; --n) // write it
1654 *to_nxt++ = *p++;
1655 ++frm_nxt;
1656 // look for next null in frm
1657 for (fend = frm_nxt; fend != frm_end; ++fend)
1658 if (*fend == 0)
1659 break;
1660 }
1661 }
1662 return frm_nxt == frm_end ? ok : partial;
1663}
1664
1665codecvt<wchar_t, char, mbstate_t>::result
1666codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001667 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001668 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1669{
1670 // look for first internal null in frm
1671 const extern_type* fend = frm;
1672 for (; fend != frm_end; ++fend)
1673 if (*fend == 0)
1674 break;
1675 // loop over all null-terminated sequences in frm
1676 to_nxt = to;
1677 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1678 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001679 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001680 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001681 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1682 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001683 if (n == size_t(-1))
1684 {
1685 // need to recover to_nxt
1686 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1687 {
Ben Craig3756b922016-03-09 15:39:39 +00001688 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1689 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001690 switch (n)
1691 {
1692 case 0:
1693 ++frm;
1694 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001695 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001696 frm_nxt = frm;
1697 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001698 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001699 frm_nxt = frm;
1700 return partial;
1701 default:
1702 frm += n;
1703 break;
1704 }
1705 }
1706 frm_nxt = frm;
1707 return frm_nxt == frm_end ? ok : partial;
1708 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001709 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001710 return error;
1711 to_nxt += n;
1712 if (to_nxt == to_end)
1713 break;
1714 if (fend != frm_end) // set up next null terminated sequence
1715 {
1716 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001717 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001718 if (n != 0) // on error
1719 return error;
1720 ++to_nxt;
1721 ++frm_nxt;
1722 // look for next null in frm
1723 for (fend = frm_nxt; fend != frm_end; ++fend)
1724 if (*fend == 0)
1725 break;
1726 }
1727 }
1728 return frm_nxt == frm_end ? ok : partial;
1729}
1730
1731codecvt<wchar_t, char, mbstate_t>::result
1732codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1733 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1734{
1735 to_nxt = to;
1736 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001737 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001738 if (n == size_t(-1) || n == 0) // on error
1739 return error;
1740 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001741 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001742 return partial;
1743 for (extern_type* p = tmp; n; --n) // write it
1744 *to_nxt++ = *p++;
1745 return ok;
1746}
1747
1748int
Louis Dionne65358e12021-03-01 12:09:45 -05001749codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001750{
Ben Craig3756b922016-03-09 15:39:39 +00001751 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001752 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001753
1754 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001755 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001756 return 1; // which take more than 1 char to form a wchar_t
1757 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001758}
1759
1760bool
Louis Dionne65358e12021-03-01 12:09:45 -05001761codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001762{
1763 return false;
1764}
1765
1766int
1767codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1768 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1769{
1770 int nbytes = 0;
1771 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1772 {
Ben Craig3756b922016-03-09 15:39:39 +00001773 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001774 switch (n)
1775 {
1776 case 0:
1777 ++nbytes;
1778 ++frm;
1779 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001780 case size_t(-1):
1781 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001782 return nbytes;
1783 default:
1784 nbytes += n;
1785 frm += n;
1786 break;
1787 }
1788 }
1789 return nbytes;
1790}
1791
1792int
Louis Dionne65358e12021-03-01 12:09:45 -05001793codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001794{
Ben Craig3756b922016-03-09 15:39:39 +00001795 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001796}
Louis Dionne89258142021-08-23 15:32:36 -04001797#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001798
1799// Valid UTF ranges
1800// UTF-32 UTF-16 UTF-8 # of code points
1801// first second first second third fourth
1802// 000000 - 00007F 0000 - 007F 00 - 7F 127
1803// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1804// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1805// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1806// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1807// 00D800 - 00DFFF invalid
1808// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1809// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1810// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1811// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1812
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001813static
1814codecvt_base::result
1815utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1816 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1817 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1818{
1819 frm_nxt = frm;
1820 to_nxt = to;
1821 if (mode & generate_header)
1822 {
1823 if (to_end-to_nxt < 3)
1824 return codecvt_base::partial;
1825 *to_nxt++ = static_cast<uint8_t>(0xEF);
1826 *to_nxt++ = static_cast<uint8_t>(0xBB);
1827 *to_nxt++ = static_cast<uint8_t>(0xBF);
1828 }
1829 for (; frm_nxt < frm_end; ++frm_nxt)
1830 {
1831 uint16_t wc1 = *frm_nxt;
1832 if (wc1 > Maxcode)
1833 return codecvt_base::error;
1834 if (wc1 < 0x0080)
1835 {
1836 if (to_end-to_nxt < 1)
1837 return codecvt_base::partial;
1838 *to_nxt++ = static_cast<uint8_t>(wc1);
1839 }
1840 else if (wc1 < 0x0800)
1841 {
1842 if (to_end-to_nxt < 2)
1843 return codecvt_base::partial;
1844 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1845 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1846 }
1847 else if (wc1 < 0xD800)
1848 {
1849 if (to_end-to_nxt < 3)
1850 return codecvt_base::partial;
1851 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1852 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1853 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1854 }
1855 else if (wc1 < 0xDC00)
1856 {
1857 if (frm_end-frm_nxt < 2)
1858 return codecvt_base::partial;
1859 uint16_t wc2 = frm_nxt[1];
1860 if ((wc2 & 0xFC00) != 0xDC00)
1861 return codecvt_base::error;
1862 if (to_end-to_nxt < 4)
1863 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001864 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1865 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001866 return codecvt_base::error;
1867 ++frm_nxt;
1868 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1869 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1870 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1871 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1872 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1873 }
1874 else if (wc1 < 0xE000)
1875 {
1876 return codecvt_base::error;
1877 }
1878 else
1879 {
1880 if (to_end-to_nxt < 3)
1881 return codecvt_base::partial;
1882 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1883 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1884 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1885 }
1886 }
1887 return codecvt_base::ok;
1888}
1889
1890static
1891codecvt_base::result
1892utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1893 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1894 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1895{
1896 frm_nxt = frm;
1897 to_nxt = to;
1898 if (mode & generate_header)
1899 {
1900 if (to_end-to_nxt < 3)
1901 return codecvt_base::partial;
1902 *to_nxt++ = static_cast<uint8_t>(0xEF);
1903 *to_nxt++ = static_cast<uint8_t>(0xBB);
1904 *to_nxt++ = static_cast<uint8_t>(0xBF);
1905 }
1906 for (; frm_nxt < frm_end; ++frm_nxt)
1907 {
1908 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1909 if (wc1 > Maxcode)
1910 return codecvt_base::error;
1911 if (wc1 < 0x0080)
1912 {
1913 if (to_end-to_nxt < 1)
1914 return codecvt_base::partial;
1915 *to_nxt++ = static_cast<uint8_t>(wc1);
1916 }
1917 else if (wc1 < 0x0800)
1918 {
1919 if (to_end-to_nxt < 2)
1920 return codecvt_base::partial;
1921 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1922 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1923 }
1924 else if (wc1 < 0xD800)
1925 {
1926 if (to_end-to_nxt < 3)
1927 return codecvt_base::partial;
1928 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1929 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1930 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1931 }
1932 else if (wc1 < 0xDC00)
1933 {
1934 if (frm_end-frm_nxt < 2)
1935 return codecvt_base::partial;
1936 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1937 if ((wc2 & 0xFC00) != 0xDC00)
1938 return codecvt_base::error;
1939 if (to_end-to_nxt < 4)
1940 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001941 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1942 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001943 return codecvt_base::error;
1944 ++frm_nxt;
1945 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1946 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1947 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1948 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1949 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1950 }
1951 else if (wc1 < 0xE000)
1952 {
1953 return codecvt_base::error;
1954 }
1955 else
1956 {
1957 if (to_end-to_nxt < 3)
1958 return codecvt_base::partial;
1959 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1960 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1961 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1962 }
1963 }
1964 return codecvt_base::ok;
1965}
1966
1967static
1968codecvt_base::result
1969utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1970 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1971 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1972{
1973 frm_nxt = frm;
1974 to_nxt = to;
1975 if (mode & consume_header)
1976 {
1977 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1978 frm_nxt[2] == 0xBF)
1979 frm_nxt += 3;
1980 }
1981 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1982 {
1983 uint8_t c1 = *frm_nxt;
1984 if (c1 > Maxcode)
1985 return codecvt_base::error;
1986 if (c1 < 0x80)
1987 {
1988 *to_nxt = static_cast<uint16_t>(c1);
1989 ++frm_nxt;
1990 }
1991 else if (c1 < 0xC2)
1992 {
1993 return codecvt_base::error;
1994 }
1995 else if (c1 < 0xE0)
1996 {
1997 if (frm_end-frm_nxt < 2)
1998 return codecvt_base::partial;
1999 uint8_t c2 = frm_nxt[1];
2000 if ((c2 & 0xC0) != 0x80)
2001 return codecvt_base::error;
2002 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2003 if (t > Maxcode)
2004 return codecvt_base::error;
2005 *to_nxt = t;
2006 frm_nxt += 2;
2007 }
2008 else if (c1 < 0xF0)
2009 {
2010 if (frm_end-frm_nxt < 3)
2011 return codecvt_base::partial;
2012 uint8_t c2 = frm_nxt[1];
2013 uint8_t c3 = frm_nxt[2];
2014 switch (c1)
2015 {
2016 case 0xE0:
2017 if ((c2 & 0xE0) != 0xA0)
2018 return codecvt_base::error;
2019 break;
2020 case 0xED:
2021 if ((c2 & 0xE0) != 0x80)
2022 return codecvt_base::error;
2023 break;
2024 default:
2025 if ((c2 & 0xC0) != 0x80)
2026 return codecvt_base::error;
2027 break;
2028 }
2029 if ((c3 & 0xC0) != 0x80)
2030 return codecvt_base::error;
2031 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2032 | ((c2 & 0x3F) << 6)
2033 | (c3 & 0x3F));
2034 if (t > Maxcode)
2035 return codecvt_base::error;
2036 *to_nxt = t;
2037 frm_nxt += 3;
2038 }
2039 else if (c1 < 0xF5)
2040 {
2041 if (frm_end-frm_nxt < 4)
2042 return codecvt_base::partial;
2043 uint8_t c2 = frm_nxt[1];
2044 uint8_t c3 = frm_nxt[2];
2045 uint8_t c4 = frm_nxt[3];
2046 switch (c1)
2047 {
2048 case 0xF0:
2049 if (!(0x90 <= c2 && c2 <= 0xBF))
2050 return codecvt_base::error;
2051 break;
2052 case 0xF4:
2053 if ((c2 & 0xF0) != 0x80)
2054 return codecvt_base::error;
2055 break;
2056 default:
2057 if ((c2 & 0xC0) != 0x80)
2058 return codecvt_base::error;
2059 break;
2060 }
2061 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2062 return codecvt_base::error;
2063 if (to_end-to_nxt < 2)
2064 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002065 if ((((c1 & 7UL) << 18) +
2066 ((c2 & 0x3FUL) << 12) +
2067 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002068 return codecvt_base::error;
2069 *to_nxt = static_cast<uint16_t>(
2070 0xD800
2071 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2072 | ((c2 & 0x0F) << 2)
2073 | ((c3 & 0x30) >> 4));
2074 *++to_nxt = static_cast<uint16_t>(
2075 0xDC00
2076 | ((c3 & 0x0F) << 6)
2077 | (c4 & 0x3F));
2078 frm_nxt += 4;
2079 }
2080 else
2081 {
2082 return codecvt_base::error;
2083 }
2084 }
2085 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2086}
2087
2088static
2089codecvt_base::result
2090utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2091 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2092 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2093{
2094 frm_nxt = frm;
2095 to_nxt = to;
2096 if (mode & consume_header)
2097 {
2098 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2099 frm_nxt[2] == 0xBF)
2100 frm_nxt += 3;
2101 }
2102 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2103 {
2104 uint8_t c1 = *frm_nxt;
2105 if (c1 > Maxcode)
2106 return codecvt_base::error;
2107 if (c1 < 0x80)
2108 {
2109 *to_nxt = static_cast<uint32_t>(c1);
2110 ++frm_nxt;
2111 }
2112 else if (c1 < 0xC2)
2113 {
2114 return codecvt_base::error;
2115 }
2116 else if (c1 < 0xE0)
2117 {
2118 if (frm_end-frm_nxt < 2)
2119 return codecvt_base::partial;
2120 uint8_t c2 = frm_nxt[1];
2121 if ((c2 & 0xC0) != 0x80)
2122 return codecvt_base::error;
2123 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2124 if (t > Maxcode)
2125 return codecvt_base::error;
2126 *to_nxt = static_cast<uint32_t>(t);
2127 frm_nxt += 2;
2128 }
2129 else if (c1 < 0xF0)
2130 {
2131 if (frm_end-frm_nxt < 3)
2132 return codecvt_base::partial;
2133 uint8_t c2 = frm_nxt[1];
2134 uint8_t c3 = frm_nxt[2];
2135 switch (c1)
2136 {
2137 case 0xE0:
2138 if ((c2 & 0xE0) != 0xA0)
2139 return codecvt_base::error;
2140 break;
2141 case 0xED:
2142 if ((c2 & 0xE0) != 0x80)
2143 return codecvt_base::error;
2144 break;
2145 default:
2146 if ((c2 & 0xC0) != 0x80)
2147 return codecvt_base::error;
2148 break;
2149 }
2150 if ((c3 & 0xC0) != 0x80)
2151 return codecvt_base::error;
2152 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2153 | ((c2 & 0x3F) << 6)
2154 | (c3 & 0x3F));
2155 if (t > Maxcode)
2156 return codecvt_base::error;
2157 *to_nxt = static_cast<uint32_t>(t);
2158 frm_nxt += 3;
2159 }
2160 else if (c1 < 0xF5)
2161 {
2162 if (frm_end-frm_nxt < 4)
2163 return codecvt_base::partial;
2164 uint8_t c2 = frm_nxt[1];
2165 uint8_t c3 = frm_nxt[2];
2166 uint8_t c4 = frm_nxt[3];
2167 switch (c1)
2168 {
2169 case 0xF0:
2170 if (!(0x90 <= c2 && c2 <= 0xBF))
2171 return codecvt_base::error;
2172 break;
2173 case 0xF4:
2174 if ((c2 & 0xF0) != 0x80)
2175 return codecvt_base::error;
2176 break;
2177 default:
2178 if ((c2 & 0xC0) != 0x80)
2179 return codecvt_base::error;
2180 break;
2181 }
2182 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2183 return codecvt_base::error;
2184 if (to_end-to_nxt < 2)
2185 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002186 if ((((c1 & 7UL) << 18) +
2187 ((c2 & 0x3FUL) << 12) +
2188 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002189 return codecvt_base::error;
2190 *to_nxt = static_cast<uint32_t>(
2191 0xD800
2192 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2193 | ((c2 & 0x0F) << 2)
2194 | ((c3 & 0x30) >> 4));
2195 *++to_nxt = static_cast<uint32_t>(
2196 0xDC00
2197 | ((c3 & 0x0F) << 6)
2198 | (c4 & 0x3F));
2199 frm_nxt += 4;
2200 }
2201 else
2202 {
2203 return codecvt_base::error;
2204 }
2205 }
2206 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2207}
2208
2209static
2210int
2211utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2212 size_t mx, unsigned long Maxcode = 0x10FFFF,
2213 codecvt_mode mode = codecvt_mode(0))
2214{
2215 const uint8_t* frm_nxt = frm;
2216 if (mode & consume_header)
2217 {
2218 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2219 frm_nxt[2] == 0xBF)
2220 frm_nxt += 3;
2221 }
2222 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2223 {
2224 uint8_t c1 = *frm_nxt;
2225 if (c1 > Maxcode)
2226 break;
2227 if (c1 < 0x80)
2228 {
2229 ++frm_nxt;
2230 }
2231 else if (c1 < 0xC2)
2232 {
2233 break;
2234 }
2235 else if (c1 < 0xE0)
2236 {
2237 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2238 break;
2239 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2240 if (t > Maxcode)
2241 break;
2242 frm_nxt += 2;
2243 }
2244 else if (c1 < 0xF0)
2245 {
2246 if (frm_end-frm_nxt < 3)
2247 break;
2248 uint8_t c2 = frm_nxt[1];
2249 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002250 switch (c1)
2251 {
2252 case 0xE0:
2253 if ((c2 & 0xE0) != 0xA0)
2254 return static_cast<int>(frm_nxt - frm);
2255 break;
2256 case 0xED:
2257 if ((c2 & 0xE0) != 0x80)
2258 return static_cast<int>(frm_nxt - frm);
2259 break;
2260 default:
2261 if ((c2 & 0xC0) != 0x80)
2262 return static_cast<int>(frm_nxt - frm);
2263 break;
2264 }
2265 if ((c3 & 0xC0) != 0x80)
2266 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002267 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002268 break;
2269 frm_nxt += 3;
2270 }
2271 else if (c1 < 0xF5)
2272 {
2273 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2274 break;
2275 uint8_t c2 = frm_nxt[1];
2276 uint8_t c3 = frm_nxt[2];
2277 uint8_t c4 = frm_nxt[3];
2278 switch (c1)
2279 {
2280 case 0xF0:
2281 if (!(0x90 <= c2 && c2 <= 0xBF))
2282 return static_cast<int>(frm_nxt - frm);
2283 break;
2284 case 0xF4:
2285 if ((c2 & 0xF0) != 0x80)
2286 return static_cast<int>(frm_nxt - frm);
2287 break;
2288 default:
2289 if ((c2 & 0xC0) != 0x80)
2290 return static_cast<int>(frm_nxt - frm);
2291 break;
2292 }
2293 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2294 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002295 if ((((c1 & 7UL) << 18) +
2296 ((c2 & 0x3FUL) << 12) +
2297 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002298 break;
2299 ++nchar16_t;
2300 frm_nxt += 4;
2301 }
2302 else
2303 {
2304 break;
2305 }
2306 }
2307 return static_cast<int>(frm_nxt - frm);
2308}
2309
2310static
2311codecvt_base::result
2312ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2313 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2314 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2315{
2316 frm_nxt = frm;
2317 to_nxt = to;
2318 if (mode & generate_header)
2319 {
2320 if (to_end-to_nxt < 3)
2321 return codecvt_base::partial;
2322 *to_nxt++ = static_cast<uint8_t>(0xEF);
2323 *to_nxt++ = static_cast<uint8_t>(0xBB);
2324 *to_nxt++ = static_cast<uint8_t>(0xBF);
2325 }
2326 for (; frm_nxt < frm_end; ++frm_nxt)
2327 {
2328 uint32_t wc = *frm_nxt;
2329 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2330 return codecvt_base::error;
2331 if (wc < 0x000080)
2332 {
2333 if (to_end-to_nxt < 1)
2334 return codecvt_base::partial;
2335 *to_nxt++ = static_cast<uint8_t>(wc);
2336 }
2337 else if (wc < 0x000800)
2338 {
2339 if (to_end-to_nxt < 2)
2340 return codecvt_base::partial;
2341 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2342 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2343 }
2344 else if (wc < 0x010000)
2345 {
2346 if (to_end-to_nxt < 3)
2347 return codecvt_base::partial;
2348 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2349 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2350 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2351 }
2352 else // if (wc < 0x110000)
2353 {
2354 if (to_end-to_nxt < 4)
2355 return codecvt_base::partial;
2356 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2357 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2358 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2359 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2360 }
2361 }
2362 return codecvt_base::ok;
2363}
2364
2365static
2366codecvt_base::result
2367utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2368 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2369 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2370{
2371 frm_nxt = frm;
2372 to_nxt = to;
2373 if (mode & consume_header)
2374 {
2375 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2376 frm_nxt[2] == 0xBF)
2377 frm_nxt += 3;
2378 }
2379 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2380 {
2381 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2382 if (c1 < 0x80)
2383 {
2384 if (c1 > Maxcode)
2385 return codecvt_base::error;
2386 *to_nxt = static_cast<uint32_t>(c1);
2387 ++frm_nxt;
2388 }
2389 else if (c1 < 0xC2)
2390 {
2391 return codecvt_base::error;
2392 }
2393 else if (c1 < 0xE0)
2394 {
2395 if (frm_end-frm_nxt < 2)
2396 return codecvt_base::partial;
2397 uint8_t c2 = frm_nxt[1];
2398 if ((c2 & 0xC0) != 0x80)
2399 return codecvt_base::error;
2400 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2401 | (c2 & 0x3F));
2402 if (t > Maxcode)
2403 return codecvt_base::error;
2404 *to_nxt = t;
2405 frm_nxt += 2;
2406 }
2407 else if (c1 < 0xF0)
2408 {
2409 if (frm_end-frm_nxt < 3)
2410 return codecvt_base::partial;
2411 uint8_t c2 = frm_nxt[1];
2412 uint8_t c3 = frm_nxt[2];
2413 switch (c1)
2414 {
2415 case 0xE0:
2416 if ((c2 & 0xE0) != 0xA0)
2417 return codecvt_base::error;
2418 break;
2419 case 0xED:
2420 if ((c2 & 0xE0) != 0x80)
2421 return codecvt_base::error;
2422 break;
2423 default:
2424 if ((c2 & 0xC0) != 0x80)
2425 return codecvt_base::error;
2426 break;
2427 }
2428 if ((c3 & 0xC0) != 0x80)
2429 return codecvt_base::error;
2430 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2431 | ((c2 & 0x3F) << 6)
2432 | (c3 & 0x3F));
2433 if (t > Maxcode)
2434 return codecvt_base::error;
2435 *to_nxt = t;
2436 frm_nxt += 3;
2437 }
2438 else if (c1 < 0xF5)
2439 {
2440 if (frm_end-frm_nxt < 4)
2441 return codecvt_base::partial;
2442 uint8_t c2 = frm_nxt[1];
2443 uint8_t c3 = frm_nxt[2];
2444 uint8_t c4 = frm_nxt[3];
2445 switch (c1)
2446 {
2447 case 0xF0:
2448 if (!(0x90 <= c2 && c2 <= 0xBF))
2449 return codecvt_base::error;
2450 break;
2451 case 0xF4:
2452 if ((c2 & 0xF0) != 0x80)
2453 return codecvt_base::error;
2454 break;
2455 default:
2456 if ((c2 & 0xC0) != 0x80)
2457 return codecvt_base::error;
2458 break;
2459 }
2460 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2461 return codecvt_base::error;
2462 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2463 | ((c2 & 0x3F) << 12)
2464 | ((c3 & 0x3F) << 6)
2465 | (c4 & 0x3F));
2466 if (t > Maxcode)
2467 return codecvt_base::error;
2468 *to_nxt = t;
2469 frm_nxt += 4;
2470 }
2471 else
2472 {
2473 return codecvt_base::error;
2474 }
2475 }
2476 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2477}
2478
2479static
2480int
2481utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2482 size_t mx, unsigned long Maxcode = 0x10FFFF,
2483 codecvt_mode mode = codecvt_mode(0))
2484{
2485 const uint8_t* frm_nxt = frm;
2486 if (mode & consume_header)
2487 {
2488 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2489 frm_nxt[2] == 0xBF)
2490 frm_nxt += 3;
2491 }
2492 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2493 {
2494 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2495 if (c1 < 0x80)
2496 {
2497 if (c1 > Maxcode)
2498 break;
2499 ++frm_nxt;
2500 }
2501 else if (c1 < 0xC2)
2502 {
2503 break;
2504 }
2505 else if (c1 < 0xE0)
2506 {
2507 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2508 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002509 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002510 break;
2511 frm_nxt += 2;
2512 }
2513 else if (c1 < 0xF0)
2514 {
2515 if (frm_end-frm_nxt < 3)
2516 break;
2517 uint8_t c2 = frm_nxt[1];
2518 uint8_t c3 = frm_nxt[2];
2519 switch (c1)
2520 {
2521 case 0xE0:
2522 if ((c2 & 0xE0) != 0xA0)
2523 return static_cast<int>(frm_nxt - frm);
2524 break;
2525 case 0xED:
2526 if ((c2 & 0xE0) != 0x80)
2527 return static_cast<int>(frm_nxt - frm);
2528 break;
2529 default:
2530 if ((c2 & 0xC0) != 0x80)
2531 return static_cast<int>(frm_nxt - frm);
2532 break;
2533 }
2534 if ((c3 & 0xC0) != 0x80)
2535 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002536 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002537 break;
2538 frm_nxt += 3;
2539 }
2540 else if (c1 < 0xF5)
2541 {
2542 if (frm_end-frm_nxt < 4)
2543 break;
2544 uint8_t c2 = frm_nxt[1];
2545 uint8_t c3 = frm_nxt[2];
2546 uint8_t c4 = frm_nxt[3];
2547 switch (c1)
2548 {
2549 case 0xF0:
2550 if (!(0x90 <= c2 && c2 <= 0xBF))
2551 return static_cast<int>(frm_nxt - frm);
2552 break;
2553 case 0xF4:
2554 if ((c2 & 0xF0) != 0x80)
2555 return static_cast<int>(frm_nxt - frm);
2556 break;
2557 default:
2558 if ((c2 & 0xC0) != 0x80)
2559 return static_cast<int>(frm_nxt - frm);
2560 break;
2561 }
2562 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2563 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002564 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2565 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002566 break;
2567 frm_nxt += 4;
2568 }
2569 else
2570 {
2571 break;
2572 }
2573 }
2574 return static_cast<int>(frm_nxt - frm);
2575}
2576
2577static
2578codecvt_base::result
2579ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2580 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2581 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2582{
2583 frm_nxt = frm;
2584 to_nxt = to;
2585 if (mode & generate_header)
2586 {
2587 if (to_end-to_nxt < 3)
2588 return codecvt_base::partial;
2589 *to_nxt++ = static_cast<uint8_t>(0xEF);
2590 *to_nxt++ = static_cast<uint8_t>(0xBB);
2591 *to_nxt++ = static_cast<uint8_t>(0xBF);
2592 }
2593 for (; frm_nxt < frm_end; ++frm_nxt)
2594 {
2595 uint16_t wc = *frm_nxt;
2596 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2597 return codecvt_base::error;
2598 if (wc < 0x0080)
2599 {
2600 if (to_end-to_nxt < 1)
2601 return codecvt_base::partial;
2602 *to_nxt++ = static_cast<uint8_t>(wc);
2603 }
2604 else if (wc < 0x0800)
2605 {
2606 if (to_end-to_nxt < 2)
2607 return codecvt_base::partial;
2608 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2609 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2610 }
2611 else // if (wc <= 0xFFFF)
2612 {
2613 if (to_end-to_nxt < 3)
2614 return codecvt_base::partial;
2615 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2616 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2617 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2618 }
2619 }
2620 return codecvt_base::ok;
2621}
2622
2623static
2624codecvt_base::result
2625utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2626 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2627 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2628{
2629 frm_nxt = frm;
2630 to_nxt = to;
2631 if (mode & consume_header)
2632 {
2633 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2634 frm_nxt[2] == 0xBF)
2635 frm_nxt += 3;
2636 }
2637 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2638 {
2639 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2640 if (c1 < 0x80)
2641 {
2642 if (c1 > Maxcode)
2643 return codecvt_base::error;
2644 *to_nxt = static_cast<uint16_t>(c1);
2645 ++frm_nxt;
2646 }
2647 else if (c1 < 0xC2)
2648 {
2649 return codecvt_base::error;
2650 }
2651 else if (c1 < 0xE0)
2652 {
2653 if (frm_end-frm_nxt < 2)
2654 return codecvt_base::partial;
2655 uint8_t c2 = frm_nxt[1];
2656 if ((c2 & 0xC0) != 0x80)
2657 return codecvt_base::error;
2658 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2659 | (c2 & 0x3F));
2660 if (t > Maxcode)
2661 return codecvt_base::error;
2662 *to_nxt = t;
2663 frm_nxt += 2;
2664 }
2665 else if (c1 < 0xF0)
2666 {
2667 if (frm_end-frm_nxt < 3)
2668 return codecvt_base::partial;
2669 uint8_t c2 = frm_nxt[1];
2670 uint8_t c3 = frm_nxt[2];
2671 switch (c1)
2672 {
2673 case 0xE0:
2674 if ((c2 & 0xE0) != 0xA0)
2675 return codecvt_base::error;
2676 break;
2677 case 0xED:
2678 if ((c2 & 0xE0) != 0x80)
2679 return codecvt_base::error;
2680 break;
2681 default:
2682 if ((c2 & 0xC0) != 0x80)
2683 return codecvt_base::error;
2684 break;
2685 }
2686 if ((c3 & 0xC0) != 0x80)
2687 return codecvt_base::error;
2688 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2689 | ((c2 & 0x3F) << 6)
2690 | (c3 & 0x3F));
2691 if (t > Maxcode)
2692 return codecvt_base::error;
2693 *to_nxt = t;
2694 frm_nxt += 3;
2695 }
2696 else
2697 {
2698 return codecvt_base::error;
2699 }
2700 }
2701 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2702}
2703
2704static
2705int
2706utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2707 size_t mx, unsigned long Maxcode = 0x10FFFF,
2708 codecvt_mode mode = codecvt_mode(0))
2709{
2710 const uint8_t* frm_nxt = frm;
2711 if (mode & consume_header)
2712 {
2713 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2714 frm_nxt[2] == 0xBF)
2715 frm_nxt += 3;
2716 }
2717 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2718 {
2719 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2720 if (c1 < 0x80)
2721 {
2722 if (c1 > Maxcode)
2723 break;
2724 ++frm_nxt;
2725 }
2726 else if (c1 < 0xC2)
2727 {
2728 break;
2729 }
2730 else if (c1 < 0xE0)
2731 {
2732 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2733 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002734 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002735 break;
2736 frm_nxt += 2;
2737 }
2738 else if (c1 < 0xF0)
2739 {
2740 if (frm_end-frm_nxt < 3)
2741 break;
2742 uint8_t c2 = frm_nxt[1];
2743 uint8_t c3 = frm_nxt[2];
2744 switch (c1)
2745 {
2746 case 0xE0:
2747 if ((c2 & 0xE0) != 0xA0)
2748 return static_cast<int>(frm_nxt - frm);
2749 break;
2750 case 0xED:
2751 if ((c2 & 0xE0) != 0x80)
2752 return static_cast<int>(frm_nxt - frm);
2753 break;
2754 default:
2755 if ((c2 & 0xC0) != 0x80)
2756 return static_cast<int>(frm_nxt - frm);
2757 break;
2758 }
2759 if ((c3 & 0xC0) != 0x80)
2760 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002761 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002762 break;
2763 frm_nxt += 3;
2764 }
2765 else
2766 {
2767 break;
2768 }
2769 }
2770 return static_cast<int>(frm_nxt - frm);
2771}
2772
2773static
2774codecvt_base::result
2775ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2776 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2777 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2778{
2779 frm_nxt = frm;
2780 to_nxt = to;
2781 if (mode & generate_header)
2782 {
2783 if (to_end-to_nxt < 2)
2784 return codecvt_base::partial;
2785 *to_nxt++ = static_cast<uint8_t>(0xFE);
2786 *to_nxt++ = static_cast<uint8_t>(0xFF);
2787 }
2788 for (; frm_nxt < frm_end; ++frm_nxt)
2789 {
2790 uint32_t wc = *frm_nxt;
2791 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2792 return codecvt_base::error;
2793 if (wc < 0x010000)
2794 {
2795 if (to_end-to_nxt < 2)
2796 return codecvt_base::partial;
2797 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2798 *to_nxt++ = static_cast<uint8_t>(wc);
2799 }
2800 else
2801 {
2802 if (to_end-to_nxt < 4)
2803 return codecvt_base::partial;
2804 uint16_t t = static_cast<uint16_t>(
2805 0xD800
2806 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2807 | ((wc & 0x00FC00) >> 10));
2808 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2809 *to_nxt++ = static_cast<uint8_t>(t);
2810 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2811 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2812 *to_nxt++ = static_cast<uint8_t>(t);
2813 }
2814 }
2815 return codecvt_base::ok;
2816}
2817
2818static
2819codecvt_base::result
2820utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2821 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2822 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2823{
2824 frm_nxt = frm;
2825 to_nxt = to;
2826 if (mode & consume_header)
2827 {
2828 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2829 frm_nxt += 2;
2830 }
2831 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2832 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002833 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002834 if ((c1 & 0xFC00) == 0xDC00)
2835 return codecvt_base::error;
2836 if ((c1 & 0xFC00) != 0xD800)
2837 {
2838 if (c1 > Maxcode)
2839 return codecvt_base::error;
2840 *to_nxt = static_cast<uint32_t>(c1);
2841 frm_nxt += 2;
2842 }
2843 else
2844 {
2845 if (frm_end-frm_nxt < 4)
2846 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002847 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002848 if ((c2 & 0xFC00) != 0xDC00)
2849 return codecvt_base::error;
2850 uint32_t t = static_cast<uint32_t>(
2851 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2852 | ((c1 & 0x003F) << 10)
2853 | (c2 & 0x03FF));
2854 if (t > Maxcode)
2855 return codecvt_base::error;
2856 *to_nxt = t;
2857 frm_nxt += 4;
2858 }
2859 }
2860 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2861}
2862
2863static
2864int
2865utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2866 size_t mx, unsigned long Maxcode = 0x10FFFF,
2867 codecvt_mode mode = codecvt_mode(0))
2868{
2869 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002870 if (mode & consume_header)
2871 {
2872 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2873 frm_nxt += 2;
2874 }
2875 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2876 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002877 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002878 if ((c1 & 0xFC00) == 0xDC00)
2879 break;
2880 if ((c1 & 0xFC00) != 0xD800)
2881 {
2882 if (c1 > Maxcode)
2883 break;
2884 frm_nxt += 2;
2885 }
2886 else
2887 {
2888 if (frm_end-frm_nxt < 4)
2889 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002890 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002891 if ((c2 & 0xFC00) != 0xDC00)
2892 break;
2893 uint32_t t = static_cast<uint32_t>(
2894 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2895 | ((c1 & 0x003F) << 10)
2896 | (c2 & 0x03FF));
2897 if (t > Maxcode)
2898 break;
2899 frm_nxt += 4;
2900 }
2901 }
2902 return static_cast<int>(frm_nxt - frm);
2903}
2904
2905static
2906codecvt_base::result
2907ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2908 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2909 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2910{
2911 frm_nxt = frm;
2912 to_nxt = to;
2913 if (mode & generate_header)
2914 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002915 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002916 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002917 *to_nxt++ = static_cast<uint8_t>(0xFF);
2918 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002919 }
2920 for (; frm_nxt < frm_end; ++frm_nxt)
2921 {
2922 uint32_t wc = *frm_nxt;
2923 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2924 return codecvt_base::error;
2925 if (wc < 0x010000)
2926 {
2927 if (to_end-to_nxt < 2)
2928 return codecvt_base::partial;
2929 *to_nxt++ = static_cast<uint8_t>(wc);
2930 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2931 }
2932 else
2933 {
2934 if (to_end-to_nxt < 4)
2935 return codecvt_base::partial;
2936 uint16_t t = static_cast<uint16_t>(
2937 0xD800
2938 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2939 | ((wc & 0x00FC00) >> 10));
2940 *to_nxt++ = static_cast<uint8_t>(t);
2941 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2942 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2943 *to_nxt++ = static_cast<uint8_t>(t);
2944 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2945 }
2946 }
2947 return codecvt_base::ok;
2948}
2949
2950static
2951codecvt_base::result
2952utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2953 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2954 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2955{
2956 frm_nxt = frm;
2957 to_nxt = to;
2958 if (mode & consume_header)
2959 {
2960 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2961 frm_nxt += 2;
2962 }
2963 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2964 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002965 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002966 if ((c1 & 0xFC00) == 0xDC00)
2967 return codecvt_base::error;
2968 if ((c1 & 0xFC00) != 0xD800)
2969 {
2970 if (c1 > Maxcode)
2971 return codecvt_base::error;
2972 *to_nxt = static_cast<uint32_t>(c1);
2973 frm_nxt += 2;
2974 }
2975 else
2976 {
2977 if (frm_end-frm_nxt < 4)
2978 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002979 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002980 if ((c2 & 0xFC00) != 0xDC00)
2981 return codecvt_base::error;
2982 uint32_t t = static_cast<uint32_t>(
2983 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2984 | ((c1 & 0x003F) << 10)
2985 | (c2 & 0x03FF));
2986 if (t > Maxcode)
2987 return codecvt_base::error;
2988 *to_nxt = t;
2989 frm_nxt += 4;
2990 }
2991 }
2992 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2993}
2994
2995static
2996int
2997utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2998 size_t mx, unsigned long Maxcode = 0x10FFFF,
2999 codecvt_mode mode = codecvt_mode(0))
3000{
3001 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003002 if (mode & consume_header)
3003 {
3004 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3005 frm_nxt += 2;
3006 }
3007 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3008 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003009 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003010 if ((c1 & 0xFC00) == 0xDC00)
3011 break;
3012 if ((c1 & 0xFC00) != 0xD800)
3013 {
3014 if (c1 > Maxcode)
3015 break;
3016 frm_nxt += 2;
3017 }
3018 else
3019 {
3020 if (frm_end-frm_nxt < 4)
3021 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00003022 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003023 if ((c2 & 0xFC00) != 0xDC00)
3024 break;
3025 uint32_t t = static_cast<uint32_t>(
3026 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3027 | ((c1 & 0x003F) << 10)
3028 | (c2 & 0x03FF));
3029 if (t > Maxcode)
3030 break;
3031 frm_nxt += 4;
3032 }
3033 }
3034 return static_cast<int>(frm_nxt - frm);
3035}
3036
3037static
3038codecvt_base::result
3039ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3040 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3041 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3042{
3043 frm_nxt = frm;
3044 to_nxt = to;
3045 if (mode & generate_header)
3046 {
3047 if (to_end-to_nxt < 2)
3048 return codecvt_base::partial;
3049 *to_nxt++ = static_cast<uint8_t>(0xFE);
3050 *to_nxt++ = static_cast<uint8_t>(0xFF);
3051 }
3052 for (; frm_nxt < frm_end; ++frm_nxt)
3053 {
3054 uint16_t wc = *frm_nxt;
3055 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3056 return codecvt_base::error;
3057 if (to_end-to_nxt < 2)
3058 return codecvt_base::partial;
3059 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3060 *to_nxt++ = static_cast<uint8_t>(wc);
3061 }
3062 return codecvt_base::ok;
3063}
3064
3065static
3066codecvt_base::result
3067utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3068 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3069 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3070{
3071 frm_nxt = frm;
3072 to_nxt = to;
3073 if (mode & consume_header)
3074 {
3075 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3076 frm_nxt += 2;
3077 }
3078 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3079 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003080 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003081 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3082 return codecvt_base::error;
3083 *to_nxt = c1;
3084 frm_nxt += 2;
3085 }
3086 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3087}
3088
3089static
3090int
3091utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3092 size_t mx, unsigned long Maxcode = 0x10FFFF,
3093 codecvt_mode mode = codecvt_mode(0))
3094{
3095 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003096 if (mode & consume_header)
3097 {
3098 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3099 frm_nxt += 2;
3100 }
3101 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3102 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003103 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003104 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3105 break;
3106 frm_nxt += 2;
3107 }
3108 return static_cast<int>(frm_nxt - frm);
3109}
3110
3111static
3112codecvt_base::result
3113ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3114 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3115 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3116{
3117 frm_nxt = frm;
3118 to_nxt = to;
3119 if (mode & generate_header)
3120 {
3121 if (to_end-to_nxt < 2)
3122 return codecvt_base::partial;
3123 *to_nxt++ = static_cast<uint8_t>(0xFF);
3124 *to_nxt++ = static_cast<uint8_t>(0xFE);
3125 }
3126 for (; frm_nxt < frm_end; ++frm_nxt)
3127 {
3128 uint16_t wc = *frm_nxt;
3129 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3130 return codecvt_base::error;
3131 if (to_end-to_nxt < 2)
3132 return codecvt_base::partial;
3133 *to_nxt++ = static_cast<uint8_t>(wc);
3134 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3135 }
3136 return codecvt_base::ok;
3137}
3138
3139static
3140codecvt_base::result
3141utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3142 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3143 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3144{
3145 frm_nxt = frm;
3146 to_nxt = to;
3147 if (mode & consume_header)
3148 {
3149 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3150 frm_nxt += 2;
3151 }
3152 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3153 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003154 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003155 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3156 return codecvt_base::error;
3157 *to_nxt = c1;
3158 frm_nxt += 2;
3159 }
3160 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3161}
3162
3163static
3164int
3165utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3166 size_t mx, unsigned long Maxcode = 0x10FFFF,
3167 codecvt_mode mode = codecvt_mode(0))
3168{
3169 const uint8_t* frm_nxt = frm;
3170 frm_nxt = frm;
3171 if (mode & consume_header)
3172 {
3173 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3174 frm_nxt += 2;
3175 }
3176 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3177 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003178 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003179 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3180 break;
3181 frm_nxt += 2;
3182 }
3183 return static_cast<int>(frm_nxt - frm);
3184}
3185
Howard Hinnantc51e1022010-05-11 19:42:16 +00003186// template <> class codecvt<char16_t, char, mbstate_t>
3187
Howard Hinnantffb308e2010-08-22 00:03:27 +00003188locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003189
3190codecvt<char16_t, char, mbstate_t>::~codecvt()
3191{
3192}
3193
3194codecvt<char16_t, char, mbstate_t>::result
3195codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003196 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003197 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3198{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003199 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3200 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3201 const uint16_t* _frm_nxt = _frm;
3202 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3203 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3204 uint8_t* _to_nxt = _to;
3205 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3206 frm_nxt = frm + (_frm_nxt - _frm);
3207 to_nxt = to + (_to_nxt - _to);
3208 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003209}
3210
3211codecvt<char16_t, char, mbstate_t>::result
3212codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003213 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003214 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3215{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003216 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3217 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3218 const uint8_t* _frm_nxt = _frm;
3219 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3220 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3221 uint16_t* _to_nxt = _to;
3222 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3223 frm_nxt = frm + (_frm_nxt - _frm);
3224 to_nxt = to + (_to_nxt - _to);
3225 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003226}
3227
3228codecvt<char16_t, char, mbstate_t>::result
3229codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3230 extern_type* to, extern_type*, extern_type*& to_nxt) const
3231{
3232 to_nxt = to;
3233 return noconv;
3234}
3235
3236int
Louis Dionne65358e12021-03-01 12:09:45 -05003237codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003238{
3239 return 0;
3240}
3241
3242bool
Louis Dionne65358e12021-03-01 12:09:45 -05003243codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003244{
3245 return false;
3246}
3247
3248int
3249codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3250 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3251{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003252 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3253 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3254 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003255}
3256
3257int
Louis Dionne65358e12021-03-01 12:09:45 -05003258codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003259{
3260 return 4;
3261}
3262
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003263#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003264
3265// template <> class codecvt<char16_t, char8_t, mbstate_t>
3266
3267locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3268
3269codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3270{
3271}
3272
3273codecvt<char16_t, char8_t, mbstate_t>::result
3274codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3275 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3276 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3277{
3278 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3279 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3280 const uint16_t* _frm_nxt = _frm;
3281 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3282 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3283 uint8_t* _to_nxt = _to;
3284 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3285 frm_nxt = frm + (_frm_nxt - _frm);
3286 to_nxt = to + (_to_nxt - _to);
3287 return r;
3288}
3289
3290codecvt<char16_t, char8_t, mbstate_t>::result
3291codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3292 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3293 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3294{
3295 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3296 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3297 const uint8_t* _frm_nxt = _frm;
3298 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3299 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3300 uint16_t* _to_nxt = _to;
3301 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3302 frm_nxt = frm + (_frm_nxt - _frm);
3303 to_nxt = to + (_to_nxt - _to);
3304 return r;
3305}
3306
3307codecvt<char16_t, char8_t, mbstate_t>::result
3308codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3309 extern_type* to, extern_type*, extern_type*& to_nxt) const
3310{
3311 to_nxt = to;
3312 return noconv;
3313}
3314
3315int
Louis Dionne65358e12021-03-01 12:09:45 -05003316codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003317{
3318 return 0;
3319}
3320
3321bool
Louis Dionne65358e12021-03-01 12:09:45 -05003322codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003323{
3324 return false;
3325}
3326
3327int
3328codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3329 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3330{
3331 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3332 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3333 return utf8_to_utf16_length(_frm, _frm_end, mx);
3334}
3335
3336int
Louis Dionne65358e12021-03-01 12:09:45 -05003337codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003338{
3339 return 4;
3340}
3341
3342#endif
3343
Howard Hinnantc51e1022010-05-11 19:42:16 +00003344// template <> class codecvt<char32_t, char, mbstate_t>
3345
Howard Hinnantffb308e2010-08-22 00:03:27 +00003346locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003347
3348codecvt<char32_t, char, mbstate_t>::~codecvt()
3349{
3350}
3351
3352codecvt<char32_t, char, mbstate_t>::result
3353codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003354 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003355 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3356{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003357 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3358 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3359 const uint32_t* _frm_nxt = _frm;
3360 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3361 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3362 uint8_t* _to_nxt = _to;
3363 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3364 frm_nxt = frm + (_frm_nxt - _frm);
3365 to_nxt = to + (_to_nxt - _to);
3366 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003367}
3368
3369codecvt<char32_t, char, mbstate_t>::result
3370codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003371 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003372 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3373{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003374 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3375 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3376 const uint8_t* _frm_nxt = _frm;
3377 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3378 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3379 uint32_t* _to_nxt = _to;
3380 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3381 frm_nxt = frm + (_frm_nxt - _frm);
3382 to_nxt = to + (_to_nxt - _to);
3383 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003384}
3385
3386codecvt<char32_t, char, mbstate_t>::result
3387codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3388 extern_type* to, extern_type*, extern_type*& to_nxt) const
3389{
3390 to_nxt = to;
3391 return noconv;
3392}
3393
3394int
Louis Dionne65358e12021-03-01 12:09:45 -05003395codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003396{
3397 return 0;
3398}
3399
3400bool
Louis Dionne65358e12021-03-01 12:09:45 -05003401codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003402{
3403 return false;
3404}
3405
3406int
3407codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3408 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3409{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003410 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3411 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3412 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003413}
3414
3415int
Louis Dionne65358e12021-03-01 12:09:45 -05003416codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003417{
3418 return 4;
3419}
3420
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003421#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003422
3423// template <> class codecvt<char32_t, char8_t, mbstate_t>
3424
3425locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3426
3427codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3428{
3429}
3430
3431codecvt<char32_t, char8_t, mbstate_t>::result
3432codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3433 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3434 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3435{
3436 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3437 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3438 const uint32_t* _frm_nxt = _frm;
3439 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3440 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3441 uint8_t* _to_nxt = _to;
3442 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3443 frm_nxt = frm + (_frm_nxt - _frm);
3444 to_nxt = to + (_to_nxt - _to);
3445 return r;
3446}
3447
3448codecvt<char32_t, char8_t, mbstate_t>::result
3449codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3450 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3451 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3452{
3453 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3454 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3455 const uint8_t* _frm_nxt = _frm;
3456 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3457 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3458 uint32_t* _to_nxt = _to;
3459 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3460 frm_nxt = frm + (_frm_nxt - _frm);
3461 to_nxt = to + (_to_nxt - _to);
3462 return r;
3463}
3464
3465codecvt<char32_t, char8_t, mbstate_t>::result
3466codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3467 extern_type* to, extern_type*, extern_type*& to_nxt) const
3468{
3469 to_nxt = to;
3470 return noconv;
3471}
3472
3473int
Louis Dionne65358e12021-03-01 12:09:45 -05003474codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003475{
3476 return 0;
3477}
3478
3479bool
Louis Dionne65358e12021-03-01 12:09:45 -05003480codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003481{
3482 return false;
3483}
3484
3485int
3486codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3487 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3488{
3489 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3490 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3491 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3492}
3493
3494int
Louis Dionne65358e12021-03-01 12:09:45 -05003495codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003496{
3497 return 4;
3498}
3499
3500#endif
3501
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003502// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003503
Louis Dionne89258142021-08-23 15:32:36 -04003504#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003505__codecvt_utf8<wchar_t>::result
3506__codecvt_utf8<wchar_t>::do_out(state_type&,
3507 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003508 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3509{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003510#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003511 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3512 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3513 const uint16_t* _frm_nxt = _frm;
3514#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003515 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3516 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3517 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003518#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003519 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3520 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3521 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003522#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003523 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3524 _Maxcode_, _Mode_);
3525#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003526 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3527 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003528#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003529 frm_nxt = frm + (_frm_nxt - _frm);
3530 to_nxt = to + (_to_nxt - _to);
3531 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003532}
3533
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003534__codecvt_utf8<wchar_t>::result
3535__codecvt_utf8<wchar_t>::do_in(state_type&,
3536 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003537 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3538{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003539 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3540 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3541 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003542#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003543 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3544 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3545 uint16_t* _to_nxt = _to;
3546 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3547 _Maxcode_, _Mode_);
3548#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003549 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3550 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3551 uint32_t* _to_nxt = _to;
3552 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3553 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003554#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003555 frm_nxt = frm + (_frm_nxt - _frm);
3556 to_nxt = to + (_to_nxt - _to);
3557 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003558}
3559
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003560__codecvt_utf8<wchar_t>::result
3561__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003562 extern_type* to, extern_type*, extern_type*& to_nxt) const
3563{
3564 to_nxt = to;
3565 return noconv;
3566}
3567
3568int
Louis Dionne65358e12021-03-01 12:09:45 -05003569__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003570{
3571 return 0;
3572}
3573
3574bool
Louis Dionne65358e12021-03-01 12:09:45 -05003575__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003576{
3577 return false;
3578}
3579
3580int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003581__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003582 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3583{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003584 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3585 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003586#if defined(_LIBCPP_SHORT_WCHAR)
3587 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3588#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003589 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003590#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003591}
3592
3593int
Louis Dionne65358e12021-03-01 12:09:45 -05003594__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003595{
Xing Xue50b0eb42021-09-09 16:20:36 -04003596#if defined(_LIBCPP_SHORT_WCHAR)
3597 if (_Mode_ & consume_header)
3598 return 6;
3599 return 3;
3600#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003601 if (_Mode_ & consume_header)
3602 return 7;
3603 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003604#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003605}
Louis Dionne89258142021-08-23 15:32:36 -04003606#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003607
3608// __codecvt_utf8<char16_t>
3609
3610__codecvt_utf8<char16_t>::result
3611__codecvt_utf8<char16_t>::do_out(state_type&,
3612 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3613 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3614{
3615 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3616 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3617 const uint16_t* _frm_nxt = _frm;
3618 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3619 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3620 uint8_t* _to_nxt = _to;
3621 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3622 _Maxcode_, _Mode_);
3623 frm_nxt = frm + (_frm_nxt - _frm);
3624 to_nxt = to + (_to_nxt - _to);
3625 return r;
3626}
3627
3628__codecvt_utf8<char16_t>::result
3629__codecvt_utf8<char16_t>::do_in(state_type&,
3630 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3631 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3632{
3633 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3634 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3635 const uint8_t* _frm_nxt = _frm;
3636 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3637 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3638 uint16_t* _to_nxt = _to;
3639 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3640 _Maxcode_, _Mode_);
3641 frm_nxt = frm + (_frm_nxt - _frm);
3642 to_nxt = to + (_to_nxt - _to);
3643 return r;
3644}
3645
3646__codecvt_utf8<char16_t>::result
3647__codecvt_utf8<char16_t>::do_unshift(state_type&,
3648 extern_type* to, extern_type*, extern_type*& to_nxt) const
3649{
3650 to_nxt = to;
3651 return noconv;
3652}
3653
3654int
Louis Dionne65358e12021-03-01 12:09:45 -05003655__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003656{
3657 return 0;
3658}
3659
3660bool
Louis Dionne65358e12021-03-01 12:09:45 -05003661__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003662{
3663 return false;
3664}
3665
3666int
3667__codecvt_utf8<char16_t>::do_length(state_type&,
3668 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3669{
3670 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3671 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3672 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3673}
3674
3675int
Louis Dionne65358e12021-03-01 12:09:45 -05003676__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003677{
3678 if (_Mode_ & consume_header)
3679 return 6;
3680 return 3;
3681}
3682
3683// __codecvt_utf8<char32_t>
3684
3685__codecvt_utf8<char32_t>::result
3686__codecvt_utf8<char32_t>::do_out(state_type&,
3687 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3688 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3689{
3690 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3691 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3692 const uint32_t* _frm_nxt = _frm;
3693 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3694 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3695 uint8_t* _to_nxt = _to;
3696 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3697 _Maxcode_, _Mode_);
3698 frm_nxt = frm + (_frm_nxt - _frm);
3699 to_nxt = to + (_to_nxt - _to);
3700 return r;
3701}
3702
3703__codecvt_utf8<char32_t>::result
3704__codecvt_utf8<char32_t>::do_in(state_type&,
3705 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3706 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3707{
3708 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3709 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3710 const uint8_t* _frm_nxt = _frm;
3711 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3712 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3713 uint32_t* _to_nxt = _to;
3714 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3715 _Maxcode_, _Mode_);
3716 frm_nxt = frm + (_frm_nxt - _frm);
3717 to_nxt = to + (_to_nxt - _to);
3718 return r;
3719}
3720
3721__codecvt_utf8<char32_t>::result
3722__codecvt_utf8<char32_t>::do_unshift(state_type&,
3723 extern_type* to, extern_type*, extern_type*& to_nxt) const
3724{
3725 to_nxt = to;
3726 return noconv;
3727}
3728
3729int
Louis Dionne65358e12021-03-01 12:09:45 -05003730__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003731{
3732 return 0;
3733}
3734
3735bool
Louis Dionne65358e12021-03-01 12:09:45 -05003736__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003737{
3738 return false;
3739}
3740
3741int
3742__codecvt_utf8<char32_t>::do_length(state_type&,
3743 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3744{
3745 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3746 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3747 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3748}
3749
3750int
Louis Dionne65358e12021-03-01 12:09:45 -05003751__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003752{
3753 if (_Mode_ & consume_header)
3754 return 7;
3755 return 4;
3756}
3757
3758// __codecvt_utf16<wchar_t, false>
3759
Louis Dionne89258142021-08-23 15:32:36 -04003760#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003761__codecvt_utf16<wchar_t, false>::result
3762__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3763 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3764 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3765{
Xing Xue50b0eb42021-09-09 16:20:36 -04003766#if defined(_LIBCPP_SHORT_WCHAR)
3767 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3768 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3769 const uint16_t* _frm_nxt = _frm;
3770#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003771 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3772 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3773 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003774#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003775 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3776 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3777 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003778#if defined(_LIBCPP_SHORT_WCHAR)
3779 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3780 _Maxcode_, _Mode_);
3781#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003782 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3783 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003784#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003785 frm_nxt = frm + (_frm_nxt - _frm);
3786 to_nxt = to + (_to_nxt - _to);
3787 return r;
3788}
3789
3790__codecvt_utf16<wchar_t, false>::result
3791__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3792 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3793 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3794{
3795 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3796 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3797 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003798#if defined(_LIBCPP_SHORT_WCHAR)
3799 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3800 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3801 uint16_t* _to_nxt = _to;
3802 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3803 _Maxcode_, _Mode_);
3804#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003805 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3806 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3807 uint32_t* _to_nxt = _to;
3808 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3809 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003810#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003811 frm_nxt = frm + (_frm_nxt - _frm);
3812 to_nxt = to + (_to_nxt - _to);
3813 return r;
3814}
3815
3816__codecvt_utf16<wchar_t, false>::result
3817__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3818 extern_type* to, extern_type*, extern_type*& to_nxt) const
3819{
3820 to_nxt = to;
3821 return noconv;
3822}
3823
3824int
Louis Dionne65358e12021-03-01 12:09:45 -05003825__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003826{
3827 return 0;
3828}
3829
3830bool
Louis Dionne65358e12021-03-01 12:09:45 -05003831__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003832{
3833 return false;
3834}
3835
3836int
3837__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3838 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3839{
3840 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3841 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003842#if defined(_LIBCPP_SHORT_WCHAR)
3843 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3844#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003845 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003846#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003847}
3848
3849int
Louis Dionne65358e12021-03-01 12:09:45 -05003850__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003851{
Xing Xue50b0eb42021-09-09 16:20:36 -04003852#if defined(_LIBCPP_SHORT_WCHAR)
3853 if (_Mode_ & consume_header)
3854 return 4;
3855 return 2;
3856#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003857 if (_Mode_ & consume_header)
3858 return 6;
3859 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003860#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003861}
3862
3863// __codecvt_utf16<wchar_t, true>
3864
3865__codecvt_utf16<wchar_t, true>::result
3866__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3867 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3868 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3869{
Xing Xue50b0eb42021-09-09 16:20:36 -04003870#if defined(_LIBCPP_SHORT_WCHAR)
3871 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3872 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3873 const uint16_t* _frm_nxt = _frm;
3874#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003875 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3876 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3877 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003878#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003879 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3880 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3881 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003882#if defined(_LIBCPP_SHORT_WCHAR)
3883 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3884 _Maxcode_, _Mode_);
3885#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003886 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3887 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003888#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003889 frm_nxt = frm + (_frm_nxt - _frm);
3890 to_nxt = to + (_to_nxt - _to);
3891 return r;
3892}
3893
3894__codecvt_utf16<wchar_t, true>::result
3895__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3896 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3897 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3898{
3899 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3900 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3901 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003902#if defined(_LIBCPP_SHORT_WCHAR)
3903 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3904 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3905 uint16_t* _to_nxt = _to;
3906 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3907 _Maxcode_, _Mode_);
3908#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003909 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3910 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3911 uint32_t* _to_nxt = _to;
3912 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3913 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003914#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003915 frm_nxt = frm + (_frm_nxt - _frm);
3916 to_nxt = to + (_to_nxt - _to);
3917 return r;
3918}
3919
3920__codecvt_utf16<wchar_t, true>::result
3921__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3922 extern_type* to, extern_type*, extern_type*& to_nxt) const
3923{
3924 to_nxt = to;
3925 return noconv;
3926}
3927
3928int
Louis Dionne65358e12021-03-01 12:09:45 -05003929__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003930{
3931 return 0;
3932}
3933
3934bool
Louis Dionne65358e12021-03-01 12:09:45 -05003935__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003936{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003937 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003938}
3939
3940int
3941__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3942 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3943{
3944 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3945 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003946#if defined(_LIBCPP_SHORT_WCHAR)
3947 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3948#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003949 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003950#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003951}
3952
3953int
Louis Dionne65358e12021-03-01 12:09:45 -05003954__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003955{
Xing Xue50b0eb42021-09-09 16:20:36 -04003956#if defined(_LIBCPP_SHORT_WCHAR)
3957 if (_Mode_ & consume_header)
3958 return 4;
3959 return 2;
3960#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003961 if (_Mode_ & consume_header)
3962 return 6;
3963 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003964#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003965}
Louis Dionne89258142021-08-23 15:32:36 -04003966#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003967
3968// __codecvt_utf16<char16_t, false>
3969
3970__codecvt_utf16<char16_t, false>::result
3971__codecvt_utf16<char16_t, false>::do_out(state_type&,
3972 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3973 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3974{
3975 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3976 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3977 const uint16_t* _frm_nxt = _frm;
3978 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3979 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3980 uint8_t* _to_nxt = _to;
3981 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3982 _Maxcode_, _Mode_);
3983 frm_nxt = frm + (_frm_nxt - _frm);
3984 to_nxt = to + (_to_nxt - _to);
3985 return r;
3986}
3987
3988__codecvt_utf16<char16_t, false>::result
3989__codecvt_utf16<char16_t, false>::do_in(state_type&,
3990 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3991 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3992{
3993 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3994 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3995 const uint8_t* _frm_nxt = _frm;
3996 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3997 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3998 uint16_t* _to_nxt = _to;
3999 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4000 _Maxcode_, _Mode_);
4001 frm_nxt = frm + (_frm_nxt - _frm);
4002 to_nxt = to + (_to_nxt - _to);
4003 return r;
4004}
4005
4006__codecvt_utf16<char16_t, false>::result
4007__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4008 extern_type* to, extern_type*, extern_type*& to_nxt) const
4009{
4010 to_nxt = to;
4011 return noconv;
4012}
4013
4014int
Louis Dionne65358e12021-03-01 12:09:45 -05004015__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004016{
4017 return 0;
4018}
4019
4020bool
Louis Dionne65358e12021-03-01 12:09:45 -05004021__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004022{
4023 return false;
4024}
4025
4026int
4027__codecvt_utf16<char16_t, false>::do_length(state_type&,
4028 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4029{
4030 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4031 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4032 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4033}
4034
4035int
Louis Dionne65358e12021-03-01 12:09:45 -05004036__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004037{
4038 if (_Mode_ & consume_header)
4039 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004040 return 2;
4041}
4042
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004043// __codecvt_utf16<char16_t, true>
4044
4045__codecvt_utf16<char16_t, true>::result
4046__codecvt_utf16<char16_t, true>::do_out(state_type&,
4047 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4048 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4049{
4050 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4051 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4052 const uint16_t* _frm_nxt = _frm;
4053 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4054 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4055 uint8_t* _to_nxt = _to;
4056 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4057 _Maxcode_, _Mode_);
4058 frm_nxt = frm + (_frm_nxt - _frm);
4059 to_nxt = to + (_to_nxt - _to);
4060 return r;
4061}
4062
4063__codecvt_utf16<char16_t, true>::result
4064__codecvt_utf16<char16_t, true>::do_in(state_type&,
4065 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4066 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4067{
4068 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4069 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4070 const uint8_t* _frm_nxt = _frm;
4071 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4072 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4073 uint16_t* _to_nxt = _to;
4074 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4075 _Maxcode_, _Mode_);
4076 frm_nxt = frm + (_frm_nxt - _frm);
4077 to_nxt = to + (_to_nxt - _to);
4078 return r;
4079}
4080
4081__codecvt_utf16<char16_t, true>::result
4082__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4083 extern_type* to, extern_type*, extern_type*& to_nxt) const
4084{
4085 to_nxt = to;
4086 return noconv;
4087}
4088
4089int
Louis Dionne65358e12021-03-01 12:09:45 -05004090__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004091{
4092 return 0;
4093}
4094
4095bool
Louis Dionne65358e12021-03-01 12:09:45 -05004096__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004097{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004098 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004099}
4100
4101int
4102__codecvt_utf16<char16_t, true>::do_length(state_type&,
4103 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4104{
4105 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4106 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4107 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4108}
4109
4110int
Louis Dionne65358e12021-03-01 12:09:45 -05004111__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004112{
4113 if (_Mode_ & consume_header)
4114 return 4;
4115 return 2;
4116}
4117
4118// __codecvt_utf16<char32_t, false>
4119
4120__codecvt_utf16<char32_t, false>::result
4121__codecvt_utf16<char32_t, false>::do_out(state_type&,
4122 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4123 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4124{
4125 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4126 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4127 const uint32_t* _frm_nxt = _frm;
4128 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4129 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4130 uint8_t* _to_nxt = _to;
4131 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4132 _Maxcode_, _Mode_);
4133 frm_nxt = frm + (_frm_nxt - _frm);
4134 to_nxt = to + (_to_nxt - _to);
4135 return r;
4136}
4137
4138__codecvt_utf16<char32_t, false>::result
4139__codecvt_utf16<char32_t, false>::do_in(state_type&,
4140 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4141 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4142{
4143 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4144 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4145 const uint8_t* _frm_nxt = _frm;
4146 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4147 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4148 uint32_t* _to_nxt = _to;
4149 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4150 _Maxcode_, _Mode_);
4151 frm_nxt = frm + (_frm_nxt - _frm);
4152 to_nxt = to + (_to_nxt - _to);
4153 return r;
4154}
4155
4156__codecvt_utf16<char32_t, false>::result
4157__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4158 extern_type* to, extern_type*, extern_type*& to_nxt) const
4159{
4160 to_nxt = to;
4161 return noconv;
4162}
4163
4164int
Louis Dionne65358e12021-03-01 12:09:45 -05004165__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004166{
4167 return 0;
4168}
4169
4170bool
Louis Dionne65358e12021-03-01 12:09:45 -05004171__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004172{
4173 return false;
4174}
4175
4176int
4177__codecvt_utf16<char32_t, false>::do_length(state_type&,
4178 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4179{
4180 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4181 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4182 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4183}
4184
4185int
Louis Dionne65358e12021-03-01 12:09:45 -05004186__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004187{
4188 if (_Mode_ & consume_header)
4189 return 6;
4190 return 4;
4191}
4192
4193// __codecvt_utf16<char32_t, true>
4194
4195__codecvt_utf16<char32_t, true>::result
4196__codecvt_utf16<char32_t, true>::do_out(state_type&,
4197 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4198 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4199{
4200 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4201 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4202 const uint32_t* _frm_nxt = _frm;
4203 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4204 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4205 uint8_t* _to_nxt = _to;
4206 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4207 _Maxcode_, _Mode_);
4208 frm_nxt = frm + (_frm_nxt - _frm);
4209 to_nxt = to + (_to_nxt - _to);
4210 return r;
4211}
4212
4213__codecvt_utf16<char32_t, true>::result
4214__codecvt_utf16<char32_t, true>::do_in(state_type&,
4215 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4216 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4217{
4218 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4219 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4220 const uint8_t* _frm_nxt = _frm;
4221 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4222 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4223 uint32_t* _to_nxt = _to;
4224 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4225 _Maxcode_, _Mode_);
4226 frm_nxt = frm + (_frm_nxt - _frm);
4227 to_nxt = to + (_to_nxt - _to);
4228 return r;
4229}
4230
4231__codecvt_utf16<char32_t, true>::result
4232__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4233 extern_type* to, extern_type*, extern_type*& to_nxt) const
4234{
4235 to_nxt = to;
4236 return noconv;
4237}
4238
4239int
Louis Dionne65358e12021-03-01 12:09:45 -05004240__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004241{
4242 return 0;
4243}
4244
4245bool
Louis Dionne65358e12021-03-01 12:09:45 -05004246__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004247{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004248 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004249}
4250
4251int
4252__codecvt_utf16<char32_t, true>::do_length(state_type&,
4253 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4254{
4255 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4256 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4257 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4258}
4259
4260int
Louis Dionne65358e12021-03-01 12:09:45 -05004261__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004262{
4263 if (_Mode_ & consume_header)
4264 return 6;
4265 return 4;
4266}
4267
4268// __codecvt_utf8_utf16<wchar_t>
4269
Louis Dionne89258142021-08-23 15:32:36 -04004270#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004271__codecvt_utf8_utf16<wchar_t>::result
4272__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4273 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4274 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4275{
Xing Xue50b0eb42021-09-09 16:20:36 -04004276#if defined(_LIBCPP_SHORT_WCHAR)
4277 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4278 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4279 const uint16_t* _frm_nxt = _frm;
4280#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004281 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4282 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4283 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004284#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004285 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4286 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4287 uint8_t* _to_nxt = _to;
4288 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4289 _Maxcode_, _Mode_);
4290 frm_nxt = frm + (_frm_nxt - _frm);
4291 to_nxt = to + (_to_nxt - _to);
4292 return r;
4293}
4294
4295__codecvt_utf8_utf16<wchar_t>::result
4296__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4297 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4298 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4299{
4300 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4301 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4302 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004303#if defined(_LIBCPP_SHORT_WCHAR)
4304 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4305 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4306 uint16_t* _to_nxt = _to;
4307#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004308 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4309 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4310 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004311#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004312 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4313 _Maxcode_, _Mode_);
4314 frm_nxt = frm + (_frm_nxt - _frm);
4315 to_nxt = to + (_to_nxt - _to);
4316 return r;
4317}
4318
4319__codecvt_utf8_utf16<wchar_t>::result
4320__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4321 extern_type* to, extern_type*, extern_type*& to_nxt) const
4322{
4323 to_nxt = to;
4324 return noconv;
4325}
4326
4327int
Louis Dionne65358e12021-03-01 12:09:45 -05004328__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004329{
4330 return 0;
4331}
4332
4333bool
Louis Dionne65358e12021-03-01 12:09:45 -05004334__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004335{
4336 return false;
4337}
4338
4339int
4340__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4341 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4342{
4343 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4344 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4345 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4346}
4347
4348int
Louis Dionne65358e12021-03-01 12:09:45 -05004349__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004350{
4351 if (_Mode_ & consume_header)
4352 return 7;
4353 return 4;
4354}
Louis Dionne89258142021-08-23 15:32:36 -04004355#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004356
4357// __codecvt_utf8_utf16<char16_t>
4358
4359__codecvt_utf8_utf16<char16_t>::result
4360__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4361 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4362 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4363{
4364 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4365 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4366 const uint16_t* _frm_nxt = _frm;
4367 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4368 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4369 uint8_t* _to_nxt = _to;
4370 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4371 _Maxcode_, _Mode_);
4372 frm_nxt = frm + (_frm_nxt - _frm);
4373 to_nxt = to + (_to_nxt - _to);
4374 return r;
4375}
4376
4377__codecvt_utf8_utf16<char16_t>::result
4378__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4379 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4380 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4381{
4382 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4383 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4384 const uint8_t* _frm_nxt = _frm;
4385 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4386 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4387 uint16_t* _to_nxt = _to;
4388 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4389 _Maxcode_, _Mode_);
4390 frm_nxt = frm + (_frm_nxt - _frm);
4391 to_nxt = to + (_to_nxt - _to);
4392 return r;
4393}
4394
4395__codecvt_utf8_utf16<char16_t>::result
4396__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4397 extern_type* to, extern_type*, extern_type*& to_nxt) const
4398{
4399 to_nxt = to;
4400 return noconv;
4401}
4402
4403int
Louis Dionne65358e12021-03-01 12:09:45 -05004404__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004405{
4406 return 0;
4407}
4408
4409bool
Louis Dionne65358e12021-03-01 12:09:45 -05004410__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004411{
4412 return false;
4413}
4414
4415int
4416__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4417 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4418{
4419 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4420 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4421 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4422}
4423
4424int
Louis Dionne65358e12021-03-01 12:09:45 -05004425__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004426{
4427 if (_Mode_ & consume_header)
4428 return 7;
4429 return 4;
4430}
4431
4432// __codecvt_utf8_utf16<char32_t>
4433
4434__codecvt_utf8_utf16<char32_t>::result
4435__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4436 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4437 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4438{
4439 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4440 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4441 const uint32_t* _frm_nxt = _frm;
4442 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4443 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4444 uint8_t* _to_nxt = _to;
4445 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4446 _Maxcode_, _Mode_);
4447 frm_nxt = frm + (_frm_nxt - _frm);
4448 to_nxt = to + (_to_nxt - _to);
4449 return r;
4450}
4451
4452__codecvt_utf8_utf16<char32_t>::result
4453__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4454 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4455 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4456{
4457 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4458 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4459 const uint8_t* _frm_nxt = _frm;
4460 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4461 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4462 uint32_t* _to_nxt = _to;
4463 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4464 _Maxcode_, _Mode_);
4465 frm_nxt = frm + (_frm_nxt - _frm);
4466 to_nxt = to + (_to_nxt - _to);
4467 return r;
4468}
4469
4470__codecvt_utf8_utf16<char32_t>::result
4471__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4472 extern_type* to, extern_type*, extern_type*& to_nxt) const
4473{
4474 to_nxt = to;
4475 return noconv;
4476}
4477
4478int
Louis Dionne65358e12021-03-01 12:09:45 -05004479__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004480{
4481 return 0;
4482}
4483
4484bool
Louis Dionne65358e12021-03-01 12:09:45 -05004485__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004486{
4487 return false;
4488}
4489
4490int
4491__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4492 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4493{
4494 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4495 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4496 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4497}
4498
4499int
Louis Dionne65358e12021-03-01 12:09:45 -05004500__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004501{
4502 if (_Mode_ & consume_header)
4503 return 7;
4504 return 4;
4505}
4506
Howard Hinnantc51e1022010-05-11 19:42:16 +00004507// __narrow_to_utf8<16>
4508
4509__narrow_to_utf8<16>::~__narrow_to_utf8()
4510{
4511}
4512
4513// __narrow_to_utf8<32>
4514
4515__narrow_to_utf8<32>::~__narrow_to_utf8()
4516{
4517}
4518
4519// __widen_from_utf8<16>
4520
4521__widen_from_utf8<16>::~__widen_from_utf8()
4522{
4523}
4524
4525// __widen_from_utf8<32>
4526
4527__widen_from_utf8<32>::~__widen_from_utf8()
4528{
4529}
4530
Louis Dionne89258142021-08-23 15:32:36 -04004531#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004532static bool checked_string_to_wchar_convert(wchar_t& dest,
4533 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004534 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004535 if (*ptr == '\0')
4536 return false;
4537 mbstate_t mb = {};
4538 wchar_t out;
4539 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4540 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4541 return false;
4542 }
4543 dest = out;
4544 return true;
4545}
Louis Dionne89258142021-08-23 15:32:36 -04004546#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004547
Mark de Weverffed1402021-11-03 19:25:20 +01004548#ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4549static bool is_narrow_non_breaking_space(const char* ptr) {
4550 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4551 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4552}
4553
4554static bool is_non_breaking_space(const char* ptr) {
4555 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4556 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4557}
4558#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4559
Eric Fiselierbf945a22016-12-11 00:20:59 +00004560static bool checked_string_to_char_convert(char& dest,
4561 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004562 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004563 if (*ptr == '\0')
4564 return false;
4565 if (!ptr[1]) {
4566 dest = *ptr;
4567 return true;
4568 }
Louis Dionne89258142021-08-23 15:32:36 -04004569
4570#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004571 // First convert the MBS into a wide char then attempt to narrow it using
4572 // wctob_l.
4573 wchar_t wout;
4574 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4575 return false;
4576 int res;
4577 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4578 dest = res;
4579 return true;
4580 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004581 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004582 // translate into a different single byte.
4583 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004584 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004585 case L'\u00A0': // non-breaking space
4586 dest = ' ';
4587 return true;
4588 default:
4589 return false;
4590 }
Louis Dionne89258142021-08-23 15:32:36 -04004591#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverffed1402021-11-03 19:25:20 +01004592 // FIXME: Work around specific multibyte sequences that we can reasonably
4593 // translate into a different single byte.
4594 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4595 dest = ' ';
4596 return true;
4597 }
4598
Louis Dionne89258142021-08-23 15:32:36 -04004599 return false;
4600#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004601 _LIBCPP_UNREACHABLE();
4602}
4603
4604
Howard Hinnantc51e1022010-05-11 19:42:16 +00004605// numpunct<char> && numpunct<wchar_t>
4606
4607locale::id numpunct< char >::id;
Louis Dionne89258142021-08-23 15:32:36 -04004608#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004609locale::id numpunct<wchar_t>::id;
Louis Dionne89258142021-08-23 15:32:36 -04004610#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004611
4612numpunct<char>::numpunct(size_t refs)
4613 : locale::facet(refs),
4614 __decimal_point_('.'),
4615 __thousands_sep_(',')
4616{
4617}
4618
Louis Dionne89258142021-08-23 15:32:36 -04004619#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004620numpunct<wchar_t>::numpunct(size_t refs)
4621 : locale::facet(refs),
4622 __decimal_point_(L'.'),
4623 __thousands_sep_(L',')
4624{
4625}
Louis Dionne89258142021-08-23 15:32:36 -04004626#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004627
4628numpunct<char>::~numpunct()
4629{
4630}
4631
Louis Dionne89258142021-08-23 15:32:36 -04004632#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004633numpunct<wchar_t>::~numpunct()
4634{
4635}
Louis Dionne89258142021-08-23 15:32:36 -04004636#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004637
4638 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004639#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004640wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004641#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004642
4643 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004644#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004645wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004646#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004647
4648string numpunct< char >::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004649#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004650string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004651#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004652
4653 string numpunct< char >::do_truename() const {return "true";}
Louis Dionne89258142021-08-23 15:32:36 -04004654#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004655wstring numpunct<wchar_t>::do_truename() const {return L"true";}
Louis Dionne89258142021-08-23 15:32:36 -04004656#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004657
4658 string numpunct< char >::do_falsename() const {return "false";}
Louis Dionne89258142021-08-23 15:32:36 -04004659#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004660wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
Louis Dionne89258142021-08-23 15:32:36 -04004661#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004662
4663// numpunct_byname<char>
4664
4665numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4666 : numpunct<char>(refs)
4667{
4668 __init(nm);
4669}
4670
4671numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4672 : numpunct<char>(refs)
4673{
4674 __init(nm.c_str());
4675}
4676
4677numpunct_byname<char>::~numpunct_byname()
4678{
4679}
4680
4681void
4682numpunct_byname<char>::__init(const char* nm)
4683{
Louis Dionne89258142021-08-23 15:32:36 -04004684 typedef numpunct<char> base;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004685 if (strcmp(nm, "C") != 0)
4686 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004687 __libcpp_unique_locale loc(nm);
4688 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004689 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004690 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004691
Ben Craig3756b922016-03-09 15:39:39 +00004692 lconv* lc = __libcpp_localeconv_l(loc.get());
Louis Dionne89258142021-08-23 15:32:36 -04004693 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4694 loc.get()))
4695 __decimal_point_ = base::do_decimal_point();
4696 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4697 loc.get()))
4698 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00004699 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004700 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004701 }
4702}
4703
4704// numpunct_byname<wchar_t>
4705
Louis Dionne89258142021-08-23 15:32:36 -04004706#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004707numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4708 : numpunct<wchar_t>(refs)
4709{
4710 __init(nm);
4711}
4712
4713numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4714 : numpunct<wchar_t>(refs)
4715{
4716 __init(nm.c_str());
4717}
4718
4719numpunct_byname<wchar_t>::~numpunct_byname()
4720{
4721}
4722
4723void
4724numpunct_byname<wchar_t>::__init(const char* nm)
4725{
4726 if (strcmp(nm, "C") != 0)
4727 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004728 __libcpp_unique_locale loc(nm);
4729 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004730 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004731 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004732
Ben Craig3756b922016-03-09 15:39:39 +00004733 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004734 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4735 loc.get());
4736 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4737 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004738 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004739 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004740 }
4741}
Louis Dionne89258142021-08-23 15:32:36 -04004742#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004743
4744// num_get helpers
4745
4746int
4747__num_get_base::__get_base(ios_base& iob)
4748{
4749 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4750 if (__basefield == ios_base::oct)
4751 return 8;
4752 else if (__basefield == ios_base::hex)
4753 return 16;
4754 else if (__basefield == 0)
4755 return 0;
4756 return 10;
4757}
4758
4759const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4760
4761void
4762__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4763 ios_base::iostate& __err)
4764{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004765// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4766// 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 +00004767 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004768 {
4769 reverse(__g, __g_end);
4770 const char* __ig = __grouping.data();
4771 const char* __eg = __ig + __grouping.size();
4772 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4773 {
4774 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4775 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004776 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004777 {
4778 __err = ios_base::failbit;
4779 return;
4780 }
4781 }
4782 if (__eg - __ig > 1)
4783 ++__ig;
4784 }
4785 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4786 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004787 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004788 __err = ios_base::failbit;
4789 }
4790 }
4791}
4792
4793void
4794__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4795 ios_base::fmtflags __flags)
4796{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004797 if ((__flags & ios_base::showpos) &&
4798 (__flags & ios_base::basefield) != ios_base::oct &&
4799 (__flags & ios_base::basefield) != ios_base::hex &&
4800 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004801 *__fmtp++ = '+';
4802 if (__flags & ios_base::showbase)
4803 *__fmtp++ = '#';
4804 while(*__len)
4805 *__fmtp++ = *__len++;
4806 if ((__flags & ios_base::basefield) == ios_base::oct)
4807 *__fmtp = 'o';
4808 else if ((__flags & ios_base::basefield) == ios_base::hex)
4809 {
4810 if (__flags & ios_base::uppercase)
4811 *__fmtp = 'X';
4812 else
4813 *__fmtp = 'x';
4814 }
4815 else if (__signd)
4816 *__fmtp = 'd';
4817 else
4818 *__fmtp = 'u';
4819}
4820
4821bool
4822__num_put_base::__format_float(char* __fmtp, const char* __len,
4823 ios_base::fmtflags __flags)
4824{
4825 bool specify_precision = true;
4826 if (__flags & ios_base::showpos)
4827 *__fmtp++ = '+';
4828 if (__flags & ios_base::showpoint)
4829 *__fmtp++ = '#';
4830 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004831 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004832 if (floatfield == (ios_base::fixed | ios_base::scientific))
4833 specify_precision = false;
4834 else
4835 {
4836 *__fmtp++ = '.';
4837 *__fmtp++ = '*';
4838 }
4839 while(*__len)
4840 *__fmtp++ = *__len++;
4841 if (floatfield == ios_base::fixed)
4842 {
4843 if (uppercase)
4844 *__fmtp = 'F';
4845 else
4846 *__fmtp = 'f';
4847 }
4848 else if (floatfield == ios_base::scientific)
4849 {
4850 if (uppercase)
4851 *__fmtp = 'E';
4852 else
4853 *__fmtp = 'e';
4854 }
4855 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4856 {
4857 if (uppercase)
4858 *__fmtp = 'A';
4859 else
4860 *__fmtp = 'a';
4861 }
4862 else
4863 {
4864 if (uppercase)
4865 *__fmtp = 'G';
4866 else
4867 *__fmtp = 'g';
4868 }
4869 return specify_precision;
4870}
4871
4872char*
4873__num_put_base::__identify_padding(char* __nb, char* __ne,
4874 const ios_base& __iob)
4875{
4876 switch (__iob.flags() & ios_base::adjustfield)
4877 {
4878 case ios_base::internal:
4879 if (__nb[0] == '-' || __nb[0] == '+')
4880 return __nb+1;
4881 if (__ne - __nb >= 2 && __nb[0] == '0'
4882 && (__nb[1] == 'x' || __nb[1] == 'X'))
4883 return __nb+2;
4884 break;
4885 case ios_base::left:
4886 return __ne;
4887 case ios_base::right:
4888 default:
4889 break;
4890 }
4891 return __nb;
4892}
4893
4894// time_get
4895
4896static
4897string*
4898init_weeks()
4899{
4900 static string weeks[14];
4901 weeks[0] = "Sunday";
4902 weeks[1] = "Monday";
4903 weeks[2] = "Tuesday";
4904 weeks[3] = "Wednesday";
4905 weeks[4] = "Thursday";
4906 weeks[5] = "Friday";
4907 weeks[6] = "Saturday";
4908 weeks[7] = "Sun";
4909 weeks[8] = "Mon";
4910 weeks[9] = "Tue";
4911 weeks[10] = "Wed";
4912 weeks[11] = "Thu";
4913 weeks[12] = "Fri";
4914 weeks[13] = "Sat";
4915 return weeks;
4916}
4917
Louis Dionne89258142021-08-23 15:32:36 -04004918#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004919static
4920wstring*
4921init_wweeks()
4922{
4923 static wstring weeks[14];
4924 weeks[0] = L"Sunday";
4925 weeks[1] = L"Monday";
4926 weeks[2] = L"Tuesday";
4927 weeks[3] = L"Wednesday";
4928 weeks[4] = L"Thursday";
4929 weeks[5] = L"Friday";
4930 weeks[6] = L"Saturday";
4931 weeks[7] = L"Sun";
4932 weeks[8] = L"Mon";
4933 weeks[9] = L"Tue";
4934 weeks[10] = L"Wed";
4935 weeks[11] = L"Thu";
4936 weeks[12] = L"Fri";
4937 weeks[13] = L"Sat";
4938 return weeks;
4939}
Louis Dionne89258142021-08-23 15:32:36 -04004940#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004941
4942template <>
4943const string*
4944__time_get_c_storage<char>::__weeks() const
4945{
4946 static const string* weeks = init_weeks();
4947 return weeks;
4948}
4949
Louis Dionne89258142021-08-23 15:32:36 -04004950#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004951template <>
4952const wstring*
4953__time_get_c_storage<wchar_t>::__weeks() const
4954{
4955 static const wstring* weeks = init_wweeks();
4956 return weeks;
4957}
Louis Dionne89258142021-08-23 15:32:36 -04004958#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004959
4960static
4961string*
4962init_months()
4963{
4964 static string months[24];
4965 months[0] = "January";
4966 months[1] = "February";
4967 months[2] = "March";
4968 months[3] = "April";
4969 months[4] = "May";
4970 months[5] = "June";
4971 months[6] = "July";
4972 months[7] = "August";
4973 months[8] = "September";
4974 months[9] = "October";
4975 months[10] = "November";
4976 months[11] = "December";
4977 months[12] = "Jan";
4978 months[13] = "Feb";
4979 months[14] = "Mar";
4980 months[15] = "Apr";
4981 months[16] = "May";
4982 months[17] = "Jun";
4983 months[18] = "Jul";
4984 months[19] = "Aug";
4985 months[20] = "Sep";
4986 months[21] = "Oct";
4987 months[22] = "Nov";
4988 months[23] = "Dec";
4989 return months;
4990}
4991
Louis Dionne89258142021-08-23 15:32:36 -04004992#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004993static
4994wstring*
4995init_wmonths()
4996{
4997 static wstring months[24];
4998 months[0] = L"January";
4999 months[1] = L"February";
5000 months[2] = L"March";
5001 months[3] = L"April";
5002 months[4] = L"May";
5003 months[5] = L"June";
5004 months[6] = L"July";
5005 months[7] = L"August";
5006 months[8] = L"September";
5007 months[9] = L"October";
5008 months[10] = L"November";
5009 months[11] = L"December";
5010 months[12] = L"Jan";
5011 months[13] = L"Feb";
5012 months[14] = L"Mar";
5013 months[15] = L"Apr";
5014 months[16] = L"May";
5015 months[17] = L"Jun";
5016 months[18] = L"Jul";
5017 months[19] = L"Aug";
5018 months[20] = L"Sep";
5019 months[21] = L"Oct";
5020 months[22] = L"Nov";
5021 months[23] = L"Dec";
5022 return months;
5023}
Louis Dionne89258142021-08-23 15:32:36 -04005024#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005025
5026template <>
5027const string*
5028__time_get_c_storage<char>::__months() const
5029{
5030 static const string* months = init_months();
5031 return months;
5032}
5033
Louis Dionne89258142021-08-23 15:32:36 -04005034#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005035template <>
5036const wstring*
5037__time_get_c_storage<wchar_t>::__months() const
5038{
5039 static const wstring* months = init_wmonths();
5040 return months;
5041}
Louis Dionne89258142021-08-23 15:32:36 -04005042#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005043
5044static
5045string*
5046init_am_pm()
5047{
Marshall Clow5cc04922018-01-11 17:16:52 +00005048 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005049 am_pm[0] = "AM";
5050 am_pm[1] = "PM";
5051 return am_pm;
5052}
5053
Louis Dionne89258142021-08-23 15:32:36 -04005054#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005055static
5056wstring*
5057init_wam_pm()
5058{
Marshall Clow5cc04922018-01-11 17:16:52 +00005059 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005060 am_pm[0] = L"AM";
5061 am_pm[1] = L"PM";
5062 return am_pm;
5063}
Louis Dionne89258142021-08-23 15:32:36 -04005064#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005065
5066template <>
5067const string*
5068__time_get_c_storage<char>::__am_pm() const
5069{
5070 static const string* am_pm = init_am_pm();
5071 return am_pm;
5072}
5073
Louis Dionne89258142021-08-23 15:32:36 -04005074#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005075template <>
5076const wstring*
5077__time_get_c_storage<wchar_t>::__am_pm() const
5078{
5079 static const wstring* am_pm = init_wam_pm();
5080 return am_pm;
5081}
Louis Dionne89258142021-08-23 15:32:36 -04005082#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005083
5084template <>
5085const string&
5086__time_get_c_storage<char>::__x() const
5087{
5088 static string s("%m/%d/%y");
5089 return s;
5090}
5091
Louis Dionne89258142021-08-23 15:32:36 -04005092#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005093template <>
5094const wstring&
5095__time_get_c_storage<wchar_t>::__x() const
5096{
5097 static wstring s(L"%m/%d/%y");
5098 return s;
5099}
Louis Dionne89258142021-08-23 15:32:36 -04005100#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005101
5102template <>
5103const string&
5104__time_get_c_storage<char>::__X() const
5105{
5106 static string s("%H:%M:%S");
5107 return s;
5108}
5109
Louis Dionne89258142021-08-23 15:32:36 -04005110#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005111template <>
5112const wstring&
5113__time_get_c_storage<wchar_t>::__X() const
5114{
5115 static wstring s(L"%H:%M:%S");
5116 return s;
5117}
Louis Dionne89258142021-08-23 15:32:36 -04005118#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005119
5120template <>
5121const string&
5122__time_get_c_storage<char>::__c() const
5123{
5124 static string s("%a %b %d %H:%M:%S %Y");
5125 return s;
5126}
5127
Louis Dionne89258142021-08-23 15:32:36 -04005128#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005129template <>
5130const wstring&
5131__time_get_c_storage<wchar_t>::__c() const
5132{
5133 static wstring s(L"%a %b %d %H:%M:%S %Y");
5134 return s;
5135}
Louis Dionne89258142021-08-23 15:32:36 -04005136#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005137
5138template <>
5139const string&
5140__time_get_c_storage<char>::__r() const
5141{
5142 static string s("%I:%M:%S %p");
5143 return s;
5144}
5145
Louis Dionne89258142021-08-23 15:32:36 -04005146#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005147template <>
5148const wstring&
5149__time_get_c_storage<wchar_t>::__r() const
5150{
5151 static wstring s(L"%I:%M:%S %p");
5152 return s;
5153}
Louis Dionne89258142021-08-23 15:32:36 -04005154#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005155
5156// time_get_byname
5157
5158__time_get::__time_get(const char* nm)
5159 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5160{
5161 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005162 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005163 " failed to construct for " + string(nm));
5164}
5165
5166__time_get::__time_get(const string& nm)
5167 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5168{
5169 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005170 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005171 " failed to construct for " + nm);
5172}
5173
5174__time_get::~__time_get()
5175{
5176 freelocale(__loc_);
5177}
Marshall Clowd920eea2013-10-21 15:07:28 +00005178#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005179#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005180#endif
5181#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00005182#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005183#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005184
Howard Hinnantc51e1022010-05-11 19:42:16 +00005185template <>
5186string
5187__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5188{
Howard Hinnant990207c2012-02-19 14:55:32 +00005189 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005190 t.tm_sec = 59;
5191 t.tm_min = 55;
5192 t.tm_hour = 23;
5193 t.tm_mday = 31;
5194 t.tm_mon = 11;
5195 t.tm_year = 161;
5196 t.tm_wday = 6;
5197 t.tm_yday = 364;
5198 t.tm_isdst = -1;
5199 char buf[100];
5200 char f[3] = {0};
5201 f[0] = '%';
5202 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005203 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005204 char* bb = buf;
5205 char* be = buf + n;
5206 string result;
5207 while (bb != be)
5208 {
5209 if (ct.is(ctype_base::space, *bb))
5210 {
5211 result.push_back(' ');
5212 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5213 ;
5214 continue;
5215 }
5216 char* w = bb;
5217 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005218 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005219 ct, err, false)
5220 - this->__weeks_;
5221 if (i < 14)
5222 {
5223 result.push_back('%');
5224 if (i < 7)
5225 result.push_back('A');
5226 else
5227 result.push_back('a');
5228 bb = w;
5229 continue;
5230 }
5231 w = bb;
5232 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5233 ct, err, false)
5234 - this->__months_;
5235 if (i < 24)
5236 {
5237 result.push_back('%');
5238 if (i < 12)
5239 result.push_back('B');
5240 else
5241 result.push_back('b');
5242 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5243 result.back() = 'm';
5244 bb = w;
5245 continue;
5246 }
5247 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5248 {
5249 w = bb;
5250 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5251 ct, err, false) - this->__am_pm_;
5252 if (i < 2)
5253 {
5254 result.push_back('%');
5255 result.push_back('p');
5256 bb = w;
5257 continue;
5258 }
5259 }
5260 w = bb;
5261 if (ct.is(ctype_base::digit, *bb))
5262 {
5263 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5264 {
5265 case 6:
5266 result.push_back('%');
5267 result.push_back('w');
5268 break;
5269 case 7:
5270 result.push_back('%');
5271 result.push_back('u');
5272 break;
5273 case 11:
5274 result.push_back('%');
5275 result.push_back('I');
5276 break;
5277 case 12:
5278 result.push_back('%');
5279 result.push_back('m');
5280 break;
5281 case 23:
5282 result.push_back('%');
5283 result.push_back('H');
5284 break;
5285 case 31:
5286 result.push_back('%');
5287 result.push_back('d');
5288 break;
5289 case 55:
5290 result.push_back('%');
5291 result.push_back('M');
5292 break;
5293 case 59:
5294 result.push_back('%');
5295 result.push_back('S');
5296 break;
5297 case 61:
5298 result.push_back('%');
5299 result.push_back('y');
5300 break;
5301 case 364:
5302 result.push_back('%');
5303 result.push_back('j');
5304 break;
5305 case 2061:
5306 result.push_back('%');
5307 result.push_back('Y');
5308 break;
5309 default:
5310 for (; w != bb; ++w)
5311 result.push_back(*w);
5312 break;
5313 }
5314 continue;
5315 }
5316 if (*bb == '%')
5317 {
5318 result.push_back('%');
5319 result.push_back('%');
5320 ++bb;
5321 continue;
5322 }
5323 result.push_back(*bb);
5324 ++bb;
5325 }
5326 return result;
5327}
5328
Marshall Clowd920eea2013-10-21 15:07:28 +00005329#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005330#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005331#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005332
Louis Dionne89258142021-08-23 15:32:36 -04005333#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005334template <>
5335wstring
5336__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5337{
Howard Hinnant990207c2012-02-19 14:55:32 +00005338 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005339 t.tm_sec = 59;
5340 t.tm_min = 55;
5341 t.tm_hour = 23;
5342 t.tm_mday = 31;
5343 t.tm_mon = 11;
5344 t.tm_year = 161;
5345 t.tm_wday = 6;
5346 t.tm_yday = 364;
5347 t.tm_isdst = -1;
5348 char buf[100];
5349 char f[3] = {0};
5350 f[0] = '%';
5351 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005352 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005353 wchar_t wbuf[100];
5354 wchar_t* wbb = wbuf;
5355 mbstate_t mb = {0};
5356 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005357 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005358 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005359 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005360 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005361 wstring result;
5362 while (wbb != wbe)
5363 {
5364 if (ct.is(ctype_base::space, *wbb))
5365 {
5366 result.push_back(L' ');
5367 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5368 ;
5369 continue;
5370 }
5371 wchar_t* w = wbb;
5372 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005373 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005374 ct, err, false)
5375 - this->__weeks_;
5376 if (i < 14)
5377 {
5378 result.push_back(L'%');
5379 if (i < 7)
5380 result.push_back(L'A');
5381 else
5382 result.push_back(L'a');
5383 wbb = w;
5384 continue;
5385 }
5386 w = wbb;
5387 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5388 ct, err, false)
5389 - this->__months_;
5390 if (i < 24)
5391 {
5392 result.push_back(L'%');
5393 if (i < 12)
5394 result.push_back(L'B');
5395 else
5396 result.push_back(L'b');
5397 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5398 result.back() = L'm';
5399 wbb = w;
5400 continue;
5401 }
5402 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5403 {
5404 w = wbb;
5405 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5406 ct, err, false) - this->__am_pm_;
5407 if (i < 2)
5408 {
5409 result.push_back(L'%');
5410 result.push_back(L'p');
5411 wbb = w;
5412 continue;
5413 }
5414 }
5415 w = wbb;
5416 if (ct.is(ctype_base::digit, *wbb))
5417 {
5418 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5419 {
5420 case 6:
5421 result.push_back(L'%');
5422 result.push_back(L'w');
5423 break;
5424 case 7:
5425 result.push_back(L'%');
5426 result.push_back(L'u');
5427 break;
5428 case 11:
5429 result.push_back(L'%');
5430 result.push_back(L'I');
5431 break;
5432 case 12:
5433 result.push_back(L'%');
5434 result.push_back(L'm');
5435 break;
5436 case 23:
5437 result.push_back(L'%');
5438 result.push_back(L'H');
5439 break;
5440 case 31:
5441 result.push_back(L'%');
5442 result.push_back(L'd');
5443 break;
5444 case 55:
5445 result.push_back(L'%');
5446 result.push_back(L'M');
5447 break;
5448 case 59:
5449 result.push_back(L'%');
5450 result.push_back(L'S');
5451 break;
5452 case 61:
5453 result.push_back(L'%');
5454 result.push_back(L'y');
5455 break;
5456 case 364:
5457 result.push_back(L'%');
5458 result.push_back(L'j');
5459 break;
5460 case 2061:
5461 result.push_back(L'%');
5462 result.push_back(L'Y');
5463 break;
5464 default:
5465 for (; w != wbb; ++w)
5466 result.push_back(*w);
5467 break;
5468 }
5469 continue;
5470 }
5471 if (ct.narrow(*wbb, 0) == '%')
5472 {
5473 result.push_back(L'%');
5474 result.push_back(L'%');
5475 ++wbb;
5476 continue;
5477 }
5478 result.push_back(*wbb);
5479 ++wbb;
5480 }
5481 return result;
5482}
Louis Dionne89258142021-08-23 15:32:36 -04005483#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005484
5485template <>
5486void
5487__time_get_storage<char>::init(const ctype<char>& ct)
5488{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005489 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005490 char buf[100];
5491 // __weeks_
5492 for (int i = 0; i < 7; ++i)
5493 {
5494 t.tm_wday = i;
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] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005497 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005498 __weeks_[i+7] = buf;
5499 }
5500 // __months_
5501 for (int i = 0; i < 12; ++i)
5502 {
5503 t.tm_mon = i;
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] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005506 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005507 __months_[i+12] = buf;
5508 }
5509 // __am_pm_
5510 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005511 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005512 __am_pm_[0] = buf;
5513 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005514 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005515 __am_pm_[1] = buf;
5516 __c_ = __analyze('c', ct);
5517 __r_ = __analyze('r', ct);
5518 __x_ = __analyze('x', ct);
5519 __X_ = __analyze('X', ct);
5520}
5521
Louis Dionne89258142021-08-23 15:32:36 -04005522#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005523template <>
5524void
5525__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5526{
5527 tm t = {0};
5528 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005529 wchar_t wbuf[100];
5530 wchar_t* wbe;
5531 mbstate_t mb = {0};
5532 // __weeks_
5533 for (int i = 0; i < 7; ++i)
5534 {
5535 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005536 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005537 mb = mbstate_t();
5538 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005539 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005540 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005541 __throw_runtime_error("locale not supported");
5542 wbe = wbuf + j;
5543 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005544 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005545 mb = mbstate_t();
5546 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005547 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005548 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005549 __throw_runtime_error("locale not supported");
5550 wbe = wbuf + j;
5551 __weeks_[i+7].assign(wbuf, wbe);
5552 }
5553 // __months_
5554 for (int i = 0; i < 12; ++i)
5555 {
5556 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005557 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005558 mb = mbstate_t();
5559 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005560 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005561 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005562 __throw_runtime_error("locale not supported");
5563 wbe = wbuf + j;
5564 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005565 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005566 mb = mbstate_t();
5567 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005568 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005569 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005570 __throw_runtime_error("locale not supported");
5571 wbe = wbuf + j;
5572 __months_[i+12].assign(wbuf, wbe);
5573 }
5574 // __am_pm_
5575 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005576 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 mb = mbstate_t();
5578 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005579 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005580 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005581 __throw_runtime_error("locale not supported");
5582 wbe = wbuf + j;
5583 __am_pm_[0].assign(wbuf, wbe);
5584 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005585 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005586 mb = mbstate_t();
5587 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005588 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005589 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005590 __throw_runtime_error("locale not supported");
5591 wbe = wbuf + j;
5592 __am_pm_[1].assign(wbuf, wbe);
5593 __c_ = __analyze('c', ct);
5594 __r_ = __analyze('r', ct);
5595 __x_ = __analyze('x', ct);
5596 __X_ = __analyze('X', ct);
5597}
Louis Dionne89258142021-08-23 15:32:36 -04005598#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599
5600template <class CharT>
5601struct _LIBCPP_HIDDEN __time_get_temp
5602 : public ctype_byname<CharT>
5603{
5604 explicit __time_get_temp(const char* nm)
5605 : ctype_byname<CharT>(nm, 1) {}
5606 explicit __time_get_temp(const string& nm)
5607 : ctype_byname<CharT>(nm, 1) {}
5608};
5609
5610template <>
5611__time_get_storage<char>::__time_get_storage(const char* __nm)
5612 : __time_get(__nm)
5613{
5614 const __time_get_temp<char> ct(__nm);
5615 init(ct);
5616}
5617
5618template <>
5619__time_get_storage<char>::__time_get_storage(const string& __nm)
5620 : __time_get(__nm)
5621{
5622 const __time_get_temp<char> ct(__nm);
5623 init(ct);
5624}
5625
Louis Dionne89258142021-08-23 15:32:36 -04005626#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005627template <>
5628__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5629 : __time_get(__nm)
5630{
5631 const __time_get_temp<wchar_t> ct(__nm);
5632 init(ct);
5633}
5634
5635template <>
5636__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5637 : __time_get(__nm)
5638{
5639 const __time_get_temp<wchar_t> ct(__nm);
5640 init(ct);
5641}
Louis Dionne89258142021-08-23 15:32:36 -04005642#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005643
5644template <>
5645time_base::dateorder
5646__time_get_storage<char>::__do_date_order() const
5647{
5648 unsigned i;
5649 for (i = 0; i < __x_.size(); ++i)
5650 if (__x_[i] == '%')
5651 break;
5652 ++i;
5653 switch (__x_[i])
5654 {
5655 case 'y':
5656 case 'Y':
5657 for (++i; i < __x_.size(); ++i)
5658 if (__x_[i] == '%')
5659 break;
5660 if (i == __x_.size())
5661 break;
5662 ++i;
5663 switch (__x_[i])
5664 {
5665 case 'm':
5666 for (++i; i < __x_.size(); ++i)
5667 if (__x_[i] == '%')
5668 break;
5669 if (i == __x_.size())
5670 break;
5671 ++i;
5672 if (__x_[i] == 'd')
5673 return time_base::ymd;
5674 break;
5675 case 'd':
5676 for (++i; i < __x_.size(); ++i)
5677 if (__x_[i] == '%')
5678 break;
5679 if (i == __x_.size())
5680 break;
5681 ++i;
5682 if (__x_[i] == 'm')
5683 return time_base::ydm;
5684 break;
5685 }
5686 break;
5687 case 'm':
5688 for (++i; i < __x_.size(); ++i)
5689 if (__x_[i] == '%')
5690 break;
5691 if (i == __x_.size())
5692 break;
5693 ++i;
5694 if (__x_[i] == 'd')
5695 {
5696 for (++i; i < __x_.size(); ++i)
5697 if (__x_[i] == '%')
5698 break;
5699 if (i == __x_.size())
5700 break;
5701 ++i;
5702 if (__x_[i] == 'y' || __x_[i] == 'Y')
5703 return time_base::mdy;
5704 break;
5705 }
5706 break;
5707 case 'd':
5708 for (++i; i < __x_.size(); ++i)
5709 if (__x_[i] == '%')
5710 break;
5711 if (i == __x_.size())
5712 break;
5713 ++i;
5714 if (__x_[i] == 'm')
5715 {
5716 for (++i; i < __x_.size(); ++i)
5717 if (__x_[i] == '%')
5718 break;
5719 if (i == __x_.size())
5720 break;
5721 ++i;
5722 if (__x_[i] == 'y' || __x_[i] == 'Y')
5723 return time_base::dmy;
5724 break;
5725 }
5726 break;
5727 }
5728 return time_base::no_order;
5729}
5730
Louis Dionne89258142021-08-23 15:32:36 -04005731#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005732template <>
5733time_base::dateorder
5734__time_get_storage<wchar_t>::__do_date_order() const
5735{
5736 unsigned i;
5737 for (i = 0; i < __x_.size(); ++i)
5738 if (__x_[i] == L'%')
5739 break;
5740 ++i;
5741 switch (__x_[i])
5742 {
5743 case L'y':
5744 case L'Y':
5745 for (++i; i < __x_.size(); ++i)
5746 if (__x_[i] == L'%')
5747 break;
5748 if (i == __x_.size())
5749 break;
5750 ++i;
5751 switch (__x_[i])
5752 {
5753 case L'm':
5754 for (++i; i < __x_.size(); ++i)
5755 if (__x_[i] == L'%')
5756 break;
5757 if (i == __x_.size())
5758 break;
5759 ++i;
5760 if (__x_[i] == L'd')
5761 return time_base::ymd;
5762 break;
5763 case L'd':
5764 for (++i; i < __x_.size(); ++i)
5765 if (__x_[i] == L'%')
5766 break;
5767 if (i == __x_.size())
5768 break;
5769 ++i;
5770 if (__x_[i] == L'm')
5771 return time_base::ydm;
5772 break;
5773 }
5774 break;
5775 case L'm':
5776 for (++i; i < __x_.size(); ++i)
5777 if (__x_[i] == L'%')
5778 break;
5779 if (i == __x_.size())
5780 break;
5781 ++i;
5782 if (__x_[i] == L'd')
5783 {
5784 for (++i; i < __x_.size(); ++i)
5785 if (__x_[i] == L'%')
5786 break;
5787 if (i == __x_.size())
5788 break;
5789 ++i;
5790 if (__x_[i] == L'y' || __x_[i] == L'Y')
5791 return time_base::mdy;
5792 break;
5793 }
5794 break;
5795 case L'd':
5796 for (++i; i < __x_.size(); ++i)
5797 if (__x_[i] == L'%')
5798 break;
5799 if (i == __x_.size())
5800 break;
5801 ++i;
5802 if (__x_[i] == L'm')
5803 {
5804 for (++i; i < __x_.size(); ++i)
5805 if (__x_[i] == L'%')
5806 break;
5807 if (i == __x_.size())
5808 break;
5809 ++i;
5810 if (__x_[i] == L'y' || __x_[i] == L'Y')
5811 return time_base::dmy;
5812 break;
5813 }
5814 break;
5815 }
5816 return time_base::no_order;
5817}
Louis Dionne89258142021-08-23 15:32:36 -04005818#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005819
5820// time_put
5821
5822__time_put::__time_put(const char* nm)
5823 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5824{
5825 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005826 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005827 " failed to construct for " + string(nm));
5828}
5829
5830__time_put::__time_put(const string& nm)
5831 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5832{
5833 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005834 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005835 " failed to construct for " + nm);
5836}
5837
5838__time_put::~__time_put()
5839{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005840 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005841 freelocale(__loc_);
5842}
5843
5844void
5845__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5846 char __fmt, char __mod) const
5847{
5848 char fmt[] = {'%', __fmt, __mod, 0};
5849 if (__mod != 0)
5850 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005851 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005852 __ne = __nb + n;
5853}
5854
Louis Dionne89258142021-08-23 15:32:36 -04005855#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005856void
5857__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5858 char __fmt, char __mod) const
5859{
5860 char __nar[100];
5861 char* __ne = __nar + 100;
5862 __do_put(__nar, __ne, __tm, __fmt, __mod);
5863 mbstate_t mb = {0};
5864 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005865 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005866 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005867 __throw_runtime_error("locale not supported");
5868 __we = __wb + j;
5869}
Louis Dionne89258142021-08-23 15:32:36 -04005870#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005871
5872// moneypunct_byname
5873
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005874template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005875static
5876void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005877__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5878 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5879 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005880{
5881 const char sign = static_cast<char>(money_base::sign);
5882 const char space = static_cast<char>(money_base::space);
5883 const char none = static_cast<char>(money_base::none);
5884 const char symbol = static_cast<char>(money_base::symbol);
5885 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005886 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5887
5888 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5889 // function'. "Space between sign and symbol or value" means that
5890 // if the sign is adjacent to the symbol, there's a space between
5891 // them, and otherwise there's a space between the sign and value.
5892 //
5893 // C11's localeconv specifies that the fourth character of an
5894 // international curr_symbol is used to separate the sign and
5895 // value when sep_by_space says to do so. C++ can't represent
5896 // that, so we just use a space. When sep_by_space says to
5897 // separate the symbol and value-or-sign with a space, we rearrange the
5898 // curr_symbol to put its spacing character on the correct side of
5899 // the symbol.
5900 //
5901 // We also need to avoid adding an extra space between the sign
5902 // and value when the currency symbol is suppressed (by not
5903 // setting showbase). We match glibc's strfmon by interpreting
5904 // sep_by_space==1 as "omit the space when the currency symbol is
5905 // absent".
5906 //
5907 // Users who want to get this right should use ICU instead.
5908
Howard Hinnantc51e1022010-05-11 19:42:16 +00005909 switch (cs_precedes)
5910 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005911 case 0: // value before curr_symbol
5912 if (symbol_contains_sep) {
5913 // Move the separator to before the symbol, to place it
5914 // between the value and symbol.
5915 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5916 __curr_symbol_.end());
5917 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005918 switch (sign_posn)
5919 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005920 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005921 pat.field[0] = sign;
5922 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005923 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005924 pat.field[3] = symbol;
5925 switch (sep_by_space)
5926 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005927 case 0: // No space separates the currency symbol and value.
5928 // This case may have changed between C99 and C11;
5929 // assume the currency symbol matches the intention.
5930 case 2: // Space between sign and currency or value.
5931 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005932 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005933 case 1: // Space between currency-and-sign or currency and value.
5934 if (!symbol_contains_sep) {
5935 // We insert the space into the symbol instead of
5936 // setting pat.field[2]=space so that when
5937 // showbase is not set, the space goes away too.
5938 __curr_symbol_.insert(0, 1, space_char);
5939 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005940 return;
5941 default:
5942 break;
5943 }
5944 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005945 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005946 pat.field[0] = sign;
5947 pat.field[3] = symbol;
5948 switch (sep_by_space)
5949 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005950 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005951 pat.field[1] = value;
5952 pat.field[2] = none;
5953 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005954 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005955 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005956 pat.field[2] = none;
5957 if (!symbol_contains_sep) {
5958 // We insert the space into the symbol instead of
5959 // setting pat.field[2]=space so that when
5960 // showbase is not set, the space goes away too.
5961 __curr_symbol_.insert(0, 1, space_char);
5962 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005963 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005964 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005965 pat.field[1] = space;
5966 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005967 if (symbol_contains_sep) {
5968 // Remove the separator from the symbol, since it
5969 // has already appeared after the sign.
5970 __curr_symbol_.erase(__curr_symbol_.begin());
5971 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005972 return;
5973 default:
5974 break;
5975 }
5976 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005977 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005978 pat.field[0] = value;
5979 pat.field[3] = sign;
5980 switch (sep_by_space)
5981 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005982 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005983 pat.field[1] = none;
5984 pat.field[2] = symbol;
5985 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005986 case 1: // Space between currency-and-sign or currency and value.
5987 if (!symbol_contains_sep) {
5988 // We insert the space into the symbol instead of
5989 // setting pat.field[1]=space so that when
5990 // showbase is not set, the space goes away too.
5991 __curr_symbol_.insert(0, 1, space_char);
5992 }
5993 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005994 pat.field[2] = symbol;
5995 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005996 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005997 pat.field[1] = symbol;
5998 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005999 if (symbol_contains_sep) {
6000 // Remove the separator from the symbol, since it
6001 // should not be removed if showbase is absent.
6002 __curr_symbol_.erase(__curr_symbol_.begin());
6003 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006004 return;
6005 default:
6006 break;
6007 }
6008 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006009 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006010 pat.field[0] = value;
6011 pat.field[3] = symbol;
6012 switch (sep_by_space)
6013 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006014 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006015 pat.field[1] = none;
6016 pat.field[2] = sign;
6017 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006018 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006019 pat.field[1] = space;
6020 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006021 if (symbol_contains_sep) {
6022 // Remove the separator from the symbol, since it
6023 // has already appeared before the sign.
6024 __curr_symbol_.erase(__curr_symbol_.begin());
6025 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006026 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006027 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006028 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006029 pat.field[2] = none;
6030 if (!symbol_contains_sep) {
6031 // We insert the space into the symbol instead of
6032 // setting pat.field[2]=space so that when
6033 // showbase is not set, the space goes away too.
6034 __curr_symbol_.insert(0, 1, space_char);
6035 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006036 return;
6037 default:
6038 break;
6039 }
6040 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006041 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006042 pat.field[0] = value;
6043 pat.field[3] = sign;
6044 switch (sep_by_space)
6045 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006046 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006047 pat.field[1] = none;
6048 pat.field[2] = symbol;
6049 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006050 case 1: // Space between currency-and-sign or currency and value.
6051 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006052 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006053 if (!symbol_contains_sep) {
6054 // We insert the space into the symbol instead of
6055 // setting pat.field[1]=space so that when
6056 // showbase is not set, the space goes away too.
6057 __curr_symbol_.insert(0, 1, space_char);
6058 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006059 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006060 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006061 pat.field[1] = symbol;
6062 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006063 if (symbol_contains_sep) {
6064 // Remove the separator from the symbol, since it
6065 // should not disappear when showbase is absent.
6066 __curr_symbol_.erase(__curr_symbol_.begin());
6067 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006068 return;
6069 default:
6070 break;
6071 }
6072 break;
6073 default:
6074 break;
6075 }
6076 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006077 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00006078 switch (sign_posn)
6079 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006080 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006081 pat.field[0] = sign;
6082 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006083 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006084 pat.field[3] = value;
6085 switch (sep_by_space)
6086 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006087 case 0: // No space separates the currency symbol and value.
6088 // This case may have changed between C99 and C11;
6089 // assume the currency symbol matches the intention.
6090 case 2: // Space between sign and currency or value.
6091 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006092 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006093 case 1: // Space between currency-and-sign or currency and value.
6094 if (!symbol_contains_sep) {
6095 // We insert the space into the symbol instead of
6096 // setting pat.field[2]=space so that when
6097 // showbase is not set, the space goes away too.
6098 __curr_symbol_.insert(0, 1, space_char);
6099 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006100 return;
6101 default:
6102 break;
6103 }
6104 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006105 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006106 pat.field[0] = sign;
6107 pat.field[3] = value;
6108 switch (sep_by_space)
6109 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006110 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006111 pat.field[1] = symbol;
6112 pat.field[2] = none;
6113 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006114 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006115 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006116 pat.field[2] = none;
6117 if (!symbol_contains_sep) {
6118 // We insert the space into the symbol instead of
6119 // setting pat.field[2]=space so that when
6120 // showbase is not set, the space goes away too.
6121 __curr_symbol_.push_back(space_char);
6122 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006123 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006124 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125 pat.field[1] = space;
6126 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006127 if (symbol_contains_sep) {
6128 // Remove the separator from the symbol, since it
6129 // has already appeared after the sign.
6130 __curr_symbol_.pop_back();
6131 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006132 return;
6133 default:
6134 break;
6135 }
6136 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006137 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006138 pat.field[0] = symbol;
6139 pat.field[3] = sign;
6140 switch (sep_by_space)
6141 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006142 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006143 pat.field[1] = none;
6144 pat.field[2] = value;
6145 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006146 case 1: // Space between currency-and-sign or currency and value.
6147 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006148 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006149 if (!symbol_contains_sep) {
6150 // We insert the space into the symbol instead of
6151 // setting pat.field[1]=space so that when
6152 // showbase is not set, the space goes away too.
6153 __curr_symbol_.push_back(space_char);
6154 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006155 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006156 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006157 pat.field[1] = value;
6158 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006159 if (symbol_contains_sep) {
6160 // Remove the separator from the symbol, since it
6161 // will appear before the sign.
6162 __curr_symbol_.pop_back();
6163 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006164 return;
6165 default:
6166 break;
6167 }
6168 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006169 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006170 pat.field[0] = sign;
6171 pat.field[3] = value;
6172 switch (sep_by_space)
6173 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006174 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006175 pat.field[1] = symbol;
6176 pat.field[2] = none;
6177 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006178 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006179 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006180 pat.field[2] = none;
6181 if (!symbol_contains_sep) {
6182 // We insert the space into the symbol instead of
6183 // setting pat.field[2]=space so that when
6184 // showbase is not set, the space goes away too.
6185 __curr_symbol_.push_back(space_char);
6186 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006187 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006188 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006189 pat.field[1] = space;
6190 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006191 if (symbol_contains_sep) {
6192 // Remove the separator from the symbol, since it
6193 // has already appeared after the sign.
6194 __curr_symbol_.pop_back();
6195 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006196 return;
6197 default:
6198 break;
6199 }
6200 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006201 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006202 pat.field[0] = symbol;
6203 pat.field[3] = value;
6204 switch (sep_by_space)
6205 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006206 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006207 pat.field[1] = sign;
6208 pat.field[2] = none;
6209 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006210 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006211 pat.field[1] = sign;
6212 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006213 if (symbol_contains_sep) {
6214 // Remove the separator from the symbol, since it
6215 // should not disappear when showbase is absent.
6216 __curr_symbol_.pop_back();
6217 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006218 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006219 case 2: // Space between sign and currency or value.
6220 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006221 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006222 if (!symbol_contains_sep) {
6223 // We insert the space into the symbol instead of
6224 // setting pat.field[1]=space so that when
6225 // showbase is not set, the space goes away too.
6226 __curr_symbol_.push_back(space_char);
6227 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006228 return;
6229 default:
6230 break;
6231 }
6232 break;
6233 default:
6234 break;
6235 }
6236 break;
6237 default:
6238 break;
6239 }
6240 pat.field[0] = symbol;
6241 pat.field[1] = sign;
6242 pat.field[2] = none;
6243 pat.field[3] = value;
6244}
6245
6246template<>
6247void
6248moneypunct_byname<char, false>::init(const char* nm)
6249{
6250 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006251 __libcpp_unique_locale loc(nm);
6252 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006253 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006254 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006255
Ben Craig3756b922016-03-09 15:39:39 +00006256 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006257 if (!checked_string_to_char_convert(__decimal_point_,
6258 lc->mon_decimal_point,
6259 loc.get()))
6260 __decimal_point_ = base::do_decimal_point();
6261 if (!checked_string_to_char_convert(__thousands_sep_,
6262 lc->mon_thousands_sep,
6263 loc.get()))
6264 __thousands_sep_ = base::do_thousands_sep();
6265
Howard Hinnantc51e1022010-05-11 19:42:16 +00006266 __grouping_ = lc->mon_grouping;
6267 __curr_symbol_ = lc->currency_symbol;
6268 if (lc->frac_digits != CHAR_MAX)
6269 __frac_digits_ = lc->frac_digits;
6270 else
6271 __frac_digits_ = base::do_frac_digits();
6272 if (lc->p_sign_posn == 0)
6273 __positive_sign_ = "()";
6274 else
6275 __positive_sign_ = lc->positive_sign;
6276 if (lc->n_sign_posn == 0)
6277 __negative_sign_ = "()";
6278 else
6279 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006280 // Assume the positive and negative formats will want spaces in
6281 // the same places in curr_symbol since there's no way to
6282 // represent anything else.
6283 string_type __dummy_curr_symbol = __curr_symbol_;
6284 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6285 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6286 __init_pat(__neg_format_, __curr_symbol_, false,
6287 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006288}
6289
6290template<>
6291void
6292moneypunct_byname<char, true>::init(const char* nm)
6293{
6294 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006295 __libcpp_unique_locale loc(nm);
6296 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006297 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006298 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006299
Ben Craig3756b922016-03-09 15:39:39 +00006300 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006301 if (!checked_string_to_char_convert(__decimal_point_,
6302 lc->mon_decimal_point,
6303 loc.get()))
6304 __decimal_point_ = base::do_decimal_point();
6305 if (!checked_string_to_char_convert(__thousands_sep_,
6306 lc->mon_thousands_sep,
6307 loc.get()))
6308 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006309 __grouping_ = lc->mon_grouping;
6310 __curr_symbol_ = lc->int_curr_symbol;
6311 if (lc->int_frac_digits != CHAR_MAX)
6312 __frac_digits_ = lc->int_frac_digits;
6313 else
6314 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006315#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006316 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006317#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006318 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006319#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006320 __positive_sign_ = "()";
6321 else
6322 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006323#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006324 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006325#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006326 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006327#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006328 __negative_sign_ = "()";
6329 else
6330 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006331 // Assume the positive and negative formats will want spaces in
6332 // the same places in curr_symbol since there's no way to
6333 // represent anything else.
6334 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006335#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006336 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6337 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6338 __init_pat(__neg_format_, __curr_symbol_, true,
6339 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006340#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006341 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6342 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6343 lc->int_p_sign_posn, ' ');
6344 __init_pat(__neg_format_, __curr_symbol_, true,
6345 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6346 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006347#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006348}
6349
Louis Dionne89258142021-08-23 15:32:36 -04006350#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006351template<>
6352void
6353moneypunct_byname<wchar_t, false>::init(const char* nm)
6354{
6355 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006356 __libcpp_unique_locale loc(nm);
6357 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006358 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006359 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006360 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006361 if (!checked_string_to_wchar_convert(__decimal_point_,
6362 lc->mon_decimal_point,
6363 loc.get()))
6364 __decimal_point_ = base::do_decimal_point();
6365 if (!checked_string_to_wchar_convert(__thousands_sep_,
6366 lc->mon_thousands_sep,
6367 loc.get()))
6368 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006369 __grouping_ = lc->mon_grouping;
6370 wchar_t wbuf[100];
6371 mbstate_t mb = {0};
6372 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006373 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006374 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006375 __throw_runtime_error("locale not supported");
6376 wchar_t* wbe = wbuf + j;
6377 __curr_symbol_.assign(wbuf, wbe);
6378 if (lc->frac_digits != CHAR_MAX)
6379 __frac_digits_ = lc->frac_digits;
6380 else
6381 __frac_digits_ = base::do_frac_digits();
6382 if (lc->p_sign_posn == 0)
6383 __positive_sign_ = L"()";
6384 else
6385 {
6386 mb = mbstate_t();
6387 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006388 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006389 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006390 __throw_runtime_error("locale not supported");
6391 wbe = wbuf + j;
6392 __positive_sign_.assign(wbuf, wbe);
6393 }
6394 if (lc->n_sign_posn == 0)
6395 __negative_sign_ = L"()";
6396 else
6397 {
6398 mb = mbstate_t();
6399 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006400 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006401 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006402 __throw_runtime_error("locale not supported");
6403 wbe = wbuf + j;
6404 __negative_sign_.assign(wbuf, wbe);
6405 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006406 // Assume the positive and negative formats will want spaces in
6407 // the same places in curr_symbol since there's no way to
6408 // represent anything else.
6409 string_type __dummy_curr_symbol = __curr_symbol_;
6410 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6411 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6412 __init_pat(__neg_format_, __curr_symbol_, false,
6413 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006414}
6415
6416template<>
6417void
6418moneypunct_byname<wchar_t, true>::init(const char* nm)
6419{
6420 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006421 __libcpp_unique_locale loc(nm);
6422 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006423 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006424 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006425
Ben Craig3756b922016-03-09 15:39:39 +00006426 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006427 if (!checked_string_to_wchar_convert(__decimal_point_,
6428 lc->mon_decimal_point,
6429 loc.get()))
6430 __decimal_point_ = base::do_decimal_point();
6431 if (!checked_string_to_wchar_convert(__thousands_sep_,
6432 lc->mon_thousands_sep,
6433 loc.get()))
6434 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006435 __grouping_ = lc->mon_grouping;
6436 wchar_t wbuf[100];
6437 mbstate_t mb = {0};
6438 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006439 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006440 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006441 __throw_runtime_error("locale not supported");
6442 wchar_t* wbe = wbuf + j;
6443 __curr_symbol_.assign(wbuf, wbe);
6444 if (lc->int_frac_digits != CHAR_MAX)
6445 __frac_digits_ = lc->int_frac_digits;
6446 else
6447 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006448#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006449 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006450#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006451 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006452#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006453 __positive_sign_ = L"()";
6454 else
6455 {
6456 mb = mbstate_t();
6457 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006458 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006459 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006460 __throw_runtime_error("locale not supported");
6461 wbe = wbuf + j;
6462 __positive_sign_.assign(wbuf, wbe);
6463 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006464#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006465 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006466#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006467 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006468#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006469 __negative_sign_ = L"()";
6470 else
6471 {
6472 mb = mbstate_t();
6473 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006474 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006475 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006476 __throw_runtime_error("locale not supported");
6477 wbe = wbuf + j;
6478 __negative_sign_.assign(wbuf, wbe);
6479 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006480 // Assume the positive and negative formats will want spaces in
6481 // the same places in curr_symbol since there's no way to
6482 // represent anything else.
6483 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006484#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006485 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6486 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6487 __init_pat(__neg_format_, __curr_symbol_, true,
6488 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006489#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006490 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6491 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6492 lc->int_p_sign_posn, L' ');
6493 __init_pat(__neg_format_, __curr_symbol_, true,
6494 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6495 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006496#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006497}
Louis Dionne89258142021-08-23 15:32:36 -04006498#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006499
6500void __do_nothing(void*) {}
6501
6502void __throw_runtime_error(const char* msg)
6503{
Howard Hinnant72f73582010-08-11 17:04:31 +00006504#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006505 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006506#else
6507 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006508 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006509#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006510}
6511
Louis Dionne89258142021-08-23 15:32:36 -04006512 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6513_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006514
Louis Dionne89258142021-08-23 15:32:36 -04006515 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6516_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006517
Louis Dionne89258142021-08-23 15:32:36 -04006518 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6519_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006520
Louis Dionne89258142021-08-23 15:32:36 -04006521 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6522_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006523
Louis Dionne89258142021-08-23 15:32:36 -04006524 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6525_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006526
Louis Dionne89258142021-08-23 15:32:36 -04006527 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6528_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006529
Louis Dionne89258142021-08-23 15:32:36 -04006530 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6531_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006532
Louis Dionne89258142021-08-23 15:32:36 -04006533 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6534_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006535
Louis Dionne89258142021-08-23 15:32:36 -04006536 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6537_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006538
Louis Dionne89258142021-08-23 15:32:36 -04006539 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6540 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6541_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6542_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006543
Louis Dionne89258142021-08-23 15:32:36 -04006544 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6545 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6546_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6547_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006548
Louis Dionne89258142021-08-23 15:32:36 -04006549 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6550_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006551
Louis Dionne89258142021-08-23 15:32:36 -04006552 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6553_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006554
Louis Dionne89258142021-08-23 15:32:36 -04006555 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6556_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006557
Louis Dionne89258142021-08-23 15:32:36 -04006558 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6559_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006560
Louis Dionne89258142021-08-23 15:32:36 -04006561 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6562_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006563
Louis Dionne89258142021-08-23 15:32:36 -04006564 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6565_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006566
Louis Dionne89258142021-08-23 15:32:36 -04006567 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6568_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 -08006569template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6570template 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 -04006571#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006572template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6573template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6574#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006575
Howard Hinnantc51e1022010-05-11 19:42:16 +00006576_LIBCPP_END_NAMESPACE_STD