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