blob: 2234784769dd3f3b89f84963c06c3da54f607ef0 [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__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500901 defined(__NetBSD__) || defined(__MVS__)
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__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500915 defined(__NetBSD__) || defined(__MVS__)
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__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500930 defined(__NetBSD__) || defined(__MVS__)
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__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500944 defined(__NetBSD__) || defined(__MVS__)
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)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001016#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
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)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001033#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
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)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001050#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
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)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001066#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
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;
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001214#elif defined(__MVS__)
1215# if defined(__NATIVE_ASCII_F)
1216 return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1217# else
1218 return const_cast<const ctype<char>::mask*> (__ctypec);
1219# endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001220#else
David Chisnall8074c342012-02-29 13:05:08 +00001221 // Platform not supported: abort so the person doing the port knows what to
1222 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001223# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001224 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001225 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001226 return NULL;
1227#endif
1228}
Marshall Clowb3f62842015-03-04 16:10:14 +00001229#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001230
Howard Hinnantd7a78632011-09-29 13:33:15 +00001231#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001232const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001233ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001234{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001235 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001236}
1237
1238const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001239ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001240{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001241 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001242}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001243#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001244const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001245ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001246{
1247 return _C_tolower_tab_ + 1;
1248}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001249
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001250const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001251ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001252{
1253 return _C_toupper_tab_ + 1;
1254}
1255
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001256#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001257const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001258ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001259{
1260 return *__ctype_tolower_loc();
1261}
1262
1263const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001264ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001265{
1266 return *__ctype_toupper_loc();
1267}
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001268#elif defined(__MVS__)
1269const unsigned short*
1270ctype<char>::__classic_lower_table() _NOEXCEPT
1271{
1272# if defined(__NATIVE_ASCII_F)
1273 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1274# else
1275 return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1276# endif
1277}
1278const unsigned short *
1279ctype<char>::__classic_upper_table() _NOEXCEPT
1280{
1281# if defined(__NATIVE_ASCII_F)
1282 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1283# else
1284 return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1285# endif
1286}
1287#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001288
Howard Hinnantc51e1022010-05-11 19:42:16 +00001289// template <> class ctype_byname<char>
1290
1291ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1292 : ctype<char>(0, false, refs),
1293 __l(newlocale(LC_ALL_MASK, name, 0))
1294{
1295 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001296 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001297 " failed to construct for " + string(name));
1298}
1299
1300ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1301 : ctype<char>(0, false, refs),
1302 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1303{
1304 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001305 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001306 " failed to construct for " + name);
1307}
1308
1309ctype_byname<char>::~ctype_byname()
1310{
1311 freelocale(__l);
1312}
1313
1314char
1315ctype_byname<char>::do_toupper(char_type c) const
1316{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001317 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001318}
1319
1320const char*
1321ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1322{
1323 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001324 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001325 return low;
1326}
1327
1328char
1329ctype_byname<char>::do_tolower(char_type c) const
1330{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001331 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001332}
1333
1334const char*
1335ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1336{
1337 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001338 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001339 return low;
1340}
1341
1342// template <> class ctype_byname<wchar_t>
1343
Louis Dionne89258142021-08-23 15:32:36 -04001344#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1346 : ctype<wchar_t>(refs),
1347 __l(newlocale(LC_ALL_MASK, name, 0))
1348{
1349 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001350 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001351 " failed to construct for " + string(name));
1352}
1353
1354ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1355 : ctype<wchar_t>(refs),
1356 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1357{
1358 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001359 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001360 " failed to construct for " + name);
1361}
1362
1363ctype_byname<wchar_t>::~ctype_byname()
1364{
1365 freelocale(__l);
1366}
1367
1368bool
1369ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1370{
Alexis Huntc2017f12011-07-09 03:40:04 +00001371#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001372 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001373#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001374 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001375 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001376 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1377 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1378 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1379 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1380 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1381 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1382 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1383 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1384 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1385 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001386 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001387#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001388}
1389
1390const wchar_t*
1391ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1392{
1393 for (; low != high; ++low, ++vec)
1394 {
1395 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001396 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001397 else
1398 {
1399 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001400 wint_t ch = static_cast<wint_t>(*low);
1401 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001402 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001403#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001404 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001405 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001406#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001407 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001408 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001409 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001410 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001411 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001412 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001413#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001414 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001415 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001416#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001417 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001418 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001419 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001420 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001421#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001422 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001423 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001424#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001425#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001426 if (iswblank_l(ch, __l))
1427 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001428#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001429 }
1430 }
1431 return low;
1432}
1433
1434const wchar_t*
1435ctype_byname<wchar_t>::do_scan_is(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)) break;
1445 if ((m & print) == print && iswprint_l(ch, __l)) break;
1446 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1447 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1448 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1449 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1450 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1451 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1452 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1453 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001454#endif
1455 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001456 return low;
1457}
1458
1459const wchar_t*
1460ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1461{
1462 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001463 {
1464#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001465 if (!iswctype_l(*low, m, __l))
1466 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001467#else
Marshall Clowada0f732013-02-07 14:22:51 +00001468 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001469 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1470 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1471 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1472 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1473 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1474 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1475 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1476 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1477 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1478 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001479 break;
1480#endif
1481 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001482 return low;
1483}
1484
1485wchar_t
1486ctype_byname<wchar_t>::do_toupper(char_type c) const
1487{
1488 return towupper_l(c, __l);
1489}
1490
1491const wchar_t*
1492ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1493{
1494 for (; low != high; ++low)
1495 *low = towupper_l(*low, __l);
1496 return low;
1497}
1498
1499wchar_t
1500ctype_byname<wchar_t>::do_tolower(char_type c) const
1501{
1502 return towlower_l(c, __l);
1503}
1504
1505const wchar_t*
1506ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1507{
1508 for (; low != high; ++low)
1509 *low = towlower_l(*low, __l);
1510 return low;
1511}
1512
1513wchar_t
1514ctype_byname<wchar_t>::do_widen(char c) const
1515{
Ben Craig3756b922016-03-09 15:39:39 +00001516 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001517}
1518
1519const char*
1520ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1521{
1522 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001523 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001524 return low;
1525}
1526
1527char
1528ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1529{
Ben Craig3756b922016-03-09 15:39:39 +00001530 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001531 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001532}
1533
1534const wchar_t*
1535ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1536{
1537 for (; low != high; ++low, ++dest)
1538 {
Ben Craig3756b922016-03-09 15:39:39 +00001539 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001540 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001541 }
1542 return low;
1543}
Louis Dionne89258142021-08-23 15:32:36 -04001544#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001545
1546// template <> class codecvt<char, char, mbstate_t>
1547
Howard Hinnantffb308e2010-08-22 00:03:27 +00001548locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001549
1550codecvt<char, char, mbstate_t>::~codecvt()
1551{
1552}
1553
1554codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001555codecvt<char, char, mbstate_t>::do_out(state_type&,
1556 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001557 extern_type* to, extern_type*, extern_type*& to_nxt) const
1558{
1559 frm_nxt = frm;
1560 to_nxt = to;
1561 return noconv;
1562}
1563
1564codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001565codecvt<char, char, mbstate_t>::do_in(state_type&,
1566 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001567 intern_type* to, intern_type*, intern_type*& to_nxt) const
1568{
1569 frm_nxt = frm;
1570 to_nxt = to;
1571 return noconv;
1572}
1573
1574codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001575codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001576 extern_type* to, extern_type*, extern_type*& to_nxt) const
1577{
1578 to_nxt = to;
1579 return noconv;
1580}
1581
1582int
Louis Dionne65358e12021-03-01 12:09:45 -05001583codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001584{
1585 return 1;
1586}
1587
1588bool
Louis Dionne65358e12021-03-01 12:09:45 -05001589codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001590{
1591 return true;
1592}
1593
1594int
1595codecvt<char, char, mbstate_t>::do_length(state_type&,
1596 const extern_type* frm, const extern_type* end, size_t mx) const
1597{
Howard Hinnant28b24882011-12-01 20:21:04 +00001598 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001599}
1600
1601int
Louis Dionne65358e12021-03-01 12:09:45 -05001602codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001603{
1604 return 1;
1605}
1606
1607// template <> class codecvt<wchar_t, char, mbstate_t>
1608
Louis Dionne89258142021-08-23 15:32:36 -04001609#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantffb308e2010-08-22 00:03:27 +00001610locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611
1612codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1613 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001614 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001615{
1616}
1617
1618codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1619 : locale::facet(refs),
1620 __l(newlocale(LC_ALL_MASK, nm, 0))
1621{
1622 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001623 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001624 " failed to construct for " + string(nm));
1625}
1626
1627codecvt<wchar_t, char, mbstate_t>::~codecvt()
1628{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001629 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001630 freelocale(__l);
1631}
1632
1633codecvt<wchar_t, char, mbstate_t>::result
1634codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001635 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001636 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1637{
1638 // look for first internal null in frm
1639 const intern_type* fend = frm;
1640 for (; fend != frm_end; ++fend)
1641 if (*fend == 0)
1642 break;
1643 // loop over all null-terminated sequences in frm
1644 to_nxt = to;
1645 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1646 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001647 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001648 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001649 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1650 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001651 if (n == size_t(-1))
1652 {
1653 // need to recover to_nxt
1654 for (to_nxt = to; frm != frm_nxt; ++frm)
1655 {
Ben Craig3756b922016-03-09 15:39:39 +00001656 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001657 if (n == size_t(-1))
1658 break;
1659 to_nxt += n;
1660 }
1661 frm_nxt = frm;
1662 return error;
1663 }
1664 if (n == 0)
1665 return partial;
1666 to_nxt += n;
1667 if (to_nxt == to_end)
1668 break;
1669 if (fend != frm_end) // set up next null terminated sequence
1670 {
1671 // Try to write the terminating null
1672 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001673 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001674 if (n == size_t(-1)) // on error
1675 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001676 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001677 return partial;
1678 for (extern_type* p = tmp; n; --n) // write it
1679 *to_nxt++ = *p++;
1680 ++frm_nxt;
1681 // look for next null in frm
1682 for (fend = frm_nxt; fend != frm_end; ++fend)
1683 if (*fend == 0)
1684 break;
1685 }
1686 }
1687 return frm_nxt == frm_end ? ok : partial;
1688}
1689
1690codecvt<wchar_t, char, mbstate_t>::result
1691codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001692 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001693 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1694{
1695 // look for first internal null in frm
1696 const extern_type* fend = frm;
1697 for (; fend != frm_end; ++fend)
1698 if (*fend == 0)
1699 break;
1700 // loop over all null-terminated sequences in frm
1701 to_nxt = to;
1702 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1703 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001704 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001705 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001706 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1707 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001708 if (n == size_t(-1))
1709 {
1710 // need to recover to_nxt
1711 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1712 {
Ben Craig3756b922016-03-09 15:39:39 +00001713 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1714 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001715 switch (n)
1716 {
1717 case 0:
1718 ++frm;
1719 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001720 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001721 frm_nxt = frm;
1722 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001723 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001724 frm_nxt = frm;
1725 return partial;
1726 default:
1727 frm += n;
1728 break;
1729 }
1730 }
1731 frm_nxt = frm;
1732 return frm_nxt == frm_end ? ok : partial;
1733 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001734 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001735 return error;
1736 to_nxt += n;
1737 if (to_nxt == to_end)
1738 break;
1739 if (fend != frm_end) // set up next null terminated sequence
1740 {
1741 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001742 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001743 if (n != 0) // on error
1744 return error;
1745 ++to_nxt;
1746 ++frm_nxt;
1747 // look for next null in frm
1748 for (fend = frm_nxt; fend != frm_end; ++fend)
1749 if (*fend == 0)
1750 break;
1751 }
1752 }
1753 return frm_nxt == frm_end ? ok : partial;
1754}
1755
1756codecvt<wchar_t, char, mbstate_t>::result
1757codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1758 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1759{
1760 to_nxt = to;
1761 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001762 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001763 if (n == size_t(-1) || n == 0) // on error
1764 return error;
1765 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001766 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001767 return partial;
1768 for (extern_type* p = tmp; n; --n) // write it
1769 *to_nxt++ = *p++;
1770 return ok;
1771}
1772
1773int
Louis Dionne65358e12021-03-01 12:09:45 -05001774codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001775{
Ben Craig3756b922016-03-09 15:39:39 +00001776 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001777 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001778
1779 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001780 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001781 return 1; // which take more than 1 char to form a wchar_t
1782 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001783}
1784
1785bool
Louis Dionne65358e12021-03-01 12:09:45 -05001786codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001787{
1788 return false;
1789}
1790
1791int
1792codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1793 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1794{
1795 int nbytes = 0;
1796 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1797 {
Ben Craig3756b922016-03-09 15:39:39 +00001798 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001799 switch (n)
1800 {
1801 case 0:
1802 ++nbytes;
1803 ++frm;
1804 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001805 case size_t(-1):
1806 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001807 return nbytes;
1808 default:
1809 nbytes += n;
1810 frm += n;
1811 break;
1812 }
1813 }
1814 return nbytes;
1815}
1816
1817int
Louis Dionne65358e12021-03-01 12:09:45 -05001818codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001819{
Ben Craig3756b922016-03-09 15:39:39 +00001820 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001821}
Louis Dionne89258142021-08-23 15:32:36 -04001822#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001823
1824// Valid UTF ranges
1825// UTF-32 UTF-16 UTF-8 # of code points
1826// first second first second third fourth
1827// 000000 - 00007F 0000 - 007F 00 - 7F 127
1828// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1829// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1830// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1831// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1832// 00D800 - 00DFFF invalid
1833// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1834// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1835// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1836// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1837
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001838static
1839codecvt_base::result
1840utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1841 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1842 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1843{
1844 frm_nxt = frm;
1845 to_nxt = to;
1846 if (mode & generate_header)
1847 {
1848 if (to_end-to_nxt < 3)
1849 return codecvt_base::partial;
1850 *to_nxt++ = static_cast<uint8_t>(0xEF);
1851 *to_nxt++ = static_cast<uint8_t>(0xBB);
1852 *to_nxt++ = static_cast<uint8_t>(0xBF);
1853 }
1854 for (; frm_nxt < frm_end; ++frm_nxt)
1855 {
1856 uint16_t wc1 = *frm_nxt;
1857 if (wc1 > Maxcode)
1858 return codecvt_base::error;
1859 if (wc1 < 0x0080)
1860 {
1861 if (to_end-to_nxt < 1)
1862 return codecvt_base::partial;
1863 *to_nxt++ = static_cast<uint8_t>(wc1);
1864 }
1865 else if (wc1 < 0x0800)
1866 {
1867 if (to_end-to_nxt < 2)
1868 return codecvt_base::partial;
1869 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1870 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1871 }
1872 else if (wc1 < 0xD800)
1873 {
1874 if (to_end-to_nxt < 3)
1875 return codecvt_base::partial;
1876 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1877 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1878 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1879 }
1880 else if (wc1 < 0xDC00)
1881 {
1882 if (frm_end-frm_nxt < 2)
1883 return codecvt_base::partial;
1884 uint16_t wc2 = frm_nxt[1];
1885 if ((wc2 & 0xFC00) != 0xDC00)
1886 return codecvt_base::error;
1887 if (to_end-to_nxt < 4)
1888 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001889 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1890 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001891 return codecvt_base::error;
1892 ++frm_nxt;
1893 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1894 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1895 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1896 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1897 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1898 }
1899 else if (wc1 < 0xE000)
1900 {
1901 return codecvt_base::error;
1902 }
1903 else
1904 {
1905 if (to_end-to_nxt < 3)
1906 return codecvt_base::partial;
1907 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1908 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1909 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1910 }
1911 }
1912 return codecvt_base::ok;
1913}
1914
1915static
1916codecvt_base::result
1917utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1918 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1919 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1920{
1921 frm_nxt = frm;
1922 to_nxt = to;
1923 if (mode & generate_header)
1924 {
1925 if (to_end-to_nxt < 3)
1926 return codecvt_base::partial;
1927 *to_nxt++ = static_cast<uint8_t>(0xEF);
1928 *to_nxt++ = static_cast<uint8_t>(0xBB);
1929 *to_nxt++ = static_cast<uint8_t>(0xBF);
1930 }
1931 for (; frm_nxt < frm_end; ++frm_nxt)
1932 {
1933 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1934 if (wc1 > Maxcode)
1935 return codecvt_base::error;
1936 if (wc1 < 0x0080)
1937 {
1938 if (to_end-to_nxt < 1)
1939 return codecvt_base::partial;
1940 *to_nxt++ = static_cast<uint8_t>(wc1);
1941 }
1942 else if (wc1 < 0x0800)
1943 {
1944 if (to_end-to_nxt < 2)
1945 return codecvt_base::partial;
1946 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1947 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1948 }
1949 else if (wc1 < 0xD800)
1950 {
1951 if (to_end-to_nxt < 3)
1952 return codecvt_base::partial;
1953 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1954 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1955 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1956 }
1957 else if (wc1 < 0xDC00)
1958 {
1959 if (frm_end-frm_nxt < 2)
1960 return codecvt_base::partial;
1961 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1962 if ((wc2 & 0xFC00) != 0xDC00)
1963 return codecvt_base::error;
1964 if (to_end-to_nxt < 4)
1965 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001966 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1967 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001968 return codecvt_base::error;
1969 ++frm_nxt;
1970 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1971 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1972 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1973 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1974 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1975 }
1976 else if (wc1 < 0xE000)
1977 {
1978 return codecvt_base::error;
1979 }
1980 else
1981 {
1982 if (to_end-to_nxt < 3)
1983 return codecvt_base::partial;
1984 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1985 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1986 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1987 }
1988 }
1989 return codecvt_base::ok;
1990}
1991
1992static
1993codecvt_base::result
1994utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1995 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1996 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1997{
1998 frm_nxt = frm;
1999 to_nxt = to;
2000 if (mode & consume_header)
2001 {
2002 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2003 frm_nxt[2] == 0xBF)
2004 frm_nxt += 3;
2005 }
2006 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2007 {
2008 uint8_t c1 = *frm_nxt;
2009 if (c1 > Maxcode)
2010 return codecvt_base::error;
2011 if (c1 < 0x80)
2012 {
2013 *to_nxt = static_cast<uint16_t>(c1);
2014 ++frm_nxt;
2015 }
2016 else if (c1 < 0xC2)
2017 {
2018 return codecvt_base::error;
2019 }
2020 else if (c1 < 0xE0)
2021 {
2022 if (frm_end-frm_nxt < 2)
2023 return codecvt_base::partial;
2024 uint8_t c2 = frm_nxt[1];
2025 if ((c2 & 0xC0) != 0x80)
2026 return codecvt_base::error;
2027 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2028 if (t > Maxcode)
2029 return codecvt_base::error;
2030 *to_nxt = t;
2031 frm_nxt += 2;
2032 }
2033 else if (c1 < 0xF0)
2034 {
2035 if (frm_end-frm_nxt < 3)
2036 return codecvt_base::partial;
2037 uint8_t c2 = frm_nxt[1];
2038 uint8_t c3 = frm_nxt[2];
2039 switch (c1)
2040 {
2041 case 0xE0:
2042 if ((c2 & 0xE0) != 0xA0)
2043 return codecvt_base::error;
2044 break;
2045 case 0xED:
2046 if ((c2 & 0xE0) != 0x80)
2047 return codecvt_base::error;
2048 break;
2049 default:
2050 if ((c2 & 0xC0) != 0x80)
2051 return codecvt_base::error;
2052 break;
2053 }
2054 if ((c3 & 0xC0) != 0x80)
2055 return codecvt_base::error;
2056 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2057 | ((c2 & 0x3F) << 6)
2058 | (c3 & 0x3F));
2059 if (t > Maxcode)
2060 return codecvt_base::error;
2061 *to_nxt = t;
2062 frm_nxt += 3;
2063 }
2064 else if (c1 < 0xF5)
2065 {
2066 if (frm_end-frm_nxt < 4)
2067 return codecvt_base::partial;
2068 uint8_t c2 = frm_nxt[1];
2069 uint8_t c3 = frm_nxt[2];
2070 uint8_t c4 = frm_nxt[3];
2071 switch (c1)
2072 {
2073 case 0xF0:
2074 if (!(0x90 <= c2 && c2 <= 0xBF))
2075 return codecvt_base::error;
2076 break;
2077 case 0xF4:
2078 if ((c2 & 0xF0) != 0x80)
2079 return codecvt_base::error;
2080 break;
2081 default:
2082 if ((c2 & 0xC0) != 0x80)
2083 return codecvt_base::error;
2084 break;
2085 }
2086 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2087 return codecvt_base::error;
2088 if (to_end-to_nxt < 2)
2089 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002090 if ((((c1 & 7UL) << 18) +
2091 ((c2 & 0x3FUL) << 12) +
2092 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002093 return codecvt_base::error;
2094 *to_nxt = static_cast<uint16_t>(
2095 0xD800
2096 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2097 | ((c2 & 0x0F) << 2)
2098 | ((c3 & 0x30) >> 4));
2099 *++to_nxt = static_cast<uint16_t>(
2100 0xDC00
2101 | ((c3 & 0x0F) << 6)
2102 | (c4 & 0x3F));
2103 frm_nxt += 4;
2104 }
2105 else
2106 {
2107 return codecvt_base::error;
2108 }
2109 }
2110 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2111}
2112
2113static
2114codecvt_base::result
2115utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2116 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2117 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2118{
2119 frm_nxt = frm;
2120 to_nxt = to;
2121 if (mode & consume_header)
2122 {
2123 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2124 frm_nxt[2] == 0xBF)
2125 frm_nxt += 3;
2126 }
2127 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2128 {
2129 uint8_t c1 = *frm_nxt;
2130 if (c1 > Maxcode)
2131 return codecvt_base::error;
2132 if (c1 < 0x80)
2133 {
2134 *to_nxt = static_cast<uint32_t>(c1);
2135 ++frm_nxt;
2136 }
2137 else if (c1 < 0xC2)
2138 {
2139 return codecvt_base::error;
2140 }
2141 else if (c1 < 0xE0)
2142 {
2143 if (frm_end-frm_nxt < 2)
2144 return codecvt_base::partial;
2145 uint8_t c2 = frm_nxt[1];
2146 if ((c2 & 0xC0) != 0x80)
2147 return codecvt_base::error;
2148 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2149 if (t > Maxcode)
2150 return codecvt_base::error;
2151 *to_nxt = static_cast<uint32_t>(t);
2152 frm_nxt += 2;
2153 }
2154 else if (c1 < 0xF0)
2155 {
2156 if (frm_end-frm_nxt < 3)
2157 return codecvt_base::partial;
2158 uint8_t c2 = frm_nxt[1];
2159 uint8_t c3 = frm_nxt[2];
2160 switch (c1)
2161 {
2162 case 0xE0:
2163 if ((c2 & 0xE0) != 0xA0)
2164 return codecvt_base::error;
2165 break;
2166 case 0xED:
2167 if ((c2 & 0xE0) != 0x80)
2168 return codecvt_base::error;
2169 break;
2170 default:
2171 if ((c2 & 0xC0) != 0x80)
2172 return codecvt_base::error;
2173 break;
2174 }
2175 if ((c3 & 0xC0) != 0x80)
2176 return codecvt_base::error;
2177 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2178 | ((c2 & 0x3F) << 6)
2179 | (c3 & 0x3F));
2180 if (t > Maxcode)
2181 return codecvt_base::error;
2182 *to_nxt = static_cast<uint32_t>(t);
2183 frm_nxt += 3;
2184 }
2185 else if (c1 < 0xF5)
2186 {
2187 if (frm_end-frm_nxt < 4)
2188 return codecvt_base::partial;
2189 uint8_t c2 = frm_nxt[1];
2190 uint8_t c3 = frm_nxt[2];
2191 uint8_t c4 = frm_nxt[3];
2192 switch (c1)
2193 {
2194 case 0xF0:
2195 if (!(0x90 <= c2 && c2 <= 0xBF))
2196 return codecvt_base::error;
2197 break;
2198 case 0xF4:
2199 if ((c2 & 0xF0) != 0x80)
2200 return codecvt_base::error;
2201 break;
2202 default:
2203 if ((c2 & 0xC0) != 0x80)
2204 return codecvt_base::error;
2205 break;
2206 }
2207 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2208 return codecvt_base::error;
2209 if (to_end-to_nxt < 2)
2210 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002211 if ((((c1 & 7UL) << 18) +
2212 ((c2 & 0x3FUL) << 12) +
2213 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002214 return codecvt_base::error;
2215 *to_nxt = static_cast<uint32_t>(
2216 0xD800
2217 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2218 | ((c2 & 0x0F) << 2)
2219 | ((c3 & 0x30) >> 4));
2220 *++to_nxt = static_cast<uint32_t>(
2221 0xDC00
2222 | ((c3 & 0x0F) << 6)
2223 | (c4 & 0x3F));
2224 frm_nxt += 4;
2225 }
2226 else
2227 {
2228 return codecvt_base::error;
2229 }
2230 }
2231 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2232}
2233
2234static
2235int
2236utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2237 size_t mx, unsigned long Maxcode = 0x10FFFF,
2238 codecvt_mode mode = codecvt_mode(0))
2239{
2240 const uint8_t* frm_nxt = frm;
2241 if (mode & consume_header)
2242 {
2243 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2244 frm_nxt[2] == 0xBF)
2245 frm_nxt += 3;
2246 }
2247 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2248 {
2249 uint8_t c1 = *frm_nxt;
2250 if (c1 > Maxcode)
2251 break;
2252 if (c1 < 0x80)
2253 {
2254 ++frm_nxt;
2255 }
2256 else if (c1 < 0xC2)
2257 {
2258 break;
2259 }
2260 else if (c1 < 0xE0)
2261 {
2262 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2263 break;
2264 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2265 if (t > Maxcode)
2266 break;
2267 frm_nxt += 2;
2268 }
2269 else if (c1 < 0xF0)
2270 {
2271 if (frm_end-frm_nxt < 3)
2272 break;
2273 uint8_t c2 = frm_nxt[1];
2274 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002275 switch (c1)
2276 {
2277 case 0xE0:
2278 if ((c2 & 0xE0) != 0xA0)
2279 return static_cast<int>(frm_nxt - frm);
2280 break;
2281 case 0xED:
2282 if ((c2 & 0xE0) != 0x80)
2283 return static_cast<int>(frm_nxt - frm);
2284 break;
2285 default:
2286 if ((c2 & 0xC0) != 0x80)
2287 return static_cast<int>(frm_nxt - frm);
2288 break;
2289 }
2290 if ((c3 & 0xC0) != 0x80)
2291 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002292 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002293 break;
2294 frm_nxt += 3;
2295 }
2296 else if (c1 < 0xF5)
2297 {
2298 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2299 break;
2300 uint8_t c2 = frm_nxt[1];
2301 uint8_t c3 = frm_nxt[2];
2302 uint8_t c4 = frm_nxt[3];
2303 switch (c1)
2304 {
2305 case 0xF0:
2306 if (!(0x90 <= c2 && c2 <= 0xBF))
2307 return static_cast<int>(frm_nxt - frm);
2308 break;
2309 case 0xF4:
2310 if ((c2 & 0xF0) != 0x80)
2311 return static_cast<int>(frm_nxt - frm);
2312 break;
2313 default:
2314 if ((c2 & 0xC0) != 0x80)
2315 return static_cast<int>(frm_nxt - frm);
2316 break;
2317 }
2318 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2319 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002320 if ((((c1 & 7UL) << 18) +
2321 ((c2 & 0x3FUL) << 12) +
2322 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002323 break;
2324 ++nchar16_t;
2325 frm_nxt += 4;
2326 }
2327 else
2328 {
2329 break;
2330 }
2331 }
2332 return static_cast<int>(frm_nxt - frm);
2333}
2334
2335static
2336codecvt_base::result
2337ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2338 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2339 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2340{
2341 frm_nxt = frm;
2342 to_nxt = to;
2343 if (mode & generate_header)
2344 {
2345 if (to_end-to_nxt < 3)
2346 return codecvt_base::partial;
2347 *to_nxt++ = static_cast<uint8_t>(0xEF);
2348 *to_nxt++ = static_cast<uint8_t>(0xBB);
2349 *to_nxt++ = static_cast<uint8_t>(0xBF);
2350 }
2351 for (; frm_nxt < frm_end; ++frm_nxt)
2352 {
2353 uint32_t wc = *frm_nxt;
2354 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2355 return codecvt_base::error;
2356 if (wc < 0x000080)
2357 {
2358 if (to_end-to_nxt < 1)
2359 return codecvt_base::partial;
2360 *to_nxt++ = static_cast<uint8_t>(wc);
2361 }
2362 else if (wc < 0x000800)
2363 {
2364 if (to_end-to_nxt < 2)
2365 return codecvt_base::partial;
2366 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2367 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2368 }
2369 else if (wc < 0x010000)
2370 {
2371 if (to_end-to_nxt < 3)
2372 return codecvt_base::partial;
2373 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2374 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2375 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2376 }
2377 else // if (wc < 0x110000)
2378 {
2379 if (to_end-to_nxt < 4)
2380 return codecvt_base::partial;
2381 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2382 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2383 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2384 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2385 }
2386 }
2387 return codecvt_base::ok;
2388}
2389
2390static
2391codecvt_base::result
2392utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2393 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2394 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2395{
2396 frm_nxt = frm;
2397 to_nxt = to;
2398 if (mode & consume_header)
2399 {
2400 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2401 frm_nxt[2] == 0xBF)
2402 frm_nxt += 3;
2403 }
2404 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2405 {
2406 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2407 if (c1 < 0x80)
2408 {
2409 if (c1 > Maxcode)
2410 return codecvt_base::error;
2411 *to_nxt = static_cast<uint32_t>(c1);
2412 ++frm_nxt;
2413 }
2414 else if (c1 < 0xC2)
2415 {
2416 return codecvt_base::error;
2417 }
2418 else if (c1 < 0xE0)
2419 {
2420 if (frm_end-frm_nxt < 2)
2421 return codecvt_base::partial;
2422 uint8_t c2 = frm_nxt[1];
2423 if ((c2 & 0xC0) != 0x80)
2424 return codecvt_base::error;
2425 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2426 | (c2 & 0x3F));
2427 if (t > Maxcode)
2428 return codecvt_base::error;
2429 *to_nxt = t;
2430 frm_nxt += 2;
2431 }
2432 else if (c1 < 0xF0)
2433 {
2434 if (frm_end-frm_nxt < 3)
2435 return codecvt_base::partial;
2436 uint8_t c2 = frm_nxt[1];
2437 uint8_t c3 = frm_nxt[2];
2438 switch (c1)
2439 {
2440 case 0xE0:
2441 if ((c2 & 0xE0) != 0xA0)
2442 return codecvt_base::error;
2443 break;
2444 case 0xED:
2445 if ((c2 & 0xE0) != 0x80)
2446 return codecvt_base::error;
2447 break;
2448 default:
2449 if ((c2 & 0xC0) != 0x80)
2450 return codecvt_base::error;
2451 break;
2452 }
2453 if ((c3 & 0xC0) != 0x80)
2454 return codecvt_base::error;
2455 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2456 | ((c2 & 0x3F) << 6)
2457 | (c3 & 0x3F));
2458 if (t > Maxcode)
2459 return codecvt_base::error;
2460 *to_nxt = t;
2461 frm_nxt += 3;
2462 }
2463 else if (c1 < 0xF5)
2464 {
2465 if (frm_end-frm_nxt < 4)
2466 return codecvt_base::partial;
2467 uint8_t c2 = frm_nxt[1];
2468 uint8_t c3 = frm_nxt[2];
2469 uint8_t c4 = frm_nxt[3];
2470 switch (c1)
2471 {
2472 case 0xF0:
2473 if (!(0x90 <= c2 && c2 <= 0xBF))
2474 return codecvt_base::error;
2475 break;
2476 case 0xF4:
2477 if ((c2 & 0xF0) != 0x80)
2478 return codecvt_base::error;
2479 break;
2480 default:
2481 if ((c2 & 0xC0) != 0x80)
2482 return codecvt_base::error;
2483 break;
2484 }
2485 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2486 return codecvt_base::error;
2487 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2488 | ((c2 & 0x3F) << 12)
2489 | ((c3 & 0x3F) << 6)
2490 | (c4 & 0x3F));
2491 if (t > Maxcode)
2492 return codecvt_base::error;
2493 *to_nxt = t;
2494 frm_nxt += 4;
2495 }
2496 else
2497 {
2498 return codecvt_base::error;
2499 }
2500 }
2501 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2502}
2503
2504static
2505int
2506utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2507 size_t mx, unsigned long Maxcode = 0x10FFFF,
2508 codecvt_mode mode = codecvt_mode(0))
2509{
2510 const uint8_t* frm_nxt = frm;
2511 if (mode & consume_header)
2512 {
2513 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2514 frm_nxt[2] == 0xBF)
2515 frm_nxt += 3;
2516 }
2517 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2518 {
2519 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2520 if (c1 < 0x80)
2521 {
2522 if (c1 > Maxcode)
2523 break;
2524 ++frm_nxt;
2525 }
2526 else if (c1 < 0xC2)
2527 {
2528 break;
2529 }
2530 else if (c1 < 0xE0)
2531 {
2532 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2533 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002534 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002535 break;
2536 frm_nxt += 2;
2537 }
2538 else if (c1 < 0xF0)
2539 {
2540 if (frm_end-frm_nxt < 3)
2541 break;
2542 uint8_t c2 = frm_nxt[1];
2543 uint8_t c3 = frm_nxt[2];
2544 switch (c1)
2545 {
2546 case 0xE0:
2547 if ((c2 & 0xE0) != 0xA0)
2548 return static_cast<int>(frm_nxt - frm);
2549 break;
2550 case 0xED:
2551 if ((c2 & 0xE0) != 0x80)
2552 return static_cast<int>(frm_nxt - frm);
2553 break;
2554 default:
2555 if ((c2 & 0xC0) != 0x80)
2556 return static_cast<int>(frm_nxt - frm);
2557 break;
2558 }
2559 if ((c3 & 0xC0) != 0x80)
2560 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002561 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002562 break;
2563 frm_nxt += 3;
2564 }
2565 else if (c1 < 0xF5)
2566 {
2567 if (frm_end-frm_nxt < 4)
2568 break;
2569 uint8_t c2 = frm_nxt[1];
2570 uint8_t c3 = frm_nxt[2];
2571 uint8_t c4 = frm_nxt[3];
2572 switch (c1)
2573 {
2574 case 0xF0:
2575 if (!(0x90 <= c2 && c2 <= 0xBF))
2576 return static_cast<int>(frm_nxt - frm);
2577 break;
2578 case 0xF4:
2579 if ((c2 & 0xF0) != 0x80)
2580 return static_cast<int>(frm_nxt - frm);
2581 break;
2582 default:
2583 if ((c2 & 0xC0) != 0x80)
2584 return static_cast<int>(frm_nxt - frm);
2585 break;
2586 }
2587 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2588 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002589 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2590 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002591 break;
2592 frm_nxt += 4;
2593 }
2594 else
2595 {
2596 break;
2597 }
2598 }
2599 return static_cast<int>(frm_nxt - frm);
2600}
2601
2602static
2603codecvt_base::result
2604ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2605 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2606 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2607{
2608 frm_nxt = frm;
2609 to_nxt = to;
2610 if (mode & generate_header)
2611 {
2612 if (to_end-to_nxt < 3)
2613 return codecvt_base::partial;
2614 *to_nxt++ = static_cast<uint8_t>(0xEF);
2615 *to_nxt++ = static_cast<uint8_t>(0xBB);
2616 *to_nxt++ = static_cast<uint8_t>(0xBF);
2617 }
2618 for (; frm_nxt < frm_end; ++frm_nxt)
2619 {
2620 uint16_t wc = *frm_nxt;
2621 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2622 return codecvt_base::error;
2623 if (wc < 0x0080)
2624 {
2625 if (to_end-to_nxt < 1)
2626 return codecvt_base::partial;
2627 *to_nxt++ = static_cast<uint8_t>(wc);
2628 }
2629 else if (wc < 0x0800)
2630 {
2631 if (to_end-to_nxt < 2)
2632 return codecvt_base::partial;
2633 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2634 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2635 }
2636 else // if (wc <= 0xFFFF)
2637 {
2638 if (to_end-to_nxt < 3)
2639 return codecvt_base::partial;
2640 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2641 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2642 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2643 }
2644 }
2645 return codecvt_base::ok;
2646}
2647
2648static
2649codecvt_base::result
2650utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2651 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2652 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2653{
2654 frm_nxt = frm;
2655 to_nxt = to;
2656 if (mode & consume_header)
2657 {
2658 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2659 frm_nxt[2] == 0xBF)
2660 frm_nxt += 3;
2661 }
2662 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2663 {
2664 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2665 if (c1 < 0x80)
2666 {
2667 if (c1 > Maxcode)
2668 return codecvt_base::error;
2669 *to_nxt = static_cast<uint16_t>(c1);
2670 ++frm_nxt;
2671 }
2672 else if (c1 < 0xC2)
2673 {
2674 return codecvt_base::error;
2675 }
2676 else if (c1 < 0xE0)
2677 {
2678 if (frm_end-frm_nxt < 2)
2679 return codecvt_base::partial;
2680 uint8_t c2 = frm_nxt[1];
2681 if ((c2 & 0xC0) != 0x80)
2682 return codecvt_base::error;
2683 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2684 | (c2 & 0x3F));
2685 if (t > Maxcode)
2686 return codecvt_base::error;
2687 *to_nxt = t;
2688 frm_nxt += 2;
2689 }
2690 else if (c1 < 0xF0)
2691 {
2692 if (frm_end-frm_nxt < 3)
2693 return codecvt_base::partial;
2694 uint8_t c2 = frm_nxt[1];
2695 uint8_t c3 = frm_nxt[2];
2696 switch (c1)
2697 {
2698 case 0xE0:
2699 if ((c2 & 0xE0) != 0xA0)
2700 return codecvt_base::error;
2701 break;
2702 case 0xED:
2703 if ((c2 & 0xE0) != 0x80)
2704 return codecvt_base::error;
2705 break;
2706 default:
2707 if ((c2 & 0xC0) != 0x80)
2708 return codecvt_base::error;
2709 break;
2710 }
2711 if ((c3 & 0xC0) != 0x80)
2712 return codecvt_base::error;
2713 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2714 | ((c2 & 0x3F) << 6)
2715 | (c3 & 0x3F));
2716 if (t > Maxcode)
2717 return codecvt_base::error;
2718 *to_nxt = t;
2719 frm_nxt += 3;
2720 }
2721 else
2722 {
2723 return codecvt_base::error;
2724 }
2725 }
2726 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2727}
2728
2729static
2730int
2731utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2732 size_t mx, unsigned long Maxcode = 0x10FFFF,
2733 codecvt_mode mode = codecvt_mode(0))
2734{
2735 const uint8_t* frm_nxt = frm;
2736 if (mode & consume_header)
2737 {
2738 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2739 frm_nxt[2] == 0xBF)
2740 frm_nxt += 3;
2741 }
2742 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2743 {
2744 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2745 if (c1 < 0x80)
2746 {
2747 if (c1 > Maxcode)
2748 break;
2749 ++frm_nxt;
2750 }
2751 else if (c1 < 0xC2)
2752 {
2753 break;
2754 }
2755 else if (c1 < 0xE0)
2756 {
2757 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2758 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002759 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002760 break;
2761 frm_nxt += 2;
2762 }
2763 else if (c1 < 0xF0)
2764 {
2765 if (frm_end-frm_nxt < 3)
2766 break;
2767 uint8_t c2 = frm_nxt[1];
2768 uint8_t c3 = frm_nxt[2];
2769 switch (c1)
2770 {
2771 case 0xE0:
2772 if ((c2 & 0xE0) != 0xA0)
2773 return static_cast<int>(frm_nxt - frm);
2774 break;
2775 case 0xED:
2776 if ((c2 & 0xE0) != 0x80)
2777 return static_cast<int>(frm_nxt - frm);
2778 break;
2779 default:
2780 if ((c2 & 0xC0) != 0x80)
2781 return static_cast<int>(frm_nxt - frm);
2782 break;
2783 }
2784 if ((c3 & 0xC0) != 0x80)
2785 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002786 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002787 break;
2788 frm_nxt += 3;
2789 }
2790 else
2791 {
2792 break;
2793 }
2794 }
2795 return static_cast<int>(frm_nxt - frm);
2796}
2797
2798static
2799codecvt_base::result
2800ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2801 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2802 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2803{
2804 frm_nxt = frm;
2805 to_nxt = to;
2806 if (mode & generate_header)
2807 {
2808 if (to_end-to_nxt < 2)
2809 return codecvt_base::partial;
2810 *to_nxt++ = static_cast<uint8_t>(0xFE);
2811 *to_nxt++ = static_cast<uint8_t>(0xFF);
2812 }
2813 for (; frm_nxt < frm_end; ++frm_nxt)
2814 {
2815 uint32_t wc = *frm_nxt;
2816 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2817 return codecvt_base::error;
2818 if (wc < 0x010000)
2819 {
2820 if (to_end-to_nxt < 2)
2821 return codecvt_base::partial;
2822 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2823 *to_nxt++ = static_cast<uint8_t>(wc);
2824 }
2825 else
2826 {
2827 if (to_end-to_nxt < 4)
2828 return codecvt_base::partial;
2829 uint16_t t = static_cast<uint16_t>(
2830 0xD800
2831 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2832 | ((wc & 0x00FC00) >> 10));
2833 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2834 *to_nxt++ = static_cast<uint8_t>(t);
2835 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2836 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2837 *to_nxt++ = static_cast<uint8_t>(t);
2838 }
2839 }
2840 return codecvt_base::ok;
2841}
2842
2843static
2844codecvt_base::result
2845utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2846 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2847 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2848{
2849 frm_nxt = frm;
2850 to_nxt = to;
2851 if (mode & consume_header)
2852 {
2853 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2854 frm_nxt += 2;
2855 }
2856 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2857 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002858 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002859 if ((c1 & 0xFC00) == 0xDC00)
2860 return codecvt_base::error;
2861 if ((c1 & 0xFC00) != 0xD800)
2862 {
2863 if (c1 > Maxcode)
2864 return codecvt_base::error;
2865 *to_nxt = static_cast<uint32_t>(c1);
2866 frm_nxt += 2;
2867 }
2868 else
2869 {
2870 if (frm_end-frm_nxt < 4)
2871 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002872 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002873 if ((c2 & 0xFC00) != 0xDC00)
2874 return codecvt_base::error;
2875 uint32_t t = static_cast<uint32_t>(
2876 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2877 | ((c1 & 0x003F) << 10)
2878 | (c2 & 0x03FF));
2879 if (t > Maxcode)
2880 return codecvt_base::error;
2881 *to_nxt = t;
2882 frm_nxt += 4;
2883 }
2884 }
2885 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2886}
2887
2888static
2889int
2890utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2891 size_t mx, unsigned long Maxcode = 0x10FFFF,
2892 codecvt_mode mode = codecvt_mode(0))
2893{
2894 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002895 if (mode & consume_header)
2896 {
2897 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2898 frm_nxt += 2;
2899 }
2900 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2901 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002902 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002903 if ((c1 & 0xFC00) == 0xDC00)
2904 break;
2905 if ((c1 & 0xFC00) != 0xD800)
2906 {
2907 if (c1 > Maxcode)
2908 break;
2909 frm_nxt += 2;
2910 }
2911 else
2912 {
2913 if (frm_end-frm_nxt < 4)
2914 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002915 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002916 if ((c2 & 0xFC00) != 0xDC00)
2917 break;
2918 uint32_t t = static_cast<uint32_t>(
2919 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2920 | ((c1 & 0x003F) << 10)
2921 | (c2 & 0x03FF));
2922 if (t > Maxcode)
2923 break;
2924 frm_nxt += 4;
2925 }
2926 }
2927 return static_cast<int>(frm_nxt - frm);
2928}
2929
2930static
2931codecvt_base::result
2932ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2933 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2934 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2935{
2936 frm_nxt = frm;
2937 to_nxt = to;
2938 if (mode & generate_header)
2939 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002940 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002941 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002942 *to_nxt++ = static_cast<uint8_t>(0xFF);
2943 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002944 }
2945 for (; frm_nxt < frm_end; ++frm_nxt)
2946 {
2947 uint32_t wc = *frm_nxt;
2948 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2949 return codecvt_base::error;
2950 if (wc < 0x010000)
2951 {
2952 if (to_end-to_nxt < 2)
2953 return codecvt_base::partial;
2954 *to_nxt++ = static_cast<uint8_t>(wc);
2955 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2956 }
2957 else
2958 {
2959 if (to_end-to_nxt < 4)
2960 return codecvt_base::partial;
2961 uint16_t t = static_cast<uint16_t>(
2962 0xD800
2963 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2964 | ((wc & 0x00FC00) >> 10));
2965 *to_nxt++ = static_cast<uint8_t>(t);
2966 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2967 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2968 *to_nxt++ = static_cast<uint8_t>(t);
2969 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2970 }
2971 }
2972 return codecvt_base::ok;
2973}
2974
2975static
2976codecvt_base::result
2977utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2978 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2979 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2980{
2981 frm_nxt = frm;
2982 to_nxt = to;
2983 if (mode & consume_header)
2984 {
2985 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2986 frm_nxt += 2;
2987 }
2988 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2989 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002990 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002991 if ((c1 & 0xFC00) == 0xDC00)
2992 return codecvt_base::error;
2993 if ((c1 & 0xFC00) != 0xD800)
2994 {
2995 if (c1 > Maxcode)
2996 return codecvt_base::error;
2997 *to_nxt = static_cast<uint32_t>(c1);
2998 frm_nxt += 2;
2999 }
3000 else
3001 {
3002 if (frm_end-frm_nxt < 4)
3003 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00003004 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003005 if ((c2 & 0xFC00) != 0xDC00)
3006 return codecvt_base::error;
3007 uint32_t t = static_cast<uint32_t>(
3008 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3009 | ((c1 & 0x003F) << 10)
3010 | (c2 & 0x03FF));
3011 if (t > Maxcode)
3012 return codecvt_base::error;
3013 *to_nxt = t;
3014 frm_nxt += 4;
3015 }
3016 }
3017 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3018}
3019
3020static
3021int
3022utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
3023 size_t mx, unsigned long Maxcode = 0x10FFFF,
3024 codecvt_mode mode = codecvt_mode(0))
3025{
3026 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003027 if (mode & consume_header)
3028 {
3029 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3030 frm_nxt += 2;
3031 }
3032 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3033 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003034 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003035 if ((c1 & 0xFC00) == 0xDC00)
3036 break;
3037 if ((c1 & 0xFC00) != 0xD800)
3038 {
3039 if (c1 > Maxcode)
3040 break;
3041 frm_nxt += 2;
3042 }
3043 else
3044 {
3045 if (frm_end-frm_nxt < 4)
3046 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00003047 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003048 if ((c2 & 0xFC00) != 0xDC00)
3049 break;
3050 uint32_t t = static_cast<uint32_t>(
3051 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3052 | ((c1 & 0x003F) << 10)
3053 | (c2 & 0x03FF));
3054 if (t > Maxcode)
3055 break;
3056 frm_nxt += 4;
3057 }
3058 }
3059 return static_cast<int>(frm_nxt - frm);
3060}
3061
3062static
3063codecvt_base::result
3064ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3065 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3066 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3067{
3068 frm_nxt = frm;
3069 to_nxt = to;
3070 if (mode & generate_header)
3071 {
3072 if (to_end-to_nxt < 2)
3073 return codecvt_base::partial;
3074 *to_nxt++ = static_cast<uint8_t>(0xFE);
3075 *to_nxt++ = static_cast<uint8_t>(0xFF);
3076 }
3077 for (; frm_nxt < frm_end; ++frm_nxt)
3078 {
3079 uint16_t wc = *frm_nxt;
3080 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3081 return codecvt_base::error;
3082 if (to_end-to_nxt < 2)
3083 return codecvt_base::partial;
3084 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3085 *to_nxt++ = static_cast<uint8_t>(wc);
3086 }
3087 return codecvt_base::ok;
3088}
3089
3090static
3091codecvt_base::result
3092utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3093 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3094 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3095{
3096 frm_nxt = frm;
3097 to_nxt = to;
3098 if (mode & consume_header)
3099 {
3100 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3101 frm_nxt += 2;
3102 }
3103 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3104 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003105 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003106 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3107 return codecvt_base::error;
3108 *to_nxt = c1;
3109 frm_nxt += 2;
3110 }
3111 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3112}
3113
3114static
3115int
3116utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3117 size_t mx, unsigned long Maxcode = 0x10FFFF,
3118 codecvt_mode mode = codecvt_mode(0))
3119{
3120 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003121 if (mode & consume_header)
3122 {
3123 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3124 frm_nxt += 2;
3125 }
3126 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3127 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003128 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003129 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3130 break;
3131 frm_nxt += 2;
3132 }
3133 return static_cast<int>(frm_nxt - frm);
3134}
3135
3136static
3137codecvt_base::result
3138ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3139 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3140 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3141{
3142 frm_nxt = frm;
3143 to_nxt = to;
3144 if (mode & generate_header)
3145 {
3146 if (to_end-to_nxt < 2)
3147 return codecvt_base::partial;
3148 *to_nxt++ = static_cast<uint8_t>(0xFF);
3149 *to_nxt++ = static_cast<uint8_t>(0xFE);
3150 }
3151 for (; frm_nxt < frm_end; ++frm_nxt)
3152 {
3153 uint16_t wc = *frm_nxt;
3154 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3155 return codecvt_base::error;
3156 if (to_end-to_nxt < 2)
3157 return codecvt_base::partial;
3158 *to_nxt++ = static_cast<uint8_t>(wc);
3159 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3160 }
3161 return codecvt_base::ok;
3162}
3163
3164static
3165codecvt_base::result
3166utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3167 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3168 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3169{
3170 frm_nxt = frm;
3171 to_nxt = to;
3172 if (mode & consume_header)
3173 {
3174 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3175 frm_nxt += 2;
3176 }
3177 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3178 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003179 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003180 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3181 return codecvt_base::error;
3182 *to_nxt = c1;
3183 frm_nxt += 2;
3184 }
3185 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3186}
3187
3188static
3189int
3190utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3191 size_t mx, unsigned long Maxcode = 0x10FFFF,
3192 codecvt_mode mode = codecvt_mode(0))
3193{
3194 const uint8_t* frm_nxt = frm;
3195 frm_nxt = frm;
3196 if (mode & consume_header)
3197 {
3198 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3199 frm_nxt += 2;
3200 }
3201 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3202 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003203 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003204 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3205 break;
3206 frm_nxt += 2;
3207 }
3208 return static_cast<int>(frm_nxt - frm);
3209}
3210
Howard Hinnantc51e1022010-05-11 19:42:16 +00003211// template <> class codecvt<char16_t, char, mbstate_t>
3212
Howard Hinnantffb308e2010-08-22 00:03:27 +00003213locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003214
3215codecvt<char16_t, char, mbstate_t>::~codecvt()
3216{
3217}
3218
3219codecvt<char16_t, char, mbstate_t>::result
3220codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003221 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003222 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3223{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003224 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3225 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3226 const uint16_t* _frm_nxt = _frm;
3227 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3228 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3229 uint8_t* _to_nxt = _to;
3230 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3231 frm_nxt = frm + (_frm_nxt - _frm);
3232 to_nxt = to + (_to_nxt - _to);
3233 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003234}
3235
3236codecvt<char16_t, char, mbstate_t>::result
3237codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003238 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003239 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3240{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003241 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3242 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3243 const uint8_t* _frm_nxt = _frm;
3244 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3245 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3246 uint16_t* _to_nxt = _to;
3247 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3248 frm_nxt = frm + (_frm_nxt - _frm);
3249 to_nxt = to + (_to_nxt - _to);
3250 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003251}
3252
3253codecvt<char16_t, char, mbstate_t>::result
3254codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3255 extern_type* to, extern_type*, extern_type*& to_nxt) const
3256{
3257 to_nxt = to;
3258 return noconv;
3259}
3260
3261int
Louis Dionne65358e12021-03-01 12:09:45 -05003262codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003263{
3264 return 0;
3265}
3266
3267bool
Louis Dionne65358e12021-03-01 12:09:45 -05003268codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003269{
3270 return false;
3271}
3272
3273int
3274codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3275 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3276{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003277 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3278 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3279 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003280}
3281
3282int
Louis Dionne65358e12021-03-01 12:09:45 -05003283codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003284{
3285 return 4;
3286}
3287
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003288#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003289
3290// template <> class codecvt<char16_t, char8_t, mbstate_t>
3291
3292locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3293
3294codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3295{
3296}
3297
3298codecvt<char16_t, char8_t, mbstate_t>::result
3299codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3300 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3301 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3302{
3303 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3304 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3305 const uint16_t* _frm_nxt = _frm;
3306 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3307 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3308 uint8_t* _to_nxt = _to;
3309 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3310 frm_nxt = frm + (_frm_nxt - _frm);
3311 to_nxt = to + (_to_nxt - _to);
3312 return r;
3313}
3314
3315codecvt<char16_t, char8_t, mbstate_t>::result
3316codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3317 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3318 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3319{
3320 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3321 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3322 const uint8_t* _frm_nxt = _frm;
3323 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3324 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3325 uint16_t* _to_nxt = _to;
3326 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3327 frm_nxt = frm + (_frm_nxt - _frm);
3328 to_nxt = to + (_to_nxt - _to);
3329 return r;
3330}
3331
3332codecvt<char16_t, char8_t, mbstate_t>::result
3333codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3334 extern_type* to, extern_type*, extern_type*& to_nxt) const
3335{
3336 to_nxt = to;
3337 return noconv;
3338}
3339
3340int
Louis Dionne65358e12021-03-01 12:09:45 -05003341codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003342{
3343 return 0;
3344}
3345
3346bool
Louis Dionne65358e12021-03-01 12:09:45 -05003347codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003348{
3349 return false;
3350}
3351
3352int
3353codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3354 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3355{
3356 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3357 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3358 return utf8_to_utf16_length(_frm, _frm_end, mx);
3359}
3360
3361int
Louis Dionne65358e12021-03-01 12:09:45 -05003362codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003363{
3364 return 4;
3365}
3366
3367#endif
3368
Howard Hinnantc51e1022010-05-11 19:42:16 +00003369// template <> class codecvt<char32_t, char, mbstate_t>
3370
Howard Hinnantffb308e2010-08-22 00:03:27 +00003371locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003372
3373codecvt<char32_t, char, mbstate_t>::~codecvt()
3374{
3375}
3376
3377codecvt<char32_t, char, mbstate_t>::result
3378codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003379 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003380 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3381{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003382 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3383 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3384 const uint32_t* _frm_nxt = _frm;
3385 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3386 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3387 uint8_t* _to_nxt = _to;
3388 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3389 frm_nxt = frm + (_frm_nxt - _frm);
3390 to_nxt = to + (_to_nxt - _to);
3391 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003392}
3393
3394codecvt<char32_t, char, mbstate_t>::result
3395codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003396 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003397 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3398{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003399 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3400 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3401 const uint8_t* _frm_nxt = _frm;
3402 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3403 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3404 uint32_t* _to_nxt = _to;
3405 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3406 frm_nxt = frm + (_frm_nxt - _frm);
3407 to_nxt = to + (_to_nxt - _to);
3408 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003409}
3410
3411codecvt<char32_t, char, mbstate_t>::result
3412codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3413 extern_type* to, extern_type*, extern_type*& to_nxt) const
3414{
3415 to_nxt = to;
3416 return noconv;
3417}
3418
3419int
Louis Dionne65358e12021-03-01 12:09:45 -05003420codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003421{
3422 return 0;
3423}
3424
3425bool
Louis Dionne65358e12021-03-01 12:09:45 -05003426codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003427{
3428 return false;
3429}
3430
3431int
3432codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3433 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3434{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003435 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3436 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3437 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003438}
3439
3440int
Louis Dionne65358e12021-03-01 12:09:45 -05003441codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003442{
3443 return 4;
3444}
3445
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003446#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003447
3448// template <> class codecvt<char32_t, char8_t, mbstate_t>
3449
3450locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3451
3452codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3453{
3454}
3455
3456codecvt<char32_t, char8_t, mbstate_t>::result
3457codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3458 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3459 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3460{
3461 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3462 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3463 const uint32_t* _frm_nxt = _frm;
3464 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3465 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3466 uint8_t* _to_nxt = _to;
3467 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3468 frm_nxt = frm + (_frm_nxt - _frm);
3469 to_nxt = to + (_to_nxt - _to);
3470 return r;
3471}
3472
3473codecvt<char32_t, char8_t, mbstate_t>::result
3474codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3475 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3476 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3477{
3478 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3479 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3480 const uint8_t* _frm_nxt = _frm;
3481 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3482 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3483 uint32_t* _to_nxt = _to;
3484 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3485 frm_nxt = frm + (_frm_nxt - _frm);
3486 to_nxt = to + (_to_nxt - _to);
3487 return r;
3488}
3489
3490codecvt<char32_t, char8_t, mbstate_t>::result
3491codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3492 extern_type* to, extern_type*, extern_type*& to_nxt) const
3493{
3494 to_nxt = to;
3495 return noconv;
3496}
3497
3498int
Louis Dionne65358e12021-03-01 12:09:45 -05003499codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003500{
3501 return 0;
3502}
3503
3504bool
Louis Dionne65358e12021-03-01 12:09:45 -05003505codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003506{
3507 return false;
3508}
3509
3510int
3511codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3512 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3513{
3514 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3515 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3516 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3517}
3518
3519int
Louis Dionne65358e12021-03-01 12:09:45 -05003520codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003521{
3522 return 4;
3523}
3524
3525#endif
3526
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003527// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003528
Louis Dionne89258142021-08-23 15:32:36 -04003529#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003530__codecvt_utf8<wchar_t>::result
3531__codecvt_utf8<wchar_t>::do_out(state_type&,
3532 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003533 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3534{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003535#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003536 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3537 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3538 const uint16_t* _frm_nxt = _frm;
3539#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003540 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3541 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3542 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003543#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003544 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3545 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3546 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003547#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003548 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3549 _Maxcode_, _Mode_);
3550#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003551 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3552 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003553#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003554 frm_nxt = frm + (_frm_nxt - _frm);
3555 to_nxt = to + (_to_nxt - _to);
3556 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003557}
3558
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003559__codecvt_utf8<wchar_t>::result
3560__codecvt_utf8<wchar_t>::do_in(state_type&,
3561 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003562 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3563{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003564 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3565 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3566 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003567#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003568 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3569 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3570 uint16_t* _to_nxt = _to;
3571 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3572 _Maxcode_, _Mode_);
3573#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003574 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3575 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3576 uint32_t* _to_nxt = _to;
3577 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3578 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003579#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003580 frm_nxt = frm + (_frm_nxt - _frm);
3581 to_nxt = to + (_to_nxt - _to);
3582 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003583}
3584
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003585__codecvt_utf8<wchar_t>::result
3586__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003587 extern_type* to, extern_type*, extern_type*& to_nxt) const
3588{
3589 to_nxt = to;
3590 return noconv;
3591}
3592
3593int
Louis Dionne65358e12021-03-01 12:09:45 -05003594__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003595{
3596 return 0;
3597}
3598
3599bool
Louis Dionne65358e12021-03-01 12:09:45 -05003600__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003601{
3602 return false;
3603}
3604
3605int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003606__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003607 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3608{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003609 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3610 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003611#if defined(_LIBCPP_SHORT_WCHAR)
3612 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3613#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003614 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003615#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003616}
3617
3618int
Louis Dionne65358e12021-03-01 12:09:45 -05003619__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003620{
Xing Xue50b0eb42021-09-09 16:20:36 -04003621#if defined(_LIBCPP_SHORT_WCHAR)
3622 if (_Mode_ & consume_header)
3623 return 6;
3624 return 3;
3625#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003626 if (_Mode_ & consume_header)
3627 return 7;
3628 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003629#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003630}
Louis Dionne89258142021-08-23 15:32:36 -04003631#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003632
3633// __codecvt_utf8<char16_t>
3634
3635__codecvt_utf8<char16_t>::result
3636__codecvt_utf8<char16_t>::do_out(state_type&,
3637 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3638 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3639{
3640 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3641 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3642 const uint16_t* _frm_nxt = _frm;
3643 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3644 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3645 uint8_t* _to_nxt = _to;
3646 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3647 _Maxcode_, _Mode_);
3648 frm_nxt = frm + (_frm_nxt - _frm);
3649 to_nxt = to + (_to_nxt - _to);
3650 return r;
3651}
3652
3653__codecvt_utf8<char16_t>::result
3654__codecvt_utf8<char16_t>::do_in(state_type&,
3655 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3656 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3657{
3658 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3659 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3660 const uint8_t* _frm_nxt = _frm;
3661 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3662 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3663 uint16_t* _to_nxt = _to;
3664 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3665 _Maxcode_, _Mode_);
3666 frm_nxt = frm + (_frm_nxt - _frm);
3667 to_nxt = to + (_to_nxt - _to);
3668 return r;
3669}
3670
3671__codecvt_utf8<char16_t>::result
3672__codecvt_utf8<char16_t>::do_unshift(state_type&,
3673 extern_type* to, extern_type*, extern_type*& to_nxt) const
3674{
3675 to_nxt = to;
3676 return noconv;
3677}
3678
3679int
Louis Dionne65358e12021-03-01 12:09:45 -05003680__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003681{
3682 return 0;
3683}
3684
3685bool
Louis Dionne65358e12021-03-01 12:09:45 -05003686__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003687{
3688 return false;
3689}
3690
3691int
3692__codecvt_utf8<char16_t>::do_length(state_type&,
3693 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3694{
3695 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3696 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3697 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3698}
3699
3700int
Louis Dionne65358e12021-03-01 12:09:45 -05003701__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003702{
3703 if (_Mode_ & consume_header)
3704 return 6;
3705 return 3;
3706}
3707
3708// __codecvt_utf8<char32_t>
3709
3710__codecvt_utf8<char32_t>::result
3711__codecvt_utf8<char32_t>::do_out(state_type&,
3712 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3713 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3714{
3715 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3716 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3717 const uint32_t* _frm_nxt = _frm;
3718 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3719 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3720 uint8_t* _to_nxt = _to;
3721 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3722 _Maxcode_, _Mode_);
3723 frm_nxt = frm + (_frm_nxt - _frm);
3724 to_nxt = to + (_to_nxt - _to);
3725 return r;
3726}
3727
3728__codecvt_utf8<char32_t>::result
3729__codecvt_utf8<char32_t>::do_in(state_type&,
3730 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3731 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3732{
3733 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3734 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3735 const uint8_t* _frm_nxt = _frm;
3736 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3737 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3738 uint32_t* _to_nxt = _to;
3739 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3740 _Maxcode_, _Mode_);
3741 frm_nxt = frm + (_frm_nxt - _frm);
3742 to_nxt = to + (_to_nxt - _to);
3743 return r;
3744}
3745
3746__codecvt_utf8<char32_t>::result
3747__codecvt_utf8<char32_t>::do_unshift(state_type&,
3748 extern_type* to, extern_type*, extern_type*& to_nxt) const
3749{
3750 to_nxt = to;
3751 return noconv;
3752}
3753
3754int
Louis Dionne65358e12021-03-01 12:09:45 -05003755__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003756{
3757 return 0;
3758}
3759
3760bool
Louis Dionne65358e12021-03-01 12:09:45 -05003761__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003762{
3763 return false;
3764}
3765
3766int
3767__codecvt_utf8<char32_t>::do_length(state_type&,
3768 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3769{
3770 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3771 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3772 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3773}
3774
3775int
Louis Dionne65358e12021-03-01 12:09:45 -05003776__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003777{
3778 if (_Mode_ & consume_header)
3779 return 7;
3780 return 4;
3781}
3782
3783// __codecvt_utf16<wchar_t, false>
3784
Louis Dionne89258142021-08-23 15:32:36 -04003785#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003786__codecvt_utf16<wchar_t, false>::result
3787__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3788 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3789 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3790{
Xing Xue50b0eb42021-09-09 16:20:36 -04003791#if defined(_LIBCPP_SHORT_WCHAR)
3792 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3793 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3794 const uint16_t* _frm_nxt = _frm;
3795#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003796 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3797 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3798 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003799#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003800 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3801 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3802 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003803#if defined(_LIBCPP_SHORT_WCHAR)
3804 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3805 _Maxcode_, _Mode_);
3806#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003807 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3808 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003809#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003810 frm_nxt = frm + (_frm_nxt - _frm);
3811 to_nxt = to + (_to_nxt - _to);
3812 return r;
3813}
3814
3815__codecvt_utf16<wchar_t, false>::result
3816__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3817 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3818 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3819{
3820 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3821 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3822 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003823#if defined(_LIBCPP_SHORT_WCHAR)
3824 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3825 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3826 uint16_t* _to_nxt = _to;
3827 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3828 _Maxcode_, _Mode_);
3829#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003830 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3831 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3832 uint32_t* _to_nxt = _to;
3833 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3834 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003835#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003836 frm_nxt = frm + (_frm_nxt - _frm);
3837 to_nxt = to + (_to_nxt - _to);
3838 return r;
3839}
3840
3841__codecvt_utf16<wchar_t, false>::result
3842__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3843 extern_type* to, extern_type*, extern_type*& to_nxt) const
3844{
3845 to_nxt = to;
3846 return noconv;
3847}
3848
3849int
Louis Dionne65358e12021-03-01 12:09:45 -05003850__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003851{
3852 return 0;
3853}
3854
3855bool
Louis Dionne65358e12021-03-01 12:09:45 -05003856__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003857{
3858 return false;
3859}
3860
3861int
3862__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3863 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3864{
3865 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3866 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003867#if defined(_LIBCPP_SHORT_WCHAR)
3868 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3869#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003870 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003871#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003872}
3873
3874int
Louis Dionne65358e12021-03-01 12:09:45 -05003875__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003876{
Xing Xue50b0eb42021-09-09 16:20:36 -04003877#if defined(_LIBCPP_SHORT_WCHAR)
3878 if (_Mode_ & consume_header)
3879 return 4;
3880 return 2;
3881#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003882 if (_Mode_ & consume_header)
3883 return 6;
3884 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003885#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003886}
3887
3888// __codecvt_utf16<wchar_t, true>
3889
3890__codecvt_utf16<wchar_t, true>::result
3891__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3892 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3893 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3894{
Xing Xue50b0eb42021-09-09 16:20:36 -04003895#if defined(_LIBCPP_SHORT_WCHAR)
3896 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3897 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3898 const uint16_t* _frm_nxt = _frm;
3899#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003900 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3901 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3902 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003903#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003904 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3905 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3906 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003907#if defined(_LIBCPP_SHORT_WCHAR)
3908 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3909 _Maxcode_, _Mode_);
3910#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003911 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3912 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003913#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003914 frm_nxt = frm + (_frm_nxt - _frm);
3915 to_nxt = to + (_to_nxt - _to);
3916 return r;
3917}
3918
3919__codecvt_utf16<wchar_t, true>::result
3920__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3921 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3922 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3923{
3924 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3925 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3926 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003927#if defined(_LIBCPP_SHORT_WCHAR)
3928 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3929 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3930 uint16_t* _to_nxt = _to;
3931 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3932 _Maxcode_, _Mode_);
3933#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003934 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3935 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3936 uint32_t* _to_nxt = _to;
3937 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3938 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003939#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003940 frm_nxt = frm + (_frm_nxt - _frm);
3941 to_nxt = to + (_to_nxt - _to);
3942 return r;
3943}
3944
3945__codecvt_utf16<wchar_t, true>::result
3946__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3947 extern_type* to, extern_type*, extern_type*& to_nxt) const
3948{
3949 to_nxt = to;
3950 return noconv;
3951}
3952
3953int
Louis Dionne65358e12021-03-01 12:09:45 -05003954__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003955{
3956 return 0;
3957}
3958
3959bool
Louis Dionne65358e12021-03-01 12:09:45 -05003960__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003961{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003962 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003963}
3964
3965int
3966__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3967 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3968{
3969 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3970 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003971#if defined(_LIBCPP_SHORT_WCHAR)
3972 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3973#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003974 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003975#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003976}
3977
3978int
Louis Dionne65358e12021-03-01 12:09:45 -05003979__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003980{
Xing Xue50b0eb42021-09-09 16:20:36 -04003981#if defined(_LIBCPP_SHORT_WCHAR)
3982 if (_Mode_ & consume_header)
3983 return 4;
3984 return 2;
3985#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003986 if (_Mode_ & consume_header)
3987 return 6;
3988 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003989#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003990}
Louis Dionne89258142021-08-23 15:32:36 -04003991#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003992
3993// __codecvt_utf16<char16_t, false>
3994
3995__codecvt_utf16<char16_t, false>::result
3996__codecvt_utf16<char16_t, false>::do_out(state_type&,
3997 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3998 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3999{
4000 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4001 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4002 const uint16_t* _frm_nxt = _frm;
4003 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4004 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4005 uint8_t* _to_nxt = _to;
4006 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4007 _Maxcode_, _Mode_);
4008 frm_nxt = frm + (_frm_nxt - _frm);
4009 to_nxt = to + (_to_nxt - _to);
4010 return r;
4011}
4012
4013__codecvt_utf16<char16_t, false>::result
4014__codecvt_utf16<char16_t, false>::do_in(state_type&,
4015 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4016 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4017{
4018 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4019 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4020 const uint8_t* _frm_nxt = _frm;
4021 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4022 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4023 uint16_t* _to_nxt = _to;
4024 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4025 _Maxcode_, _Mode_);
4026 frm_nxt = frm + (_frm_nxt - _frm);
4027 to_nxt = to + (_to_nxt - _to);
4028 return r;
4029}
4030
4031__codecvt_utf16<char16_t, false>::result
4032__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4033 extern_type* to, extern_type*, extern_type*& to_nxt) const
4034{
4035 to_nxt = to;
4036 return noconv;
4037}
4038
4039int
Louis Dionne65358e12021-03-01 12:09:45 -05004040__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004041{
4042 return 0;
4043}
4044
4045bool
Louis Dionne65358e12021-03-01 12:09:45 -05004046__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004047{
4048 return false;
4049}
4050
4051int
4052__codecvt_utf16<char16_t, false>::do_length(state_type&,
4053 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4054{
4055 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4056 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4057 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4058}
4059
4060int
Louis Dionne65358e12021-03-01 12:09:45 -05004061__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004062{
4063 if (_Mode_ & consume_header)
4064 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004065 return 2;
4066}
4067
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004068// __codecvt_utf16<char16_t, true>
4069
4070__codecvt_utf16<char16_t, true>::result
4071__codecvt_utf16<char16_t, true>::do_out(state_type&,
4072 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4073 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4074{
4075 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4076 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4077 const uint16_t* _frm_nxt = _frm;
4078 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4079 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4080 uint8_t* _to_nxt = _to;
4081 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4082 _Maxcode_, _Mode_);
4083 frm_nxt = frm + (_frm_nxt - _frm);
4084 to_nxt = to + (_to_nxt - _to);
4085 return r;
4086}
4087
4088__codecvt_utf16<char16_t, true>::result
4089__codecvt_utf16<char16_t, true>::do_in(state_type&,
4090 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4091 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4092{
4093 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4094 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4095 const uint8_t* _frm_nxt = _frm;
4096 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4097 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4098 uint16_t* _to_nxt = _to;
4099 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4100 _Maxcode_, _Mode_);
4101 frm_nxt = frm + (_frm_nxt - _frm);
4102 to_nxt = to + (_to_nxt - _to);
4103 return r;
4104}
4105
4106__codecvt_utf16<char16_t, true>::result
4107__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4108 extern_type* to, extern_type*, extern_type*& to_nxt) const
4109{
4110 to_nxt = to;
4111 return noconv;
4112}
4113
4114int
Louis Dionne65358e12021-03-01 12:09:45 -05004115__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004116{
4117 return 0;
4118}
4119
4120bool
Louis Dionne65358e12021-03-01 12:09:45 -05004121__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004122{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004123 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004124}
4125
4126int
4127__codecvt_utf16<char16_t, true>::do_length(state_type&,
4128 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4129{
4130 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4131 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4132 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4133}
4134
4135int
Louis Dionne65358e12021-03-01 12:09:45 -05004136__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004137{
4138 if (_Mode_ & consume_header)
4139 return 4;
4140 return 2;
4141}
4142
4143// __codecvt_utf16<char32_t, false>
4144
4145__codecvt_utf16<char32_t, false>::result
4146__codecvt_utf16<char32_t, false>::do_out(state_type&,
4147 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4148 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4149{
4150 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4151 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4152 const uint32_t* _frm_nxt = _frm;
4153 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4154 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4155 uint8_t* _to_nxt = _to;
4156 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4157 _Maxcode_, _Mode_);
4158 frm_nxt = frm + (_frm_nxt - _frm);
4159 to_nxt = to + (_to_nxt - _to);
4160 return r;
4161}
4162
4163__codecvt_utf16<char32_t, false>::result
4164__codecvt_utf16<char32_t, false>::do_in(state_type&,
4165 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4166 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4167{
4168 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4169 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4170 const uint8_t* _frm_nxt = _frm;
4171 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4172 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4173 uint32_t* _to_nxt = _to;
4174 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4175 _Maxcode_, _Mode_);
4176 frm_nxt = frm + (_frm_nxt - _frm);
4177 to_nxt = to + (_to_nxt - _to);
4178 return r;
4179}
4180
4181__codecvt_utf16<char32_t, false>::result
4182__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4183 extern_type* to, extern_type*, extern_type*& to_nxt) const
4184{
4185 to_nxt = to;
4186 return noconv;
4187}
4188
4189int
Louis Dionne65358e12021-03-01 12:09:45 -05004190__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004191{
4192 return 0;
4193}
4194
4195bool
Louis Dionne65358e12021-03-01 12:09:45 -05004196__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004197{
4198 return false;
4199}
4200
4201int
4202__codecvt_utf16<char32_t, false>::do_length(state_type&,
4203 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4204{
4205 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4206 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4207 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4208}
4209
4210int
Louis Dionne65358e12021-03-01 12:09:45 -05004211__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004212{
4213 if (_Mode_ & consume_header)
4214 return 6;
4215 return 4;
4216}
4217
4218// __codecvt_utf16<char32_t, true>
4219
4220__codecvt_utf16<char32_t, true>::result
4221__codecvt_utf16<char32_t, true>::do_out(state_type&,
4222 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4223 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4224{
4225 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4226 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4227 const uint32_t* _frm_nxt = _frm;
4228 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4229 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4230 uint8_t* _to_nxt = _to;
4231 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4232 _Maxcode_, _Mode_);
4233 frm_nxt = frm + (_frm_nxt - _frm);
4234 to_nxt = to + (_to_nxt - _to);
4235 return r;
4236}
4237
4238__codecvt_utf16<char32_t, true>::result
4239__codecvt_utf16<char32_t, true>::do_in(state_type&,
4240 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4241 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4242{
4243 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4244 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4245 const uint8_t* _frm_nxt = _frm;
4246 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4247 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4248 uint32_t* _to_nxt = _to;
4249 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4250 _Maxcode_, _Mode_);
4251 frm_nxt = frm + (_frm_nxt - _frm);
4252 to_nxt = to + (_to_nxt - _to);
4253 return r;
4254}
4255
4256__codecvt_utf16<char32_t, true>::result
4257__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4258 extern_type* to, extern_type*, extern_type*& to_nxt) const
4259{
4260 to_nxt = to;
4261 return noconv;
4262}
4263
4264int
Louis Dionne65358e12021-03-01 12:09:45 -05004265__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004266{
4267 return 0;
4268}
4269
4270bool
Louis Dionne65358e12021-03-01 12:09:45 -05004271__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004272{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004273 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004274}
4275
4276int
4277__codecvt_utf16<char32_t, true>::do_length(state_type&,
4278 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4279{
4280 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4281 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4282 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4283}
4284
4285int
Louis Dionne65358e12021-03-01 12:09:45 -05004286__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004287{
4288 if (_Mode_ & consume_header)
4289 return 6;
4290 return 4;
4291}
4292
4293// __codecvt_utf8_utf16<wchar_t>
4294
Louis Dionne89258142021-08-23 15:32:36 -04004295#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004296__codecvt_utf8_utf16<wchar_t>::result
4297__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4298 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4299 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4300{
Xing Xue50b0eb42021-09-09 16:20:36 -04004301#if defined(_LIBCPP_SHORT_WCHAR)
4302 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4303 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4304 const uint16_t* _frm_nxt = _frm;
4305#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004306 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4307 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4308 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004309#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004310 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4311 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4312 uint8_t* _to_nxt = _to;
4313 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4314 _Maxcode_, _Mode_);
4315 frm_nxt = frm + (_frm_nxt - _frm);
4316 to_nxt = to + (_to_nxt - _to);
4317 return r;
4318}
4319
4320__codecvt_utf8_utf16<wchar_t>::result
4321__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4322 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4323 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4324{
4325 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4326 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4327 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004328#if defined(_LIBCPP_SHORT_WCHAR)
4329 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4330 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4331 uint16_t* _to_nxt = _to;
4332#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004333 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4334 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4335 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004336#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004337 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4338 _Maxcode_, _Mode_);
4339 frm_nxt = frm + (_frm_nxt - _frm);
4340 to_nxt = to + (_to_nxt - _to);
4341 return r;
4342}
4343
4344__codecvt_utf8_utf16<wchar_t>::result
4345__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4346 extern_type* to, extern_type*, extern_type*& to_nxt) const
4347{
4348 to_nxt = to;
4349 return noconv;
4350}
4351
4352int
Louis Dionne65358e12021-03-01 12:09:45 -05004353__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004354{
4355 return 0;
4356}
4357
4358bool
Louis Dionne65358e12021-03-01 12:09:45 -05004359__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004360{
4361 return false;
4362}
4363
4364int
4365__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4366 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4367{
4368 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4369 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4370 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4371}
4372
4373int
Louis Dionne65358e12021-03-01 12:09:45 -05004374__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004375{
4376 if (_Mode_ & consume_header)
4377 return 7;
4378 return 4;
4379}
Louis Dionne89258142021-08-23 15:32:36 -04004380#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004381
4382// __codecvt_utf8_utf16<char16_t>
4383
4384__codecvt_utf8_utf16<char16_t>::result
4385__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4386 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4387 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4388{
4389 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4390 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4391 const uint16_t* _frm_nxt = _frm;
4392 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4393 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4394 uint8_t* _to_nxt = _to;
4395 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4396 _Maxcode_, _Mode_);
4397 frm_nxt = frm + (_frm_nxt - _frm);
4398 to_nxt = to + (_to_nxt - _to);
4399 return r;
4400}
4401
4402__codecvt_utf8_utf16<char16_t>::result
4403__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4404 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4405 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4406{
4407 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4408 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4409 const uint8_t* _frm_nxt = _frm;
4410 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4411 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4412 uint16_t* _to_nxt = _to;
4413 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4414 _Maxcode_, _Mode_);
4415 frm_nxt = frm + (_frm_nxt - _frm);
4416 to_nxt = to + (_to_nxt - _to);
4417 return r;
4418}
4419
4420__codecvt_utf8_utf16<char16_t>::result
4421__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4422 extern_type* to, extern_type*, extern_type*& to_nxt) const
4423{
4424 to_nxt = to;
4425 return noconv;
4426}
4427
4428int
Louis Dionne65358e12021-03-01 12:09:45 -05004429__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004430{
4431 return 0;
4432}
4433
4434bool
Louis Dionne65358e12021-03-01 12:09:45 -05004435__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004436{
4437 return false;
4438}
4439
4440int
4441__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4442 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4443{
4444 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4445 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4446 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4447}
4448
4449int
Louis Dionne65358e12021-03-01 12:09:45 -05004450__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004451{
4452 if (_Mode_ & consume_header)
4453 return 7;
4454 return 4;
4455}
4456
4457// __codecvt_utf8_utf16<char32_t>
4458
4459__codecvt_utf8_utf16<char32_t>::result
4460__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4461 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4462 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4463{
4464 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4465 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4466 const uint32_t* _frm_nxt = _frm;
4467 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4468 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4469 uint8_t* _to_nxt = _to;
4470 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4471 _Maxcode_, _Mode_);
4472 frm_nxt = frm + (_frm_nxt - _frm);
4473 to_nxt = to + (_to_nxt - _to);
4474 return r;
4475}
4476
4477__codecvt_utf8_utf16<char32_t>::result
4478__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4479 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4480 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4481{
4482 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4483 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4484 const uint8_t* _frm_nxt = _frm;
4485 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4486 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4487 uint32_t* _to_nxt = _to;
4488 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4489 _Maxcode_, _Mode_);
4490 frm_nxt = frm + (_frm_nxt - _frm);
4491 to_nxt = to + (_to_nxt - _to);
4492 return r;
4493}
4494
4495__codecvt_utf8_utf16<char32_t>::result
4496__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4497 extern_type* to, extern_type*, extern_type*& to_nxt) const
4498{
4499 to_nxt = to;
4500 return noconv;
4501}
4502
4503int
Louis Dionne65358e12021-03-01 12:09:45 -05004504__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004505{
4506 return 0;
4507}
4508
4509bool
Louis Dionne65358e12021-03-01 12:09:45 -05004510__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004511{
4512 return false;
4513}
4514
4515int
4516__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4517 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4518{
4519 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4520 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4521 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4522}
4523
4524int
Louis Dionne65358e12021-03-01 12:09:45 -05004525__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004526{
4527 if (_Mode_ & consume_header)
4528 return 7;
4529 return 4;
4530}
4531
Howard Hinnantc51e1022010-05-11 19:42:16 +00004532// __narrow_to_utf8<16>
4533
4534__narrow_to_utf8<16>::~__narrow_to_utf8()
4535{
4536}
4537
4538// __narrow_to_utf8<32>
4539
4540__narrow_to_utf8<32>::~__narrow_to_utf8()
4541{
4542}
4543
4544// __widen_from_utf8<16>
4545
4546__widen_from_utf8<16>::~__widen_from_utf8()
4547{
4548}
4549
4550// __widen_from_utf8<32>
4551
4552__widen_from_utf8<32>::~__widen_from_utf8()
4553{
4554}
4555
Louis Dionne89258142021-08-23 15:32:36 -04004556#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004557static bool checked_string_to_wchar_convert(wchar_t& dest,
4558 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004559 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004560 if (*ptr == '\0')
4561 return false;
4562 mbstate_t mb = {};
4563 wchar_t out;
4564 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4565 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4566 return false;
4567 }
4568 dest = out;
4569 return true;
4570}
Louis Dionne89258142021-08-23 15:32:36 -04004571#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004572
Mark de Weverffed1402021-11-03 19:25:20 +01004573#ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4574static bool is_narrow_non_breaking_space(const char* ptr) {
4575 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4576 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4577}
4578
4579static bool is_non_breaking_space(const char* ptr) {
4580 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4581 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4582}
4583#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4584
Eric Fiselierbf945a22016-12-11 00:20:59 +00004585static bool checked_string_to_char_convert(char& dest,
4586 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004587 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004588 if (*ptr == '\0')
4589 return false;
4590 if (!ptr[1]) {
4591 dest = *ptr;
4592 return true;
4593 }
Louis Dionne89258142021-08-23 15:32:36 -04004594
4595#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004596 // First convert the MBS into a wide char then attempt to narrow it using
4597 // wctob_l.
4598 wchar_t wout;
4599 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4600 return false;
4601 int res;
4602 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4603 dest = res;
4604 return true;
4605 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004606 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004607 // translate into a different single byte.
4608 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004609 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004610 case L'\u00A0': // non-breaking space
4611 dest = ' ';
4612 return true;
4613 default:
4614 return false;
4615 }
Louis Dionne89258142021-08-23 15:32:36 -04004616#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverffed1402021-11-03 19:25:20 +01004617 // FIXME: Work around specific multibyte sequences that we can reasonably
4618 // translate into a different single byte.
4619 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4620 dest = ' ';
4621 return true;
4622 }
4623
Louis Dionne89258142021-08-23 15:32:36 -04004624 return false;
4625#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004626 _LIBCPP_UNREACHABLE();
4627}
4628
4629
Howard Hinnantc51e1022010-05-11 19:42:16 +00004630// numpunct<char> && numpunct<wchar_t>
4631
4632locale::id numpunct< char >::id;
Louis Dionne89258142021-08-23 15:32:36 -04004633#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004634locale::id numpunct<wchar_t>::id;
Louis Dionne89258142021-08-23 15:32:36 -04004635#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004636
4637numpunct<char>::numpunct(size_t refs)
4638 : locale::facet(refs),
4639 __decimal_point_('.'),
4640 __thousands_sep_(',')
4641{
4642}
4643
Louis Dionne89258142021-08-23 15:32:36 -04004644#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004645numpunct<wchar_t>::numpunct(size_t refs)
4646 : locale::facet(refs),
4647 __decimal_point_(L'.'),
4648 __thousands_sep_(L',')
4649{
4650}
Louis Dionne89258142021-08-23 15:32:36 -04004651#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004652
4653numpunct<char>::~numpunct()
4654{
4655}
4656
Louis Dionne89258142021-08-23 15:32:36 -04004657#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004658numpunct<wchar_t>::~numpunct()
4659{
4660}
Louis Dionne89258142021-08-23 15:32:36 -04004661#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004662
4663 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004664#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004665wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004666#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004667
4668 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004669#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004670wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004671#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004672
4673string numpunct< char >::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004674#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004675string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004676#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004677
4678 string numpunct< char >::do_truename() const {return "true";}
Louis Dionne89258142021-08-23 15:32:36 -04004679#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004680wstring numpunct<wchar_t>::do_truename() const {return L"true";}
Louis Dionne89258142021-08-23 15:32:36 -04004681#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004682
4683 string numpunct< char >::do_falsename() const {return "false";}
Louis Dionne89258142021-08-23 15:32:36 -04004684#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004685wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
Louis Dionne89258142021-08-23 15:32:36 -04004686#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004687
4688// numpunct_byname<char>
4689
4690numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4691 : numpunct<char>(refs)
4692{
4693 __init(nm);
4694}
4695
4696numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4697 : numpunct<char>(refs)
4698{
4699 __init(nm.c_str());
4700}
4701
4702numpunct_byname<char>::~numpunct_byname()
4703{
4704}
4705
4706void
4707numpunct_byname<char>::__init(const char* nm)
4708{
Louis Dionne89258142021-08-23 15:32:36 -04004709 typedef numpunct<char> base;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004710 if (strcmp(nm, "C") != 0)
4711 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004712 __libcpp_unique_locale loc(nm);
4713 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004714 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004715 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004716
Ben Craig3756b922016-03-09 15:39:39 +00004717 lconv* lc = __libcpp_localeconv_l(loc.get());
Louis Dionne89258142021-08-23 15:32:36 -04004718 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4719 loc.get()))
4720 __decimal_point_ = base::do_decimal_point();
4721 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4722 loc.get()))
4723 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00004724 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004725 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004726 }
4727}
4728
4729// numpunct_byname<wchar_t>
4730
Louis Dionne89258142021-08-23 15:32:36 -04004731#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004732numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4733 : numpunct<wchar_t>(refs)
4734{
4735 __init(nm);
4736}
4737
4738numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4739 : numpunct<wchar_t>(refs)
4740{
4741 __init(nm.c_str());
4742}
4743
4744numpunct_byname<wchar_t>::~numpunct_byname()
4745{
4746}
4747
4748void
4749numpunct_byname<wchar_t>::__init(const char* nm)
4750{
4751 if (strcmp(nm, "C") != 0)
4752 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004753 __libcpp_unique_locale loc(nm);
4754 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004755 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004756 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004757
Ben Craig3756b922016-03-09 15:39:39 +00004758 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004759 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4760 loc.get());
4761 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4762 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004763 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004764 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004765 }
4766}
Louis Dionne89258142021-08-23 15:32:36 -04004767#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004768
4769// num_get helpers
4770
4771int
4772__num_get_base::__get_base(ios_base& iob)
4773{
4774 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4775 if (__basefield == ios_base::oct)
4776 return 8;
4777 else if (__basefield == ios_base::hex)
4778 return 16;
4779 else if (__basefield == 0)
4780 return 0;
4781 return 10;
4782}
4783
4784const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4785
4786void
4787__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4788 ios_base::iostate& __err)
4789{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004790// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4791// 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 +00004792 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004793 {
4794 reverse(__g, __g_end);
4795 const char* __ig = __grouping.data();
4796 const char* __eg = __ig + __grouping.size();
4797 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4798 {
4799 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4800 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004801 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004802 {
4803 __err = ios_base::failbit;
4804 return;
4805 }
4806 }
4807 if (__eg - __ig > 1)
4808 ++__ig;
4809 }
4810 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4811 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004812 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004813 __err = ios_base::failbit;
4814 }
4815 }
4816}
4817
4818void
4819__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4820 ios_base::fmtflags __flags)
4821{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004822 if ((__flags & ios_base::showpos) &&
4823 (__flags & ios_base::basefield) != ios_base::oct &&
4824 (__flags & ios_base::basefield) != ios_base::hex &&
4825 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004826 *__fmtp++ = '+';
4827 if (__flags & ios_base::showbase)
4828 *__fmtp++ = '#';
4829 while(*__len)
4830 *__fmtp++ = *__len++;
4831 if ((__flags & ios_base::basefield) == ios_base::oct)
4832 *__fmtp = 'o';
4833 else if ((__flags & ios_base::basefield) == ios_base::hex)
4834 {
4835 if (__flags & ios_base::uppercase)
4836 *__fmtp = 'X';
4837 else
4838 *__fmtp = 'x';
4839 }
4840 else if (__signd)
4841 *__fmtp = 'd';
4842 else
4843 *__fmtp = 'u';
4844}
4845
4846bool
4847__num_put_base::__format_float(char* __fmtp, const char* __len,
4848 ios_base::fmtflags __flags)
4849{
4850 bool specify_precision = true;
4851 if (__flags & ios_base::showpos)
4852 *__fmtp++ = '+';
4853 if (__flags & ios_base::showpoint)
4854 *__fmtp++ = '#';
4855 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004856 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004857 if (floatfield == (ios_base::fixed | ios_base::scientific))
4858 specify_precision = false;
4859 else
4860 {
4861 *__fmtp++ = '.';
4862 *__fmtp++ = '*';
4863 }
4864 while(*__len)
4865 *__fmtp++ = *__len++;
4866 if (floatfield == ios_base::fixed)
4867 {
4868 if (uppercase)
4869 *__fmtp = 'F';
4870 else
4871 *__fmtp = 'f';
4872 }
4873 else if (floatfield == ios_base::scientific)
4874 {
4875 if (uppercase)
4876 *__fmtp = 'E';
4877 else
4878 *__fmtp = 'e';
4879 }
4880 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4881 {
4882 if (uppercase)
4883 *__fmtp = 'A';
4884 else
4885 *__fmtp = 'a';
4886 }
4887 else
4888 {
4889 if (uppercase)
4890 *__fmtp = 'G';
4891 else
4892 *__fmtp = 'g';
4893 }
4894 return specify_precision;
4895}
4896
4897char*
4898__num_put_base::__identify_padding(char* __nb, char* __ne,
4899 const ios_base& __iob)
4900{
4901 switch (__iob.flags() & ios_base::adjustfield)
4902 {
4903 case ios_base::internal:
4904 if (__nb[0] == '-' || __nb[0] == '+')
4905 return __nb+1;
4906 if (__ne - __nb >= 2 && __nb[0] == '0'
4907 && (__nb[1] == 'x' || __nb[1] == 'X'))
4908 return __nb+2;
4909 break;
4910 case ios_base::left:
4911 return __ne;
4912 case ios_base::right:
4913 default:
4914 break;
4915 }
4916 return __nb;
4917}
4918
4919// time_get
4920
4921static
4922string*
4923init_weeks()
4924{
4925 static string weeks[14];
4926 weeks[0] = "Sunday";
4927 weeks[1] = "Monday";
4928 weeks[2] = "Tuesday";
4929 weeks[3] = "Wednesday";
4930 weeks[4] = "Thursday";
4931 weeks[5] = "Friday";
4932 weeks[6] = "Saturday";
4933 weeks[7] = "Sun";
4934 weeks[8] = "Mon";
4935 weeks[9] = "Tue";
4936 weeks[10] = "Wed";
4937 weeks[11] = "Thu";
4938 weeks[12] = "Fri";
4939 weeks[13] = "Sat";
4940 return weeks;
4941}
4942
Louis Dionne89258142021-08-23 15:32:36 -04004943#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004944static
4945wstring*
4946init_wweeks()
4947{
4948 static wstring weeks[14];
4949 weeks[0] = L"Sunday";
4950 weeks[1] = L"Monday";
4951 weeks[2] = L"Tuesday";
4952 weeks[3] = L"Wednesday";
4953 weeks[4] = L"Thursday";
4954 weeks[5] = L"Friday";
4955 weeks[6] = L"Saturday";
4956 weeks[7] = L"Sun";
4957 weeks[8] = L"Mon";
4958 weeks[9] = L"Tue";
4959 weeks[10] = L"Wed";
4960 weeks[11] = L"Thu";
4961 weeks[12] = L"Fri";
4962 weeks[13] = L"Sat";
4963 return weeks;
4964}
Louis Dionne89258142021-08-23 15:32:36 -04004965#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004966
4967template <>
4968const string*
4969__time_get_c_storage<char>::__weeks() const
4970{
4971 static const string* weeks = init_weeks();
4972 return weeks;
4973}
4974
Louis Dionne89258142021-08-23 15:32:36 -04004975#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004976template <>
4977const wstring*
4978__time_get_c_storage<wchar_t>::__weeks() const
4979{
4980 static const wstring* weeks = init_wweeks();
4981 return weeks;
4982}
Louis Dionne89258142021-08-23 15:32:36 -04004983#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004984
4985static
4986string*
4987init_months()
4988{
4989 static string months[24];
4990 months[0] = "January";
4991 months[1] = "February";
4992 months[2] = "March";
4993 months[3] = "April";
4994 months[4] = "May";
4995 months[5] = "June";
4996 months[6] = "July";
4997 months[7] = "August";
4998 months[8] = "September";
4999 months[9] = "October";
5000 months[10] = "November";
5001 months[11] = "December";
5002 months[12] = "Jan";
5003 months[13] = "Feb";
5004 months[14] = "Mar";
5005 months[15] = "Apr";
5006 months[16] = "May";
5007 months[17] = "Jun";
5008 months[18] = "Jul";
5009 months[19] = "Aug";
5010 months[20] = "Sep";
5011 months[21] = "Oct";
5012 months[22] = "Nov";
5013 months[23] = "Dec";
5014 return months;
5015}
5016
Louis Dionne89258142021-08-23 15:32:36 -04005017#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005018static
5019wstring*
5020init_wmonths()
5021{
5022 static wstring months[24];
5023 months[0] = L"January";
5024 months[1] = L"February";
5025 months[2] = L"March";
5026 months[3] = L"April";
5027 months[4] = L"May";
5028 months[5] = L"June";
5029 months[6] = L"July";
5030 months[7] = L"August";
5031 months[8] = L"September";
5032 months[9] = L"October";
5033 months[10] = L"November";
5034 months[11] = L"December";
5035 months[12] = L"Jan";
5036 months[13] = L"Feb";
5037 months[14] = L"Mar";
5038 months[15] = L"Apr";
5039 months[16] = L"May";
5040 months[17] = L"Jun";
5041 months[18] = L"Jul";
5042 months[19] = L"Aug";
5043 months[20] = L"Sep";
5044 months[21] = L"Oct";
5045 months[22] = L"Nov";
5046 months[23] = L"Dec";
5047 return months;
5048}
Louis Dionne89258142021-08-23 15:32:36 -04005049#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005050
5051template <>
5052const string*
5053__time_get_c_storage<char>::__months() const
5054{
5055 static const string* months = init_months();
5056 return months;
5057}
5058
Louis Dionne89258142021-08-23 15:32:36 -04005059#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005060template <>
5061const wstring*
5062__time_get_c_storage<wchar_t>::__months() const
5063{
5064 static const wstring* months = init_wmonths();
5065 return months;
5066}
Louis Dionne89258142021-08-23 15:32:36 -04005067#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005068
5069static
5070string*
5071init_am_pm()
5072{
Marshall Clow5cc04922018-01-11 17:16:52 +00005073 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005074 am_pm[0] = "AM";
5075 am_pm[1] = "PM";
5076 return am_pm;
5077}
5078
Louis Dionne89258142021-08-23 15:32:36 -04005079#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005080static
5081wstring*
5082init_wam_pm()
5083{
Marshall Clow5cc04922018-01-11 17:16:52 +00005084 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005085 am_pm[0] = L"AM";
5086 am_pm[1] = L"PM";
5087 return am_pm;
5088}
Louis Dionne89258142021-08-23 15:32:36 -04005089#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005090
5091template <>
5092const string*
5093__time_get_c_storage<char>::__am_pm() const
5094{
5095 static const string* am_pm = init_am_pm();
5096 return am_pm;
5097}
5098
Louis Dionne89258142021-08-23 15:32:36 -04005099#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005100template <>
5101const wstring*
5102__time_get_c_storage<wchar_t>::__am_pm() const
5103{
5104 static const wstring* am_pm = init_wam_pm();
5105 return am_pm;
5106}
Louis Dionne89258142021-08-23 15:32:36 -04005107#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005108
5109template <>
5110const string&
5111__time_get_c_storage<char>::__x() const
5112{
5113 static string s("%m/%d/%y");
5114 return s;
5115}
5116
Louis Dionne89258142021-08-23 15:32:36 -04005117#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005118template <>
5119const wstring&
5120__time_get_c_storage<wchar_t>::__x() const
5121{
5122 static wstring s(L"%m/%d/%y");
5123 return s;
5124}
Louis Dionne89258142021-08-23 15:32:36 -04005125#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005126
5127template <>
5128const string&
5129__time_get_c_storage<char>::__X() const
5130{
5131 static string s("%H:%M:%S");
5132 return s;
5133}
5134
Louis Dionne89258142021-08-23 15:32:36 -04005135#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005136template <>
5137const wstring&
5138__time_get_c_storage<wchar_t>::__X() const
5139{
5140 static wstring s(L"%H:%M:%S");
5141 return s;
5142}
Louis Dionne89258142021-08-23 15:32:36 -04005143#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005144
5145template <>
5146const string&
5147__time_get_c_storage<char>::__c() const
5148{
5149 static string s("%a %b %d %H:%M:%S %Y");
5150 return s;
5151}
5152
Louis Dionne89258142021-08-23 15:32:36 -04005153#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005154template <>
5155const wstring&
5156__time_get_c_storage<wchar_t>::__c() const
5157{
5158 static wstring s(L"%a %b %d %H:%M:%S %Y");
5159 return s;
5160}
Louis Dionne89258142021-08-23 15:32:36 -04005161#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005162
5163template <>
5164const string&
5165__time_get_c_storage<char>::__r() const
5166{
5167 static string s("%I:%M:%S %p");
5168 return s;
5169}
5170
Louis Dionne89258142021-08-23 15:32:36 -04005171#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005172template <>
5173const wstring&
5174__time_get_c_storage<wchar_t>::__r() const
5175{
5176 static wstring s(L"%I:%M:%S %p");
5177 return s;
5178}
Louis Dionne89258142021-08-23 15:32:36 -04005179#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005180
5181// time_get_byname
5182
5183__time_get::__time_get(const char* nm)
5184 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5185{
5186 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005187 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005188 " failed to construct for " + string(nm));
5189}
5190
5191__time_get::__time_get(const string& nm)
5192 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5193{
5194 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005195 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005196 " failed to construct for " + nm);
5197}
5198
5199__time_get::~__time_get()
5200{
5201 freelocale(__loc_);
5202}
Marshall Clowd920eea2013-10-21 15:07:28 +00005203#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005204#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005205#endif
5206#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00005207#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005208#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005209
Howard Hinnantc51e1022010-05-11 19:42:16 +00005210template <>
5211string
5212__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5213{
Howard Hinnant990207c2012-02-19 14:55:32 +00005214 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005215 t.tm_sec = 59;
5216 t.tm_min = 55;
5217 t.tm_hour = 23;
5218 t.tm_mday = 31;
5219 t.tm_mon = 11;
5220 t.tm_year = 161;
5221 t.tm_wday = 6;
5222 t.tm_yday = 364;
5223 t.tm_isdst = -1;
5224 char buf[100];
5225 char f[3] = {0};
5226 f[0] = '%';
5227 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005228 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005229 char* bb = buf;
5230 char* be = buf + n;
5231 string result;
5232 while (bb != be)
5233 {
5234 if (ct.is(ctype_base::space, *bb))
5235 {
5236 result.push_back(' ');
5237 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5238 ;
5239 continue;
5240 }
5241 char* w = bb;
5242 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005243 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005244 ct, err, false)
5245 - this->__weeks_;
5246 if (i < 14)
5247 {
5248 result.push_back('%');
5249 if (i < 7)
5250 result.push_back('A');
5251 else
5252 result.push_back('a');
5253 bb = w;
5254 continue;
5255 }
5256 w = bb;
5257 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5258 ct, err, false)
5259 - this->__months_;
5260 if (i < 24)
5261 {
5262 result.push_back('%');
5263 if (i < 12)
5264 result.push_back('B');
5265 else
5266 result.push_back('b');
5267 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5268 result.back() = 'm';
5269 bb = w;
5270 continue;
5271 }
5272 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5273 {
5274 w = bb;
5275 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5276 ct, err, false) - this->__am_pm_;
5277 if (i < 2)
5278 {
5279 result.push_back('%');
5280 result.push_back('p');
5281 bb = w;
5282 continue;
5283 }
5284 }
5285 w = bb;
5286 if (ct.is(ctype_base::digit, *bb))
5287 {
5288 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5289 {
5290 case 6:
5291 result.push_back('%');
5292 result.push_back('w');
5293 break;
5294 case 7:
5295 result.push_back('%');
5296 result.push_back('u');
5297 break;
5298 case 11:
5299 result.push_back('%');
5300 result.push_back('I');
5301 break;
5302 case 12:
5303 result.push_back('%');
5304 result.push_back('m');
5305 break;
5306 case 23:
5307 result.push_back('%');
5308 result.push_back('H');
5309 break;
5310 case 31:
5311 result.push_back('%');
5312 result.push_back('d');
5313 break;
5314 case 55:
5315 result.push_back('%');
5316 result.push_back('M');
5317 break;
5318 case 59:
5319 result.push_back('%');
5320 result.push_back('S');
5321 break;
5322 case 61:
5323 result.push_back('%');
5324 result.push_back('y');
5325 break;
5326 case 364:
5327 result.push_back('%');
5328 result.push_back('j');
5329 break;
5330 case 2061:
5331 result.push_back('%');
5332 result.push_back('Y');
5333 break;
5334 default:
5335 for (; w != bb; ++w)
5336 result.push_back(*w);
5337 break;
5338 }
5339 continue;
5340 }
5341 if (*bb == '%')
5342 {
5343 result.push_back('%');
5344 result.push_back('%');
5345 ++bb;
5346 continue;
5347 }
5348 result.push_back(*bb);
5349 ++bb;
5350 }
5351 return result;
5352}
5353
Marshall Clowd920eea2013-10-21 15:07:28 +00005354#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005355#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005356#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005357
Louis Dionne89258142021-08-23 15:32:36 -04005358#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005359template <>
5360wstring
5361__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5362{
Howard Hinnant990207c2012-02-19 14:55:32 +00005363 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005364 t.tm_sec = 59;
5365 t.tm_min = 55;
5366 t.tm_hour = 23;
5367 t.tm_mday = 31;
5368 t.tm_mon = 11;
5369 t.tm_year = 161;
5370 t.tm_wday = 6;
5371 t.tm_yday = 364;
5372 t.tm_isdst = -1;
5373 char buf[100];
5374 char f[3] = {0};
5375 f[0] = '%';
5376 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005377 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005378 wchar_t wbuf[100];
5379 wchar_t* wbb = wbuf;
5380 mbstate_t mb = {0};
5381 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005382 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005383 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005384 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005385 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005386 wstring result;
5387 while (wbb != wbe)
5388 {
5389 if (ct.is(ctype_base::space, *wbb))
5390 {
5391 result.push_back(L' ');
5392 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5393 ;
5394 continue;
5395 }
5396 wchar_t* w = wbb;
5397 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005398 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005399 ct, err, false)
5400 - this->__weeks_;
5401 if (i < 14)
5402 {
5403 result.push_back(L'%');
5404 if (i < 7)
5405 result.push_back(L'A');
5406 else
5407 result.push_back(L'a');
5408 wbb = w;
5409 continue;
5410 }
5411 w = wbb;
5412 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5413 ct, err, false)
5414 - this->__months_;
5415 if (i < 24)
5416 {
5417 result.push_back(L'%');
5418 if (i < 12)
5419 result.push_back(L'B');
5420 else
5421 result.push_back(L'b');
5422 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5423 result.back() = L'm';
5424 wbb = w;
5425 continue;
5426 }
5427 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5428 {
5429 w = wbb;
5430 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5431 ct, err, false) - this->__am_pm_;
5432 if (i < 2)
5433 {
5434 result.push_back(L'%');
5435 result.push_back(L'p');
5436 wbb = w;
5437 continue;
5438 }
5439 }
5440 w = wbb;
5441 if (ct.is(ctype_base::digit, *wbb))
5442 {
5443 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5444 {
5445 case 6:
5446 result.push_back(L'%');
5447 result.push_back(L'w');
5448 break;
5449 case 7:
5450 result.push_back(L'%');
5451 result.push_back(L'u');
5452 break;
5453 case 11:
5454 result.push_back(L'%');
5455 result.push_back(L'I');
5456 break;
5457 case 12:
5458 result.push_back(L'%');
5459 result.push_back(L'm');
5460 break;
5461 case 23:
5462 result.push_back(L'%');
5463 result.push_back(L'H');
5464 break;
5465 case 31:
5466 result.push_back(L'%');
5467 result.push_back(L'd');
5468 break;
5469 case 55:
5470 result.push_back(L'%');
5471 result.push_back(L'M');
5472 break;
5473 case 59:
5474 result.push_back(L'%');
5475 result.push_back(L'S');
5476 break;
5477 case 61:
5478 result.push_back(L'%');
5479 result.push_back(L'y');
5480 break;
5481 case 364:
5482 result.push_back(L'%');
5483 result.push_back(L'j');
5484 break;
5485 case 2061:
5486 result.push_back(L'%');
5487 result.push_back(L'Y');
5488 break;
5489 default:
5490 for (; w != wbb; ++w)
5491 result.push_back(*w);
5492 break;
5493 }
5494 continue;
5495 }
5496 if (ct.narrow(*wbb, 0) == '%')
5497 {
5498 result.push_back(L'%');
5499 result.push_back(L'%');
5500 ++wbb;
5501 continue;
5502 }
5503 result.push_back(*wbb);
5504 ++wbb;
5505 }
5506 return result;
5507}
Louis Dionne89258142021-08-23 15:32:36 -04005508#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005509
5510template <>
5511void
5512__time_get_storage<char>::init(const ctype<char>& ct)
5513{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005514 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005515 char buf[100];
5516 // __weeks_
5517 for (int i = 0; i < 7; ++i)
5518 {
5519 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005520 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005521 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005522 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005523 __weeks_[i+7] = buf;
5524 }
5525 // __months_
5526 for (int i = 0; i < 12; ++i)
5527 {
5528 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005529 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005530 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005531 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005532 __months_[i+12] = buf;
5533 }
5534 // __am_pm_
5535 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005536 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005537 __am_pm_[0] = buf;
5538 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005539 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005540 __am_pm_[1] = buf;
5541 __c_ = __analyze('c', ct);
5542 __r_ = __analyze('r', ct);
5543 __x_ = __analyze('x', ct);
5544 __X_ = __analyze('X', ct);
5545}
5546
Louis Dionne89258142021-08-23 15:32:36 -04005547#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005548template <>
5549void
5550__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5551{
5552 tm t = {0};
5553 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005554 wchar_t wbuf[100];
5555 wchar_t* wbe;
5556 mbstate_t mb = {0};
5557 // __weeks_
5558 for (int i = 0; i < 7; ++i)
5559 {
5560 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005561 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005562 mb = mbstate_t();
5563 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005564 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005565 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005566 __throw_runtime_error("locale not supported");
5567 wbe = wbuf + j;
5568 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005569 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005570 mb = mbstate_t();
5571 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005572 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005573 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005574 __throw_runtime_error("locale not supported");
5575 wbe = wbuf + j;
5576 __weeks_[i+7].assign(wbuf, wbe);
5577 }
5578 // __months_
5579 for (int i = 0; i < 12; ++i)
5580 {
5581 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005582 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005583 mb = mbstate_t();
5584 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005585 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005586 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005587 __throw_runtime_error("locale not supported");
5588 wbe = wbuf + j;
5589 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005590 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005591 mb = mbstate_t();
5592 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005593 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005594 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005595 __throw_runtime_error("locale not supported");
5596 wbe = wbuf + j;
5597 __months_[i+12].assign(wbuf, wbe);
5598 }
5599 // __am_pm_
5600 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005601 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602 mb = mbstate_t();
5603 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005604 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005605 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005606 __throw_runtime_error("locale not supported");
5607 wbe = wbuf + j;
5608 __am_pm_[0].assign(wbuf, wbe);
5609 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005610 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005611 mb = mbstate_t();
5612 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005613 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005614 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005615 __throw_runtime_error("locale not supported");
5616 wbe = wbuf + j;
5617 __am_pm_[1].assign(wbuf, wbe);
5618 __c_ = __analyze('c', ct);
5619 __r_ = __analyze('r', ct);
5620 __x_ = __analyze('x', ct);
5621 __X_ = __analyze('X', ct);
5622}
Louis Dionne89258142021-08-23 15:32:36 -04005623#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005624
5625template <class CharT>
5626struct _LIBCPP_HIDDEN __time_get_temp
5627 : public ctype_byname<CharT>
5628{
5629 explicit __time_get_temp(const char* nm)
5630 : ctype_byname<CharT>(nm, 1) {}
5631 explicit __time_get_temp(const string& nm)
5632 : ctype_byname<CharT>(nm, 1) {}
5633};
5634
5635template <>
5636__time_get_storage<char>::__time_get_storage(const char* __nm)
5637 : __time_get(__nm)
5638{
5639 const __time_get_temp<char> ct(__nm);
5640 init(ct);
5641}
5642
5643template <>
5644__time_get_storage<char>::__time_get_storage(const string& __nm)
5645 : __time_get(__nm)
5646{
5647 const __time_get_temp<char> ct(__nm);
5648 init(ct);
5649}
5650
Louis Dionne89258142021-08-23 15:32:36 -04005651#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005652template <>
5653__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5654 : __time_get(__nm)
5655{
5656 const __time_get_temp<wchar_t> ct(__nm);
5657 init(ct);
5658}
5659
5660template <>
5661__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5662 : __time_get(__nm)
5663{
5664 const __time_get_temp<wchar_t> ct(__nm);
5665 init(ct);
5666}
Louis Dionne89258142021-08-23 15:32:36 -04005667#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005668
5669template <>
5670time_base::dateorder
5671__time_get_storage<char>::__do_date_order() const
5672{
5673 unsigned i;
5674 for (i = 0; i < __x_.size(); ++i)
5675 if (__x_[i] == '%')
5676 break;
5677 ++i;
5678 switch (__x_[i])
5679 {
5680 case 'y':
5681 case 'Y':
5682 for (++i; i < __x_.size(); ++i)
5683 if (__x_[i] == '%')
5684 break;
5685 if (i == __x_.size())
5686 break;
5687 ++i;
5688 switch (__x_[i])
5689 {
5690 case 'm':
5691 for (++i; i < __x_.size(); ++i)
5692 if (__x_[i] == '%')
5693 break;
5694 if (i == __x_.size())
5695 break;
5696 ++i;
5697 if (__x_[i] == 'd')
5698 return time_base::ymd;
5699 break;
5700 case 'd':
5701 for (++i; i < __x_.size(); ++i)
5702 if (__x_[i] == '%')
5703 break;
5704 if (i == __x_.size())
5705 break;
5706 ++i;
5707 if (__x_[i] == 'm')
5708 return time_base::ydm;
5709 break;
5710 }
5711 break;
5712 case 'm':
5713 for (++i; i < __x_.size(); ++i)
5714 if (__x_[i] == '%')
5715 break;
5716 if (i == __x_.size())
5717 break;
5718 ++i;
5719 if (__x_[i] == 'd')
5720 {
5721 for (++i; i < __x_.size(); ++i)
5722 if (__x_[i] == '%')
5723 break;
5724 if (i == __x_.size())
5725 break;
5726 ++i;
5727 if (__x_[i] == 'y' || __x_[i] == 'Y')
5728 return time_base::mdy;
5729 break;
5730 }
5731 break;
5732 case 'd':
5733 for (++i; i < __x_.size(); ++i)
5734 if (__x_[i] == '%')
5735 break;
5736 if (i == __x_.size())
5737 break;
5738 ++i;
5739 if (__x_[i] == 'm')
5740 {
5741 for (++i; i < __x_.size(); ++i)
5742 if (__x_[i] == '%')
5743 break;
5744 if (i == __x_.size())
5745 break;
5746 ++i;
5747 if (__x_[i] == 'y' || __x_[i] == 'Y')
5748 return time_base::dmy;
5749 break;
5750 }
5751 break;
5752 }
5753 return time_base::no_order;
5754}
5755
Louis Dionne89258142021-08-23 15:32:36 -04005756#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005757template <>
5758time_base::dateorder
5759__time_get_storage<wchar_t>::__do_date_order() const
5760{
5761 unsigned i;
5762 for (i = 0; i < __x_.size(); ++i)
5763 if (__x_[i] == L'%')
5764 break;
5765 ++i;
5766 switch (__x_[i])
5767 {
5768 case L'y':
5769 case L'Y':
5770 for (++i; i < __x_.size(); ++i)
5771 if (__x_[i] == L'%')
5772 break;
5773 if (i == __x_.size())
5774 break;
5775 ++i;
5776 switch (__x_[i])
5777 {
5778 case L'm':
5779 for (++i; i < __x_.size(); ++i)
5780 if (__x_[i] == L'%')
5781 break;
5782 if (i == __x_.size())
5783 break;
5784 ++i;
5785 if (__x_[i] == L'd')
5786 return time_base::ymd;
5787 break;
5788 case L'd':
5789 for (++i; i < __x_.size(); ++i)
5790 if (__x_[i] == L'%')
5791 break;
5792 if (i == __x_.size())
5793 break;
5794 ++i;
5795 if (__x_[i] == L'm')
5796 return time_base::ydm;
5797 break;
5798 }
5799 break;
5800 case L'm':
5801 for (++i; i < __x_.size(); ++i)
5802 if (__x_[i] == L'%')
5803 break;
5804 if (i == __x_.size())
5805 break;
5806 ++i;
5807 if (__x_[i] == L'd')
5808 {
5809 for (++i; i < __x_.size(); ++i)
5810 if (__x_[i] == L'%')
5811 break;
5812 if (i == __x_.size())
5813 break;
5814 ++i;
5815 if (__x_[i] == L'y' || __x_[i] == L'Y')
5816 return time_base::mdy;
5817 break;
5818 }
5819 break;
5820 case L'd':
5821 for (++i; i < __x_.size(); ++i)
5822 if (__x_[i] == L'%')
5823 break;
5824 if (i == __x_.size())
5825 break;
5826 ++i;
5827 if (__x_[i] == L'm')
5828 {
5829 for (++i; i < __x_.size(); ++i)
5830 if (__x_[i] == L'%')
5831 break;
5832 if (i == __x_.size())
5833 break;
5834 ++i;
5835 if (__x_[i] == L'y' || __x_[i] == L'Y')
5836 return time_base::dmy;
5837 break;
5838 }
5839 break;
5840 }
5841 return time_base::no_order;
5842}
Louis Dionne89258142021-08-23 15:32:36 -04005843#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005844
5845// time_put
5846
5847__time_put::__time_put(const char* nm)
5848 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5849{
5850 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005851 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005852 " failed to construct for " + string(nm));
5853}
5854
5855__time_put::__time_put(const string& nm)
5856 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5857{
5858 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005859 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005860 " failed to construct for " + nm);
5861}
5862
5863__time_put::~__time_put()
5864{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005865 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005866 freelocale(__loc_);
5867}
5868
5869void
5870__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5871 char __fmt, char __mod) const
5872{
5873 char fmt[] = {'%', __fmt, __mod, 0};
5874 if (__mod != 0)
5875 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005876 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005877 __ne = __nb + n;
5878}
5879
Louis Dionne89258142021-08-23 15:32:36 -04005880#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005881void
5882__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5883 char __fmt, char __mod) const
5884{
5885 char __nar[100];
5886 char* __ne = __nar + 100;
5887 __do_put(__nar, __ne, __tm, __fmt, __mod);
5888 mbstate_t mb = {0};
5889 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005890 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005891 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005892 __throw_runtime_error("locale not supported");
5893 __we = __wb + j;
5894}
Louis Dionne89258142021-08-23 15:32:36 -04005895#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005896
5897// moneypunct_byname
5898
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005899template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005900static
5901void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005902__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5903 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5904 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005905{
5906 const char sign = static_cast<char>(money_base::sign);
5907 const char space = static_cast<char>(money_base::space);
5908 const char none = static_cast<char>(money_base::none);
5909 const char symbol = static_cast<char>(money_base::symbol);
5910 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005911 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5912
5913 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5914 // function'. "Space between sign and symbol or value" means that
5915 // if the sign is adjacent to the symbol, there's a space between
5916 // them, and otherwise there's a space between the sign and value.
5917 //
5918 // C11's localeconv specifies that the fourth character of an
5919 // international curr_symbol is used to separate the sign and
5920 // value when sep_by_space says to do so. C++ can't represent
5921 // that, so we just use a space. When sep_by_space says to
5922 // separate the symbol and value-or-sign with a space, we rearrange the
5923 // curr_symbol to put its spacing character on the correct side of
5924 // the symbol.
5925 //
5926 // We also need to avoid adding an extra space between the sign
5927 // and value when the currency symbol is suppressed (by not
5928 // setting showbase). We match glibc's strfmon by interpreting
5929 // sep_by_space==1 as "omit the space when the currency symbol is
5930 // absent".
5931 //
5932 // Users who want to get this right should use ICU instead.
5933
Howard Hinnantc51e1022010-05-11 19:42:16 +00005934 switch (cs_precedes)
5935 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005936 case 0: // value before curr_symbol
5937 if (symbol_contains_sep) {
5938 // Move the separator to before the symbol, to place it
5939 // between the value and symbol.
5940 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5941 __curr_symbol_.end());
5942 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005943 switch (sign_posn)
5944 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005945 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005946 pat.field[0] = sign;
5947 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005948 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005949 pat.field[3] = symbol;
5950 switch (sep_by_space)
5951 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005952 case 0: // No space separates the currency symbol and value.
5953 // This case may have changed between C99 and C11;
5954 // assume the currency symbol matches the intention.
5955 case 2: // Space between sign and currency or value.
5956 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005957 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005958 case 1: // Space between currency-and-sign or currency and value.
5959 if (!symbol_contains_sep) {
5960 // We insert the space into the symbol instead of
5961 // setting pat.field[2]=space so that when
5962 // showbase is not set, the space goes away too.
5963 __curr_symbol_.insert(0, 1, space_char);
5964 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005965 return;
5966 default:
5967 break;
5968 }
5969 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005970 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005971 pat.field[0] = sign;
5972 pat.field[3] = symbol;
5973 switch (sep_by_space)
5974 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005975 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005976 pat.field[1] = value;
5977 pat.field[2] = none;
5978 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005979 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005980 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005981 pat.field[2] = none;
5982 if (!symbol_contains_sep) {
5983 // We insert the space into the symbol instead of
5984 // setting pat.field[2]=space so that when
5985 // showbase is not set, the space goes away too.
5986 __curr_symbol_.insert(0, 1, space_char);
5987 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005988 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005989 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005990 pat.field[1] = space;
5991 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005992 if (symbol_contains_sep) {
5993 // Remove the separator from the symbol, since it
5994 // has already appeared after the sign.
5995 __curr_symbol_.erase(__curr_symbol_.begin());
5996 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005997 return;
5998 default:
5999 break;
6000 }
6001 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006002 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006003 pat.field[0] = value;
6004 pat.field[3] = sign;
6005 switch (sep_by_space)
6006 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006007 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006008 pat.field[1] = none;
6009 pat.field[2] = symbol;
6010 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006011 case 1: // Space between currency-and-sign or currency and value.
6012 if (!symbol_contains_sep) {
6013 // We insert the space into the symbol instead of
6014 // setting pat.field[1]=space so that when
6015 // showbase is not set, the space goes away too.
6016 __curr_symbol_.insert(0, 1, space_char);
6017 }
6018 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006019 pat.field[2] = symbol;
6020 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006021 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006022 pat.field[1] = symbol;
6023 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006024 if (symbol_contains_sep) {
6025 // Remove the separator from the symbol, since it
6026 // should not be removed if showbase is absent.
6027 __curr_symbol_.erase(__curr_symbol_.begin());
6028 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006029 return;
6030 default:
6031 break;
6032 }
6033 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006034 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006035 pat.field[0] = value;
6036 pat.field[3] = symbol;
6037 switch (sep_by_space)
6038 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006039 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006040 pat.field[1] = none;
6041 pat.field[2] = sign;
6042 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006043 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006044 pat.field[1] = space;
6045 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006046 if (symbol_contains_sep) {
6047 // Remove the separator from the symbol, since it
6048 // has already appeared before the sign.
6049 __curr_symbol_.erase(__curr_symbol_.begin());
6050 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006051 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006052 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006053 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006054 pat.field[2] = none;
6055 if (!symbol_contains_sep) {
6056 // We insert the space into the symbol instead of
6057 // setting pat.field[2]=space so that when
6058 // showbase is not set, the space goes away too.
6059 __curr_symbol_.insert(0, 1, space_char);
6060 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006061 return;
6062 default:
6063 break;
6064 }
6065 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006066 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006067 pat.field[0] = value;
6068 pat.field[3] = sign;
6069 switch (sep_by_space)
6070 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006071 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006072 pat.field[1] = none;
6073 pat.field[2] = symbol;
6074 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006075 case 1: // Space between currency-and-sign or currency and value.
6076 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006077 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006078 if (!symbol_contains_sep) {
6079 // We insert the space into the symbol instead of
6080 // setting pat.field[1]=space so that when
6081 // showbase is not set, the space goes away too.
6082 __curr_symbol_.insert(0, 1, space_char);
6083 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006084 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006085 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006086 pat.field[1] = symbol;
6087 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006088 if (symbol_contains_sep) {
6089 // Remove the separator from the symbol, since it
6090 // should not disappear when showbase is absent.
6091 __curr_symbol_.erase(__curr_symbol_.begin());
6092 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006093 return;
6094 default:
6095 break;
6096 }
6097 break;
6098 default:
6099 break;
6100 }
6101 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006102 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00006103 switch (sign_posn)
6104 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006105 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006106 pat.field[0] = sign;
6107 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006108 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006109 pat.field[3] = value;
6110 switch (sep_by_space)
6111 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006112 case 0: // No space separates the currency symbol and value.
6113 // This case may have changed between C99 and C11;
6114 // assume the currency symbol matches the intention.
6115 case 2: // Space between sign and currency or value.
6116 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006117 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006118 case 1: // Space between currency-and-sign or currency and value.
6119 if (!symbol_contains_sep) {
6120 // We insert the space into the symbol instead of
6121 // setting pat.field[2]=space so that when
6122 // showbase is not set, the space goes away too.
6123 __curr_symbol_.insert(0, 1, space_char);
6124 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125 return;
6126 default:
6127 break;
6128 }
6129 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006130 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006131 pat.field[0] = sign;
6132 pat.field[3] = value;
6133 switch (sep_by_space)
6134 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006135 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006136 pat.field[1] = symbol;
6137 pat.field[2] = none;
6138 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006139 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006140 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006141 pat.field[2] = none;
6142 if (!symbol_contains_sep) {
6143 // We insert the space into the symbol instead of
6144 // setting pat.field[2]=space so that when
6145 // showbase is not set, the space goes away too.
6146 __curr_symbol_.push_back(space_char);
6147 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006148 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006149 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006150 pat.field[1] = space;
6151 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006152 if (symbol_contains_sep) {
6153 // Remove the separator from the symbol, since it
6154 // has already appeared after the sign.
6155 __curr_symbol_.pop_back();
6156 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006157 return;
6158 default:
6159 break;
6160 }
6161 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006162 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006163 pat.field[0] = symbol;
6164 pat.field[3] = sign;
6165 switch (sep_by_space)
6166 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006167 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006168 pat.field[1] = none;
6169 pat.field[2] = value;
6170 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006171 case 1: // Space between currency-and-sign or currency and value.
6172 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006173 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006174 if (!symbol_contains_sep) {
6175 // We insert the space into the symbol instead of
6176 // setting pat.field[1]=space so that when
6177 // showbase is not set, the space goes away too.
6178 __curr_symbol_.push_back(space_char);
6179 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006180 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006181 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006182 pat.field[1] = value;
6183 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006184 if (symbol_contains_sep) {
6185 // Remove the separator from the symbol, since it
6186 // will appear before the sign.
6187 __curr_symbol_.pop_back();
6188 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006189 return;
6190 default:
6191 break;
6192 }
6193 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006194 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006195 pat.field[0] = sign;
6196 pat.field[3] = value;
6197 switch (sep_by_space)
6198 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006199 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006200 pat.field[1] = symbol;
6201 pat.field[2] = none;
6202 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006203 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006204 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006205 pat.field[2] = none;
6206 if (!symbol_contains_sep) {
6207 // We insert the space into the symbol instead of
6208 // setting pat.field[2]=space so that when
6209 // showbase is not set, the space goes away too.
6210 __curr_symbol_.push_back(space_char);
6211 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006212 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006213 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006214 pat.field[1] = space;
6215 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006216 if (symbol_contains_sep) {
6217 // Remove the separator from the symbol, since it
6218 // has already appeared after the sign.
6219 __curr_symbol_.pop_back();
6220 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006221 return;
6222 default:
6223 break;
6224 }
6225 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006226 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006227 pat.field[0] = symbol;
6228 pat.field[3] = value;
6229 switch (sep_by_space)
6230 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006231 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006232 pat.field[1] = sign;
6233 pat.field[2] = none;
6234 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006235 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006236 pat.field[1] = sign;
6237 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006238 if (symbol_contains_sep) {
6239 // Remove the separator from the symbol, since it
6240 // should not disappear when showbase is absent.
6241 __curr_symbol_.pop_back();
6242 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006243 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006244 case 2: // Space between sign and currency or value.
6245 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006246 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006247 if (!symbol_contains_sep) {
6248 // We insert the space into the symbol instead of
6249 // setting pat.field[1]=space so that when
6250 // showbase is not set, the space goes away too.
6251 __curr_symbol_.push_back(space_char);
6252 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006253 return;
6254 default:
6255 break;
6256 }
6257 break;
6258 default:
6259 break;
6260 }
6261 break;
6262 default:
6263 break;
6264 }
6265 pat.field[0] = symbol;
6266 pat.field[1] = sign;
6267 pat.field[2] = none;
6268 pat.field[3] = value;
6269}
6270
6271template<>
6272void
6273moneypunct_byname<char, false>::init(const char* nm)
6274{
6275 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006276 __libcpp_unique_locale loc(nm);
6277 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006278 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006279 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006280
Ben Craig3756b922016-03-09 15:39:39 +00006281 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006282 if (!checked_string_to_char_convert(__decimal_point_,
6283 lc->mon_decimal_point,
6284 loc.get()))
6285 __decimal_point_ = base::do_decimal_point();
6286 if (!checked_string_to_char_convert(__thousands_sep_,
6287 lc->mon_thousands_sep,
6288 loc.get()))
6289 __thousands_sep_ = base::do_thousands_sep();
6290
Howard Hinnantc51e1022010-05-11 19:42:16 +00006291 __grouping_ = lc->mon_grouping;
6292 __curr_symbol_ = lc->currency_symbol;
6293 if (lc->frac_digits != CHAR_MAX)
6294 __frac_digits_ = lc->frac_digits;
6295 else
6296 __frac_digits_ = base::do_frac_digits();
6297 if (lc->p_sign_posn == 0)
6298 __positive_sign_ = "()";
6299 else
6300 __positive_sign_ = lc->positive_sign;
6301 if (lc->n_sign_posn == 0)
6302 __negative_sign_ = "()";
6303 else
6304 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006305 // Assume the positive and negative formats will want spaces in
6306 // the same places in curr_symbol since there's no way to
6307 // represent anything else.
6308 string_type __dummy_curr_symbol = __curr_symbol_;
6309 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6310 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6311 __init_pat(__neg_format_, __curr_symbol_, false,
6312 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006313}
6314
6315template<>
6316void
6317moneypunct_byname<char, true>::init(const char* nm)
6318{
6319 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006320 __libcpp_unique_locale loc(nm);
6321 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006322 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006323 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006324
Ben Craig3756b922016-03-09 15:39:39 +00006325 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006326 if (!checked_string_to_char_convert(__decimal_point_,
6327 lc->mon_decimal_point,
6328 loc.get()))
6329 __decimal_point_ = base::do_decimal_point();
6330 if (!checked_string_to_char_convert(__thousands_sep_,
6331 lc->mon_thousands_sep,
6332 loc.get()))
6333 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006334 __grouping_ = lc->mon_grouping;
6335 __curr_symbol_ = lc->int_curr_symbol;
6336 if (lc->int_frac_digits != CHAR_MAX)
6337 __frac_digits_ = lc->int_frac_digits;
6338 else
6339 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006340#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006341 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006342#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006343 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006344#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006345 __positive_sign_ = "()";
6346 else
6347 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006348#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006349 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006350#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006351 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006352#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006353 __negative_sign_ = "()";
6354 else
6355 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006356 // Assume the positive and negative formats will want spaces in
6357 // the same places in curr_symbol since there's no way to
6358 // represent anything else.
6359 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006360#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006361 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6362 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6363 __init_pat(__neg_format_, __curr_symbol_, true,
6364 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006365#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006366 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6367 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6368 lc->int_p_sign_posn, ' ');
6369 __init_pat(__neg_format_, __curr_symbol_, true,
6370 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6371 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006372#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006373}
6374
Louis Dionne89258142021-08-23 15:32:36 -04006375#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006376template<>
6377void
6378moneypunct_byname<wchar_t, false>::init(const char* nm)
6379{
6380 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006381 __libcpp_unique_locale loc(nm);
6382 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006383 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006384 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006385 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006386 if (!checked_string_to_wchar_convert(__decimal_point_,
6387 lc->mon_decimal_point,
6388 loc.get()))
6389 __decimal_point_ = base::do_decimal_point();
6390 if (!checked_string_to_wchar_convert(__thousands_sep_,
6391 lc->mon_thousands_sep,
6392 loc.get()))
6393 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006394 __grouping_ = lc->mon_grouping;
6395 wchar_t wbuf[100];
6396 mbstate_t mb = {0};
6397 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006398 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006399 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006400 __throw_runtime_error("locale not supported");
6401 wchar_t* wbe = wbuf + j;
6402 __curr_symbol_.assign(wbuf, wbe);
6403 if (lc->frac_digits != CHAR_MAX)
6404 __frac_digits_ = lc->frac_digits;
6405 else
6406 __frac_digits_ = base::do_frac_digits();
6407 if (lc->p_sign_posn == 0)
6408 __positive_sign_ = L"()";
6409 else
6410 {
6411 mb = mbstate_t();
6412 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006413 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006414 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006415 __throw_runtime_error("locale not supported");
6416 wbe = wbuf + j;
6417 __positive_sign_.assign(wbuf, wbe);
6418 }
6419 if (lc->n_sign_posn == 0)
6420 __negative_sign_ = L"()";
6421 else
6422 {
6423 mb = mbstate_t();
6424 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006425 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006426 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006427 __throw_runtime_error("locale not supported");
6428 wbe = wbuf + j;
6429 __negative_sign_.assign(wbuf, wbe);
6430 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006431 // Assume the positive and negative formats will want spaces in
6432 // the same places in curr_symbol since there's no way to
6433 // represent anything else.
6434 string_type __dummy_curr_symbol = __curr_symbol_;
6435 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6436 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6437 __init_pat(__neg_format_, __curr_symbol_, false,
6438 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006439}
6440
6441template<>
6442void
6443moneypunct_byname<wchar_t, true>::init(const char* nm)
6444{
6445 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006446 __libcpp_unique_locale loc(nm);
6447 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006448 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006449 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006450
Ben Craig3756b922016-03-09 15:39:39 +00006451 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006452 if (!checked_string_to_wchar_convert(__decimal_point_,
6453 lc->mon_decimal_point,
6454 loc.get()))
6455 __decimal_point_ = base::do_decimal_point();
6456 if (!checked_string_to_wchar_convert(__thousands_sep_,
6457 lc->mon_thousands_sep,
6458 loc.get()))
6459 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006460 __grouping_ = lc->mon_grouping;
6461 wchar_t wbuf[100];
6462 mbstate_t mb = {0};
6463 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006464 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006465 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006466 __throw_runtime_error("locale not supported");
6467 wchar_t* wbe = wbuf + j;
6468 __curr_symbol_.assign(wbuf, wbe);
6469 if (lc->int_frac_digits != CHAR_MAX)
6470 __frac_digits_ = lc->int_frac_digits;
6471 else
6472 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006473#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006474 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006475#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006476 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006477#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006478 __positive_sign_ = L"()";
6479 else
6480 {
6481 mb = mbstate_t();
6482 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006483 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006484 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006485 __throw_runtime_error("locale not supported");
6486 wbe = wbuf + j;
6487 __positive_sign_.assign(wbuf, wbe);
6488 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006489#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006490 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006491#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006492 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006493#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006494 __negative_sign_ = L"()";
6495 else
6496 {
6497 mb = mbstate_t();
6498 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006499 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006500 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006501 __throw_runtime_error("locale not supported");
6502 wbe = wbuf + j;
6503 __negative_sign_.assign(wbuf, wbe);
6504 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006505 // Assume the positive and negative formats will want spaces in
6506 // the same places in curr_symbol since there's no way to
6507 // represent anything else.
6508 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006509#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006510 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6511 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6512 __init_pat(__neg_format_, __curr_symbol_, true,
6513 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006514#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006515 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6516 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6517 lc->int_p_sign_posn, L' ');
6518 __init_pat(__neg_format_, __curr_symbol_, true,
6519 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6520 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006521#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006522}
Louis Dionne89258142021-08-23 15:32:36 -04006523#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006524
6525void __do_nothing(void*) {}
6526
6527void __throw_runtime_error(const char* msg)
6528{
Howard Hinnant72f73582010-08-11 17:04:31 +00006529#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006530 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006531#else
6532 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006533 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006534#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006535}
6536
Louis Dionne89258142021-08-23 15:32:36 -04006537 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6538_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006539
Louis Dionne89258142021-08-23 15:32:36 -04006540 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6541_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006542
Louis Dionne89258142021-08-23 15:32:36 -04006543 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6544_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006545
Louis Dionne89258142021-08-23 15:32:36 -04006546 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6547_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006548
Louis Dionne89258142021-08-23 15:32:36 -04006549 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6550_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<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 time_get<char>;
6553_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_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 time_get_byname<char>;
6556_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<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 time_put<char>;
6559_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_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 time_put_byname<char>;
6562_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<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 moneypunct<char, false>;
6565 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6566_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6567_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006568
Louis Dionne89258142021-08-23 15:32:36 -04006569 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6570 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6571_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6572_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006573
Louis Dionne89258142021-08-23 15:32:36 -04006574 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6575_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006576
Louis Dionne89258142021-08-23 15:32:36 -04006577 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6578_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006579
Louis Dionne89258142021-08-23 15:32:36 -04006580 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6581_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006582
Louis Dionne89258142021-08-23 15:32:36 -04006583 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6584_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006585
Louis Dionne89258142021-08-23 15:32:36 -04006586 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6587_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006588
Louis Dionne89258142021-08-23 15:32:36 -04006589 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6590_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006591
Louis Dionne89258142021-08-23 15:32:36 -04006592 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6593_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 -08006594template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6595template 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 -04006596#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006597template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6598template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6599#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006600
Howard Hinnantc51e1022010-05-11 19:42:16 +00006601_LIBCPP_END_NAMESPACE_STD