blob: 3f8a2610ccc679a45fd55233a62e9f8fca51c2f0 [file] [log] [blame]
Louis Dionne9bd93882021-11-17 16:25:01 -05001//===----------------------------------------------------------------------===//
Howard Hinnantc51e1022010-05-11 19:42:16 +00002//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantc51e1022010-05-11 19:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
David Chisnall8074c342012-02-29 13:05:08 +00009// On Solaris, we need to define something to make the C99 parts of localeconv
10// visible.
11#ifdef __sun__
12#define _LCONV_C99
13#endif
14
Nikolas Klausercfe21472022-02-14 18:26:02 +010015#include <__utility/unreachable.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +000016#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000017#include "clocale"
Louis Dionneafc98402021-09-09 13:52:38 -040018#include "codecvt"
19#include "cstdio"
20#include "cstdlib"
Howard Hinnantc51e1022010-05-11 19:42:16 +000021#include "cstring"
Louis Dionneafc98402021-09-09 13:52:38 -040022#include "locale"
23#include "string"
24#include "type_traits"
25#include "typeinfo"
26#include "vector"
27
Louis Dionne89258142021-08-23 15:32:36 -040028#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
29# include "cwctype"
30#endif
31
David Tenty725f16e2021-10-12 11:53:12 -040032#if defined(_AIX)
33# include <sys/localedef.h> // for __lc_ctype_ptr
34#endif
35
Louis Dionneafc98402021-09-09 13:52:38 -040036#if defined(_LIBCPP_MSVCRT)
37# define _CTYPE_DISABLE_MACROS
Marshall Clow3477ec92014-07-10 15:20:28 +000038#endif
Louis Dionneafc98402021-09-09 13:52:38 -040039
40#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
41# include "__support/win32/locale_win32.h"
42#elif !defined(__BIONIC__) && !defined(__NuttX__)
43# include <langinfo.h>
44#endif
45
Weiming Zhaob613db72017-09-19 23:18:03 +000046#include "include/atomic_support.h"
Arthur O'Dwyerf5c4bb02021-04-26 09:56:50 -040047#include "include/sso_allocator.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000048#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000049
Marshall Clowab9c1772013-02-07 17:20:56 +000050// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070051// lots of noise in the build log, but no bugs that I know of.
Nikolas Klauser41c59762022-02-14 18:52:28 +010052_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion")
Marshall Clowab9c1772013-02-07 17:20:56 +000053
Howard Hinnantc51e1022010-05-11 19:42:16 +000054_LIBCPP_BEGIN_NAMESPACE_STD
55
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000056struct __libcpp_unique_locale {
57 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
58
59 ~__libcpp_unique_locale() {
60 if (__loc_)
61 freelocale(__loc_);
62 }
63
64 explicit operator bool() const { return __loc_; }
65
66 locale_t& get() { return __loc_; }
67
68 locale_t __loc_;
69private:
70 __libcpp_unique_locale(__libcpp_unique_locale const&);
71 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
72};
73
Howard Hinnantf312e3e2011-09-28 23:39:33 +000074#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000075locale_t __cloc() {
76 // In theory this could create a race condition. In practice
77 // the race condition is non-fatal since it will just create
78 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000079 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
80 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000081}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000082#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000083
Howard Hinnantc51e1022010-05-11 19:42:16 +000084namespace {
85
86struct release
87{
88 void operator()(locale::facet* p) {p->__release_shared();}
89};
90
Louis Dionne6e41a152021-08-09 13:26:04 -040091template <class T, class ...Args>
92T& make(Args ...args)
Howard Hinnantc51e1022010-05-11 19:42:16 +000093{
94 static typename aligned_storage<sizeof(T)>::type buf;
Louis Dionne6e41a152021-08-09 13:26:04 -040095 auto *obj = ::new (&buf) T(args...);
Eric Fiselier4db80032017-05-05 20:32:26 +000096 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000097}
98
Howard Hinnant3d2417c2012-12-27 21:17:53 +000099template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000100inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000101_LIBCPP_CONSTEXPR
102size_t
103countof(const T (&)[N])
104{
105 return N;
106}
107
108template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000109inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000110_LIBCPP_CONSTEXPR
111size_t
112countof(const T * const begin, const T * const end)
113{
114 return static_cast<size_t>(end - begin);
115}
116
Marshall Clow8fea1612016-08-25 15:09:01 +0000117_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
118{
119#ifndef _LIBCPP_NO_EXCEPTIONS
120 throw runtime_error(msg);
121#else
122 (void)msg;
123 _VSTD::abort();
124#endif
125}
126
Howard Hinnantc51e1022010-05-11 19:42:16 +0000127}
128
Howard Hinnantdd099492013-08-29 23:37:50 +0000129#if defined(_AIX)
130// Set priority to INT_MIN + 256 + 150
131# pragma priority ( -2147483242 )
132#endif
133
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000134const locale::category locale::none;
135const locale::category locale::collate;
136const locale::category locale::ctype;
137const locale::category locale::monetary;
138const locale::category locale::numeric;
139const locale::category locale::time;
140const locale::category locale::messages;
141const locale::category locale::all;
142
Howard Hinnantc51e1022010-05-11 19:42:16 +0000143class _LIBCPP_HIDDEN locale::__imp
144 : public facet
145{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100146 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000147#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000148// FIXME: MSVC doesn't support aligned parameters by value.
149// I can't get the __sso_allocator to work here
150// for MSVC I think for this reason.
151 vector<facet*> facets_;
152#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000153 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000154#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000155 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000156public:
157 explicit __imp(size_t refs = 0);
158 explicit __imp(const string& name, size_t refs = 0);
159 __imp(const __imp&);
160 __imp(const __imp&, const string&, locale::category c);
161 __imp(const __imp& other, const __imp& one, locale::category c);
162 __imp(const __imp&, facet* f, long id);
163 ~__imp();
164
165 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000166 bool has_facet(long id) const
167 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000168 const locale::facet* use_facet(long id) const;
169
170 static const locale& make_classic();
171 static locale& make_global();
172private:
173 void install(facet* f, long id);
174 template <class F> void install(F* f) {install(f, f->id.__get());}
175 template <class F> void install_from(const __imp& other);
176};
177
178locale::__imp::__imp(size_t refs)
179 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000180 facets_(N),
181 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000182{
183 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000184 install(&make<_VSTD::collate<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400185#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000186 install(&make<_VSTD::collate<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400187#endif
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000188 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Louis Dionne89258142021-08-23 15:32:36 -0400189#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000190 install(&make<_VSTD::ctype<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400191#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000192 install(&make<codecvt<char, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400193#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000194 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400195#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100196_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000197 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
198 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100199_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400200#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100201 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
202 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
203#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000204 install(&make<numpunct<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400205#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000206 install(&make<numpunct<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400207#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000208 install(&make<num_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400209#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000210 install(&make<num_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400211#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000212 install(&make<num_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400213#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000214 install(&make<num_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400215#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000216 install(&make<moneypunct<char, false> >(1u));
217 install(&make<moneypunct<char, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400218#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000219 install(&make<moneypunct<wchar_t, false> >(1u));
220 install(&make<moneypunct<wchar_t, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400221#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000222 install(&make<money_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400223#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000224 install(&make<money_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400225#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000226 install(&make<money_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400227#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000228 install(&make<money_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400229#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000230 install(&make<time_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400231#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000232 install(&make<time_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400233#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000234 install(&make<time_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400235#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000236 install(&make<time_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400237#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000238 install(&make<_VSTD::messages<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400239#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000240 install(&make<_VSTD::messages<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400241#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000242}
243
244locale::__imp::__imp(const string& name, size_t refs)
245 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000246 facets_(N),
247 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000248{
Howard Hinnant72f73582010-08-11 17:04:31 +0000249#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000250 try
251 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400252#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000253 facets_ = locale::classic().__locale_->facets_;
254 for (unsigned i = 0; i < facets_.size(); ++i)
255 if (facets_[i])
256 facets_[i]->__add_shared();
257 install(new collate_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400258#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000259 install(new collate_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400260#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000261 install(new ctype_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400262#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000263 install(new ctype_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400264#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000265 install(new codecvt_byname<char, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400266#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000267 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400268#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100269_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000270 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
271 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100272_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400273#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100274 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
275 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
276#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000277 install(new numpunct_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400278#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000279 install(new numpunct_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400280#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000281 install(new moneypunct_byname<char, false>(name_));
282 install(new moneypunct_byname<char, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400283#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284 install(new moneypunct_byname<wchar_t, false>(name_));
285 install(new moneypunct_byname<wchar_t, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400286#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000287 install(new time_get_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400288#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000289 install(new time_get_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400290#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000291 install(new time_put_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400292#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000293 install(new time_put_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400294#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000295 install(new messages_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400296#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000297 install(new messages_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400298#endif
Howard Hinnant72f73582010-08-11 17:04:31 +0000299#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000300 }
301 catch (...)
302 {
303 for (unsigned i = 0; i < facets_.size(); ++i)
304 if (facets_[i])
305 facets_[i]->__release_shared();
306 throw;
307 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400308#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000309}
310
311locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000312 : facets_(max<size_t>(N, other.facets_.size())),
313 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000314{
315 facets_ = other.facets_;
316 for (unsigned i = 0; i < facets_.size(); ++i)
317 if (facets_[i])
318 facets_[i]->__add_shared();
319}
320
321locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000322 : facets_(N),
323 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000324{
325 facets_ = other.facets_;
326 for (unsigned i = 0; i < facets_.size(); ++i)
327 if (facets_[i])
328 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000329#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000330 try
331 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400332#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000333 if (c & locale::collate)
334 {
335 install(new collate_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400336#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000337 install(new collate_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400338#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000339 }
340 if (c & locale::ctype)
341 {
342 install(new ctype_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400343#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000344 install(new ctype_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400345#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000346 install(new codecvt_byname<char, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400347#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000348 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400349#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100350_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000351 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
352 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100353_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400354#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100355 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
356 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
357#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000358 }
359 if (c & locale::monetary)
360 {
361 install(new moneypunct_byname<char, false>(name));
362 install(new moneypunct_byname<char, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400363#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000364 install(new moneypunct_byname<wchar_t, false>(name));
365 install(new moneypunct_byname<wchar_t, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400366#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000367 }
368 if (c & locale::numeric)
369 {
370 install(new numpunct_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400371#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000372 install(new numpunct_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400373#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000374 }
375 if (c & locale::time)
376 {
377 install(new time_get_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400378#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000379 install(new time_get_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400380#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000381 install(new time_put_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400382#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000383 install(new time_put_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400384#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000385 }
386 if (c & locale::messages)
387 {
388 install(new messages_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400389#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000390 install(new messages_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400391#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000392 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000393#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000394 }
395 catch (...)
396 {
397 for (unsigned i = 0; i < facets_.size(); ++i)
398 if (facets_[i])
399 facets_[i]->__release_shared();
400 throw;
401 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400402#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000403}
404
405template<class F>
406inline
407void
408locale::__imp::install_from(const locale::__imp& one)
409{
410 long id = F::id.__get();
411 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
412}
413
414locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000415 : facets_(N),
416 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000417{
418 facets_ = other.facets_;
419 for (unsigned i = 0; i < facets_.size(); ++i)
420 if (facets_[i])
421 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000422#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000423 try
424 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400425#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000426 if (c & locale::collate)
427 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000428 install_from<_VSTD::collate<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400429#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000430 install_from<_VSTD::collate<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400431#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000432 }
433 if (c & locale::ctype)
434 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000435 install_from<_VSTD::ctype<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400436#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000437 install_from<_VSTD::ctype<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400438#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000439 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100440_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000441 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
442 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100443_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400444#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100445 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
446 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
447#endif
Louis Dionne89258142021-08-23 15:32:36 -0400448#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000449 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400450#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000451 }
452 if (c & locale::monetary)
453 {
454 install_from<moneypunct<char, false> >(one);
455 install_from<moneypunct<char, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400456#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000457 install_from<moneypunct<wchar_t, false> >(one);
458 install_from<moneypunct<wchar_t, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400459#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000460 install_from<money_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400461#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000462 install_from<money_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400463#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000464 install_from<money_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400465#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000466 install_from<money_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400467#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000468 }
469 if (c & locale::numeric)
470 {
471 install_from<numpunct<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400472#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000473 install_from<numpunct<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400474#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000475 install_from<num_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400476#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000477 install_from<num_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400478#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000479 install_from<num_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400480#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000481 install_from<num_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400482#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000483 }
484 if (c & locale::time)
485 {
486 install_from<time_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400487#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000488 install_from<time_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400489#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000490 install_from<time_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400491#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000492 install_from<time_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400493#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000494 }
495 if (c & locale::messages)
496 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000497 install_from<_VSTD::messages<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400498#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000499 install_from<_VSTD::messages<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400500#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000501 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000502#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000503 }
504 catch (...)
505 {
506 for (unsigned i = 0; i < facets_.size(); ++i)
507 if (facets_[i])
508 facets_[i]->__release_shared();
509 throw;
510 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400511#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000512}
513
514locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000515 : facets_(max<size_t>(N, other.facets_.size()+1)),
516 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000517{
518 f->__add_shared();
519 unique_ptr<facet, release> hold(f);
520 facets_ = other.facets_;
521 for (unsigned i = 0; i < other.facets_.size(); ++i)
522 if (facets_[i])
523 facets_[i]->__add_shared();
524 install(hold.get(), id);
525}
526
527locale::__imp::~__imp()
528{
529 for (unsigned i = 0; i < facets_.size(); ++i)
530 if (facets_[i])
531 facets_[i]->__release_shared();
532}
533
534void
535locale::__imp::install(facet* f, long id)
536{
537 f->__add_shared();
538 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000539 if (static_cast<size_t>(id) >= facets_.size())
540 facets_.resize(static_cast<size_t>(id+1));
541 if (facets_[static_cast<size_t>(id)])
542 facets_[static_cast<size_t>(id)]->__release_shared();
543 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000544}
545
546const locale::facet*
547locale::__imp::use_facet(long id) const
548{
549 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000550 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000551 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000552}
553
554// locale
555
556const locale&
557locale::__imp::make_classic()
558{
559 // only one thread can get in here and it only gets in once
560 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000561 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000562 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000563 return *c;
564}
565
566const locale&
567locale::classic()
568{
569 static const locale& c = __imp::make_classic();
570 return c;
571}
572
573locale&
574locale::__imp::make_global()
575{
576 // only one thread can get in here and it only gets in once
577 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000578 auto *obj = ::new (&buf) locale(locale::classic());
579 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000580}
581
582locale&
583locale::__global()
584{
585 static locale& g = __imp::make_global();
586 return g;
587}
588
Louis Dionne65358e12021-03-01 12:09:45 -0500589locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000590 : __locale_(__global().__locale_)
591{
592 __locale_->__add_shared();
593}
594
Louis Dionne65358e12021-03-01 12:09:45 -0500595locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000596 : __locale_(l.__locale_)
597{
598 __locale_->__add_shared();
599}
600
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000601locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000602{
603 __locale_->__release_shared();
604}
605
606const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500607locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000608{
609 other.__locale_->__add_shared();
610 __locale_->__release_shared();
611 __locale_ = other.__locale_;
612 return *this;
613}
614
615locale::locale(const char* name)
616 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100617 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000618{
619 __locale_->__add_shared();
620}
621
622locale::locale(const string& name)
623 : __locale_(new __imp(name))
624{
625 __locale_->__add_shared();
626}
627
628locale::locale(const locale& other, const char* name, category c)
629 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100630 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000631{
632 __locale_->__add_shared();
633}
634
635locale::locale(const locale& other, const string& name, category c)
636 : __locale_(new __imp(*other.__locale_, name, c))
637{
638 __locale_->__add_shared();
639}
640
641locale::locale(const locale& other, const locale& one, category c)
642 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
643{
644 __locale_->__add_shared();
645}
646
647string
648locale::name() const
649{
650 return __locale_->name();
651}
652
653void
654locale::__install_ctor(const locale& other, facet* f, long id)
655{
656 if (f)
657 __locale_ = new __imp(*other.__locale_, f, id);
658 else
659 __locale_ = other.__locale_;
660 __locale_->__add_shared();
661}
662
663locale
664locale::global(const locale& loc)
665{
666 locale& g = __global();
667 locale r = g;
668 g = loc;
669 if (g.name() != "*")
670 setlocale(LC_ALL, g.name().c_str());
671 return r;
672}
673
674bool
675locale::has_facet(id& x) const
676{
677 return __locale_->has_facet(x.__get());
678}
679
680const locale::facet*
681locale::use_facet(id& x) const
682{
683 return __locale_->use_facet(x.__get());
684}
685
686bool
687locale::operator==(const locale& y) const
688{
689 return (__locale_ == y.__locale_)
690 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
691}
692
693// locale::facet
694
695locale::facet::~facet()
696{
697}
698
699void
Louis Dionne65358e12021-03-01 12:09:45 -0500700locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000701{
702 delete this;
703}
704
705// locale::id
706
707int32_t locale::id::__next_id = 0;
708
709namespace
710{
711
712class __fake_bind
713{
714 locale::id* id_;
715 void (locale::id::* pmf_)();
716public:
717 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
718 : id_(id), pmf_(pmf) {}
719
720 void operator()() const
721 {
722 (id_->*pmf_)();
723 }
724};
725
726}
727
728long
729locale::id::__get()
730{
731 call_once(__flag_, __fake_bind(&locale::id::__init, this));
732 return __id_ - 1;
733}
734
735void
736locale::id::__init()
737{
Weiming Zhaob613db72017-09-19 23:18:03 +0000738 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000739}
740
741// template <> class collate_byname<char>
742
743collate_byname<char>::collate_byname(const char* n, size_t refs)
744 : collate<char>(refs),
745 __l(newlocale(LC_ALL_MASK, n, 0))
746{
747 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000748 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000749 " failed to construct for " + string(n));
750}
751
752collate_byname<char>::collate_byname(const string& name, size_t refs)
753 : collate<char>(refs),
754 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
755{
756 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000757 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000758 " failed to construct for " + name);
759}
760
761collate_byname<char>::~collate_byname()
762{
763 freelocale(__l);
764}
765
766int
767collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
768 const char_type* __lo2, const char_type* __hi2) const
769{
770 string_type lhs(__lo1, __hi1);
771 string_type rhs(__lo2, __hi2);
772 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
773 if (r < 0)
774 return -1;
775 if (r > 0)
776 return 1;
777 return r;
778}
779
780collate_byname<char>::string_type
781collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
782{
783 const string_type in(lo, hi);
784 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
785 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
786 return out;
787}
788
789// template <> class collate_byname<wchar_t>
790
Louis Dionne89258142021-08-23 15:32:36 -0400791#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000792collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
793 : collate<wchar_t>(refs),
794 __l(newlocale(LC_ALL_MASK, n, 0))
795{
796 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000797 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000798 " failed to construct for " + string(n));
799}
800
801collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
802 : collate<wchar_t>(refs),
803 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
804{
805 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000806 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000807 " failed to construct for " + name);
808}
809
810collate_byname<wchar_t>::~collate_byname()
811{
812 freelocale(__l);
813}
814
815int
816collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
817 const char_type* __lo2, const char_type* __hi2) const
818{
819 string_type lhs(__lo1, __hi1);
820 string_type rhs(__lo2, __hi2);
821 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
822 if (r < 0)
823 return -1;
824 if (r > 0)
825 return 1;
826 return r;
827}
828
829collate_byname<wchar_t>::string_type
830collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
831{
832 const string_type in(lo, hi);
833 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
834 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
835 return out;
836}
Louis Dionne89258142021-08-23 15:32:36 -0400837#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000838
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000839const ctype_base::mask ctype_base::space;
840const ctype_base::mask ctype_base::print;
841const ctype_base::mask ctype_base::cntrl;
842const ctype_base::mask ctype_base::upper;
843const ctype_base::mask ctype_base::lower;
844const ctype_base::mask ctype_base::alpha;
845const ctype_base::mask ctype_base::digit;
846const ctype_base::mask ctype_base::punct;
847const ctype_base::mask ctype_base::xdigit;
848const ctype_base::mask ctype_base::blank;
849const ctype_base::mask ctype_base::alnum;
850const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700851
Louis Dionne945f8682021-09-09 13:29:24 -0400852// template <> class ctype<wchar_t>;
853
Louis Dionne89258142021-08-23 15:32:36 -0400854#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000855locale::id ctype<wchar_t>::id;
856
857ctype<wchar_t>::~ctype()
858{
859}
860
861bool
862ctype<wchar_t>::do_is(mask m, char_type c) const
863{
Marshall Clowd920eea2013-10-21 15:07:28 +0000864 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000865}
866
867const wchar_t*
868ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
869{
870 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000871 *vec = static_cast<mask>(isascii(*low) ?
872 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000873 return low;
874}
875
876const wchar_t*
877ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
878{
879 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000880 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000881 break;
882 return low;
883}
884
885const wchar_t*
886ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
887{
888 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000889 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890 break;
891 return low;
892}
893
894wchar_t
895ctype<wchar_t>::do_toupper(char_type c) const
896{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000897#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
898 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000899#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500900 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000901 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000902#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000903 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000904#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000905}
906
907const wchar_t*
908ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
909{
910 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000911#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
912 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000913#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500914 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000915 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
916 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000917#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000918 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000919#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000920 return low;
921}
922
923wchar_t
924ctype<wchar_t>::do_tolower(char_type c) const
925{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000926#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
927 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000928#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500929 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000930 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000931#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000932 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000933#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000934}
935
936const wchar_t*
937ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
938{
939 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000940#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
941 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000942#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500943 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000944 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
945 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000946#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000947 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000948#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000949 return low;
950}
951
952wchar_t
953ctype<wchar_t>::do_widen(char c) const
954{
955 return c;
956}
957
958const char*
959ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
960{
961 for (; low != high; ++low, ++dest)
962 *dest = *low;
963 return low;
964}
965
966char
967ctype<wchar_t>::do_narrow(char_type c, char dfault) const
968{
969 if (isascii(c))
970 return static_cast<char>(c);
971 return dfault;
972}
973
974const wchar_t*
975ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
976{
977 for (; low != high; ++low, ++dest)
978 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000979 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000980 else
981 *dest = dfault;
982 return low;
983}
Louis Dionne89258142021-08-23 15:32:36 -0400984#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000985
986// template <> class ctype<char>;
987
988locale::id ctype<char>::id;
989
Muiez Ahmedc98adb12021-11-18 15:49:45 -0500990const size_t ctype<char>::table_size;
991
Howard Hinnantc51e1022010-05-11 19:42:16 +0000992ctype<char>::ctype(const mask* tab, bool del, size_t refs)
993 : locale::facet(refs),
994 __tab_(tab),
995 __del_(del)
996{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000997 if (__tab_ == 0)
998 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000999}
1000
1001ctype<char>::~ctype()
1002{
1003 if (__tab_ && __del_)
1004 delete [] __tab_;
1005}
1006
1007char
1008ctype<char>::do_toupper(char_type c) const
1009{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001010#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001011 return isascii(c) ?
1012 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001013#elif defined(__NetBSD__)
1014 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001015#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +00001016 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001017 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001018#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001019 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001020#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001021}
1022
1023const char*
1024ctype<char>::do_toupper(char_type* low, const char_type* high) const
1025{
1026 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001027#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001028 *low = isascii(*low) ?
1029 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001030#elif defined(__NetBSD__)
1031 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001032#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001033 *low = isascii(*low) ?
1034 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001035#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001036 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001037#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001038 return low;
1039}
1040
1041char
1042ctype<char>::do_tolower(char_type c) const
1043{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001044#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001045 return isascii(c) ?
1046 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001047#elif defined(__NetBSD__)
1048 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001049#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001050 return isascii(c) ?
1051 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001052#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001053 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001054#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001055}
1056
1057const char*
1058ctype<char>::do_tolower(char_type* low, const char_type* high) const
1059{
1060 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001061#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001062 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001063#elif defined(__NetBSD__)
1064 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001065#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001066 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001067#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001068 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001069#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001070 return low;
1071}
1072
1073char
1074ctype<char>::do_widen(char c) const
1075{
1076 return c;
1077}
1078
1079const char*
1080ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1081{
1082 for (; low != high; ++low, ++dest)
1083 *dest = *low;
1084 return low;
1085}
1086
1087char
1088ctype<char>::do_narrow(char_type c, char dfault) const
1089{
1090 if (isascii(c))
1091 return static_cast<char>(c);
1092 return dfault;
1093}
1094
1095const char*
1096ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1097{
1098 for (; low != high; ++low, ++dest)
1099 if (isascii(*low))
1100 *dest = *low;
1101 else
1102 *dest = dfault;
1103 return low;
1104}
1105
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001106#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001107extern "C" const unsigned short ** __ctype_b_loc();
1108extern "C" const int ** __ctype_tolower_loc();
1109extern "C" const int ** __ctype_toupper_loc();
1110#endif
1111
Marshall Clow8f870232015-03-04 16:50:02 +00001112#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001113const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001114ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001115{
1116 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1117 cntrl, cntrl,
1118 cntrl, cntrl,
1119 cntrl, cntrl,
1120 cntrl, cntrl,
1121 cntrl, cntrl | space | blank,
1122 cntrl | space, cntrl | space,
1123 cntrl | space, cntrl | space,
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 cntrl, cntrl,
1133 space | blank | 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 punct | print, punct | print,
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 digit | print | xdigit, digit | print | xdigit,
1146 punct | print, punct | print,
1147 punct | print, punct | print,
1148 punct | print, punct | print,
1149 punct | print, upper | xdigit | print | alpha,
1150 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1151 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1152 upper | xdigit | 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, upper | print | alpha,
1162 upper | print | alpha, punct | print,
1163 punct | print, punct | print,
1164 punct | print, punct | print,
1165 punct | print, lower | xdigit | print | alpha,
1166 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1167 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1168 lower | xdigit | 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, lower | print | alpha,
1178 lower | print | alpha, punct | print,
1179 punct | print, punct | print,
1180 punct | print, cntrl,
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1189 };
1190 return builtin_table;
1191}
1192#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001193const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001194ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001195{
David Chisnall1d581062011-09-21 08:39:44 +00001196#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001197 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001198#elif defined(__NetBSD__)
1199 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001200#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001201 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001202#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001203 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001204#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001205 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001206#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001207 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001208#elif defined(_NEWLIB_VERSION)
1209 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1210 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001211#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001212 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001213#elif defined(__MVS__)
1214# if defined(__NATIVE_ASCII_F)
1215 return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1216# else
1217 return const_cast<const ctype<char>::mask*> (__ctypec);
1218# endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001219#else
David Chisnall8074c342012-02-29 13:05:08 +00001220 // Platform not supported: abort so the person doing the port knows what to
1221 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001222# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001223 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001224 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001225 return NULL;
1226#endif
1227}
Marshall Clowb3f62842015-03-04 16:10:14 +00001228#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001229
Howard Hinnantd7a78632011-09-29 13:33:15 +00001230#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001231const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001232ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001233{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001234 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001235}
1236
1237const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001238ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001239{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001240 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001241}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001242#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001243const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001244ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001245{
1246 return _C_tolower_tab_ + 1;
1247}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001248
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001249const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001250ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001251{
1252 return _C_toupper_tab_ + 1;
1253}
1254
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001255#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001256const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001257ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001258{
1259 return *__ctype_tolower_loc();
1260}
1261
1262const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001263ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001264{
1265 return *__ctype_toupper_loc();
1266}
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001267#elif defined(__MVS__)
1268const unsigned short*
1269ctype<char>::__classic_lower_table() _NOEXCEPT
1270{
1271# if defined(__NATIVE_ASCII_F)
1272 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1273# else
1274 return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1275# endif
1276}
1277const unsigned short *
1278ctype<char>::__classic_upper_table() _NOEXCEPT
1279{
1280# if defined(__NATIVE_ASCII_F)
1281 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1282# else
1283 return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1284# endif
1285}
1286#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001287
Howard Hinnantc51e1022010-05-11 19:42:16 +00001288// template <> class ctype_byname<char>
1289
1290ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1291 : ctype<char>(0, false, refs),
1292 __l(newlocale(LC_ALL_MASK, name, 0))
1293{
1294 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001295 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 " failed to construct for " + string(name));
1297}
1298
1299ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1300 : ctype<char>(0, false, refs),
1301 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1302{
1303 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001304 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001305 " failed to construct for " + name);
1306}
1307
1308ctype_byname<char>::~ctype_byname()
1309{
1310 freelocale(__l);
1311}
1312
1313char
1314ctype_byname<char>::do_toupper(char_type c) const
1315{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001316 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001317}
1318
1319const char*
1320ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1321{
1322 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001323 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001324 return low;
1325}
1326
1327char
1328ctype_byname<char>::do_tolower(char_type c) const
1329{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001330 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001331}
1332
1333const char*
1334ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1335{
1336 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001337 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001338 return low;
1339}
1340
1341// template <> class ctype_byname<wchar_t>
1342
Louis Dionne89258142021-08-23 15:32:36 -04001343#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001344ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1345 : ctype<wchar_t>(refs),
1346 __l(newlocale(LC_ALL_MASK, name, 0))
1347{
1348 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001349 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001350 " failed to construct for " + string(name));
1351}
1352
1353ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1354 : ctype<wchar_t>(refs),
1355 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1356{
1357 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001358 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001359 " failed to construct for " + name);
1360}
1361
1362ctype_byname<wchar_t>::~ctype_byname()
1363{
1364 freelocale(__l);
1365}
1366
1367bool
1368ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1369{
Alexis Huntc2017f12011-07-09 03:40:04 +00001370#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001371 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001372#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001373 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001374 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001375 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1376 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1377 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1378 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1379 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1380 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1381 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1382 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1383 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1384 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001385 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001386#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001387}
1388
1389const wchar_t*
1390ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1391{
1392 for (; low != high; ++low, ++vec)
1393 {
1394 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001395 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001396 else
1397 {
1398 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001399 wint_t ch = static_cast<wint_t>(*low);
1400 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001401 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001402#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001403 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001405#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001406 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001407 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001408 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001409 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001410 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001411 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001412#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001413 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001414 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001415#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001416 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001417 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001418 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001419 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001420#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001421 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001422 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001423#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001424#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001425 if (iswblank_l(ch, __l))
1426 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001427#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001428 }
1429 }
1430 return low;
1431}
1432
1433const wchar_t*
1434ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1435{
1436 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001437 {
1438#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001439 if (iswctype_l(*low, m, __l))
1440 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001441#else
Marshall Clowada0f732013-02-07 14:22:51 +00001442 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001443 if ((m & space) == space && iswspace_l(ch, __l)) break;
1444 if ((m & print) == print && iswprint_l(ch, __l)) break;
1445 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1446 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1447 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1448 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1449 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1450 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1451 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1452 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001453#endif
1454 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001455 return low;
1456}
1457
1458const wchar_t*
1459ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1460{
1461 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001462 {
1463#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001464 if (!iswctype_l(*low, m, __l))
1465 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001466#else
Marshall Clowada0f732013-02-07 14:22:51 +00001467 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001468 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1469 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1470 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1471 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1472 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1473 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1474 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1475 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1476 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1477 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001478 break;
1479#endif
1480 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001481 return low;
1482}
1483
1484wchar_t
1485ctype_byname<wchar_t>::do_toupper(char_type c) const
1486{
1487 return towupper_l(c, __l);
1488}
1489
1490const wchar_t*
1491ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1492{
1493 for (; low != high; ++low)
1494 *low = towupper_l(*low, __l);
1495 return low;
1496}
1497
1498wchar_t
1499ctype_byname<wchar_t>::do_tolower(char_type c) const
1500{
1501 return towlower_l(c, __l);
1502}
1503
1504const wchar_t*
1505ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1506{
1507 for (; low != high; ++low)
1508 *low = towlower_l(*low, __l);
1509 return low;
1510}
1511
1512wchar_t
1513ctype_byname<wchar_t>::do_widen(char c) const
1514{
Ben Craig3756b922016-03-09 15:39:39 +00001515 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001516}
1517
1518const char*
1519ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1520{
1521 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001522 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001523 return low;
1524}
1525
1526char
1527ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1528{
Ben Craig3756b922016-03-09 15:39:39 +00001529 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001530 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001531}
1532
1533const wchar_t*
1534ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1535{
1536 for (; low != high; ++low, ++dest)
1537 {
Ben Craig3756b922016-03-09 15:39:39 +00001538 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001539 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001540 }
1541 return low;
1542}
Louis Dionne89258142021-08-23 15:32:36 -04001543#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001544
1545// template <> class codecvt<char, char, mbstate_t>
1546
Howard Hinnantffb308e2010-08-22 00:03:27 +00001547locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001548
1549codecvt<char, char, mbstate_t>::~codecvt()
1550{
1551}
1552
1553codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001554codecvt<char, char, mbstate_t>::do_out(state_type&,
1555 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001556 extern_type* to, extern_type*, extern_type*& to_nxt) const
1557{
1558 frm_nxt = frm;
1559 to_nxt = to;
1560 return noconv;
1561}
1562
1563codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001564codecvt<char, char, mbstate_t>::do_in(state_type&,
1565 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001566 intern_type* to, intern_type*, intern_type*& to_nxt) const
1567{
1568 frm_nxt = frm;
1569 to_nxt = to;
1570 return noconv;
1571}
1572
1573codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001574codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001575 extern_type* to, extern_type*, extern_type*& to_nxt) const
1576{
1577 to_nxt = to;
1578 return noconv;
1579}
1580
1581int
Louis Dionne65358e12021-03-01 12:09:45 -05001582codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001583{
1584 return 1;
1585}
1586
1587bool
Louis Dionne65358e12021-03-01 12:09:45 -05001588codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001589{
1590 return true;
1591}
1592
1593int
1594codecvt<char, char, mbstate_t>::do_length(state_type&,
1595 const extern_type* frm, const extern_type* end, size_t mx) const
1596{
Howard Hinnant28b24882011-12-01 20:21:04 +00001597 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001598}
1599
1600int
Louis Dionne65358e12021-03-01 12:09:45 -05001601codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001602{
1603 return 1;
1604}
1605
1606// template <> class codecvt<wchar_t, char, mbstate_t>
1607
Louis Dionne89258142021-08-23 15:32:36 -04001608#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantffb308e2010-08-22 00:03:27 +00001609locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001610
1611codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1612 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001613 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001614{
1615}
1616
1617codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1618 : locale::facet(refs),
1619 __l(newlocale(LC_ALL_MASK, nm, 0))
1620{
1621 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001622 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001623 " failed to construct for " + string(nm));
1624}
1625
1626codecvt<wchar_t, char, mbstate_t>::~codecvt()
1627{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001628 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001629 freelocale(__l);
1630}
1631
1632codecvt<wchar_t, char, mbstate_t>::result
1633codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001634 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001635 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1636{
1637 // look for first internal null in frm
1638 const intern_type* fend = frm;
1639 for (; fend != frm_end; ++fend)
1640 if (*fend == 0)
1641 break;
1642 // loop over all null-terminated sequences in frm
1643 to_nxt = to;
1644 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1645 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001646 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001647 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001648 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1649 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001650 if (n == size_t(-1))
1651 {
1652 // need to recover to_nxt
1653 for (to_nxt = to; frm != frm_nxt; ++frm)
1654 {
Ben Craig3756b922016-03-09 15:39:39 +00001655 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001656 if (n == size_t(-1))
1657 break;
1658 to_nxt += n;
1659 }
1660 frm_nxt = frm;
1661 return error;
1662 }
1663 if (n == 0)
1664 return partial;
1665 to_nxt += n;
1666 if (to_nxt == to_end)
1667 break;
1668 if (fend != frm_end) // set up next null terminated sequence
1669 {
1670 // Try to write the terminating null
1671 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001672 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001673 if (n == size_t(-1)) // on error
1674 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001675 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001676 return partial;
1677 for (extern_type* p = tmp; n; --n) // write it
1678 *to_nxt++ = *p++;
1679 ++frm_nxt;
1680 // look for next null in frm
1681 for (fend = frm_nxt; fend != frm_end; ++fend)
1682 if (*fend == 0)
1683 break;
1684 }
1685 }
1686 return frm_nxt == frm_end ? ok : partial;
1687}
1688
1689codecvt<wchar_t, char, mbstate_t>::result
1690codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001691 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001692 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1693{
1694 // look for first internal null in frm
1695 const extern_type* fend = frm;
1696 for (; fend != frm_end; ++fend)
1697 if (*fend == 0)
1698 break;
1699 // loop over all null-terminated sequences in frm
1700 to_nxt = to;
1701 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1702 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001703 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001704 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001705 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1706 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001707 if (n == size_t(-1))
1708 {
1709 // need to recover to_nxt
1710 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1711 {
Ben Craig3756b922016-03-09 15:39:39 +00001712 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1713 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001714 switch (n)
1715 {
1716 case 0:
1717 ++frm;
1718 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001719 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001720 frm_nxt = frm;
1721 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001722 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001723 frm_nxt = frm;
1724 return partial;
1725 default:
1726 frm += n;
1727 break;
1728 }
1729 }
1730 frm_nxt = frm;
1731 return frm_nxt == frm_end ? ok : partial;
1732 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001733 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001734 return error;
1735 to_nxt += n;
1736 if (to_nxt == to_end)
1737 break;
1738 if (fend != frm_end) // set up next null terminated sequence
1739 {
1740 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001741 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001742 if (n != 0) // on error
1743 return error;
1744 ++to_nxt;
1745 ++frm_nxt;
1746 // look for next null in frm
1747 for (fend = frm_nxt; fend != frm_end; ++fend)
1748 if (*fend == 0)
1749 break;
1750 }
1751 }
1752 return frm_nxt == frm_end ? ok : partial;
1753}
1754
1755codecvt<wchar_t, char, mbstate_t>::result
1756codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1757 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1758{
1759 to_nxt = to;
1760 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001761 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001762 if (n == size_t(-1) || n == 0) // on error
1763 return error;
1764 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001765 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001766 return partial;
1767 for (extern_type* p = tmp; n; --n) // write it
1768 *to_nxt++ = *p++;
1769 return ok;
1770}
1771
1772int
Louis Dionne65358e12021-03-01 12:09:45 -05001773codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001774{
Ben Craig3756b922016-03-09 15:39:39 +00001775 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001776 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001777
1778 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001779 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001780 return 1; // which take more than 1 char to form a wchar_t
1781 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001782}
1783
1784bool
Louis Dionne65358e12021-03-01 12:09:45 -05001785codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001786{
1787 return false;
1788}
1789
1790int
1791codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1792 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1793{
1794 int nbytes = 0;
1795 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1796 {
Ben Craig3756b922016-03-09 15:39:39 +00001797 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001798 switch (n)
1799 {
1800 case 0:
1801 ++nbytes;
1802 ++frm;
1803 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001804 case size_t(-1):
1805 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001806 return nbytes;
1807 default:
1808 nbytes += n;
1809 frm += n;
1810 break;
1811 }
1812 }
1813 return nbytes;
1814}
1815
1816int
Louis Dionne65358e12021-03-01 12:09:45 -05001817codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001818{
Ben Craig3756b922016-03-09 15:39:39 +00001819 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001820}
Louis Dionne89258142021-08-23 15:32:36 -04001821#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001822
1823// Valid UTF ranges
1824// UTF-32 UTF-16 UTF-8 # of code points
1825// first second first second third fourth
1826// 000000 - 00007F 0000 - 007F 00 - 7F 127
1827// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1828// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1829// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1830// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1831// 00D800 - 00DFFF invalid
1832// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1833// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1834// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1835// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1836
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001837static
1838codecvt_base::result
1839utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1840 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1841 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1842{
1843 frm_nxt = frm;
1844 to_nxt = to;
1845 if (mode & generate_header)
1846 {
1847 if (to_end-to_nxt < 3)
1848 return codecvt_base::partial;
1849 *to_nxt++ = static_cast<uint8_t>(0xEF);
1850 *to_nxt++ = static_cast<uint8_t>(0xBB);
1851 *to_nxt++ = static_cast<uint8_t>(0xBF);
1852 }
1853 for (; frm_nxt < frm_end; ++frm_nxt)
1854 {
1855 uint16_t wc1 = *frm_nxt;
1856 if (wc1 > Maxcode)
1857 return codecvt_base::error;
1858 if (wc1 < 0x0080)
1859 {
1860 if (to_end-to_nxt < 1)
1861 return codecvt_base::partial;
1862 *to_nxt++ = static_cast<uint8_t>(wc1);
1863 }
1864 else if (wc1 < 0x0800)
1865 {
1866 if (to_end-to_nxt < 2)
1867 return codecvt_base::partial;
1868 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1869 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1870 }
1871 else if (wc1 < 0xD800)
1872 {
1873 if (to_end-to_nxt < 3)
1874 return codecvt_base::partial;
1875 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1876 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1877 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1878 }
1879 else if (wc1 < 0xDC00)
1880 {
1881 if (frm_end-frm_nxt < 2)
1882 return codecvt_base::partial;
1883 uint16_t wc2 = frm_nxt[1];
1884 if ((wc2 & 0xFC00) != 0xDC00)
1885 return codecvt_base::error;
1886 if (to_end-to_nxt < 4)
1887 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001888 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1889 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001890 return codecvt_base::error;
1891 ++frm_nxt;
1892 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1893 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1894 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1895 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1896 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1897 }
1898 else if (wc1 < 0xE000)
1899 {
1900 return codecvt_base::error;
1901 }
1902 else
1903 {
1904 if (to_end-to_nxt < 3)
1905 return codecvt_base::partial;
1906 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1907 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1908 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1909 }
1910 }
1911 return codecvt_base::ok;
1912}
1913
1914static
1915codecvt_base::result
1916utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1917 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1918 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1919{
1920 frm_nxt = frm;
1921 to_nxt = to;
1922 if (mode & generate_header)
1923 {
1924 if (to_end-to_nxt < 3)
1925 return codecvt_base::partial;
1926 *to_nxt++ = static_cast<uint8_t>(0xEF);
1927 *to_nxt++ = static_cast<uint8_t>(0xBB);
1928 *to_nxt++ = static_cast<uint8_t>(0xBF);
1929 }
1930 for (; frm_nxt < frm_end; ++frm_nxt)
1931 {
1932 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1933 if (wc1 > Maxcode)
1934 return codecvt_base::error;
1935 if (wc1 < 0x0080)
1936 {
1937 if (to_end-to_nxt < 1)
1938 return codecvt_base::partial;
1939 *to_nxt++ = static_cast<uint8_t>(wc1);
1940 }
1941 else if (wc1 < 0x0800)
1942 {
1943 if (to_end-to_nxt < 2)
1944 return codecvt_base::partial;
1945 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1946 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1947 }
1948 else if (wc1 < 0xD800)
1949 {
1950 if (to_end-to_nxt < 3)
1951 return codecvt_base::partial;
1952 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1953 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1954 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1955 }
1956 else if (wc1 < 0xDC00)
1957 {
1958 if (frm_end-frm_nxt < 2)
1959 return codecvt_base::partial;
1960 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1961 if ((wc2 & 0xFC00) != 0xDC00)
1962 return codecvt_base::error;
1963 if (to_end-to_nxt < 4)
1964 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001965 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1966 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001967 return codecvt_base::error;
1968 ++frm_nxt;
1969 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1970 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1971 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1972 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1973 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1974 }
1975 else if (wc1 < 0xE000)
1976 {
1977 return codecvt_base::error;
1978 }
1979 else
1980 {
1981 if (to_end-to_nxt < 3)
1982 return codecvt_base::partial;
1983 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1984 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1985 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1986 }
1987 }
1988 return codecvt_base::ok;
1989}
1990
1991static
1992codecvt_base::result
1993utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1994 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1995 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1996{
1997 frm_nxt = frm;
1998 to_nxt = to;
1999 if (mode & consume_header)
2000 {
2001 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2002 frm_nxt[2] == 0xBF)
2003 frm_nxt += 3;
2004 }
2005 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2006 {
2007 uint8_t c1 = *frm_nxt;
2008 if (c1 > Maxcode)
2009 return codecvt_base::error;
2010 if (c1 < 0x80)
2011 {
2012 *to_nxt = static_cast<uint16_t>(c1);
2013 ++frm_nxt;
2014 }
2015 else if (c1 < 0xC2)
2016 {
2017 return codecvt_base::error;
2018 }
2019 else if (c1 < 0xE0)
2020 {
2021 if (frm_end-frm_nxt < 2)
2022 return codecvt_base::partial;
2023 uint8_t c2 = frm_nxt[1];
2024 if ((c2 & 0xC0) != 0x80)
2025 return codecvt_base::error;
2026 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2027 if (t > Maxcode)
2028 return codecvt_base::error;
2029 *to_nxt = t;
2030 frm_nxt += 2;
2031 }
2032 else if (c1 < 0xF0)
2033 {
2034 if (frm_end-frm_nxt < 3)
2035 return codecvt_base::partial;
2036 uint8_t c2 = frm_nxt[1];
2037 uint8_t c3 = frm_nxt[2];
2038 switch (c1)
2039 {
2040 case 0xE0:
2041 if ((c2 & 0xE0) != 0xA0)
2042 return codecvt_base::error;
2043 break;
2044 case 0xED:
2045 if ((c2 & 0xE0) != 0x80)
2046 return codecvt_base::error;
2047 break;
2048 default:
2049 if ((c2 & 0xC0) != 0x80)
2050 return codecvt_base::error;
2051 break;
2052 }
2053 if ((c3 & 0xC0) != 0x80)
2054 return codecvt_base::error;
2055 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2056 | ((c2 & 0x3F) << 6)
2057 | (c3 & 0x3F));
2058 if (t > Maxcode)
2059 return codecvt_base::error;
2060 *to_nxt = t;
2061 frm_nxt += 3;
2062 }
2063 else if (c1 < 0xF5)
2064 {
2065 if (frm_end-frm_nxt < 4)
2066 return codecvt_base::partial;
2067 uint8_t c2 = frm_nxt[1];
2068 uint8_t c3 = frm_nxt[2];
2069 uint8_t c4 = frm_nxt[3];
2070 switch (c1)
2071 {
2072 case 0xF0:
2073 if (!(0x90 <= c2 && c2 <= 0xBF))
2074 return codecvt_base::error;
2075 break;
2076 case 0xF4:
2077 if ((c2 & 0xF0) != 0x80)
2078 return codecvt_base::error;
2079 break;
2080 default:
2081 if ((c2 & 0xC0) != 0x80)
2082 return codecvt_base::error;
2083 break;
2084 }
2085 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2086 return codecvt_base::error;
2087 if (to_end-to_nxt < 2)
2088 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002089 if ((((c1 & 7UL) << 18) +
2090 ((c2 & 0x3FUL) << 12) +
2091 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002092 return codecvt_base::error;
2093 *to_nxt = static_cast<uint16_t>(
2094 0xD800
2095 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2096 | ((c2 & 0x0F) << 2)
2097 | ((c3 & 0x30) >> 4));
2098 *++to_nxt = static_cast<uint16_t>(
2099 0xDC00
2100 | ((c3 & 0x0F) << 6)
2101 | (c4 & 0x3F));
2102 frm_nxt += 4;
2103 }
2104 else
2105 {
2106 return codecvt_base::error;
2107 }
2108 }
2109 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2110}
2111
2112static
2113codecvt_base::result
2114utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2115 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2116 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2117{
2118 frm_nxt = frm;
2119 to_nxt = to;
2120 if (mode & consume_header)
2121 {
2122 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2123 frm_nxt[2] == 0xBF)
2124 frm_nxt += 3;
2125 }
2126 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2127 {
2128 uint8_t c1 = *frm_nxt;
2129 if (c1 > Maxcode)
2130 return codecvt_base::error;
2131 if (c1 < 0x80)
2132 {
2133 *to_nxt = static_cast<uint32_t>(c1);
2134 ++frm_nxt;
2135 }
2136 else if (c1 < 0xC2)
2137 {
2138 return codecvt_base::error;
2139 }
2140 else if (c1 < 0xE0)
2141 {
2142 if (frm_end-frm_nxt < 2)
2143 return codecvt_base::partial;
2144 uint8_t c2 = frm_nxt[1];
2145 if ((c2 & 0xC0) != 0x80)
2146 return codecvt_base::error;
2147 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2148 if (t > Maxcode)
2149 return codecvt_base::error;
2150 *to_nxt = static_cast<uint32_t>(t);
2151 frm_nxt += 2;
2152 }
2153 else if (c1 < 0xF0)
2154 {
2155 if (frm_end-frm_nxt < 3)
2156 return codecvt_base::partial;
2157 uint8_t c2 = frm_nxt[1];
2158 uint8_t c3 = frm_nxt[2];
2159 switch (c1)
2160 {
2161 case 0xE0:
2162 if ((c2 & 0xE0) != 0xA0)
2163 return codecvt_base::error;
2164 break;
2165 case 0xED:
2166 if ((c2 & 0xE0) != 0x80)
2167 return codecvt_base::error;
2168 break;
2169 default:
2170 if ((c2 & 0xC0) != 0x80)
2171 return codecvt_base::error;
2172 break;
2173 }
2174 if ((c3 & 0xC0) != 0x80)
2175 return codecvt_base::error;
2176 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2177 | ((c2 & 0x3F) << 6)
2178 | (c3 & 0x3F));
2179 if (t > Maxcode)
2180 return codecvt_base::error;
2181 *to_nxt = static_cast<uint32_t>(t);
2182 frm_nxt += 3;
2183 }
2184 else if (c1 < 0xF5)
2185 {
2186 if (frm_end-frm_nxt < 4)
2187 return codecvt_base::partial;
2188 uint8_t c2 = frm_nxt[1];
2189 uint8_t c3 = frm_nxt[2];
2190 uint8_t c4 = frm_nxt[3];
2191 switch (c1)
2192 {
2193 case 0xF0:
2194 if (!(0x90 <= c2 && c2 <= 0xBF))
2195 return codecvt_base::error;
2196 break;
2197 case 0xF4:
2198 if ((c2 & 0xF0) != 0x80)
2199 return codecvt_base::error;
2200 break;
2201 default:
2202 if ((c2 & 0xC0) != 0x80)
2203 return codecvt_base::error;
2204 break;
2205 }
2206 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2207 return codecvt_base::error;
2208 if (to_end-to_nxt < 2)
2209 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002210 if ((((c1 & 7UL) << 18) +
2211 ((c2 & 0x3FUL) << 12) +
2212 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002213 return codecvt_base::error;
2214 *to_nxt = static_cast<uint32_t>(
2215 0xD800
2216 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2217 | ((c2 & 0x0F) << 2)
2218 | ((c3 & 0x30) >> 4));
2219 *++to_nxt = static_cast<uint32_t>(
2220 0xDC00
2221 | ((c3 & 0x0F) << 6)
2222 | (c4 & 0x3F));
2223 frm_nxt += 4;
2224 }
2225 else
2226 {
2227 return codecvt_base::error;
2228 }
2229 }
2230 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2231}
2232
2233static
2234int
2235utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2236 size_t mx, unsigned long Maxcode = 0x10FFFF,
2237 codecvt_mode mode = codecvt_mode(0))
2238{
2239 const uint8_t* frm_nxt = frm;
2240 if (mode & consume_header)
2241 {
2242 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2243 frm_nxt[2] == 0xBF)
2244 frm_nxt += 3;
2245 }
2246 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2247 {
2248 uint8_t c1 = *frm_nxt;
2249 if (c1 > Maxcode)
2250 break;
2251 if (c1 < 0x80)
2252 {
2253 ++frm_nxt;
2254 }
2255 else if (c1 < 0xC2)
2256 {
2257 break;
2258 }
2259 else if (c1 < 0xE0)
2260 {
2261 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2262 break;
2263 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2264 if (t > Maxcode)
2265 break;
2266 frm_nxt += 2;
2267 }
2268 else if (c1 < 0xF0)
2269 {
2270 if (frm_end-frm_nxt < 3)
2271 break;
2272 uint8_t c2 = frm_nxt[1];
2273 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002274 switch (c1)
2275 {
2276 case 0xE0:
2277 if ((c2 & 0xE0) != 0xA0)
2278 return static_cast<int>(frm_nxt - frm);
2279 break;
2280 case 0xED:
2281 if ((c2 & 0xE0) != 0x80)
2282 return static_cast<int>(frm_nxt - frm);
2283 break;
2284 default:
2285 if ((c2 & 0xC0) != 0x80)
2286 return static_cast<int>(frm_nxt - frm);
2287 break;
2288 }
2289 if ((c3 & 0xC0) != 0x80)
2290 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002291 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002292 break;
2293 frm_nxt += 3;
2294 }
2295 else if (c1 < 0xF5)
2296 {
2297 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2298 break;
2299 uint8_t c2 = frm_nxt[1];
2300 uint8_t c3 = frm_nxt[2];
2301 uint8_t c4 = frm_nxt[3];
2302 switch (c1)
2303 {
2304 case 0xF0:
2305 if (!(0x90 <= c2 && c2 <= 0xBF))
2306 return static_cast<int>(frm_nxt - frm);
2307 break;
2308 case 0xF4:
2309 if ((c2 & 0xF0) != 0x80)
2310 return static_cast<int>(frm_nxt - frm);
2311 break;
2312 default:
2313 if ((c2 & 0xC0) != 0x80)
2314 return static_cast<int>(frm_nxt - frm);
2315 break;
2316 }
2317 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2318 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002319 if ((((c1 & 7UL) << 18) +
2320 ((c2 & 0x3FUL) << 12) +
2321 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002322 break;
2323 ++nchar16_t;
2324 frm_nxt += 4;
2325 }
2326 else
2327 {
2328 break;
2329 }
2330 }
2331 return static_cast<int>(frm_nxt - frm);
2332}
2333
2334static
2335codecvt_base::result
2336ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2337 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2338 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2339{
2340 frm_nxt = frm;
2341 to_nxt = to;
2342 if (mode & generate_header)
2343 {
2344 if (to_end-to_nxt < 3)
2345 return codecvt_base::partial;
2346 *to_nxt++ = static_cast<uint8_t>(0xEF);
2347 *to_nxt++ = static_cast<uint8_t>(0xBB);
2348 *to_nxt++ = static_cast<uint8_t>(0xBF);
2349 }
2350 for (; frm_nxt < frm_end; ++frm_nxt)
2351 {
2352 uint32_t wc = *frm_nxt;
2353 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2354 return codecvt_base::error;
2355 if (wc < 0x000080)
2356 {
2357 if (to_end-to_nxt < 1)
2358 return codecvt_base::partial;
2359 *to_nxt++ = static_cast<uint8_t>(wc);
2360 }
2361 else if (wc < 0x000800)
2362 {
2363 if (to_end-to_nxt < 2)
2364 return codecvt_base::partial;
2365 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2366 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2367 }
2368 else if (wc < 0x010000)
2369 {
2370 if (to_end-to_nxt < 3)
2371 return codecvt_base::partial;
2372 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2373 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2374 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2375 }
2376 else // if (wc < 0x110000)
2377 {
2378 if (to_end-to_nxt < 4)
2379 return codecvt_base::partial;
2380 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2381 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2382 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2383 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2384 }
2385 }
2386 return codecvt_base::ok;
2387}
2388
2389static
2390codecvt_base::result
2391utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2392 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2393 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2394{
2395 frm_nxt = frm;
2396 to_nxt = to;
2397 if (mode & consume_header)
2398 {
2399 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2400 frm_nxt[2] == 0xBF)
2401 frm_nxt += 3;
2402 }
2403 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2404 {
2405 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2406 if (c1 < 0x80)
2407 {
2408 if (c1 > Maxcode)
2409 return codecvt_base::error;
2410 *to_nxt = static_cast<uint32_t>(c1);
2411 ++frm_nxt;
2412 }
2413 else if (c1 < 0xC2)
2414 {
2415 return codecvt_base::error;
2416 }
2417 else if (c1 < 0xE0)
2418 {
2419 if (frm_end-frm_nxt < 2)
2420 return codecvt_base::partial;
2421 uint8_t c2 = frm_nxt[1];
2422 if ((c2 & 0xC0) != 0x80)
2423 return codecvt_base::error;
2424 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2425 | (c2 & 0x3F));
2426 if (t > Maxcode)
2427 return codecvt_base::error;
2428 *to_nxt = t;
2429 frm_nxt += 2;
2430 }
2431 else if (c1 < 0xF0)
2432 {
2433 if (frm_end-frm_nxt < 3)
2434 return codecvt_base::partial;
2435 uint8_t c2 = frm_nxt[1];
2436 uint8_t c3 = frm_nxt[2];
2437 switch (c1)
2438 {
2439 case 0xE0:
2440 if ((c2 & 0xE0) != 0xA0)
2441 return codecvt_base::error;
2442 break;
2443 case 0xED:
2444 if ((c2 & 0xE0) != 0x80)
2445 return codecvt_base::error;
2446 break;
2447 default:
2448 if ((c2 & 0xC0) != 0x80)
2449 return codecvt_base::error;
2450 break;
2451 }
2452 if ((c3 & 0xC0) != 0x80)
2453 return codecvt_base::error;
2454 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2455 | ((c2 & 0x3F) << 6)
2456 | (c3 & 0x3F));
2457 if (t > Maxcode)
2458 return codecvt_base::error;
2459 *to_nxt = t;
2460 frm_nxt += 3;
2461 }
2462 else if (c1 < 0xF5)
2463 {
2464 if (frm_end-frm_nxt < 4)
2465 return codecvt_base::partial;
2466 uint8_t c2 = frm_nxt[1];
2467 uint8_t c3 = frm_nxt[2];
2468 uint8_t c4 = frm_nxt[3];
2469 switch (c1)
2470 {
2471 case 0xF0:
2472 if (!(0x90 <= c2 && c2 <= 0xBF))
2473 return codecvt_base::error;
2474 break;
2475 case 0xF4:
2476 if ((c2 & 0xF0) != 0x80)
2477 return codecvt_base::error;
2478 break;
2479 default:
2480 if ((c2 & 0xC0) != 0x80)
2481 return codecvt_base::error;
2482 break;
2483 }
2484 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2485 return codecvt_base::error;
2486 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2487 | ((c2 & 0x3F) << 12)
2488 | ((c3 & 0x3F) << 6)
2489 | (c4 & 0x3F));
2490 if (t > Maxcode)
2491 return codecvt_base::error;
2492 *to_nxt = t;
2493 frm_nxt += 4;
2494 }
2495 else
2496 {
2497 return codecvt_base::error;
2498 }
2499 }
2500 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2501}
2502
2503static
2504int
2505utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2506 size_t mx, unsigned long Maxcode = 0x10FFFF,
2507 codecvt_mode mode = codecvt_mode(0))
2508{
2509 const uint8_t* frm_nxt = frm;
2510 if (mode & consume_header)
2511 {
2512 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2513 frm_nxt[2] == 0xBF)
2514 frm_nxt += 3;
2515 }
2516 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2517 {
2518 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2519 if (c1 < 0x80)
2520 {
2521 if (c1 > Maxcode)
2522 break;
2523 ++frm_nxt;
2524 }
2525 else if (c1 < 0xC2)
2526 {
2527 break;
2528 }
2529 else if (c1 < 0xE0)
2530 {
2531 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2532 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002533 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002534 break;
2535 frm_nxt += 2;
2536 }
2537 else if (c1 < 0xF0)
2538 {
2539 if (frm_end-frm_nxt < 3)
2540 break;
2541 uint8_t c2 = frm_nxt[1];
2542 uint8_t c3 = frm_nxt[2];
2543 switch (c1)
2544 {
2545 case 0xE0:
2546 if ((c2 & 0xE0) != 0xA0)
2547 return static_cast<int>(frm_nxt - frm);
2548 break;
2549 case 0xED:
2550 if ((c2 & 0xE0) != 0x80)
2551 return static_cast<int>(frm_nxt - frm);
2552 break;
2553 default:
2554 if ((c2 & 0xC0) != 0x80)
2555 return static_cast<int>(frm_nxt - frm);
2556 break;
2557 }
2558 if ((c3 & 0xC0) != 0x80)
2559 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002560 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002561 break;
2562 frm_nxt += 3;
2563 }
2564 else if (c1 < 0xF5)
2565 {
2566 if (frm_end-frm_nxt < 4)
2567 break;
2568 uint8_t c2 = frm_nxt[1];
2569 uint8_t c3 = frm_nxt[2];
2570 uint8_t c4 = frm_nxt[3];
2571 switch (c1)
2572 {
2573 case 0xF0:
2574 if (!(0x90 <= c2 && c2 <= 0xBF))
2575 return static_cast<int>(frm_nxt - frm);
2576 break;
2577 case 0xF4:
2578 if ((c2 & 0xF0) != 0x80)
2579 return static_cast<int>(frm_nxt - frm);
2580 break;
2581 default:
2582 if ((c2 & 0xC0) != 0x80)
2583 return static_cast<int>(frm_nxt - frm);
2584 break;
2585 }
2586 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2587 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002588 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2589 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002590 break;
2591 frm_nxt += 4;
2592 }
2593 else
2594 {
2595 break;
2596 }
2597 }
2598 return static_cast<int>(frm_nxt - frm);
2599}
2600
2601static
2602codecvt_base::result
2603ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2604 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2605 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2606{
2607 frm_nxt = frm;
2608 to_nxt = to;
2609 if (mode & generate_header)
2610 {
2611 if (to_end-to_nxt < 3)
2612 return codecvt_base::partial;
2613 *to_nxt++ = static_cast<uint8_t>(0xEF);
2614 *to_nxt++ = static_cast<uint8_t>(0xBB);
2615 *to_nxt++ = static_cast<uint8_t>(0xBF);
2616 }
2617 for (; frm_nxt < frm_end; ++frm_nxt)
2618 {
2619 uint16_t wc = *frm_nxt;
2620 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2621 return codecvt_base::error;
2622 if (wc < 0x0080)
2623 {
2624 if (to_end-to_nxt < 1)
2625 return codecvt_base::partial;
2626 *to_nxt++ = static_cast<uint8_t>(wc);
2627 }
2628 else if (wc < 0x0800)
2629 {
2630 if (to_end-to_nxt < 2)
2631 return codecvt_base::partial;
2632 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2633 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2634 }
2635 else // if (wc <= 0xFFFF)
2636 {
2637 if (to_end-to_nxt < 3)
2638 return codecvt_base::partial;
2639 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2640 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2641 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2642 }
2643 }
2644 return codecvt_base::ok;
2645}
2646
2647static
2648codecvt_base::result
2649utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2650 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2651 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2652{
2653 frm_nxt = frm;
2654 to_nxt = to;
2655 if (mode & consume_header)
2656 {
2657 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2658 frm_nxt[2] == 0xBF)
2659 frm_nxt += 3;
2660 }
2661 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2662 {
2663 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2664 if (c1 < 0x80)
2665 {
2666 if (c1 > Maxcode)
2667 return codecvt_base::error;
2668 *to_nxt = static_cast<uint16_t>(c1);
2669 ++frm_nxt;
2670 }
2671 else if (c1 < 0xC2)
2672 {
2673 return codecvt_base::error;
2674 }
2675 else if (c1 < 0xE0)
2676 {
2677 if (frm_end-frm_nxt < 2)
2678 return codecvt_base::partial;
2679 uint8_t c2 = frm_nxt[1];
2680 if ((c2 & 0xC0) != 0x80)
2681 return codecvt_base::error;
2682 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2683 | (c2 & 0x3F));
2684 if (t > Maxcode)
2685 return codecvt_base::error;
2686 *to_nxt = t;
2687 frm_nxt += 2;
2688 }
2689 else if (c1 < 0xF0)
2690 {
2691 if (frm_end-frm_nxt < 3)
2692 return codecvt_base::partial;
2693 uint8_t c2 = frm_nxt[1];
2694 uint8_t c3 = frm_nxt[2];
2695 switch (c1)
2696 {
2697 case 0xE0:
2698 if ((c2 & 0xE0) != 0xA0)
2699 return codecvt_base::error;
2700 break;
2701 case 0xED:
2702 if ((c2 & 0xE0) != 0x80)
2703 return codecvt_base::error;
2704 break;
2705 default:
2706 if ((c2 & 0xC0) != 0x80)
2707 return codecvt_base::error;
2708 break;
2709 }
2710 if ((c3 & 0xC0) != 0x80)
2711 return codecvt_base::error;
2712 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2713 | ((c2 & 0x3F) << 6)
2714 | (c3 & 0x3F));
2715 if (t > Maxcode)
2716 return codecvt_base::error;
2717 *to_nxt = t;
2718 frm_nxt += 3;
2719 }
2720 else
2721 {
2722 return codecvt_base::error;
2723 }
2724 }
2725 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2726}
2727
2728static
2729int
2730utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2731 size_t mx, unsigned long Maxcode = 0x10FFFF,
2732 codecvt_mode mode = codecvt_mode(0))
2733{
2734 const uint8_t* frm_nxt = frm;
2735 if (mode & consume_header)
2736 {
2737 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2738 frm_nxt[2] == 0xBF)
2739 frm_nxt += 3;
2740 }
2741 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2742 {
2743 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2744 if (c1 < 0x80)
2745 {
2746 if (c1 > Maxcode)
2747 break;
2748 ++frm_nxt;
2749 }
2750 else if (c1 < 0xC2)
2751 {
2752 break;
2753 }
2754 else if (c1 < 0xE0)
2755 {
2756 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2757 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002758 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002759 break;
2760 frm_nxt += 2;
2761 }
2762 else if (c1 < 0xF0)
2763 {
2764 if (frm_end-frm_nxt < 3)
2765 break;
2766 uint8_t c2 = frm_nxt[1];
2767 uint8_t c3 = frm_nxt[2];
2768 switch (c1)
2769 {
2770 case 0xE0:
2771 if ((c2 & 0xE0) != 0xA0)
2772 return static_cast<int>(frm_nxt - frm);
2773 break;
2774 case 0xED:
2775 if ((c2 & 0xE0) != 0x80)
2776 return static_cast<int>(frm_nxt - frm);
2777 break;
2778 default:
2779 if ((c2 & 0xC0) != 0x80)
2780 return static_cast<int>(frm_nxt - frm);
2781 break;
2782 }
2783 if ((c3 & 0xC0) != 0x80)
2784 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002785 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002786 break;
2787 frm_nxt += 3;
2788 }
2789 else
2790 {
2791 break;
2792 }
2793 }
2794 return static_cast<int>(frm_nxt - frm);
2795}
2796
2797static
2798codecvt_base::result
2799ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2800 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2801 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2802{
2803 frm_nxt = frm;
2804 to_nxt = to;
2805 if (mode & generate_header)
2806 {
2807 if (to_end-to_nxt < 2)
2808 return codecvt_base::partial;
2809 *to_nxt++ = static_cast<uint8_t>(0xFE);
2810 *to_nxt++ = static_cast<uint8_t>(0xFF);
2811 }
2812 for (; frm_nxt < frm_end; ++frm_nxt)
2813 {
2814 uint32_t wc = *frm_nxt;
2815 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2816 return codecvt_base::error;
2817 if (wc < 0x010000)
2818 {
2819 if (to_end-to_nxt < 2)
2820 return codecvt_base::partial;
2821 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2822 *to_nxt++ = static_cast<uint8_t>(wc);
2823 }
2824 else
2825 {
2826 if (to_end-to_nxt < 4)
2827 return codecvt_base::partial;
2828 uint16_t t = static_cast<uint16_t>(
2829 0xD800
2830 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2831 | ((wc & 0x00FC00) >> 10));
2832 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2833 *to_nxt++ = static_cast<uint8_t>(t);
2834 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2835 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2836 *to_nxt++ = static_cast<uint8_t>(t);
2837 }
2838 }
2839 return codecvt_base::ok;
2840}
2841
2842static
2843codecvt_base::result
2844utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2845 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2846 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2847{
2848 frm_nxt = frm;
2849 to_nxt = to;
2850 if (mode & consume_header)
2851 {
2852 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2853 frm_nxt += 2;
2854 }
2855 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2856 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002857 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002858 if ((c1 & 0xFC00) == 0xDC00)
2859 return codecvt_base::error;
2860 if ((c1 & 0xFC00) != 0xD800)
2861 {
2862 if (c1 > Maxcode)
2863 return codecvt_base::error;
2864 *to_nxt = static_cast<uint32_t>(c1);
2865 frm_nxt += 2;
2866 }
2867 else
2868 {
2869 if (frm_end-frm_nxt < 4)
2870 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002871 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002872 if ((c2 & 0xFC00) != 0xDC00)
2873 return codecvt_base::error;
2874 uint32_t t = static_cast<uint32_t>(
2875 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2876 | ((c1 & 0x003F) << 10)
2877 | (c2 & 0x03FF));
2878 if (t > Maxcode)
2879 return codecvt_base::error;
2880 *to_nxt = t;
2881 frm_nxt += 4;
2882 }
2883 }
2884 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2885}
2886
2887static
2888int
2889utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2890 size_t mx, unsigned long Maxcode = 0x10FFFF,
2891 codecvt_mode mode = codecvt_mode(0))
2892{
2893 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002894 if (mode & consume_header)
2895 {
2896 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2897 frm_nxt += 2;
2898 }
2899 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2900 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002901 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002902 if ((c1 & 0xFC00) == 0xDC00)
2903 break;
2904 if ((c1 & 0xFC00) != 0xD800)
2905 {
2906 if (c1 > Maxcode)
2907 break;
2908 frm_nxt += 2;
2909 }
2910 else
2911 {
2912 if (frm_end-frm_nxt < 4)
2913 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002914 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002915 if ((c2 & 0xFC00) != 0xDC00)
2916 break;
2917 uint32_t t = static_cast<uint32_t>(
2918 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2919 | ((c1 & 0x003F) << 10)
2920 | (c2 & 0x03FF));
2921 if (t > Maxcode)
2922 break;
2923 frm_nxt += 4;
2924 }
2925 }
2926 return static_cast<int>(frm_nxt - frm);
2927}
2928
2929static
2930codecvt_base::result
2931ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2932 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2933 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2934{
2935 frm_nxt = frm;
2936 to_nxt = to;
2937 if (mode & generate_header)
2938 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002939 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002940 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002941 *to_nxt++ = static_cast<uint8_t>(0xFF);
2942 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002943 }
2944 for (; frm_nxt < frm_end; ++frm_nxt)
2945 {
2946 uint32_t wc = *frm_nxt;
2947 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2948 return codecvt_base::error;
2949 if (wc < 0x010000)
2950 {
2951 if (to_end-to_nxt < 2)
2952 return codecvt_base::partial;
2953 *to_nxt++ = static_cast<uint8_t>(wc);
2954 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2955 }
2956 else
2957 {
2958 if (to_end-to_nxt < 4)
2959 return codecvt_base::partial;
2960 uint16_t t = static_cast<uint16_t>(
2961 0xD800
2962 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2963 | ((wc & 0x00FC00) >> 10));
2964 *to_nxt++ = static_cast<uint8_t>(t);
2965 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2966 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2967 *to_nxt++ = static_cast<uint8_t>(t);
2968 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2969 }
2970 }
2971 return codecvt_base::ok;
2972}
2973
2974static
2975codecvt_base::result
2976utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2977 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2978 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2979{
2980 frm_nxt = frm;
2981 to_nxt = to;
2982 if (mode & consume_header)
2983 {
2984 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2985 frm_nxt += 2;
2986 }
2987 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2988 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002989 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002990 if ((c1 & 0xFC00) == 0xDC00)
2991 return codecvt_base::error;
2992 if ((c1 & 0xFC00) != 0xD800)
2993 {
2994 if (c1 > Maxcode)
2995 return codecvt_base::error;
2996 *to_nxt = static_cast<uint32_t>(c1);
2997 frm_nxt += 2;
2998 }
2999 else
3000 {
3001 if (frm_end-frm_nxt < 4)
3002 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00003003 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003004 if ((c2 & 0xFC00) != 0xDC00)
3005 return codecvt_base::error;
3006 uint32_t t = static_cast<uint32_t>(
3007 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3008 | ((c1 & 0x003F) << 10)
3009 | (c2 & 0x03FF));
3010 if (t > Maxcode)
3011 return codecvt_base::error;
3012 *to_nxt = t;
3013 frm_nxt += 4;
3014 }
3015 }
3016 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3017}
3018
3019static
3020int
3021utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
3022 size_t mx, unsigned long Maxcode = 0x10FFFF,
3023 codecvt_mode mode = codecvt_mode(0))
3024{
3025 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003026 if (mode & consume_header)
3027 {
3028 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3029 frm_nxt += 2;
3030 }
3031 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3032 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003033 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003034 if ((c1 & 0xFC00) == 0xDC00)
3035 break;
3036 if ((c1 & 0xFC00) != 0xD800)
3037 {
3038 if (c1 > Maxcode)
3039 break;
3040 frm_nxt += 2;
3041 }
3042 else
3043 {
3044 if (frm_end-frm_nxt < 4)
3045 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00003046 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003047 if ((c2 & 0xFC00) != 0xDC00)
3048 break;
3049 uint32_t t = static_cast<uint32_t>(
3050 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3051 | ((c1 & 0x003F) << 10)
3052 | (c2 & 0x03FF));
3053 if (t > Maxcode)
3054 break;
3055 frm_nxt += 4;
3056 }
3057 }
3058 return static_cast<int>(frm_nxt - frm);
3059}
3060
3061static
3062codecvt_base::result
3063ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3064 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3065 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3066{
3067 frm_nxt = frm;
3068 to_nxt = to;
3069 if (mode & generate_header)
3070 {
3071 if (to_end-to_nxt < 2)
3072 return codecvt_base::partial;
3073 *to_nxt++ = static_cast<uint8_t>(0xFE);
3074 *to_nxt++ = static_cast<uint8_t>(0xFF);
3075 }
3076 for (; frm_nxt < frm_end; ++frm_nxt)
3077 {
3078 uint16_t wc = *frm_nxt;
3079 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3080 return codecvt_base::error;
3081 if (to_end-to_nxt < 2)
3082 return codecvt_base::partial;
3083 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3084 *to_nxt++ = static_cast<uint8_t>(wc);
3085 }
3086 return codecvt_base::ok;
3087}
3088
3089static
3090codecvt_base::result
3091utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3092 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3093 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3094{
3095 frm_nxt = frm;
3096 to_nxt = to;
3097 if (mode & consume_header)
3098 {
3099 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3100 frm_nxt += 2;
3101 }
3102 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3103 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003104 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003105 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3106 return codecvt_base::error;
3107 *to_nxt = c1;
3108 frm_nxt += 2;
3109 }
3110 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3111}
3112
3113static
3114int
3115utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3116 size_t mx, unsigned long Maxcode = 0x10FFFF,
3117 codecvt_mode mode = codecvt_mode(0))
3118{
3119 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003120 if (mode & consume_header)
3121 {
3122 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3123 frm_nxt += 2;
3124 }
3125 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3126 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003127 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003128 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3129 break;
3130 frm_nxt += 2;
3131 }
3132 return static_cast<int>(frm_nxt - frm);
3133}
3134
3135static
3136codecvt_base::result
3137ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3138 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3139 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3140{
3141 frm_nxt = frm;
3142 to_nxt = to;
3143 if (mode & generate_header)
3144 {
3145 if (to_end-to_nxt < 2)
3146 return codecvt_base::partial;
3147 *to_nxt++ = static_cast<uint8_t>(0xFF);
3148 *to_nxt++ = static_cast<uint8_t>(0xFE);
3149 }
3150 for (; frm_nxt < frm_end; ++frm_nxt)
3151 {
3152 uint16_t wc = *frm_nxt;
3153 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3154 return codecvt_base::error;
3155 if (to_end-to_nxt < 2)
3156 return codecvt_base::partial;
3157 *to_nxt++ = static_cast<uint8_t>(wc);
3158 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3159 }
3160 return codecvt_base::ok;
3161}
3162
3163static
3164codecvt_base::result
3165utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3166 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3167 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3168{
3169 frm_nxt = frm;
3170 to_nxt = to;
3171 if (mode & consume_header)
3172 {
3173 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3174 frm_nxt += 2;
3175 }
3176 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3177 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003178 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003179 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3180 return codecvt_base::error;
3181 *to_nxt = c1;
3182 frm_nxt += 2;
3183 }
3184 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3185}
3186
3187static
3188int
3189utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3190 size_t mx, unsigned long Maxcode = 0x10FFFF,
3191 codecvt_mode mode = codecvt_mode(0))
3192{
3193 const uint8_t* frm_nxt = frm;
3194 frm_nxt = frm;
3195 if (mode & consume_header)
3196 {
3197 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3198 frm_nxt += 2;
3199 }
3200 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3201 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003202 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003203 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3204 break;
3205 frm_nxt += 2;
3206 }
3207 return static_cast<int>(frm_nxt - frm);
3208}
3209
Howard Hinnantc51e1022010-05-11 19:42:16 +00003210// template <> class codecvt<char16_t, char, mbstate_t>
3211
Howard Hinnantffb308e2010-08-22 00:03:27 +00003212locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003213
3214codecvt<char16_t, char, mbstate_t>::~codecvt()
3215{
3216}
3217
3218codecvt<char16_t, char, mbstate_t>::result
3219codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003220 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003221 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3222{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003223 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3224 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3225 const uint16_t* _frm_nxt = _frm;
3226 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3227 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3228 uint8_t* _to_nxt = _to;
3229 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3230 frm_nxt = frm + (_frm_nxt - _frm);
3231 to_nxt = to + (_to_nxt - _to);
3232 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003233}
3234
3235codecvt<char16_t, char, mbstate_t>::result
3236codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003237 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003238 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3239{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003240 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3241 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3242 const uint8_t* _frm_nxt = _frm;
3243 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3244 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3245 uint16_t* _to_nxt = _to;
3246 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3247 frm_nxt = frm + (_frm_nxt - _frm);
3248 to_nxt = to + (_to_nxt - _to);
3249 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003250}
3251
3252codecvt<char16_t, char, mbstate_t>::result
3253codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3254 extern_type* to, extern_type*, extern_type*& to_nxt) const
3255{
3256 to_nxt = to;
3257 return noconv;
3258}
3259
3260int
Louis Dionne65358e12021-03-01 12:09:45 -05003261codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003262{
3263 return 0;
3264}
3265
3266bool
Louis Dionne65358e12021-03-01 12:09:45 -05003267codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003268{
3269 return false;
3270}
3271
3272int
3273codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3274 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3275{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003276 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3277 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3278 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003279}
3280
3281int
Louis Dionne65358e12021-03-01 12:09:45 -05003282codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003283{
3284 return 4;
3285}
3286
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003287#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003288
3289// template <> class codecvt<char16_t, char8_t, mbstate_t>
3290
3291locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3292
3293codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3294{
3295}
3296
3297codecvt<char16_t, char8_t, mbstate_t>::result
3298codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3299 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3300 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3301{
3302 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3303 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3304 const uint16_t* _frm_nxt = _frm;
3305 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3306 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3307 uint8_t* _to_nxt = _to;
3308 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3309 frm_nxt = frm + (_frm_nxt - _frm);
3310 to_nxt = to + (_to_nxt - _to);
3311 return r;
3312}
3313
3314codecvt<char16_t, char8_t, mbstate_t>::result
3315codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3316 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3317 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3318{
3319 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3320 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3321 const uint8_t* _frm_nxt = _frm;
3322 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3323 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3324 uint16_t* _to_nxt = _to;
3325 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3326 frm_nxt = frm + (_frm_nxt - _frm);
3327 to_nxt = to + (_to_nxt - _to);
3328 return r;
3329}
3330
3331codecvt<char16_t, char8_t, mbstate_t>::result
3332codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3333 extern_type* to, extern_type*, extern_type*& to_nxt) const
3334{
3335 to_nxt = to;
3336 return noconv;
3337}
3338
3339int
Louis Dionne65358e12021-03-01 12:09:45 -05003340codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003341{
3342 return 0;
3343}
3344
3345bool
Louis Dionne65358e12021-03-01 12:09:45 -05003346codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003347{
3348 return false;
3349}
3350
3351int
3352codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3353 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3354{
3355 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3356 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3357 return utf8_to_utf16_length(_frm, _frm_end, mx);
3358}
3359
3360int
Louis Dionne65358e12021-03-01 12:09:45 -05003361codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003362{
3363 return 4;
3364}
3365
3366#endif
3367
Howard Hinnantc51e1022010-05-11 19:42:16 +00003368// template <> class codecvt<char32_t, char, mbstate_t>
3369
Howard Hinnantffb308e2010-08-22 00:03:27 +00003370locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003371
3372codecvt<char32_t, char, mbstate_t>::~codecvt()
3373{
3374}
3375
3376codecvt<char32_t, char, mbstate_t>::result
3377codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003378 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003379 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3380{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003381 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3382 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3383 const uint32_t* _frm_nxt = _frm;
3384 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3385 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3386 uint8_t* _to_nxt = _to;
3387 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3388 frm_nxt = frm + (_frm_nxt - _frm);
3389 to_nxt = to + (_to_nxt - _to);
3390 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003391}
3392
3393codecvt<char32_t, char, mbstate_t>::result
3394codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003395 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003396 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3397{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003398 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3399 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3400 const uint8_t* _frm_nxt = _frm;
3401 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3402 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3403 uint32_t* _to_nxt = _to;
3404 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3405 frm_nxt = frm + (_frm_nxt - _frm);
3406 to_nxt = to + (_to_nxt - _to);
3407 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003408}
3409
3410codecvt<char32_t, char, mbstate_t>::result
3411codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3412 extern_type* to, extern_type*, extern_type*& to_nxt) const
3413{
3414 to_nxt = to;
3415 return noconv;
3416}
3417
3418int
Louis Dionne65358e12021-03-01 12:09:45 -05003419codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003420{
3421 return 0;
3422}
3423
3424bool
Louis Dionne65358e12021-03-01 12:09:45 -05003425codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003426{
3427 return false;
3428}
3429
3430int
3431codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3432 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3433{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003434 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3435 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3436 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003437}
3438
3439int
Louis Dionne65358e12021-03-01 12:09:45 -05003440codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003441{
3442 return 4;
3443}
3444
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003445#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003446
3447// template <> class codecvt<char32_t, char8_t, mbstate_t>
3448
3449locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3450
3451codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3452{
3453}
3454
3455codecvt<char32_t, char8_t, mbstate_t>::result
3456codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3457 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3458 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3459{
3460 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3461 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3462 const uint32_t* _frm_nxt = _frm;
3463 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3464 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3465 uint8_t* _to_nxt = _to;
3466 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3467 frm_nxt = frm + (_frm_nxt - _frm);
3468 to_nxt = to + (_to_nxt - _to);
3469 return r;
3470}
3471
3472codecvt<char32_t, char8_t, mbstate_t>::result
3473codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3474 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3475 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3476{
3477 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3478 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3479 const uint8_t* _frm_nxt = _frm;
3480 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3481 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3482 uint32_t* _to_nxt = _to;
3483 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3484 frm_nxt = frm + (_frm_nxt - _frm);
3485 to_nxt = to + (_to_nxt - _to);
3486 return r;
3487}
3488
3489codecvt<char32_t, char8_t, mbstate_t>::result
3490codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3491 extern_type* to, extern_type*, extern_type*& to_nxt) const
3492{
3493 to_nxt = to;
3494 return noconv;
3495}
3496
3497int
Louis Dionne65358e12021-03-01 12:09:45 -05003498codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003499{
3500 return 0;
3501}
3502
3503bool
Louis Dionne65358e12021-03-01 12:09:45 -05003504codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003505{
3506 return false;
3507}
3508
3509int
3510codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3511 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3512{
3513 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3514 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3515 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3516}
3517
3518int
Louis Dionne65358e12021-03-01 12:09:45 -05003519codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003520{
3521 return 4;
3522}
3523
3524#endif
3525
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003526// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003527
Louis Dionne89258142021-08-23 15:32:36 -04003528#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003529__codecvt_utf8<wchar_t>::result
3530__codecvt_utf8<wchar_t>::do_out(state_type&,
3531 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003532 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3533{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003534#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003535 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3536 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3537 const uint16_t* _frm_nxt = _frm;
3538#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003539 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3540 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3541 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003542#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003543 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3544 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3545 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003546#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003547 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3548 _Maxcode_, _Mode_);
3549#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003550 result r = ucs4_to_utf8(_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_in(state_type&,
3560 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003561 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3562{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003563 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3564 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3565 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003566#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003567 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3568 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3569 uint16_t* _to_nxt = _to;
3570 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3571 _Maxcode_, _Mode_);
3572#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003573 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3574 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3575 uint32_t* _to_nxt = _to;
3576 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3577 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003578#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003579 frm_nxt = frm + (_frm_nxt - _frm);
3580 to_nxt = to + (_to_nxt - _to);
3581 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003582}
3583
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003584__codecvt_utf8<wchar_t>::result
3585__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003586 extern_type* to, extern_type*, extern_type*& to_nxt) const
3587{
3588 to_nxt = to;
3589 return noconv;
3590}
3591
3592int
Louis Dionne65358e12021-03-01 12:09:45 -05003593__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003594{
3595 return 0;
3596}
3597
3598bool
Louis Dionne65358e12021-03-01 12:09:45 -05003599__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003600{
3601 return false;
3602}
3603
3604int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003605__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003606 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3607{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003608 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3609 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003610#if defined(_LIBCPP_SHORT_WCHAR)
3611 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3612#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003613 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003614#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003615}
3616
3617int
Louis Dionne65358e12021-03-01 12:09:45 -05003618__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003619{
Xing Xue50b0eb42021-09-09 16:20:36 -04003620#if defined(_LIBCPP_SHORT_WCHAR)
3621 if (_Mode_ & consume_header)
3622 return 6;
3623 return 3;
3624#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003625 if (_Mode_ & consume_header)
3626 return 7;
3627 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003628#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003629}
Louis Dionne89258142021-08-23 15:32:36 -04003630#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003631
3632// __codecvt_utf8<char16_t>
3633
3634__codecvt_utf8<char16_t>::result
3635__codecvt_utf8<char16_t>::do_out(state_type&,
3636 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3637 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3638{
3639 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3640 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3641 const uint16_t* _frm_nxt = _frm;
3642 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3643 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3644 uint8_t* _to_nxt = _to;
3645 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3646 _Maxcode_, _Mode_);
3647 frm_nxt = frm + (_frm_nxt - _frm);
3648 to_nxt = to + (_to_nxt - _to);
3649 return r;
3650}
3651
3652__codecvt_utf8<char16_t>::result
3653__codecvt_utf8<char16_t>::do_in(state_type&,
3654 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3655 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3656{
3657 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3658 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3659 const uint8_t* _frm_nxt = _frm;
3660 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3661 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3662 uint16_t* _to_nxt = _to;
3663 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3664 _Maxcode_, _Mode_);
3665 frm_nxt = frm + (_frm_nxt - _frm);
3666 to_nxt = to + (_to_nxt - _to);
3667 return r;
3668}
3669
3670__codecvt_utf8<char16_t>::result
3671__codecvt_utf8<char16_t>::do_unshift(state_type&,
3672 extern_type* to, extern_type*, extern_type*& to_nxt) const
3673{
3674 to_nxt = to;
3675 return noconv;
3676}
3677
3678int
Louis Dionne65358e12021-03-01 12:09:45 -05003679__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003680{
3681 return 0;
3682}
3683
3684bool
Louis Dionne65358e12021-03-01 12:09:45 -05003685__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003686{
3687 return false;
3688}
3689
3690int
3691__codecvt_utf8<char16_t>::do_length(state_type&,
3692 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3693{
3694 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3695 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3696 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3697}
3698
3699int
Louis Dionne65358e12021-03-01 12:09:45 -05003700__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003701{
3702 if (_Mode_ & consume_header)
3703 return 6;
3704 return 3;
3705}
3706
3707// __codecvt_utf8<char32_t>
3708
3709__codecvt_utf8<char32_t>::result
3710__codecvt_utf8<char32_t>::do_out(state_type&,
3711 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3712 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3713{
3714 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3715 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3716 const uint32_t* _frm_nxt = _frm;
3717 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3718 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3719 uint8_t* _to_nxt = _to;
3720 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3721 _Maxcode_, _Mode_);
3722 frm_nxt = frm + (_frm_nxt - _frm);
3723 to_nxt = to + (_to_nxt - _to);
3724 return r;
3725}
3726
3727__codecvt_utf8<char32_t>::result
3728__codecvt_utf8<char32_t>::do_in(state_type&,
3729 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3730 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3731{
3732 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3733 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3734 const uint8_t* _frm_nxt = _frm;
3735 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3736 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3737 uint32_t* _to_nxt = _to;
3738 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3739 _Maxcode_, _Mode_);
3740 frm_nxt = frm + (_frm_nxt - _frm);
3741 to_nxt = to + (_to_nxt - _to);
3742 return r;
3743}
3744
3745__codecvt_utf8<char32_t>::result
3746__codecvt_utf8<char32_t>::do_unshift(state_type&,
3747 extern_type* to, extern_type*, extern_type*& to_nxt) const
3748{
3749 to_nxt = to;
3750 return noconv;
3751}
3752
3753int
Louis Dionne65358e12021-03-01 12:09:45 -05003754__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003755{
3756 return 0;
3757}
3758
3759bool
Louis Dionne65358e12021-03-01 12:09:45 -05003760__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003761{
3762 return false;
3763}
3764
3765int
3766__codecvt_utf8<char32_t>::do_length(state_type&,
3767 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3768{
3769 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3770 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3771 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3772}
3773
3774int
Louis Dionne65358e12021-03-01 12:09:45 -05003775__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003776{
3777 if (_Mode_ & consume_header)
3778 return 7;
3779 return 4;
3780}
3781
3782// __codecvt_utf16<wchar_t, false>
3783
Louis Dionne89258142021-08-23 15:32:36 -04003784#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003785__codecvt_utf16<wchar_t, false>::result
3786__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3787 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3788 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3789{
Xing Xue50b0eb42021-09-09 16:20:36 -04003790#if defined(_LIBCPP_SHORT_WCHAR)
3791 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3792 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3793 const uint16_t* _frm_nxt = _frm;
3794#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003795 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3796 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3797 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003798#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003799 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3800 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3801 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003802#if defined(_LIBCPP_SHORT_WCHAR)
3803 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3804 _Maxcode_, _Mode_);
3805#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003806 result r = ucs4_to_utf16be(_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_in(state_type&,
3816 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3817 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3818{
3819 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3820 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3821 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003822#if defined(_LIBCPP_SHORT_WCHAR)
3823 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3824 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3825 uint16_t* _to_nxt = _to;
3826 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3827 _Maxcode_, _Mode_);
3828#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003829 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3830 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3831 uint32_t* _to_nxt = _to;
3832 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3833 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003834#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003835 frm_nxt = frm + (_frm_nxt - _frm);
3836 to_nxt = to + (_to_nxt - _to);
3837 return r;
3838}
3839
3840__codecvt_utf16<wchar_t, false>::result
3841__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3842 extern_type* to, extern_type*, extern_type*& to_nxt) const
3843{
3844 to_nxt = to;
3845 return noconv;
3846}
3847
3848int
Louis Dionne65358e12021-03-01 12:09:45 -05003849__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003850{
3851 return 0;
3852}
3853
3854bool
Louis Dionne65358e12021-03-01 12:09:45 -05003855__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003856{
3857 return false;
3858}
3859
3860int
3861__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3862 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3863{
3864 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3865 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003866#if defined(_LIBCPP_SHORT_WCHAR)
3867 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3868#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003869 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003870#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003871}
3872
3873int
Louis Dionne65358e12021-03-01 12:09:45 -05003874__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003875{
Xing Xue50b0eb42021-09-09 16:20:36 -04003876#if defined(_LIBCPP_SHORT_WCHAR)
3877 if (_Mode_ & consume_header)
3878 return 4;
3879 return 2;
3880#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003881 if (_Mode_ & consume_header)
3882 return 6;
3883 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003884#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003885}
3886
3887// __codecvt_utf16<wchar_t, true>
3888
3889__codecvt_utf16<wchar_t, true>::result
3890__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3891 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3892 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3893{
Xing Xue50b0eb42021-09-09 16:20:36 -04003894#if defined(_LIBCPP_SHORT_WCHAR)
3895 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3896 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3897 const uint16_t* _frm_nxt = _frm;
3898#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003899 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3900 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3901 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003902#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003903 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3904 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3905 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003906#if defined(_LIBCPP_SHORT_WCHAR)
3907 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3908 _Maxcode_, _Mode_);
3909#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003910 result r = ucs4_to_utf16le(_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_in(state_type&,
3920 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3921 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3922{
3923 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3924 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3925 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003926#if defined(_LIBCPP_SHORT_WCHAR)
3927 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3928 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3929 uint16_t* _to_nxt = _to;
3930 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3931 _Maxcode_, _Mode_);
3932#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003933 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3934 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3935 uint32_t* _to_nxt = _to;
3936 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3937 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003938#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003939 frm_nxt = frm + (_frm_nxt - _frm);
3940 to_nxt = to + (_to_nxt - _to);
3941 return r;
3942}
3943
3944__codecvt_utf16<wchar_t, true>::result
3945__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3946 extern_type* to, extern_type*, extern_type*& to_nxt) const
3947{
3948 to_nxt = to;
3949 return noconv;
3950}
3951
3952int
Louis Dionne65358e12021-03-01 12:09:45 -05003953__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003954{
3955 return 0;
3956}
3957
3958bool
Louis Dionne65358e12021-03-01 12:09:45 -05003959__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003960{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003961 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003962}
3963
3964int
3965__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3966 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3967{
3968 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3969 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003970#if defined(_LIBCPP_SHORT_WCHAR)
3971 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3972#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003973 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003974#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003975}
3976
3977int
Louis Dionne65358e12021-03-01 12:09:45 -05003978__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003979{
Xing Xue50b0eb42021-09-09 16:20:36 -04003980#if defined(_LIBCPP_SHORT_WCHAR)
3981 if (_Mode_ & consume_header)
3982 return 4;
3983 return 2;
3984#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003985 if (_Mode_ & consume_header)
3986 return 6;
3987 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003988#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003989}
Louis Dionne89258142021-08-23 15:32:36 -04003990#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003991
3992// __codecvt_utf16<char16_t, false>
3993
3994__codecvt_utf16<char16_t, false>::result
3995__codecvt_utf16<char16_t, false>::do_out(state_type&,
3996 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3997 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3998{
3999 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4000 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4001 const uint16_t* _frm_nxt = _frm;
4002 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4003 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4004 uint8_t* _to_nxt = _to;
4005 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4006 _Maxcode_, _Mode_);
4007 frm_nxt = frm + (_frm_nxt - _frm);
4008 to_nxt = to + (_to_nxt - _to);
4009 return r;
4010}
4011
4012__codecvt_utf16<char16_t, false>::result
4013__codecvt_utf16<char16_t, false>::do_in(state_type&,
4014 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4015 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4016{
4017 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4018 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4019 const uint8_t* _frm_nxt = _frm;
4020 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4021 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4022 uint16_t* _to_nxt = _to;
4023 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4024 _Maxcode_, _Mode_);
4025 frm_nxt = frm + (_frm_nxt - _frm);
4026 to_nxt = to + (_to_nxt - _to);
4027 return r;
4028}
4029
4030__codecvt_utf16<char16_t, false>::result
4031__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4032 extern_type* to, extern_type*, extern_type*& to_nxt) const
4033{
4034 to_nxt = to;
4035 return noconv;
4036}
4037
4038int
Louis Dionne65358e12021-03-01 12:09:45 -05004039__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004040{
4041 return 0;
4042}
4043
4044bool
Louis Dionne65358e12021-03-01 12:09:45 -05004045__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004046{
4047 return false;
4048}
4049
4050int
4051__codecvt_utf16<char16_t, false>::do_length(state_type&,
4052 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4053{
4054 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4055 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4056 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4057}
4058
4059int
Louis Dionne65358e12021-03-01 12:09:45 -05004060__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004061{
4062 if (_Mode_ & consume_header)
4063 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004064 return 2;
4065}
4066
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004067// __codecvt_utf16<char16_t, true>
4068
4069__codecvt_utf16<char16_t, true>::result
4070__codecvt_utf16<char16_t, true>::do_out(state_type&,
4071 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4072 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4073{
4074 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4075 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4076 const uint16_t* _frm_nxt = _frm;
4077 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4078 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4079 uint8_t* _to_nxt = _to;
4080 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4081 _Maxcode_, _Mode_);
4082 frm_nxt = frm + (_frm_nxt - _frm);
4083 to_nxt = to + (_to_nxt - _to);
4084 return r;
4085}
4086
4087__codecvt_utf16<char16_t, true>::result
4088__codecvt_utf16<char16_t, true>::do_in(state_type&,
4089 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4090 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4091{
4092 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4093 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4094 const uint8_t* _frm_nxt = _frm;
4095 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4096 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4097 uint16_t* _to_nxt = _to;
4098 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4099 _Maxcode_, _Mode_);
4100 frm_nxt = frm + (_frm_nxt - _frm);
4101 to_nxt = to + (_to_nxt - _to);
4102 return r;
4103}
4104
4105__codecvt_utf16<char16_t, true>::result
4106__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4107 extern_type* to, extern_type*, extern_type*& to_nxt) const
4108{
4109 to_nxt = to;
4110 return noconv;
4111}
4112
4113int
Louis Dionne65358e12021-03-01 12:09:45 -05004114__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004115{
4116 return 0;
4117}
4118
4119bool
Louis Dionne65358e12021-03-01 12:09:45 -05004120__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004121{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004122 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004123}
4124
4125int
4126__codecvt_utf16<char16_t, true>::do_length(state_type&,
4127 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4128{
4129 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4130 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4131 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4132}
4133
4134int
Louis Dionne65358e12021-03-01 12:09:45 -05004135__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004136{
4137 if (_Mode_ & consume_header)
4138 return 4;
4139 return 2;
4140}
4141
4142// __codecvt_utf16<char32_t, false>
4143
4144__codecvt_utf16<char32_t, false>::result
4145__codecvt_utf16<char32_t, false>::do_out(state_type&,
4146 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4147 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4148{
4149 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4150 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4151 const uint32_t* _frm_nxt = _frm;
4152 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4153 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4154 uint8_t* _to_nxt = _to;
4155 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4156 _Maxcode_, _Mode_);
4157 frm_nxt = frm + (_frm_nxt - _frm);
4158 to_nxt = to + (_to_nxt - _to);
4159 return r;
4160}
4161
4162__codecvt_utf16<char32_t, false>::result
4163__codecvt_utf16<char32_t, false>::do_in(state_type&,
4164 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4165 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4166{
4167 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4168 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4169 const uint8_t* _frm_nxt = _frm;
4170 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4171 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4172 uint32_t* _to_nxt = _to;
4173 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4174 _Maxcode_, _Mode_);
4175 frm_nxt = frm + (_frm_nxt - _frm);
4176 to_nxt = to + (_to_nxt - _to);
4177 return r;
4178}
4179
4180__codecvt_utf16<char32_t, false>::result
4181__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4182 extern_type* to, extern_type*, extern_type*& to_nxt) const
4183{
4184 to_nxt = to;
4185 return noconv;
4186}
4187
4188int
Louis Dionne65358e12021-03-01 12:09:45 -05004189__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004190{
4191 return 0;
4192}
4193
4194bool
Louis Dionne65358e12021-03-01 12:09:45 -05004195__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004196{
4197 return false;
4198}
4199
4200int
4201__codecvt_utf16<char32_t, false>::do_length(state_type&,
4202 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4203{
4204 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4205 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4206 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4207}
4208
4209int
Louis Dionne65358e12021-03-01 12:09:45 -05004210__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004211{
4212 if (_Mode_ & consume_header)
4213 return 6;
4214 return 4;
4215}
4216
4217// __codecvt_utf16<char32_t, true>
4218
4219__codecvt_utf16<char32_t, true>::result
4220__codecvt_utf16<char32_t, true>::do_out(state_type&,
4221 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4222 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4223{
4224 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4225 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4226 const uint32_t* _frm_nxt = _frm;
4227 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4228 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4229 uint8_t* _to_nxt = _to;
4230 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4231 _Maxcode_, _Mode_);
4232 frm_nxt = frm + (_frm_nxt - _frm);
4233 to_nxt = to + (_to_nxt - _to);
4234 return r;
4235}
4236
4237__codecvt_utf16<char32_t, true>::result
4238__codecvt_utf16<char32_t, true>::do_in(state_type&,
4239 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4240 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4241{
4242 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4243 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4244 const uint8_t* _frm_nxt = _frm;
4245 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4246 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4247 uint32_t* _to_nxt = _to;
4248 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4249 _Maxcode_, _Mode_);
4250 frm_nxt = frm + (_frm_nxt - _frm);
4251 to_nxt = to + (_to_nxt - _to);
4252 return r;
4253}
4254
4255__codecvt_utf16<char32_t, true>::result
4256__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4257 extern_type* to, extern_type*, extern_type*& to_nxt) const
4258{
4259 to_nxt = to;
4260 return noconv;
4261}
4262
4263int
Louis Dionne65358e12021-03-01 12:09:45 -05004264__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004265{
4266 return 0;
4267}
4268
4269bool
Louis Dionne65358e12021-03-01 12:09:45 -05004270__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004271{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004272 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004273}
4274
4275int
4276__codecvt_utf16<char32_t, true>::do_length(state_type&,
4277 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4278{
4279 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4280 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4281 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4282}
4283
4284int
Louis Dionne65358e12021-03-01 12:09:45 -05004285__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004286{
4287 if (_Mode_ & consume_header)
4288 return 6;
4289 return 4;
4290}
4291
4292// __codecvt_utf8_utf16<wchar_t>
4293
Louis Dionne89258142021-08-23 15:32:36 -04004294#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004295__codecvt_utf8_utf16<wchar_t>::result
4296__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4297 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4298 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4299{
Xing Xue50b0eb42021-09-09 16:20:36 -04004300#if defined(_LIBCPP_SHORT_WCHAR)
4301 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4302 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4303 const uint16_t* _frm_nxt = _frm;
4304#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004305 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4306 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4307 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004308#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004309 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4310 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4311 uint8_t* _to_nxt = _to;
4312 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4313 _Maxcode_, _Mode_);
4314 frm_nxt = frm + (_frm_nxt - _frm);
4315 to_nxt = to + (_to_nxt - _to);
4316 return r;
4317}
4318
4319__codecvt_utf8_utf16<wchar_t>::result
4320__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4321 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4322 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4323{
4324 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4325 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4326 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004327#if defined(_LIBCPP_SHORT_WCHAR)
4328 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4329 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4330 uint16_t* _to_nxt = _to;
4331#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004332 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4333 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4334 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004335#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004336 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4337 _Maxcode_, _Mode_);
4338 frm_nxt = frm + (_frm_nxt - _frm);
4339 to_nxt = to + (_to_nxt - _to);
4340 return r;
4341}
4342
4343__codecvt_utf8_utf16<wchar_t>::result
4344__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4345 extern_type* to, extern_type*, extern_type*& to_nxt) const
4346{
4347 to_nxt = to;
4348 return noconv;
4349}
4350
4351int
Louis Dionne65358e12021-03-01 12:09:45 -05004352__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004353{
4354 return 0;
4355}
4356
4357bool
Louis Dionne65358e12021-03-01 12:09:45 -05004358__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004359{
4360 return false;
4361}
4362
4363int
4364__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4365 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4366{
4367 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4368 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4369 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4370}
4371
4372int
Louis Dionne65358e12021-03-01 12:09:45 -05004373__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004374{
4375 if (_Mode_ & consume_header)
4376 return 7;
4377 return 4;
4378}
Louis Dionne89258142021-08-23 15:32:36 -04004379#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004380
4381// __codecvt_utf8_utf16<char16_t>
4382
4383__codecvt_utf8_utf16<char16_t>::result
4384__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4385 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4386 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4387{
4388 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4389 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4390 const uint16_t* _frm_nxt = _frm;
4391 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4392 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4393 uint8_t* _to_nxt = _to;
4394 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4395 _Maxcode_, _Mode_);
4396 frm_nxt = frm + (_frm_nxt - _frm);
4397 to_nxt = to + (_to_nxt - _to);
4398 return r;
4399}
4400
4401__codecvt_utf8_utf16<char16_t>::result
4402__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4403 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4404 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4405{
4406 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4407 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4408 const uint8_t* _frm_nxt = _frm;
4409 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4410 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4411 uint16_t* _to_nxt = _to;
4412 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4413 _Maxcode_, _Mode_);
4414 frm_nxt = frm + (_frm_nxt - _frm);
4415 to_nxt = to + (_to_nxt - _to);
4416 return r;
4417}
4418
4419__codecvt_utf8_utf16<char16_t>::result
4420__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4421 extern_type* to, extern_type*, extern_type*& to_nxt) const
4422{
4423 to_nxt = to;
4424 return noconv;
4425}
4426
4427int
Louis Dionne65358e12021-03-01 12:09:45 -05004428__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004429{
4430 return 0;
4431}
4432
4433bool
Louis Dionne65358e12021-03-01 12:09:45 -05004434__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004435{
4436 return false;
4437}
4438
4439int
4440__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4441 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4442{
4443 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4444 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4445 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4446}
4447
4448int
Louis Dionne65358e12021-03-01 12:09:45 -05004449__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004450{
4451 if (_Mode_ & consume_header)
4452 return 7;
4453 return 4;
4454}
4455
4456// __codecvt_utf8_utf16<char32_t>
4457
4458__codecvt_utf8_utf16<char32_t>::result
4459__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4460 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4461 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4462{
4463 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4464 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4465 const uint32_t* _frm_nxt = _frm;
4466 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4467 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4468 uint8_t* _to_nxt = _to;
4469 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4470 _Maxcode_, _Mode_);
4471 frm_nxt = frm + (_frm_nxt - _frm);
4472 to_nxt = to + (_to_nxt - _to);
4473 return r;
4474}
4475
4476__codecvt_utf8_utf16<char32_t>::result
4477__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4478 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4479 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4480{
4481 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4482 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4483 const uint8_t* _frm_nxt = _frm;
4484 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4485 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4486 uint32_t* _to_nxt = _to;
4487 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4488 _Maxcode_, _Mode_);
4489 frm_nxt = frm + (_frm_nxt - _frm);
4490 to_nxt = to + (_to_nxt - _to);
4491 return r;
4492}
4493
4494__codecvt_utf8_utf16<char32_t>::result
4495__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4496 extern_type* to, extern_type*, extern_type*& to_nxt) const
4497{
4498 to_nxt = to;
4499 return noconv;
4500}
4501
4502int
Louis Dionne65358e12021-03-01 12:09:45 -05004503__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004504{
4505 return 0;
4506}
4507
4508bool
Louis Dionne65358e12021-03-01 12:09:45 -05004509__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004510{
4511 return false;
4512}
4513
4514int
4515__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4516 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4517{
4518 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4519 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4520 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4521}
4522
4523int
Louis Dionne65358e12021-03-01 12:09:45 -05004524__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004525{
4526 if (_Mode_ & consume_header)
4527 return 7;
4528 return 4;
4529}
4530
Howard Hinnantc51e1022010-05-11 19:42:16 +00004531// __narrow_to_utf8<16>
4532
4533__narrow_to_utf8<16>::~__narrow_to_utf8()
4534{
4535}
4536
4537// __narrow_to_utf8<32>
4538
4539__narrow_to_utf8<32>::~__narrow_to_utf8()
4540{
4541}
4542
4543// __widen_from_utf8<16>
4544
4545__widen_from_utf8<16>::~__widen_from_utf8()
4546{
4547}
4548
4549// __widen_from_utf8<32>
4550
4551__widen_from_utf8<32>::~__widen_from_utf8()
4552{
4553}
4554
Louis Dionne89258142021-08-23 15:32:36 -04004555#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004556static bool checked_string_to_wchar_convert(wchar_t& dest,
4557 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004558 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004559 if (*ptr == '\0')
4560 return false;
4561 mbstate_t mb = {};
4562 wchar_t out;
4563 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4564 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4565 return false;
4566 }
4567 dest = out;
4568 return true;
4569}
Louis Dionne89258142021-08-23 15:32:36 -04004570#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004571
Mark de Weverffed1402021-11-03 19:25:20 +01004572#ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4573static bool is_narrow_non_breaking_space(const char* ptr) {
4574 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4575 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4576}
4577
4578static bool is_non_breaking_space(const char* ptr) {
4579 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4580 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4581}
4582#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4583
Eric Fiselierbf945a22016-12-11 00:20:59 +00004584static bool checked_string_to_char_convert(char& dest,
4585 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004586 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004587 if (*ptr == '\0')
4588 return false;
4589 if (!ptr[1]) {
4590 dest = *ptr;
4591 return true;
4592 }
Louis Dionne89258142021-08-23 15:32:36 -04004593
4594#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004595 // First convert the MBS into a wide char then attempt to narrow it using
4596 // wctob_l.
4597 wchar_t wout;
4598 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4599 return false;
4600 int res;
4601 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4602 dest = res;
4603 return true;
4604 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004605 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004606 // translate into a different single byte.
4607 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004608 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004609 case L'\u00A0': // non-breaking space
4610 dest = ' ';
4611 return true;
4612 default:
4613 return false;
4614 }
Louis Dionne89258142021-08-23 15:32:36 -04004615#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverffed1402021-11-03 19:25:20 +01004616 // FIXME: Work around specific multibyte sequences that we can reasonably
4617 // translate into a different single byte.
4618 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4619 dest = ' ';
4620 return true;
4621 }
4622
Louis Dionne89258142021-08-23 15:32:36 -04004623 return false;
4624#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Nikolas Klausercfe21472022-02-14 18:26:02 +01004625 __libcpp_unreachable();
Eric Fiselierbf945a22016-12-11 00:20:59 +00004626}
4627
4628
Howard Hinnantc51e1022010-05-11 19:42:16 +00004629// numpunct<char> && numpunct<wchar_t>
4630
4631locale::id numpunct< char >::id;
Louis Dionne89258142021-08-23 15:32:36 -04004632#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004633locale::id numpunct<wchar_t>::id;
Louis Dionne89258142021-08-23 15:32:36 -04004634#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004635
4636numpunct<char>::numpunct(size_t refs)
4637 : locale::facet(refs),
4638 __decimal_point_('.'),
4639 __thousands_sep_(',')
4640{
4641}
4642
Louis Dionne89258142021-08-23 15:32:36 -04004643#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004644numpunct<wchar_t>::numpunct(size_t refs)
4645 : locale::facet(refs),
4646 __decimal_point_(L'.'),
4647 __thousands_sep_(L',')
4648{
4649}
Louis Dionne89258142021-08-23 15:32:36 -04004650#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004651
4652numpunct<char>::~numpunct()
4653{
4654}
4655
Louis Dionne89258142021-08-23 15:32:36 -04004656#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004657numpunct<wchar_t>::~numpunct()
4658{
4659}
Louis Dionne89258142021-08-23 15:32:36 -04004660#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004661
4662 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004663#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004664wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004665#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004666
4667 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004668#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004669wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004670#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004671
4672string numpunct< char >::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004673#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004674string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004675#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004676
4677 string numpunct< char >::do_truename() const {return "true";}
Louis Dionne89258142021-08-23 15:32:36 -04004678#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004679wstring numpunct<wchar_t>::do_truename() const {return L"true";}
Louis Dionne89258142021-08-23 15:32:36 -04004680#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004681
4682 string numpunct< char >::do_falsename() const {return "false";}
Louis Dionne89258142021-08-23 15:32:36 -04004683#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004684wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
Louis Dionne89258142021-08-23 15:32:36 -04004685#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004686
4687// numpunct_byname<char>
4688
4689numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4690 : numpunct<char>(refs)
4691{
4692 __init(nm);
4693}
4694
4695numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4696 : numpunct<char>(refs)
4697{
4698 __init(nm.c_str());
4699}
4700
4701numpunct_byname<char>::~numpunct_byname()
4702{
4703}
4704
4705void
4706numpunct_byname<char>::__init(const char* nm)
4707{
Louis Dionne89258142021-08-23 15:32:36 -04004708 typedef numpunct<char> base;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004709 if (strcmp(nm, "C") != 0)
4710 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004711 __libcpp_unique_locale loc(nm);
4712 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004713 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004714 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004715
Ben Craig3756b922016-03-09 15:39:39 +00004716 lconv* lc = __libcpp_localeconv_l(loc.get());
Louis Dionne89258142021-08-23 15:32:36 -04004717 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4718 loc.get()))
4719 __decimal_point_ = base::do_decimal_point();
4720 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4721 loc.get()))
4722 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00004723 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004724 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004725 }
4726}
4727
4728// numpunct_byname<wchar_t>
4729
Louis Dionne89258142021-08-23 15:32:36 -04004730#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004731numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4732 : numpunct<wchar_t>(refs)
4733{
4734 __init(nm);
4735}
4736
4737numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4738 : numpunct<wchar_t>(refs)
4739{
4740 __init(nm.c_str());
4741}
4742
4743numpunct_byname<wchar_t>::~numpunct_byname()
4744{
4745}
4746
4747void
4748numpunct_byname<wchar_t>::__init(const char* nm)
4749{
4750 if (strcmp(nm, "C") != 0)
4751 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004752 __libcpp_unique_locale loc(nm);
4753 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004754 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004755 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004756
Ben Craig3756b922016-03-09 15:39:39 +00004757 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004758 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4759 loc.get());
4760 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4761 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004762 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004763 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004764 }
4765}
Louis Dionne89258142021-08-23 15:32:36 -04004766#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004767
4768// num_get helpers
4769
4770int
4771__num_get_base::__get_base(ios_base& iob)
4772{
4773 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4774 if (__basefield == ios_base::oct)
4775 return 8;
4776 else if (__basefield == ios_base::hex)
4777 return 16;
4778 else if (__basefield == 0)
4779 return 0;
4780 return 10;
4781}
4782
4783const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4784
4785void
4786__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4787 ios_base::iostate& __err)
4788{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004789// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4790// 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 +00004791 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004792 {
4793 reverse(__g, __g_end);
4794 const char* __ig = __grouping.data();
4795 const char* __eg = __ig + __grouping.size();
4796 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4797 {
4798 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4799 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004800 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004801 {
4802 __err = ios_base::failbit;
4803 return;
4804 }
4805 }
4806 if (__eg - __ig > 1)
4807 ++__ig;
4808 }
4809 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4810 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004811 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004812 __err = ios_base::failbit;
4813 }
4814 }
4815}
4816
4817void
4818__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4819 ios_base::fmtflags __flags)
4820{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004821 if ((__flags & ios_base::showpos) &&
4822 (__flags & ios_base::basefield) != ios_base::oct &&
4823 (__flags & ios_base::basefield) != ios_base::hex &&
4824 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004825 *__fmtp++ = '+';
4826 if (__flags & ios_base::showbase)
4827 *__fmtp++ = '#';
4828 while(*__len)
4829 *__fmtp++ = *__len++;
4830 if ((__flags & ios_base::basefield) == ios_base::oct)
4831 *__fmtp = 'o';
4832 else if ((__flags & ios_base::basefield) == ios_base::hex)
4833 {
4834 if (__flags & ios_base::uppercase)
4835 *__fmtp = 'X';
4836 else
4837 *__fmtp = 'x';
4838 }
4839 else if (__signd)
4840 *__fmtp = 'd';
4841 else
4842 *__fmtp = 'u';
4843}
4844
4845bool
4846__num_put_base::__format_float(char* __fmtp, const char* __len,
4847 ios_base::fmtflags __flags)
4848{
4849 bool specify_precision = true;
4850 if (__flags & ios_base::showpos)
4851 *__fmtp++ = '+';
4852 if (__flags & ios_base::showpoint)
4853 *__fmtp++ = '#';
4854 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004855 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004856 if (floatfield == (ios_base::fixed | ios_base::scientific))
4857 specify_precision = false;
4858 else
4859 {
4860 *__fmtp++ = '.';
4861 *__fmtp++ = '*';
4862 }
4863 while(*__len)
4864 *__fmtp++ = *__len++;
4865 if (floatfield == ios_base::fixed)
4866 {
4867 if (uppercase)
4868 *__fmtp = 'F';
4869 else
4870 *__fmtp = 'f';
4871 }
4872 else if (floatfield == ios_base::scientific)
4873 {
4874 if (uppercase)
4875 *__fmtp = 'E';
4876 else
4877 *__fmtp = 'e';
4878 }
4879 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4880 {
4881 if (uppercase)
4882 *__fmtp = 'A';
4883 else
4884 *__fmtp = 'a';
4885 }
4886 else
4887 {
4888 if (uppercase)
4889 *__fmtp = 'G';
4890 else
4891 *__fmtp = 'g';
4892 }
4893 return specify_precision;
4894}
4895
4896char*
4897__num_put_base::__identify_padding(char* __nb, char* __ne,
4898 const ios_base& __iob)
4899{
4900 switch (__iob.flags() & ios_base::adjustfield)
4901 {
4902 case ios_base::internal:
4903 if (__nb[0] == '-' || __nb[0] == '+')
4904 return __nb+1;
4905 if (__ne - __nb >= 2 && __nb[0] == '0'
4906 && (__nb[1] == 'x' || __nb[1] == 'X'))
4907 return __nb+2;
4908 break;
4909 case ios_base::left:
4910 return __ne;
4911 case ios_base::right:
4912 default:
4913 break;
4914 }
4915 return __nb;
4916}
4917
4918// time_get
4919
4920static
4921string*
4922init_weeks()
4923{
4924 static string weeks[14];
4925 weeks[0] = "Sunday";
4926 weeks[1] = "Monday";
4927 weeks[2] = "Tuesday";
4928 weeks[3] = "Wednesday";
4929 weeks[4] = "Thursday";
4930 weeks[5] = "Friday";
4931 weeks[6] = "Saturday";
4932 weeks[7] = "Sun";
4933 weeks[8] = "Mon";
4934 weeks[9] = "Tue";
4935 weeks[10] = "Wed";
4936 weeks[11] = "Thu";
4937 weeks[12] = "Fri";
4938 weeks[13] = "Sat";
4939 return weeks;
4940}
4941
Louis Dionne89258142021-08-23 15:32:36 -04004942#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004943static
4944wstring*
4945init_wweeks()
4946{
4947 static wstring weeks[14];
4948 weeks[0] = L"Sunday";
4949 weeks[1] = L"Monday";
4950 weeks[2] = L"Tuesday";
4951 weeks[3] = L"Wednesday";
4952 weeks[4] = L"Thursday";
4953 weeks[5] = L"Friday";
4954 weeks[6] = L"Saturday";
4955 weeks[7] = L"Sun";
4956 weeks[8] = L"Mon";
4957 weeks[9] = L"Tue";
4958 weeks[10] = L"Wed";
4959 weeks[11] = L"Thu";
4960 weeks[12] = L"Fri";
4961 weeks[13] = L"Sat";
4962 return weeks;
4963}
Louis Dionne89258142021-08-23 15:32:36 -04004964#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004965
4966template <>
4967const string*
4968__time_get_c_storage<char>::__weeks() const
4969{
4970 static const string* weeks = init_weeks();
4971 return weeks;
4972}
4973
Louis Dionne89258142021-08-23 15:32:36 -04004974#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004975template <>
4976const wstring*
4977__time_get_c_storage<wchar_t>::__weeks() const
4978{
4979 static const wstring* weeks = init_wweeks();
4980 return weeks;
4981}
Louis Dionne89258142021-08-23 15:32:36 -04004982#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004983
4984static
4985string*
4986init_months()
4987{
4988 static string months[24];
4989 months[0] = "January";
4990 months[1] = "February";
4991 months[2] = "March";
4992 months[3] = "April";
4993 months[4] = "May";
4994 months[5] = "June";
4995 months[6] = "July";
4996 months[7] = "August";
4997 months[8] = "September";
4998 months[9] = "October";
4999 months[10] = "November";
5000 months[11] = "December";
5001 months[12] = "Jan";
5002 months[13] = "Feb";
5003 months[14] = "Mar";
5004 months[15] = "Apr";
5005 months[16] = "May";
5006 months[17] = "Jun";
5007 months[18] = "Jul";
5008 months[19] = "Aug";
5009 months[20] = "Sep";
5010 months[21] = "Oct";
5011 months[22] = "Nov";
5012 months[23] = "Dec";
5013 return months;
5014}
5015
Louis Dionne89258142021-08-23 15:32:36 -04005016#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005017static
5018wstring*
5019init_wmonths()
5020{
5021 static wstring months[24];
5022 months[0] = L"January";
5023 months[1] = L"February";
5024 months[2] = L"March";
5025 months[3] = L"April";
5026 months[4] = L"May";
5027 months[5] = L"June";
5028 months[6] = L"July";
5029 months[7] = L"August";
5030 months[8] = L"September";
5031 months[9] = L"October";
5032 months[10] = L"November";
5033 months[11] = L"December";
5034 months[12] = L"Jan";
5035 months[13] = L"Feb";
5036 months[14] = L"Mar";
5037 months[15] = L"Apr";
5038 months[16] = L"May";
5039 months[17] = L"Jun";
5040 months[18] = L"Jul";
5041 months[19] = L"Aug";
5042 months[20] = L"Sep";
5043 months[21] = L"Oct";
5044 months[22] = L"Nov";
5045 months[23] = L"Dec";
5046 return months;
5047}
Louis Dionne89258142021-08-23 15:32:36 -04005048#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005049
5050template <>
5051const string*
5052__time_get_c_storage<char>::__months() const
5053{
5054 static const string* months = init_months();
5055 return months;
5056}
5057
Louis Dionne89258142021-08-23 15:32:36 -04005058#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005059template <>
5060const wstring*
5061__time_get_c_storage<wchar_t>::__months() const
5062{
5063 static const wstring* months = init_wmonths();
5064 return months;
5065}
Louis Dionne89258142021-08-23 15:32:36 -04005066#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005067
5068static
5069string*
5070init_am_pm()
5071{
Marshall Clow5cc04922018-01-11 17:16:52 +00005072 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005073 am_pm[0] = "AM";
5074 am_pm[1] = "PM";
5075 return am_pm;
5076}
5077
Louis Dionne89258142021-08-23 15:32:36 -04005078#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005079static
5080wstring*
5081init_wam_pm()
5082{
Marshall Clow5cc04922018-01-11 17:16:52 +00005083 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005084 am_pm[0] = L"AM";
5085 am_pm[1] = L"PM";
5086 return am_pm;
5087}
Louis Dionne89258142021-08-23 15:32:36 -04005088#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005089
5090template <>
5091const string*
5092__time_get_c_storage<char>::__am_pm() const
5093{
5094 static const string* am_pm = init_am_pm();
5095 return am_pm;
5096}
5097
Louis Dionne89258142021-08-23 15:32:36 -04005098#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005099template <>
5100const wstring*
5101__time_get_c_storage<wchar_t>::__am_pm() const
5102{
5103 static const wstring* am_pm = init_wam_pm();
5104 return am_pm;
5105}
Louis Dionne89258142021-08-23 15:32:36 -04005106#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005107
5108template <>
5109const string&
5110__time_get_c_storage<char>::__x() const
5111{
5112 static string s("%m/%d/%y");
5113 return s;
5114}
5115
Louis Dionne89258142021-08-23 15:32:36 -04005116#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005117template <>
5118const wstring&
5119__time_get_c_storage<wchar_t>::__x() const
5120{
5121 static wstring s(L"%m/%d/%y");
5122 return s;
5123}
Louis Dionne89258142021-08-23 15:32:36 -04005124#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005125
5126template <>
5127const string&
5128__time_get_c_storage<char>::__X() const
5129{
5130 static string s("%H:%M:%S");
5131 return s;
5132}
5133
Louis Dionne89258142021-08-23 15:32:36 -04005134#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005135template <>
5136const wstring&
5137__time_get_c_storage<wchar_t>::__X() const
5138{
5139 static wstring s(L"%H:%M:%S");
5140 return s;
5141}
Louis Dionne89258142021-08-23 15:32:36 -04005142#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005143
5144template <>
5145const string&
5146__time_get_c_storage<char>::__c() const
5147{
5148 static string s("%a %b %d %H:%M:%S %Y");
5149 return s;
5150}
5151
Louis Dionne89258142021-08-23 15:32:36 -04005152#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005153template <>
5154const wstring&
5155__time_get_c_storage<wchar_t>::__c() const
5156{
5157 static wstring s(L"%a %b %d %H:%M:%S %Y");
5158 return s;
5159}
Louis Dionne89258142021-08-23 15:32:36 -04005160#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005161
5162template <>
5163const string&
5164__time_get_c_storage<char>::__r() const
5165{
5166 static string s("%I:%M:%S %p");
5167 return s;
5168}
5169
Louis Dionne89258142021-08-23 15:32:36 -04005170#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005171template <>
5172const wstring&
5173__time_get_c_storage<wchar_t>::__r() const
5174{
5175 static wstring s(L"%I:%M:%S %p");
5176 return s;
5177}
Louis Dionne89258142021-08-23 15:32:36 -04005178#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005179
5180// time_get_byname
5181
5182__time_get::__time_get(const char* nm)
5183 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5184{
5185 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005186 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005187 " failed to construct for " + string(nm));
5188}
5189
5190__time_get::__time_get(const string& nm)
5191 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5192{
5193 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005194 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005195 " failed to construct for " + nm);
5196}
5197
5198__time_get::~__time_get()
5199{
5200 freelocale(__loc_);
5201}
Nikolas Klauser41c59762022-02-14 18:52:28 +01005202
5203_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005204
Howard Hinnantc51e1022010-05-11 19:42:16 +00005205template <>
5206string
5207__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5208{
Howard Hinnant990207c2012-02-19 14:55:32 +00005209 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005210 t.tm_sec = 59;
5211 t.tm_min = 55;
5212 t.tm_hour = 23;
5213 t.tm_mday = 31;
5214 t.tm_mon = 11;
5215 t.tm_year = 161;
5216 t.tm_wday = 6;
5217 t.tm_yday = 364;
5218 t.tm_isdst = -1;
5219 char buf[100];
5220 char f[3] = {0};
5221 f[0] = '%';
5222 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005223 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005224 char* bb = buf;
5225 char* be = buf + n;
5226 string result;
5227 while (bb != be)
5228 {
5229 if (ct.is(ctype_base::space, *bb))
5230 {
5231 result.push_back(' ');
5232 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5233 ;
5234 continue;
5235 }
5236 char* w = bb;
5237 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005238 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005239 ct, err, false)
5240 - this->__weeks_;
5241 if (i < 14)
5242 {
5243 result.push_back('%');
5244 if (i < 7)
5245 result.push_back('A');
5246 else
5247 result.push_back('a');
5248 bb = w;
5249 continue;
5250 }
5251 w = bb;
5252 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5253 ct, err, false)
5254 - this->__months_;
5255 if (i < 24)
5256 {
5257 result.push_back('%');
5258 if (i < 12)
5259 result.push_back('B');
5260 else
5261 result.push_back('b');
5262 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5263 result.back() = 'm';
5264 bb = w;
5265 continue;
5266 }
5267 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5268 {
5269 w = bb;
5270 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5271 ct, err, false) - this->__am_pm_;
5272 if (i < 2)
5273 {
5274 result.push_back('%');
5275 result.push_back('p');
5276 bb = w;
5277 continue;
5278 }
5279 }
5280 w = bb;
5281 if (ct.is(ctype_base::digit, *bb))
5282 {
5283 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5284 {
5285 case 6:
5286 result.push_back('%');
5287 result.push_back('w');
5288 break;
5289 case 7:
5290 result.push_back('%');
5291 result.push_back('u');
5292 break;
5293 case 11:
5294 result.push_back('%');
5295 result.push_back('I');
5296 break;
5297 case 12:
5298 result.push_back('%');
5299 result.push_back('m');
5300 break;
5301 case 23:
5302 result.push_back('%');
5303 result.push_back('H');
5304 break;
5305 case 31:
5306 result.push_back('%');
5307 result.push_back('d');
5308 break;
5309 case 55:
5310 result.push_back('%');
5311 result.push_back('M');
5312 break;
5313 case 59:
5314 result.push_back('%');
5315 result.push_back('S');
5316 break;
5317 case 61:
5318 result.push_back('%');
5319 result.push_back('y');
5320 break;
5321 case 364:
5322 result.push_back('%');
5323 result.push_back('j');
5324 break;
5325 case 2061:
5326 result.push_back('%');
5327 result.push_back('Y');
5328 break;
5329 default:
5330 for (; w != bb; ++w)
5331 result.push_back(*w);
5332 break;
5333 }
5334 continue;
5335 }
5336 if (*bb == '%')
5337 {
5338 result.push_back('%');
5339 result.push_back('%');
5340 ++bb;
5341 continue;
5342 }
5343 result.push_back(*bb);
5344 ++bb;
5345 }
5346 return result;
5347}
5348
Nikolas Klauser41c59762022-02-14 18:52:28 +01005349_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces")
Howard Hinnant28b24882011-12-01 20:21:04 +00005350
Louis Dionne89258142021-08-23 15:32:36 -04005351#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005352template <>
5353wstring
5354__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5355{
Howard Hinnant990207c2012-02-19 14:55:32 +00005356 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005357 t.tm_sec = 59;
5358 t.tm_min = 55;
5359 t.tm_hour = 23;
5360 t.tm_mday = 31;
5361 t.tm_mon = 11;
5362 t.tm_year = 161;
5363 t.tm_wday = 6;
5364 t.tm_yday = 364;
5365 t.tm_isdst = -1;
5366 char buf[100];
5367 char f[3] = {0};
5368 f[0] = '%';
5369 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005370 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005371 wchar_t wbuf[100];
5372 wchar_t* wbb = wbuf;
5373 mbstate_t mb = {0};
5374 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005375 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005376 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005377 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005378 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005379 wstring result;
5380 while (wbb != wbe)
5381 {
5382 if (ct.is(ctype_base::space, *wbb))
5383 {
5384 result.push_back(L' ');
5385 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5386 ;
5387 continue;
5388 }
5389 wchar_t* w = wbb;
5390 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005391 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005392 ct, err, false)
5393 - this->__weeks_;
5394 if (i < 14)
5395 {
5396 result.push_back(L'%');
5397 if (i < 7)
5398 result.push_back(L'A');
5399 else
5400 result.push_back(L'a');
5401 wbb = w;
5402 continue;
5403 }
5404 w = wbb;
5405 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5406 ct, err, false)
5407 - this->__months_;
5408 if (i < 24)
5409 {
5410 result.push_back(L'%');
5411 if (i < 12)
5412 result.push_back(L'B');
5413 else
5414 result.push_back(L'b');
5415 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5416 result.back() = L'm';
5417 wbb = w;
5418 continue;
5419 }
5420 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5421 {
5422 w = wbb;
5423 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5424 ct, err, false) - this->__am_pm_;
5425 if (i < 2)
5426 {
5427 result.push_back(L'%');
5428 result.push_back(L'p');
5429 wbb = w;
5430 continue;
5431 }
5432 }
5433 w = wbb;
5434 if (ct.is(ctype_base::digit, *wbb))
5435 {
5436 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5437 {
5438 case 6:
5439 result.push_back(L'%');
5440 result.push_back(L'w');
5441 break;
5442 case 7:
5443 result.push_back(L'%');
5444 result.push_back(L'u');
5445 break;
5446 case 11:
5447 result.push_back(L'%');
5448 result.push_back(L'I');
5449 break;
5450 case 12:
5451 result.push_back(L'%');
5452 result.push_back(L'm');
5453 break;
5454 case 23:
5455 result.push_back(L'%');
5456 result.push_back(L'H');
5457 break;
5458 case 31:
5459 result.push_back(L'%');
5460 result.push_back(L'd');
5461 break;
5462 case 55:
5463 result.push_back(L'%');
5464 result.push_back(L'M');
5465 break;
5466 case 59:
5467 result.push_back(L'%');
5468 result.push_back(L'S');
5469 break;
5470 case 61:
5471 result.push_back(L'%');
5472 result.push_back(L'y');
5473 break;
5474 case 364:
5475 result.push_back(L'%');
5476 result.push_back(L'j');
5477 break;
5478 case 2061:
5479 result.push_back(L'%');
5480 result.push_back(L'Y');
5481 break;
5482 default:
5483 for (; w != wbb; ++w)
5484 result.push_back(*w);
5485 break;
5486 }
5487 continue;
5488 }
5489 if (ct.narrow(*wbb, 0) == '%')
5490 {
5491 result.push_back(L'%');
5492 result.push_back(L'%');
5493 ++wbb;
5494 continue;
5495 }
5496 result.push_back(*wbb);
5497 ++wbb;
5498 }
5499 return result;
5500}
Louis Dionne89258142021-08-23 15:32:36 -04005501#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005502
5503template <>
5504void
5505__time_get_storage<char>::init(const ctype<char>& ct)
5506{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005507 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005508 char buf[100];
5509 // __weeks_
5510 for (int i = 0; i < 7; ++i)
5511 {
5512 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005513 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005514 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005515 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005516 __weeks_[i+7] = buf;
5517 }
5518 // __months_
5519 for (int i = 0; i < 12; ++i)
5520 {
5521 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005522 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005523 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005524 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005525 __months_[i+12] = buf;
5526 }
5527 // __am_pm_
5528 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005529 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005530 __am_pm_[0] = buf;
5531 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005532 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005533 __am_pm_[1] = buf;
5534 __c_ = __analyze('c', ct);
5535 __r_ = __analyze('r', ct);
5536 __x_ = __analyze('x', ct);
5537 __X_ = __analyze('X', ct);
5538}
5539
Louis Dionne89258142021-08-23 15:32:36 -04005540#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005541template <>
5542void
5543__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5544{
5545 tm t = {0};
5546 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005547 wchar_t wbuf[100];
5548 wchar_t* wbe;
5549 mbstate_t mb = {0};
5550 // __weeks_
5551 for (int i = 0; i < 7; ++i)
5552 {
5553 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005554 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005555 mb = mbstate_t();
5556 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005557 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005558 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005559 __throw_runtime_error("locale not supported");
5560 wbe = wbuf + j;
5561 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005562 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005563 mb = mbstate_t();
5564 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005565 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005566 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005567 __throw_runtime_error("locale not supported");
5568 wbe = wbuf + j;
5569 __weeks_[i+7].assign(wbuf, wbe);
5570 }
5571 // __months_
5572 for (int i = 0; i < 12; ++i)
5573 {
5574 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005575 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005576 mb = mbstate_t();
5577 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005578 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005579 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005580 __throw_runtime_error("locale not supported");
5581 wbe = wbuf + j;
5582 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005583 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005584 mb = mbstate_t();
5585 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005586 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005587 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005588 __throw_runtime_error("locale not supported");
5589 wbe = wbuf + j;
5590 __months_[i+12].assign(wbuf, wbe);
5591 }
5592 // __am_pm_
5593 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005594 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005595 mb = mbstate_t();
5596 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005597 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005598 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599 __throw_runtime_error("locale not supported");
5600 wbe = wbuf + j;
5601 __am_pm_[0].assign(wbuf, wbe);
5602 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005603 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005604 mb = mbstate_t();
5605 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005606 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005607 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005608 __throw_runtime_error("locale not supported");
5609 wbe = wbuf + j;
5610 __am_pm_[1].assign(wbuf, wbe);
5611 __c_ = __analyze('c', ct);
5612 __r_ = __analyze('r', ct);
5613 __x_ = __analyze('x', ct);
5614 __X_ = __analyze('X', ct);
5615}
Louis Dionne89258142021-08-23 15:32:36 -04005616#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005617
5618template <class CharT>
5619struct _LIBCPP_HIDDEN __time_get_temp
5620 : public ctype_byname<CharT>
5621{
5622 explicit __time_get_temp(const char* nm)
5623 : ctype_byname<CharT>(nm, 1) {}
5624 explicit __time_get_temp(const string& nm)
5625 : ctype_byname<CharT>(nm, 1) {}
5626};
5627
5628template <>
5629__time_get_storage<char>::__time_get_storage(const char* __nm)
5630 : __time_get(__nm)
5631{
5632 const __time_get_temp<char> ct(__nm);
5633 init(ct);
5634}
5635
5636template <>
5637__time_get_storage<char>::__time_get_storage(const string& __nm)
5638 : __time_get(__nm)
5639{
5640 const __time_get_temp<char> ct(__nm);
5641 init(ct);
5642}
5643
Louis Dionne89258142021-08-23 15:32:36 -04005644#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005645template <>
5646__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5647 : __time_get(__nm)
5648{
5649 const __time_get_temp<wchar_t> ct(__nm);
5650 init(ct);
5651}
5652
5653template <>
5654__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5655 : __time_get(__nm)
5656{
5657 const __time_get_temp<wchar_t> ct(__nm);
5658 init(ct);
5659}
Louis Dionne89258142021-08-23 15:32:36 -04005660#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005661
5662template <>
5663time_base::dateorder
5664__time_get_storage<char>::__do_date_order() const
5665{
5666 unsigned i;
5667 for (i = 0; i < __x_.size(); ++i)
5668 if (__x_[i] == '%')
5669 break;
5670 ++i;
5671 switch (__x_[i])
5672 {
5673 case 'y':
5674 case 'Y':
5675 for (++i; i < __x_.size(); ++i)
5676 if (__x_[i] == '%')
5677 break;
5678 if (i == __x_.size())
5679 break;
5680 ++i;
5681 switch (__x_[i])
5682 {
5683 case 'm':
5684 for (++i; i < __x_.size(); ++i)
5685 if (__x_[i] == '%')
5686 break;
5687 if (i == __x_.size())
5688 break;
5689 ++i;
5690 if (__x_[i] == 'd')
5691 return time_base::ymd;
5692 break;
5693 case 'd':
5694 for (++i; i < __x_.size(); ++i)
5695 if (__x_[i] == '%')
5696 break;
5697 if (i == __x_.size())
5698 break;
5699 ++i;
5700 if (__x_[i] == 'm')
5701 return time_base::ydm;
5702 break;
5703 }
5704 break;
5705 case 'm':
5706 for (++i; i < __x_.size(); ++i)
5707 if (__x_[i] == '%')
5708 break;
5709 if (i == __x_.size())
5710 break;
5711 ++i;
5712 if (__x_[i] == 'd')
5713 {
5714 for (++i; i < __x_.size(); ++i)
5715 if (__x_[i] == '%')
5716 break;
5717 if (i == __x_.size())
5718 break;
5719 ++i;
5720 if (__x_[i] == 'y' || __x_[i] == 'Y')
5721 return time_base::mdy;
5722 break;
5723 }
5724 break;
5725 case 'd':
5726 for (++i; i < __x_.size(); ++i)
5727 if (__x_[i] == '%')
5728 break;
5729 if (i == __x_.size())
5730 break;
5731 ++i;
5732 if (__x_[i] == 'm')
5733 {
5734 for (++i; i < __x_.size(); ++i)
5735 if (__x_[i] == '%')
5736 break;
5737 if (i == __x_.size())
5738 break;
5739 ++i;
5740 if (__x_[i] == 'y' || __x_[i] == 'Y')
5741 return time_base::dmy;
5742 break;
5743 }
5744 break;
5745 }
5746 return time_base::no_order;
5747}
5748
Louis Dionne89258142021-08-23 15:32:36 -04005749#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005750template <>
5751time_base::dateorder
5752__time_get_storage<wchar_t>::__do_date_order() const
5753{
5754 unsigned i;
5755 for (i = 0; i < __x_.size(); ++i)
5756 if (__x_[i] == L'%')
5757 break;
5758 ++i;
5759 switch (__x_[i])
5760 {
5761 case L'y':
5762 case L'Y':
5763 for (++i; i < __x_.size(); ++i)
5764 if (__x_[i] == L'%')
5765 break;
5766 if (i == __x_.size())
5767 break;
5768 ++i;
5769 switch (__x_[i])
5770 {
5771 case L'm':
5772 for (++i; i < __x_.size(); ++i)
5773 if (__x_[i] == L'%')
5774 break;
5775 if (i == __x_.size())
5776 break;
5777 ++i;
5778 if (__x_[i] == L'd')
5779 return time_base::ymd;
5780 break;
5781 case L'd':
5782 for (++i; i < __x_.size(); ++i)
5783 if (__x_[i] == L'%')
5784 break;
5785 if (i == __x_.size())
5786 break;
5787 ++i;
5788 if (__x_[i] == L'm')
5789 return time_base::ydm;
5790 break;
5791 }
5792 break;
5793 case L'm':
5794 for (++i; i < __x_.size(); ++i)
5795 if (__x_[i] == L'%')
5796 break;
5797 if (i == __x_.size())
5798 break;
5799 ++i;
5800 if (__x_[i] == L'd')
5801 {
5802 for (++i; i < __x_.size(); ++i)
5803 if (__x_[i] == L'%')
5804 break;
5805 if (i == __x_.size())
5806 break;
5807 ++i;
5808 if (__x_[i] == L'y' || __x_[i] == L'Y')
5809 return time_base::mdy;
5810 break;
5811 }
5812 break;
5813 case L'd':
5814 for (++i; i < __x_.size(); ++i)
5815 if (__x_[i] == L'%')
5816 break;
5817 if (i == __x_.size())
5818 break;
5819 ++i;
5820 if (__x_[i] == L'm')
5821 {
5822 for (++i; i < __x_.size(); ++i)
5823 if (__x_[i] == L'%')
5824 break;
5825 if (i == __x_.size())
5826 break;
5827 ++i;
5828 if (__x_[i] == L'y' || __x_[i] == L'Y')
5829 return time_base::dmy;
5830 break;
5831 }
5832 break;
5833 }
5834 return time_base::no_order;
5835}
Louis Dionne89258142021-08-23 15:32:36 -04005836#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005837
5838// time_put
5839
5840__time_put::__time_put(const char* nm)
5841 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5842{
5843 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005844 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005845 " failed to construct for " + string(nm));
5846}
5847
5848__time_put::__time_put(const string& nm)
5849 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5850{
5851 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005852 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005853 " failed to construct for " + nm);
5854}
5855
5856__time_put::~__time_put()
5857{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005858 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005859 freelocale(__loc_);
5860}
5861
5862void
5863__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5864 char __fmt, char __mod) const
5865{
5866 char fmt[] = {'%', __fmt, __mod, 0};
5867 if (__mod != 0)
5868 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005869 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005870 __ne = __nb + n;
5871}
5872
Louis Dionne89258142021-08-23 15:32:36 -04005873#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005874void
5875__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5876 char __fmt, char __mod) const
5877{
5878 char __nar[100];
5879 char* __ne = __nar + 100;
5880 __do_put(__nar, __ne, __tm, __fmt, __mod);
5881 mbstate_t mb = {0};
5882 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005883 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005884 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005885 __throw_runtime_error("locale not supported");
5886 __we = __wb + j;
5887}
Louis Dionne89258142021-08-23 15:32:36 -04005888#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005889
5890// moneypunct_byname
5891
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005892template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005893static
5894void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005895__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5896 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5897 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005898{
5899 const char sign = static_cast<char>(money_base::sign);
5900 const char space = static_cast<char>(money_base::space);
5901 const char none = static_cast<char>(money_base::none);
5902 const char symbol = static_cast<char>(money_base::symbol);
5903 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005904 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5905
5906 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5907 // function'. "Space between sign and symbol or value" means that
5908 // if the sign is adjacent to the symbol, there's a space between
5909 // them, and otherwise there's a space between the sign and value.
5910 //
5911 // C11's localeconv specifies that the fourth character of an
5912 // international curr_symbol is used to separate the sign and
5913 // value when sep_by_space says to do so. C++ can't represent
5914 // that, so we just use a space. When sep_by_space says to
5915 // separate the symbol and value-or-sign with a space, we rearrange the
5916 // curr_symbol to put its spacing character on the correct side of
5917 // the symbol.
5918 //
5919 // We also need to avoid adding an extra space between the sign
5920 // and value when the currency symbol is suppressed (by not
5921 // setting showbase). We match glibc's strfmon by interpreting
5922 // sep_by_space==1 as "omit the space when the currency symbol is
5923 // absent".
5924 //
5925 // Users who want to get this right should use ICU instead.
5926
Howard Hinnantc51e1022010-05-11 19:42:16 +00005927 switch (cs_precedes)
5928 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 case 0: // value before curr_symbol
5930 if (symbol_contains_sep) {
5931 // Move the separator to before the symbol, to place it
5932 // between the value and symbol.
5933 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5934 __curr_symbol_.end());
5935 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005936 switch (sign_posn)
5937 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005938 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005939 pat.field[0] = sign;
5940 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005941 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005942 pat.field[3] = symbol;
5943 switch (sep_by_space)
5944 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005945 case 0: // No space separates the currency symbol and value.
5946 // This case may have changed between C99 and C11;
5947 // assume the currency symbol matches the intention.
5948 case 2: // Space between sign and currency or value.
5949 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005950 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005951 case 1: // Space between currency-and-sign or currency and value.
5952 if (!symbol_contains_sep) {
5953 // We insert the space into the symbol instead of
5954 // setting pat.field[2]=space so that when
5955 // showbase is not set, the space goes away too.
5956 __curr_symbol_.insert(0, 1, space_char);
5957 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005958 return;
5959 default:
5960 break;
5961 }
5962 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005963 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005964 pat.field[0] = sign;
5965 pat.field[3] = symbol;
5966 switch (sep_by_space)
5967 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005968 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 pat.field[1] = value;
5970 pat.field[2] = none;
5971 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005972 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005973 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005974 pat.field[2] = none;
5975 if (!symbol_contains_sep) {
5976 // We insert the space into the symbol instead of
5977 // setting pat.field[2]=space so that when
5978 // showbase is not set, the space goes away too.
5979 __curr_symbol_.insert(0, 1, space_char);
5980 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005981 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005982 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005983 pat.field[1] = space;
5984 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005985 if (symbol_contains_sep) {
5986 // Remove the separator from the symbol, since it
5987 // has already appeared after the sign.
5988 __curr_symbol_.erase(__curr_symbol_.begin());
5989 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005990 return;
5991 default:
5992 break;
5993 }
5994 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005995 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005996 pat.field[0] = value;
5997 pat.field[3] = sign;
5998 switch (sep_by_space)
5999 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006000 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006001 pat.field[1] = none;
6002 pat.field[2] = symbol;
6003 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006004 case 1: // Space between currency-and-sign or currency and value.
6005 if (!symbol_contains_sep) {
6006 // We insert the space into the symbol instead of
6007 // setting pat.field[1]=space so that when
6008 // showbase is not set, the space goes away too.
6009 __curr_symbol_.insert(0, 1, space_char);
6010 }
6011 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006012 pat.field[2] = symbol;
6013 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006014 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006015 pat.field[1] = symbol;
6016 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006017 if (symbol_contains_sep) {
6018 // Remove the separator from the symbol, since it
6019 // should not be removed if showbase is absent.
6020 __curr_symbol_.erase(__curr_symbol_.begin());
6021 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006022 return;
6023 default:
6024 break;
6025 }
6026 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006027 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006028 pat.field[0] = value;
6029 pat.field[3] = symbol;
6030 switch (sep_by_space)
6031 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006032 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006033 pat.field[1] = none;
6034 pat.field[2] = sign;
6035 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006036 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006037 pat.field[1] = space;
6038 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006039 if (symbol_contains_sep) {
6040 // Remove the separator from the symbol, since it
6041 // has already appeared before the sign.
6042 __curr_symbol_.erase(__curr_symbol_.begin());
6043 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006044 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006045 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006046 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006047 pat.field[2] = none;
6048 if (!symbol_contains_sep) {
6049 // We insert the space into the symbol instead of
6050 // setting pat.field[2]=space so that when
6051 // showbase is not set, the space goes away too.
6052 __curr_symbol_.insert(0, 1, space_char);
6053 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006054 return;
6055 default:
6056 break;
6057 }
6058 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006059 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006060 pat.field[0] = value;
6061 pat.field[3] = sign;
6062 switch (sep_by_space)
6063 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006064 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006065 pat.field[1] = none;
6066 pat.field[2] = symbol;
6067 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006068 case 1: // Space between currency-and-sign or currency and value.
6069 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006070 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006071 if (!symbol_contains_sep) {
6072 // We insert the space into the symbol instead of
6073 // setting pat.field[1]=space so that when
6074 // showbase is not set, the space goes away too.
6075 __curr_symbol_.insert(0, 1, space_char);
6076 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006077 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006078 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006079 pat.field[1] = symbol;
6080 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006081 if (symbol_contains_sep) {
6082 // Remove the separator from the symbol, since it
6083 // should not disappear when showbase is absent.
6084 __curr_symbol_.erase(__curr_symbol_.begin());
6085 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006086 return;
6087 default:
6088 break;
6089 }
6090 break;
6091 default:
6092 break;
6093 }
6094 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006095 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00006096 switch (sign_posn)
6097 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006098 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006099 pat.field[0] = sign;
6100 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006101 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006102 pat.field[3] = value;
6103 switch (sep_by_space)
6104 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006105 case 0: // No space separates the currency symbol and value.
6106 // This case may have changed between C99 and C11;
6107 // assume the currency symbol matches the intention.
6108 case 2: // Space between sign and currency or value.
6109 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006110 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006111 case 1: // Space between currency-and-sign or currency and value.
6112 if (!symbol_contains_sep) {
6113 // We insert the space into the symbol instead of
6114 // setting pat.field[2]=space so that when
6115 // showbase is not set, the space goes away too.
6116 __curr_symbol_.insert(0, 1, space_char);
6117 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006118 return;
6119 default:
6120 break;
6121 }
6122 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006123 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006124 pat.field[0] = sign;
6125 pat.field[3] = value;
6126 switch (sep_by_space)
6127 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006128 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006129 pat.field[1] = symbol;
6130 pat.field[2] = none;
6131 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006132 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006133 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006134 pat.field[2] = none;
6135 if (!symbol_contains_sep) {
6136 // We insert the space into the symbol instead of
6137 // setting pat.field[2]=space so that when
6138 // showbase is not set, the space goes away too.
6139 __curr_symbol_.push_back(space_char);
6140 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006142 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006143 pat.field[1] = space;
6144 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006145 if (symbol_contains_sep) {
6146 // Remove the separator from the symbol, since it
6147 // has already appeared after the sign.
6148 __curr_symbol_.pop_back();
6149 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006150 return;
6151 default:
6152 break;
6153 }
6154 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006155 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006156 pat.field[0] = symbol;
6157 pat.field[3] = sign;
6158 switch (sep_by_space)
6159 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006160 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006161 pat.field[1] = none;
6162 pat.field[2] = value;
6163 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006164 case 1: // Space between currency-and-sign or currency and value.
6165 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006166 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006167 if (!symbol_contains_sep) {
6168 // We insert the space into the symbol instead of
6169 // setting pat.field[1]=space so that when
6170 // showbase is not set, the space goes away too.
6171 __curr_symbol_.push_back(space_char);
6172 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006173 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006174 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006175 pat.field[1] = value;
6176 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006177 if (symbol_contains_sep) {
6178 // Remove the separator from the symbol, since it
6179 // will appear before the sign.
6180 __curr_symbol_.pop_back();
6181 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006182 return;
6183 default:
6184 break;
6185 }
6186 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006187 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006188 pat.field[0] = sign;
6189 pat.field[3] = value;
6190 switch (sep_by_space)
6191 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006192 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006193 pat.field[1] = symbol;
6194 pat.field[2] = none;
6195 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006196 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006197 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006198 pat.field[2] = none;
6199 if (!symbol_contains_sep) {
6200 // We insert the space into the symbol instead of
6201 // setting pat.field[2]=space so that when
6202 // showbase is not set, the space goes away too.
6203 __curr_symbol_.push_back(space_char);
6204 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006205 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006206 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006207 pat.field[1] = space;
6208 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006209 if (symbol_contains_sep) {
6210 // Remove the separator from the symbol, since it
6211 // has already appeared after the sign.
6212 __curr_symbol_.pop_back();
6213 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006214 return;
6215 default:
6216 break;
6217 }
6218 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006219 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006220 pat.field[0] = symbol;
6221 pat.field[3] = value;
6222 switch (sep_by_space)
6223 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006224 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006225 pat.field[1] = sign;
6226 pat.field[2] = none;
6227 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006228 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006229 pat.field[1] = sign;
6230 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006231 if (symbol_contains_sep) {
6232 // Remove the separator from the symbol, since it
6233 // should not disappear when showbase is absent.
6234 __curr_symbol_.pop_back();
6235 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006236 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006237 case 2: // Space between sign and currency or value.
6238 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006239 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006240 if (!symbol_contains_sep) {
6241 // We insert the space into the symbol instead of
6242 // setting pat.field[1]=space so that when
6243 // showbase is not set, the space goes away too.
6244 __curr_symbol_.push_back(space_char);
6245 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006246 return;
6247 default:
6248 break;
6249 }
6250 break;
6251 default:
6252 break;
6253 }
6254 break;
6255 default:
6256 break;
6257 }
6258 pat.field[0] = symbol;
6259 pat.field[1] = sign;
6260 pat.field[2] = none;
6261 pat.field[3] = value;
6262}
6263
6264template<>
6265void
6266moneypunct_byname<char, false>::init(const char* nm)
6267{
6268 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006269 __libcpp_unique_locale loc(nm);
6270 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006271 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006272 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006273
Ben Craig3756b922016-03-09 15:39:39 +00006274 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006275 if (!checked_string_to_char_convert(__decimal_point_,
6276 lc->mon_decimal_point,
6277 loc.get()))
6278 __decimal_point_ = base::do_decimal_point();
6279 if (!checked_string_to_char_convert(__thousands_sep_,
6280 lc->mon_thousands_sep,
6281 loc.get()))
6282 __thousands_sep_ = base::do_thousands_sep();
6283
Howard Hinnantc51e1022010-05-11 19:42:16 +00006284 __grouping_ = lc->mon_grouping;
6285 __curr_symbol_ = lc->currency_symbol;
6286 if (lc->frac_digits != CHAR_MAX)
6287 __frac_digits_ = lc->frac_digits;
6288 else
6289 __frac_digits_ = base::do_frac_digits();
6290 if (lc->p_sign_posn == 0)
6291 __positive_sign_ = "()";
6292 else
6293 __positive_sign_ = lc->positive_sign;
6294 if (lc->n_sign_posn == 0)
6295 __negative_sign_ = "()";
6296 else
6297 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006298 // Assume the positive and negative formats will want spaces in
6299 // the same places in curr_symbol since there's no way to
6300 // represent anything else.
6301 string_type __dummy_curr_symbol = __curr_symbol_;
6302 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6303 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6304 __init_pat(__neg_format_, __curr_symbol_, false,
6305 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006306}
6307
6308template<>
6309void
6310moneypunct_byname<char, true>::init(const char* nm)
6311{
6312 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006313 __libcpp_unique_locale loc(nm);
6314 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006315 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006316 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006317
Ben Craig3756b922016-03-09 15:39:39 +00006318 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006319 if (!checked_string_to_char_convert(__decimal_point_,
6320 lc->mon_decimal_point,
6321 loc.get()))
6322 __decimal_point_ = base::do_decimal_point();
6323 if (!checked_string_to_char_convert(__thousands_sep_,
6324 lc->mon_thousands_sep,
6325 loc.get()))
6326 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006327 __grouping_ = lc->mon_grouping;
6328 __curr_symbol_ = lc->int_curr_symbol;
6329 if (lc->int_frac_digits != CHAR_MAX)
6330 __frac_digits_ = lc->int_frac_digits;
6331 else
6332 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006333#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006334 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006335#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006336 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006337#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006338 __positive_sign_ = "()";
6339 else
6340 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006341#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006342 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006343#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006344 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006345#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006346 __negative_sign_ = "()";
6347 else
6348 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006349 // Assume the positive and negative formats will want spaces in
6350 // the same places in curr_symbol since there's no way to
6351 // represent anything else.
6352 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006353#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006354 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6355 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6356 __init_pat(__neg_format_, __curr_symbol_, true,
6357 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006358#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006359 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6360 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6361 lc->int_p_sign_posn, ' ');
6362 __init_pat(__neg_format_, __curr_symbol_, true,
6363 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6364 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006365#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006366}
6367
Louis Dionne89258142021-08-23 15:32:36 -04006368#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006369template<>
6370void
6371moneypunct_byname<wchar_t, false>::init(const char* nm)
6372{
6373 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006374 __libcpp_unique_locale loc(nm);
6375 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006376 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006377 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006378 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006379 if (!checked_string_to_wchar_convert(__decimal_point_,
6380 lc->mon_decimal_point,
6381 loc.get()))
6382 __decimal_point_ = base::do_decimal_point();
6383 if (!checked_string_to_wchar_convert(__thousands_sep_,
6384 lc->mon_thousands_sep,
6385 loc.get()))
6386 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006387 __grouping_ = lc->mon_grouping;
6388 wchar_t wbuf[100];
6389 mbstate_t mb = {0};
6390 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006391 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006392 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006393 __throw_runtime_error("locale not supported");
6394 wchar_t* wbe = wbuf + j;
6395 __curr_symbol_.assign(wbuf, wbe);
6396 if (lc->frac_digits != CHAR_MAX)
6397 __frac_digits_ = lc->frac_digits;
6398 else
6399 __frac_digits_ = base::do_frac_digits();
6400 if (lc->p_sign_posn == 0)
6401 __positive_sign_ = L"()";
6402 else
6403 {
6404 mb = mbstate_t();
6405 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006406 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006407 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006408 __throw_runtime_error("locale not supported");
6409 wbe = wbuf + j;
6410 __positive_sign_.assign(wbuf, wbe);
6411 }
6412 if (lc->n_sign_posn == 0)
6413 __negative_sign_ = L"()";
6414 else
6415 {
6416 mb = mbstate_t();
6417 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006418 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 wbe = wbuf + j;
6422 __negative_sign_.assign(wbuf, wbe);
6423 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006424 // Assume the positive and negative formats will want spaces in
6425 // the same places in curr_symbol since there's no way to
6426 // represent anything else.
6427 string_type __dummy_curr_symbol = __curr_symbol_;
6428 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6429 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6430 __init_pat(__neg_format_, __curr_symbol_, false,
6431 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006432}
6433
6434template<>
6435void
6436moneypunct_byname<wchar_t, true>::init(const char* nm)
6437{
6438 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006439 __libcpp_unique_locale loc(nm);
6440 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006441 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006442 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006443
Ben Craig3756b922016-03-09 15:39:39 +00006444 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006445 if (!checked_string_to_wchar_convert(__decimal_point_,
6446 lc->mon_decimal_point,
6447 loc.get()))
6448 __decimal_point_ = base::do_decimal_point();
6449 if (!checked_string_to_wchar_convert(__thousands_sep_,
6450 lc->mon_thousands_sep,
6451 loc.get()))
6452 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006453 __grouping_ = lc->mon_grouping;
6454 wchar_t wbuf[100];
6455 mbstate_t mb = {0};
6456 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006457 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006458 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006459 __throw_runtime_error("locale not supported");
6460 wchar_t* wbe = wbuf + j;
6461 __curr_symbol_.assign(wbuf, wbe);
6462 if (lc->int_frac_digits != CHAR_MAX)
6463 __frac_digits_ = lc->int_frac_digits;
6464 else
6465 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006466#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006467 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006468#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006469 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006470#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006471 __positive_sign_ = L"()";
6472 else
6473 {
6474 mb = mbstate_t();
6475 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006476 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006477 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006478 __throw_runtime_error("locale not supported");
6479 wbe = wbuf + j;
6480 __positive_sign_.assign(wbuf, wbe);
6481 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006482#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006483 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006484#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006485 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006486#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006487 __negative_sign_ = L"()";
6488 else
6489 {
6490 mb = mbstate_t();
6491 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006492 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006493 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006494 __throw_runtime_error("locale not supported");
6495 wbe = wbuf + j;
6496 __negative_sign_.assign(wbuf, wbe);
6497 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006498 // Assume the positive and negative formats will want spaces in
6499 // the same places in curr_symbol since there's no way to
6500 // represent anything else.
6501 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006502#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006503 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6504 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6505 __init_pat(__neg_format_, __curr_symbol_, true,
6506 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006507#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006508 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6509 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6510 lc->int_p_sign_posn, L' ');
6511 __init_pat(__neg_format_, __curr_symbol_, true,
6512 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6513 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006514#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006515}
Louis Dionne89258142021-08-23 15:32:36 -04006516#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006517
6518void __do_nothing(void*) {}
6519
6520void __throw_runtime_error(const char* msg)
6521{
Howard Hinnant72f73582010-08-11 17:04:31 +00006522#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006523 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006524#else
6525 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006526 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006527#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006528}
6529
Louis Dionne89258142021-08-23 15:32:36 -04006530 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6531_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006532
Louis Dionne89258142021-08-23 15:32:36 -04006533 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6534_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006535
Louis Dionne89258142021-08-23 15:32:36 -04006536 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6537_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006538
Louis Dionne89258142021-08-23 15:32:36 -04006539 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6540_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006541
Louis Dionne89258142021-08-23 15:32:36 -04006542 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6543_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006544
Louis Dionne89258142021-08-23 15:32:36 -04006545 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6546_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006547
Louis Dionne89258142021-08-23 15:32:36 -04006548 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6549_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006550
Louis Dionne89258142021-08-23 15:32:36 -04006551 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6552_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006553
Louis Dionne89258142021-08-23 15:32:36 -04006554 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6555_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006556
Louis Dionne89258142021-08-23 15:32:36 -04006557 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6558 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6559_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6560_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006561
Louis Dionne89258142021-08-23 15:32:36 -04006562 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6563 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6564_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6565_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006566
Louis Dionne89258142021-08-23 15:32:36 -04006567 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6568_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006569
Louis Dionne89258142021-08-23 15:32:36 -04006570 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6571_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006572
Louis Dionne89258142021-08-23 15:32:36 -04006573 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6574_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006575
Louis Dionne89258142021-08-23 15:32:36 -04006576 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6577_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006578
Louis Dionne89258142021-08-23 15:32:36 -04006579 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6580_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006581
Louis Dionne89258142021-08-23 15:32:36 -04006582 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6583_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006584
Louis Dionne89258142021-08-23 15:32:36 -04006585 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6586_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 -08006587template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6588template 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 -04006589#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006590template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6591template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6592#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006593
Howard Hinnantc51e1022010-05-11 19:42:16 +00006594_LIBCPP_END_NAMESPACE_STD