blob: bd3f8733f57c4664a2123b30b0aac435ce14f41c [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>
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -050016#include <algorithm>
17#include <clocale>
18#include <codecvt>
19#include <cstdio>
20#include <cstdlib>
21#include <cstring>
22#include <locale>
23#include <string>
24#include <type_traits>
25#include <typeinfo>
26#include <vector>
Louis Dionneafc98402021-09-09 13:52:38 -040027
Louis Dionne89258142021-08-23 15:32:36 -040028#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -050029# include <cwctype>
Louis Dionne89258142021-08-23 15:32:36 -040030#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"
Howard Hinnantc51e1022010-05-11 19:42:16 +000048
Marshall Clowab9c1772013-02-07 17:20:56 +000049// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070050// lots of noise in the build log, but no bugs that I know of.
Nikolas Klauser41c59762022-02-14 18:52:28 +010051_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion")
Marshall Clowab9c1772013-02-07 17:20:56 +000052
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -050053_LIBCPP_PUSH_MACROS
54#include <__undef_macros>
55
Howard Hinnantc51e1022010-05-11 19:42:16 +000056_LIBCPP_BEGIN_NAMESPACE_STD
57
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000058struct __libcpp_unique_locale {
59 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
60
61 ~__libcpp_unique_locale() {
62 if (__loc_)
63 freelocale(__loc_);
64 }
65
66 explicit operator bool() const { return __loc_; }
67
68 locale_t& get() { return __loc_; }
69
70 locale_t __loc_;
71private:
72 __libcpp_unique_locale(__libcpp_unique_locale const&);
73 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
74};
75
Howard Hinnantf312e3e2011-09-28 23:39:33 +000076#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000077locale_t __cloc() {
78 // In theory this could create a race condition. In practice
79 // the race condition is non-fatal since it will just create
80 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000081 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
82 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000083}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000084#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000085
Howard Hinnantc51e1022010-05-11 19:42:16 +000086namespace {
87
88struct release
89{
90 void operator()(locale::facet* p) {p->__release_shared();}
91};
92
Louis Dionne6e41a152021-08-09 13:26:04 -040093template <class T, class ...Args>
94T& make(Args ...args)
Howard Hinnantc51e1022010-05-11 19:42:16 +000095{
96 static typename aligned_storage<sizeof(T)>::type buf;
Louis Dionne6e41a152021-08-09 13:26:04 -040097 auto *obj = ::new (&buf) T(args...);
Eric Fiselier4db80032017-05-05 20:32:26 +000098 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000099}
100
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000101template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000102inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000103_LIBCPP_CONSTEXPR
104size_t
105countof(const T (&)[N])
106{
107 return N;
108}
109
110template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000111inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000112_LIBCPP_CONSTEXPR
113size_t
114countof(const T * const begin, const T * const end)
115{
116 return static_cast<size_t>(end - begin);
117}
118
Marshall Clow8fea1612016-08-25 15:09:01 +0000119_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
120{
121#ifndef _LIBCPP_NO_EXCEPTIONS
122 throw runtime_error(msg);
123#else
124 (void)msg;
125 _VSTD::abort();
126#endif
127}
128
Howard Hinnantc51e1022010-05-11 19:42:16 +0000129}
130
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000131const locale::category locale::none;
132const locale::category locale::collate;
133const locale::category locale::ctype;
134const locale::category locale::monetary;
135const locale::category locale::numeric;
136const locale::category locale::time;
137const locale::category locale::messages;
138const locale::category locale::all;
139
Howard Hinnantc51e1022010-05-11 19:42:16 +0000140class _LIBCPP_HIDDEN locale::__imp
141 : public facet
142{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100143 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000144#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000145// FIXME: MSVC doesn't support aligned parameters by value.
146// I can't get the __sso_allocator to work here
147// for MSVC I think for this reason.
148 vector<facet*> facets_;
149#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000150 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000151#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000152 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000153public:
154 explicit __imp(size_t refs = 0);
155 explicit __imp(const string& name, size_t refs = 0);
156 __imp(const __imp&);
157 __imp(const __imp&, const string&, locale::category c);
158 __imp(const __imp& other, const __imp& one, locale::category c);
159 __imp(const __imp&, facet* f, long id);
160 ~__imp();
161
162 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000163 bool has_facet(long id) const
164 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000165 const locale::facet* use_facet(long id) const;
166
167 static const locale& make_classic();
168 static locale& make_global();
169private:
170 void install(facet* f, long id);
171 template <class F> void install(F* f) {install(f, f->id.__get());}
172 template <class F> void install_from(const __imp& other);
173};
174
175locale::__imp::__imp(size_t refs)
176 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000177 facets_(N),
178 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000179{
180 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000181 install(&make<_VSTD::collate<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400182#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000183 install(&make<_VSTD::collate<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400184#endif
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000185 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Louis Dionne89258142021-08-23 15:32:36 -0400186#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000187 install(&make<_VSTD::ctype<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400188#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000189 install(&make<codecvt<char, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400190#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000191 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400192#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100193_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000194 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
195 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100196_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400197#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100198 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
199 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
200#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000201 install(&make<numpunct<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400202#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000203 install(&make<numpunct<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400204#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000205 install(&make<num_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400206#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000207 install(&make<num_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400208#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000209 install(&make<num_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400210#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000211 install(&make<num_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400212#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000213 install(&make<moneypunct<char, false> >(1u));
214 install(&make<moneypunct<char, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400215#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000216 install(&make<moneypunct<wchar_t, false> >(1u));
217 install(&make<moneypunct<wchar_t, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400218#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000219 install(&make<money_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400220#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000221 install(&make<money_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400222#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000223 install(&make<money_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400224#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000225 install(&make<money_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400226#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000227 install(&make<time_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400228#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000229 install(&make<time_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400230#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000231 install(&make<time_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400232#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000233 install(&make<time_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400234#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000235 install(&make<_VSTD::messages<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400236#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000237 install(&make<_VSTD::messages<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400238#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000239}
240
241locale::__imp::__imp(const string& name, size_t refs)
242 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000243 facets_(N),
244 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000245{
Howard Hinnant72f73582010-08-11 17:04:31 +0000246#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000247 try
248 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400249#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000250 facets_ = locale::classic().__locale_->facets_;
251 for (unsigned i = 0; i < facets_.size(); ++i)
252 if (facets_[i])
253 facets_[i]->__add_shared();
254 install(new collate_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400255#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000256 install(new collate_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400257#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000258 install(new ctype_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400259#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000260 install(new ctype_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400261#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262 install(new codecvt_byname<char, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400263#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000264 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400265#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100266_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000267 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
268 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100269_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400270#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100271 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
272 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
273#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000274 install(new numpunct_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400275#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276 install(new numpunct_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400277#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000278 install(new moneypunct_byname<char, false>(name_));
279 install(new moneypunct_byname<char, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400280#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000281 install(new moneypunct_byname<wchar_t, false>(name_));
282 install(new moneypunct_byname<wchar_t, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400283#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284 install(new time_get_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400285#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000286 install(new time_get_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400287#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288 install(new time_put_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400289#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000290 install(new time_put_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400291#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000292 install(new messages_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400293#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000294 install(new messages_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400295#endif
Howard Hinnant72f73582010-08-11 17:04:31 +0000296#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000297 }
298 catch (...)
299 {
300 for (unsigned i = 0; i < facets_.size(); ++i)
301 if (facets_[i])
302 facets_[i]->__release_shared();
303 throw;
304 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400305#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000306}
307
308locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000309 : facets_(max<size_t>(N, other.facets_.size())),
310 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000311{
312 facets_ = other.facets_;
313 for (unsigned i = 0; i < facets_.size(); ++i)
314 if (facets_[i])
315 facets_[i]->__add_shared();
316}
317
318locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000319 : facets_(N),
320 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000321{
322 facets_ = other.facets_;
323 for (unsigned i = 0; i < facets_.size(); ++i)
324 if (facets_[i])
325 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000326#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000327 try
328 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400329#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000330 if (c & locale::collate)
331 {
332 install(new collate_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400333#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000334 install(new collate_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400335#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000336 }
337 if (c & locale::ctype)
338 {
339 install(new ctype_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400340#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000341 install(new ctype_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400342#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000343 install(new codecvt_byname<char, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400344#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000345 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400346#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100347_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000348 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
349 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100350_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400351#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100352 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
353 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
354#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000355 }
356 if (c & locale::monetary)
357 {
358 install(new moneypunct_byname<char, false>(name));
359 install(new moneypunct_byname<char, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400360#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000361 install(new moneypunct_byname<wchar_t, false>(name));
362 install(new moneypunct_byname<wchar_t, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400363#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000364 }
365 if (c & locale::numeric)
366 {
367 install(new numpunct_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400368#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000369 install(new numpunct_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400370#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000371 }
372 if (c & locale::time)
373 {
374 install(new time_get_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400375#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000376 install(new time_get_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400377#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000378 install(new time_put_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400379#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000380 install(new time_put_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400381#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000382 }
383 if (c & locale::messages)
384 {
385 install(new messages_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400386#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000387 install(new messages_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400388#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000389 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000390#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000391 }
392 catch (...)
393 {
394 for (unsigned i = 0; i < facets_.size(); ++i)
395 if (facets_[i])
396 facets_[i]->__release_shared();
397 throw;
398 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400399#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000400}
401
402template<class F>
403inline
404void
405locale::__imp::install_from(const locale::__imp& one)
406{
407 long id = F::id.__get();
408 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
409}
410
411locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000412 : facets_(N),
413 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000414{
415 facets_ = other.facets_;
416 for (unsigned i = 0; i < facets_.size(); ++i)
417 if (facets_[i])
418 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000419#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000420 try
421 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400422#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000423 if (c & locale::collate)
424 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000425 install_from<_VSTD::collate<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400426#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000427 install_from<_VSTD::collate<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400428#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000429 }
430 if (c & locale::ctype)
431 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000432 install_from<_VSTD::ctype<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400433#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000434 install_from<_VSTD::ctype<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400435#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000436 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100437_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000438 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
439 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100440_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400441#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100442 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
443 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
444#endif
Louis Dionne89258142021-08-23 15:32:36 -0400445#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000446 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400447#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000448 }
449 if (c & locale::monetary)
450 {
451 install_from<moneypunct<char, false> >(one);
452 install_from<moneypunct<char, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400453#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000454 install_from<moneypunct<wchar_t, false> >(one);
455 install_from<moneypunct<wchar_t, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400456#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000457 install_from<money_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400458#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000459 install_from<money_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400460#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000461 install_from<money_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400462#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000463 install_from<money_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400464#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000465 }
466 if (c & locale::numeric)
467 {
468 install_from<numpunct<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400469#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000470 install_from<numpunct<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400471#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000472 install_from<num_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400473#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000474 install_from<num_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400475#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000476 install_from<num_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400477#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000478 install_from<num_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400479#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000480 }
481 if (c & locale::time)
482 {
483 install_from<time_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400484#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000485 install_from<time_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400486#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000487 install_from<time_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400488#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000489 install_from<time_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400490#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000491 }
492 if (c & locale::messages)
493 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000494 install_from<_VSTD::messages<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400495#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000496 install_from<_VSTD::messages<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400497#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000498 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000499#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000500 }
501 catch (...)
502 {
503 for (unsigned i = 0; i < facets_.size(); ++i)
504 if (facets_[i])
505 facets_[i]->__release_shared();
506 throw;
507 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400508#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509}
510
511locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000512 : facets_(max<size_t>(N, other.facets_.size()+1)),
513 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000514{
515 f->__add_shared();
516 unique_ptr<facet, release> hold(f);
517 facets_ = other.facets_;
518 for (unsigned i = 0; i < other.facets_.size(); ++i)
519 if (facets_[i])
520 facets_[i]->__add_shared();
521 install(hold.get(), id);
522}
523
524locale::__imp::~__imp()
525{
526 for (unsigned i = 0; i < facets_.size(); ++i)
527 if (facets_[i])
528 facets_[i]->__release_shared();
529}
530
531void
532locale::__imp::install(facet* f, long id)
533{
534 f->__add_shared();
535 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000536 if (static_cast<size_t>(id) >= facets_.size())
537 facets_.resize(static_cast<size_t>(id+1));
538 if (facets_[static_cast<size_t>(id)])
539 facets_[static_cast<size_t>(id)]->__release_shared();
540 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000541}
542
543const locale::facet*
544locale::__imp::use_facet(long id) const
545{
546 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000547 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000548 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000549}
550
551// locale
552
553const locale&
554locale::__imp::make_classic()
555{
556 // only one thread can get in here and it only gets in once
557 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000558 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000559 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000560 return *c;
561}
562
563const locale&
564locale::classic()
565{
566 static const locale& c = __imp::make_classic();
567 return c;
568}
569
570locale&
571locale::__imp::make_global()
572{
573 // only one thread can get in here and it only gets in once
574 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000575 auto *obj = ::new (&buf) locale(locale::classic());
576 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000577}
578
579locale&
580locale::__global()
581{
582 static locale& g = __imp::make_global();
583 return g;
584}
585
Louis Dionne65358e12021-03-01 12:09:45 -0500586locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000587 : __locale_(__global().__locale_)
588{
589 __locale_->__add_shared();
590}
591
Louis Dionne65358e12021-03-01 12:09:45 -0500592locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000593 : __locale_(l.__locale_)
594{
595 __locale_->__add_shared();
596}
597
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000598locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000599{
600 __locale_->__release_shared();
601}
602
603const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500604locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000605{
606 other.__locale_->__add_shared();
607 __locale_->__release_shared();
608 __locale_ = other.__locale_;
609 return *this;
610}
611
612locale::locale(const char* name)
613 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100614 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000615{
616 __locale_->__add_shared();
617}
618
619locale::locale(const string& name)
620 : __locale_(new __imp(name))
621{
622 __locale_->__add_shared();
623}
624
625locale::locale(const locale& other, const char* name, category c)
626 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100627 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000628{
629 __locale_->__add_shared();
630}
631
632locale::locale(const locale& other, const string& name, category c)
633 : __locale_(new __imp(*other.__locale_, name, c))
634{
635 __locale_->__add_shared();
636}
637
638locale::locale(const locale& other, const locale& one, category c)
639 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
640{
641 __locale_->__add_shared();
642}
643
644string
645locale::name() const
646{
647 return __locale_->name();
648}
649
650void
651locale::__install_ctor(const locale& other, facet* f, long id)
652{
653 if (f)
654 __locale_ = new __imp(*other.__locale_, f, id);
655 else
656 __locale_ = other.__locale_;
657 __locale_->__add_shared();
658}
659
660locale
661locale::global(const locale& loc)
662{
663 locale& g = __global();
664 locale r = g;
665 g = loc;
666 if (g.name() != "*")
667 setlocale(LC_ALL, g.name().c_str());
668 return r;
669}
670
671bool
672locale::has_facet(id& x) const
673{
674 return __locale_->has_facet(x.__get());
675}
676
677const locale::facet*
678locale::use_facet(id& x) const
679{
680 return __locale_->use_facet(x.__get());
681}
682
683bool
684locale::operator==(const locale& y) const
685{
686 return (__locale_ == y.__locale_)
687 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
688}
689
690// locale::facet
691
692locale::facet::~facet()
693{
694}
695
696void
Louis Dionne65358e12021-03-01 12:09:45 -0500697locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000698{
699 delete this;
700}
701
702// locale::id
703
704int32_t locale::id::__next_id = 0;
705
706namespace
707{
708
709class __fake_bind
710{
711 locale::id* id_;
712 void (locale::id::* pmf_)();
713public:
714 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
715 : id_(id), pmf_(pmf) {}
716
717 void operator()() const
718 {
719 (id_->*pmf_)();
720 }
721};
722
723}
724
725long
726locale::id::__get()
727{
728 call_once(__flag_, __fake_bind(&locale::id::__init, this));
729 return __id_ - 1;
730}
731
732void
733locale::id::__init()
734{
Weiming Zhaob613db72017-09-19 23:18:03 +0000735 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000736}
737
738// template <> class collate_byname<char>
739
740collate_byname<char>::collate_byname(const char* n, size_t refs)
741 : collate<char>(refs),
742 __l(newlocale(LC_ALL_MASK, n, 0))
743{
744 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000745 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000746 " failed to construct for " + string(n));
747}
748
749collate_byname<char>::collate_byname(const string& name, size_t refs)
750 : collate<char>(refs),
751 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
752{
753 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000754 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000755 " failed to construct for " + name);
756}
757
758collate_byname<char>::~collate_byname()
759{
760 freelocale(__l);
761}
762
763int
764collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
765 const char_type* __lo2, const char_type* __hi2) const
766{
767 string_type lhs(__lo1, __hi1);
768 string_type rhs(__lo2, __hi2);
769 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
770 if (r < 0)
771 return -1;
772 if (r > 0)
773 return 1;
774 return r;
775}
776
777collate_byname<char>::string_type
778collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
779{
780 const string_type in(lo, hi);
781 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
782 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
783 return out;
784}
785
786// template <> class collate_byname<wchar_t>
787
Louis Dionne89258142021-08-23 15:32:36 -0400788#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000789collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
790 : collate<wchar_t>(refs),
791 __l(newlocale(LC_ALL_MASK, n, 0))
792{
793 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000794 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000795 " failed to construct for " + string(n));
796}
797
798collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
799 : collate<wchar_t>(refs),
800 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
801{
802 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000803 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000804 " failed to construct for " + name);
805}
806
807collate_byname<wchar_t>::~collate_byname()
808{
809 freelocale(__l);
810}
811
812int
813collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
814 const char_type* __lo2, const char_type* __hi2) const
815{
816 string_type lhs(__lo1, __hi1);
817 string_type rhs(__lo2, __hi2);
818 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
819 if (r < 0)
820 return -1;
821 if (r > 0)
822 return 1;
823 return r;
824}
825
826collate_byname<wchar_t>::string_type
827collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
828{
829 const string_type in(lo, hi);
830 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
831 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
832 return out;
833}
Louis Dionne89258142021-08-23 15:32:36 -0400834#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000835
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000836const ctype_base::mask ctype_base::space;
837const ctype_base::mask ctype_base::print;
838const ctype_base::mask ctype_base::cntrl;
839const ctype_base::mask ctype_base::upper;
840const ctype_base::mask ctype_base::lower;
841const ctype_base::mask ctype_base::alpha;
842const ctype_base::mask ctype_base::digit;
843const ctype_base::mask ctype_base::punct;
844const ctype_base::mask ctype_base::xdigit;
845const ctype_base::mask ctype_base::blank;
846const ctype_base::mask ctype_base::alnum;
847const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700848
Louis Dionne945f8682021-09-09 13:29:24 -0400849// template <> class ctype<wchar_t>;
850
Louis Dionne89258142021-08-23 15:32:36 -0400851#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000852locale::id ctype<wchar_t>::id;
853
854ctype<wchar_t>::~ctype()
855{
856}
857
858bool
859ctype<wchar_t>::do_is(mask m, char_type c) const
860{
Marshall Clowd920eea2013-10-21 15:07:28 +0000861 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000862}
863
864const wchar_t*
865ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
866{
867 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000868 *vec = static_cast<mask>(isascii(*low) ?
869 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000870 return low;
871}
872
873const wchar_t*
874ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
875{
876 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000877 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000878 break;
879 return low;
880}
881
882const wchar_t*
883ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
884{
885 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000886 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000887 break;
888 return low;
889}
890
891wchar_t
892ctype<wchar_t>::do_toupper(char_type c) const
893{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000894#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
895 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000896#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500897 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000898 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000899#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000900 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000901#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000902}
903
904const wchar_t*
905ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
906{
907 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000908#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
909 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000910#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500911 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000912 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
913 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000914#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000915 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000916#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000917 return low;
918}
919
920wchar_t
921ctype<wchar_t>::do_tolower(char_type c) const
922{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000923#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
924 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000925#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500926 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000927 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000928#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000929 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000930#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000931}
932
933const wchar_t*
934ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
935{
936 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000937#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
938 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000939#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500940 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000941 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
942 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000943#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000944 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000945#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000946 return low;
947}
948
949wchar_t
950ctype<wchar_t>::do_widen(char c) const
951{
952 return c;
953}
954
955const char*
956ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
957{
958 for (; low != high; ++low, ++dest)
959 *dest = *low;
960 return low;
961}
962
963char
964ctype<wchar_t>::do_narrow(char_type c, char dfault) const
965{
966 if (isascii(c))
967 return static_cast<char>(c);
968 return dfault;
969}
970
971const wchar_t*
972ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
973{
974 for (; low != high; ++low, ++dest)
975 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000976 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000977 else
978 *dest = dfault;
979 return low;
980}
Louis Dionne89258142021-08-23 15:32:36 -0400981#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000982
983// template <> class ctype<char>;
984
985locale::id ctype<char>::id;
986
Muiez Ahmedc98adb12021-11-18 15:49:45 -0500987const size_t ctype<char>::table_size;
988
Howard Hinnantc51e1022010-05-11 19:42:16 +0000989ctype<char>::ctype(const mask* tab, bool del, size_t refs)
990 : locale::facet(refs),
991 __tab_(tab),
992 __del_(del)
993{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000994 if (__tab_ == 0)
995 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000996}
997
998ctype<char>::~ctype()
999{
1000 if (__tab_ && __del_)
1001 delete [] __tab_;
1002}
1003
1004char
1005ctype<char>::do_toupper(char_type c) const
1006{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001007#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001008 return isascii(c) ?
1009 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001010#elif defined(__NetBSD__)
1011 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001012#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +00001013 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001014 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001015#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001016 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001017#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001018}
1019
1020const char*
1021ctype<char>::do_toupper(char_type* low, const char_type* high) const
1022{
1023 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001024#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001025 *low = isascii(*low) ?
1026 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001027#elif defined(__NetBSD__)
1028 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001029#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001030 *low = isascii(*low) ?
1031 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001032#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001033 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001034#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001035 return low;
1036}
1037
1038char
1039ctype<char>::do_tolower(char_type c) const
1040{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001041#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001042 return isascii(c) ?
1043 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001044#elif defined(__NetBSD__)
1045 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001046#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001047 return isascii(c) ?
1048 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001049#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001050 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001051#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001052}
1053
1054const char*
1055ctype<char>::do_tolower(char_type* low, const char_type* high) const
1056{
1057 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001058#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001059 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001060#elif defined(__NetBSD__)
1061 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001062#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001063 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001064#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001065 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001066#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001067 return low;
1068}
1069
1070char
1071ctype<char>::do_widen(char c) const
1072{
1073 return c;
1074}
1075
1076const char*
1077ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1078{
1079 for (; low != high; ++low, ++dest)
1080 *dest = *low;
1081 return low;
1082}
1083
1084char
1085ctype<char>::do_narrow(char_type c, char dfault) const
1086{
1087 if (isascii(c))
1088 return static_cast<char>(c);
1089 return dfault;
1090}
1091
1092const char*
1093ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1094{
1095 for (; low != high; ++low, ++dest)
1096 if (isascii(*low))
1097 *dest = *low;
1098 else
1099 *dest = dfault;
1100 return low;
1101}
1102
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001103#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001104extern "C" const unsigned short ** __ctype_b_loc();
1105extern "C" const int ** __ctype_tolower_loc();
1106extern "C" const int ** __ctype_toupper_loc();
1107#endif
1108
Marshall Clow8f870232015-03-04 16:50:02 +00001109#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001110const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001111ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001112{
1113 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1114 cntrl, cntrl,
1115 cntrl, cntrl,
1116 cntrl, cntrl,
1117 cntrl, cntrl,
1118 cntrl, cntrl | space | blank,
1119 cntrl | space, cntrl | space,
1120 cntrl | space, cntrl | space,
1121 cntrl, cntrl,
1122 cntrl, cntrl,
1123 cntrl, cntrl,
1124 cntrl, cntrl,
1125 cntrl, cntrl,
1126 cntrl, cntrl,
1127 cntrl, cntrl,
1128 cntrl, cntrl,
1129 cntrl, cntrl,
1130 space | blank | print, punct | print,
1131 punct | print, punct | print,
1132 punct | print, punct | print,
1133 punct | print, punct | print,
1134 punct | print, punct | print,
1135 punct | print, punct | print,
1136 punct | print, punct | print,
1137 punct | print, punct | print,
1138 digit | print | xdigit, digit | print | xdigit,
1139 digit | print | xdigit, digit | print | xdigit,
1140 digit | print | xdigit, digit | print | xdigit,
1141 digit | print | xdigit, digit | print | xdigit,
1142 digit | print | xdigit, digit | print | xdigit,
1143 punct | print, punct | print,
1144 punct | print, punct | print,
1145 punct | print, punct | print,
1146 punct | print, upper | xdigit | print | alpha,
1147 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1148 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1149 upper | xdigit | print | alpha, upper | print | alpha,
1150 upper | print | alpha, upper | print | alpha,
1151 upper | print | alpha, upper | print | alpha,
1152 upper | print | alpha, upper | print | alpha,
1153 upper | print | alpha, upper | print | alpha,
1154 upper | print | alpha, upper | print | alpha,
1155 upper | print | alpha, upper | print | alpha,
1156 upper | print | alpha, upper | print | alpha,
1157 upper | print | alpha, upper | print | alpha,
1158 upper | print | alpha, upper | print | alpha,
1159 upper | print | alpha, punct | print,
1160 punct | print, punct | print,
1161 punct | print, punct | print,
1162 punct | print, lower | xdigit | print | alpha,
1163 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1164 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1165 lower | xdigit | print | alpha, lower | print | alpha,
1166 lower | print | alpha, lower | print | alpha,
1167 lower | print | alpha, lower | print | alpha,
1168 lower | print | alpha, lower | print | alpha,
1169 lower | print | alpha, lower | print | alpha,
1170 lower | print | alpha, lower | print | alpha,
1171 lower | print | alpha, lower | print | alpha,
1172 lower | print | alpha, lower | print | alpha,
1173 lower | print | alpha, lower | print | alpha,
1174 lower | print | alpha, lower | print | alpha,
1175 lower | print | alpha, punct | print,
1176 punct | print, punct | print,
1177 punct | print, cntrl,
1178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1186 };
1187 return builtin_table;
1188}
1189#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001190const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001191ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001192{
David Chisnall1d581062011-09-21 08:39:44 +00001193#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001194 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001195#elif defined(__NetBSD__)
1196 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001197#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001198 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001199#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001200 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001201#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001202 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001203#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001204 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001205#elif defined(_NEWLIB_VERSION)
1206 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1207 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001208#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001209 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001210#elif defined(__MVS__)
1211# if defined(__NATIVE_ASCII_F)
1212 return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1213# else
1214 return const_cast<const ctype<char>::mask*> (__ctypec);
1215# endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001216#else
David Chisnall8074c342012-02-29 13:05:08 +00001217 // Platform not supported: abort so the person doing the port knows what to
1218 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001219# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001220 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001221 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001222 return NULL;
1223#endif
1224}
Marshall Clowb3f62842015-03-04 16:10:14 +00001225#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001226
Howard Hinnantd7a78632011-09-29 13:33:15 +00001227#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001228const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001229ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001230{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001231 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001232}
1233
1234const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001235ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001236{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001237 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001238}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001239#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001240const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001241ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001242{
1243 return _C_tolower_tab_ + 1;
1244}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001245
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001246const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001247ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001248{
1249 return _C_toupper_tab_ + 1;
1250}
1251
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001252#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001253const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001254ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001255{
1256 return *__ctype_tolower_loc();
1257}
1258
1259const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001260ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001261{
1262 return *__ctype_toupper_loc();
1263}
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001264#elif defined(__MVS__)
1265const unsigned short*
1266ctype<char>::__classic_lower_table() _NOEXCEPT
1267{
1268# if defined(__NATIVE_ASCII_F)
1269 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1270# else
1271 return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1272# endif
1273}
1274const unsigned short *
1275ctype<char>::__classic_upper_table() _NOEXCEPT
1276{
1277# if defined(__NATIVE_ASCII_F)
1278 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1279# else
1280 return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1281# endif
1282}
1283#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001284
Howard Hinnantc51e1022010-05-11 19:42:16 +00001285// template <> class ctype_byname<char>
1286
1287ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1288 : ctype<char>(0, false, refs),
1289 __l(newlocale(LC_ALL_MASK, name, 0))
1290{
1291 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001292 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001293 " failed to construct for " + string(name));
1294}
1295
1296ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1297 : ctype<char>(0, false, refs),
1298 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1299{
1300 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001301 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001302 " failed to construct for " + name);
1303}
1304
1305ctype_byname<char>::~ctype_byname()
1306{
1307 freelocale(__l);
1308}
1309
1310char
1311ctype_byname<char>::do_toupper(char_type c) const
1312{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001313 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001314}
1315
1316const char*
1317ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1318{
1319 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001320 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321 return low;
1322}
1323
1324char
1325ctype_byname<char>::do_tolower(char_type c) const
1326{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001327 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001328}
1329
1330const char*
1331ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1332{
1333 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001334 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001335 return low;
1336}
1337
1338// template <> class ctype_byname<wchar_t>
1339
Louis Dionne89258142021-08-23 15:32:36 -04001340#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001341ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1342 : ctype<wchar_t>(refs),
1343 __l(newlocale(LC_ALL_MASK, name, 0))
1344{
1345 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001346 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001347 " failed to construct for " + string(name));
1348}
1349
1350ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1351 : ctype<wchar_t>(refs),
1352 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1353{
1354 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001355 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001356 " failed to construct for " + name);
1357}
1358
1359ctype_byname<wchar_t>::~ctype_byname()
1360{
1361 freelocale(__l);
1362}
1363
1364bool
1365ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1366{
Alexis Huntc2017f12011-07-09 03:40:04 +00001367#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001368 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001369#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001370 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001371 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001372 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1373 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1374 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1375 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1376 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1377 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1378 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1379 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1380 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1381 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001382 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001383#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001384}
1385
1386const wchar_t*
1387ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1388{
1389 for (; low != high; ++low, ++vec)
1390 {
1391 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001392 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001393 else
1394 {
1395 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001396 wint_t ch = static_cast<wint_t>(*low);
1397 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001398 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001399#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001400 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001401 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001402#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001403 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001405 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001406 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001407 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001408 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001409#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001410 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001411 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001412#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001413 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001414 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001415 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001416 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001417#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001418 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001419 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001420#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001421#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001422 if (iswblank_l(ch, __l))
1423 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001424#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001425 }
1426 }
1427 return low;
1428}
1429
1430const wchar_t*
1431ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1432{
1433 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001434 {
1435#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001436 if (iswctype_l(*low, m, __l))
1437 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001438#else
Marshall Clowada0f732013-02-07 14:22:51 +00001439 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001440 if ((m & space) == space && iswspace_l(ch, __l)) break;
1441 if ((m & print) == print && iswprint_l(ch, __l)) break;
1442 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1443 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1444 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1445 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1446 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1447 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1448 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1449 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001450#endif
1451 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001452 return low;
1453}
1454
1455const wchar_t*
1456ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1457{
1458 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001459 {
1460#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001461 if (!iswctype_l(*low, m, __l))
1462 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001463#else
Marshall Clowada0f732013-02-07 14:22:51 +00001464 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001465 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1466 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1467 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1468 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1469 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1470 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1471 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1472 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1473 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1474 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001475 break;
1476#endif
1477 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001478 return low;
1479}
1480
1481wchar_t
1482ctype_byname<wchar_t>::do_toupper(char_type c) const
1483{
1484 return towupper_l(c, __l);
1485}
1486
1487const wchar_t*
1488ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1489{
1490 for (; low != high; ++low)
1491 *low = towupper_l(*low, __l);
1492 return low;
1493}
1494
1495wchar_t
1496ctype_byname<wchar_t>::do_tolower(char_type c) const
1497{
1498 return towlower_l(c, __l);
1499}
1500
1501const wchar_t*
1502ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1503{
1504 for (; low != high; ++low)
1505 *low = towlower_l(*low, __l);
1506 return low;
1507}
1508
1509wchar_t
1510ctype_byname<wchar_t>::do_widen(char c) const
1511{
Ben Craig3756b922016-03-09 15:39:39 +00001512 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001513}
1514
1515const char*
1516ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1517{
1518 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001519 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001520 return low;
1521}
1522
1523char
1524ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1525{
Ben Craig3756b922016-03-09 15:39:39 +00001526 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001527 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001528}
1529
1530const wchar_t*
1531ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1532{
1533 for (; low != high; ++low, ++dest)
1534 {
Ben Craig3756b922016-03-09 15:39:39 +00001535 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001536 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001537 }
1538 return low;
1539}
Louis Dionne89258142021-08-23 15:32:36 -04001540#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001541
1542// template <> class codecvt<char, char, mbstate_t>
1543
Howard Hinnantffb308e2010-08-22 00:03:27 +00001544locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001545
1546codecvt<char, char, mbstate_t>::~codecvt()
1547{
1548}
1549
1550codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001551codecvt<char, char, mbstate_t>::do_out(state_type&,
1552 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001553 extern_type* to, extern_type*, extern_type*& to_nxt) const
1554{
1555 frm_nxt = frm;
1556 to_nxt = to;
1557 return noconv;
1558}
1559
1560codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001561codecvt<char, char, mbstate_t>::do_in(state_type&,
1562 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001563 intern_type* to, intern_type*, intern_type*& to_nxt) const
1564{
1565 frm_nxt = frm;
1566 to_nxt = to;
1567 return noconv;
1568}
1569
1570codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001571codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001572 extern_type* to, extern_type*, extern_type*& to_nxt) const
1573{
1574 to_nxt = to;
1575 return noconv;
1576}
1577
1578int
Louis Dionne65358e12021-03-01 12:09:45 -05001579codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001580{
1581 return 1;
1582}
1583
1584bool
Louis Dionne65358e12021-03-01 12:09:45 -05001585codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001586{
1587 return true;
1588}
1589
1590int
1591codecvt<char, char, mbstate_t>::do_length(state_type&,
1592 const extern_type* frm, const extern_type* end, size_t mx) const
1593{
Howard Hinnant28b24882011-12-01 20:21:04 +00001594 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001595}
1596
1597int
Louis Dionne65358e12021-03-01 12:09:45 -05001598codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001599{
1600 return 1;
1601}
1602
1603// template <> class codecvt<wchar_t, char, mbstate_t>
1604
Louis Dionne89258142021-08-23 15:32:36 -04001605#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantffb308e2010-08-22 00:03:27 +00001606locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001607
1608codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1609 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001610 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611{
1612}
1613
1614codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1615 : locale::facet(refs),
1616 __l(newlocale(LC_ALL_MASK, nm, 0))
1617{
1618 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001619 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001620 " failed to construct for " + string(nm));
1621}
1622
1623codecvt<wchar_t, char, mbstate_t>::~codecvt()
1624{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001625 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001626 freelocale(__l);
1627}
1628
1629codecvt<wchar_t, char, mbstate_t>::result
1630codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001631 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001632 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1633{
1634 // look for first internal null in frm
1635 const intern_type* fend = frm;
1636 for (; fend != frm_end; ++fend)
1637 if (*fend == 0)
1638 break;
1639 // loop over all null-terminated sequences in frm
1640 to_nxt = to;
1641 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1642 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001643 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001644 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001645 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1646 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001647 if (n == size_t(-1))
1648 {
1649 // need to recover to_nxt
1650 for (to_nxt = to; frm != frm_nxt; ++frm)
1651 {
Ben Craig3756b922016-03-09 15:39:39 +00001652 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001653 if (n == size_t(-1))
1654 break;
1655 to_nxt += n;
1656 }
1657 frm_nxt = frm;
1658 return error;
1659 }
1660 if (n == 0)
1661 return partial;
1662 to_nxt += n;
1663 if (to_nxt == to_end)
1664 break;
1665 if (fend != frm_end) // set up next null terminated sequence
1666 {
1667 // Try to write the terminating null
1668 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001669 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001670 if (n == size_t(-1)) // on error
1671 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001672 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001673 return partial;
1674 for (extern_type* p = tmp; n; --n) // write it
1675 *to_nxt++ = *p++;
1676 ++frm_nxt;
1677 // look for next null in frm
1678 for (fend = frm_nxt; fend != frm_end; ++fend)
1679 if (*fend == 0)
1680 break;
1681 }
1682 }
1683 return frm_nxt == frm_end ? ok : partial;
1684}
1685
1686codecvt<wchar_t, char, mbstate_t>::result
1687codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001688 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001689 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1690{
1691 // look for first internal null in frm
1692 const extern_type* fend = frm;
1693 for (; fend != frm_end; ++fend)
1694 if (*fend == 0)
1695 break;
1696 // loop over all null-terminated sequences in frm
1697 to_nxt = to;
1698 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1699 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001700 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001701 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001702 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1703 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001704 if (n == size_t(-1))
1705 {
1706 // need to recover to_nxt
1707 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1708 {
Ben Craig3756b922016-03-09 15:39:39 +00001709 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1710 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001711 switch (n)
1712 {
1713 case 0:
1714 ++frm;
1715 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001716 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001717 frm_nxt = frm;
1718 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001719 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001720 frm_nxt = frm;
1721 return partial;
1722 default:
1723 frm += n;
1724 break;
1725 }
1726 }
1727 frm_nxt = frm;
1728 return frm_nxt == frm_end ? ok : partial;
1729 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001730 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001731 return error;
1732 to_nxt += n;
1733 if (to_nxt == to_end)
1734 break;
1735 if (fend != frm_end) // set up next null terminated sequence
1736 {
1737 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001738 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001739 if (n != 0) // on error
1740 return error;
1741 ++to_nxt;
1742 ++frm_nxt;
1743 // look for next null in frm
1744 for (fend = frm_nxt; fend != frm_end; ++fend)
1745 if (*fend == 0)
1746 break;
1747 }
1748 }
1749 return frm_nxt == frm_end ? ok : partial;
1750}
1751
1752codecvt<wchar_t, char, mbstate_t>::result
1753codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1754 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1755{
1756 to_nxt = to;
1757 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001758 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001759 if (n == size_t(-1) || n == 0) // on error
1760 return error;
1761 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001762 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001763 return partial;
1764 for (extern_type* p = tmp; n; --n) // write it
1765 *to_nxt++ = *p++;
1766 return ok;
1767}
1768
1769int
Louis Dionne65358e12021-03-01 12:09:45 -05001770codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001771{
Ben Craig3756b922016-03-09 15:39:39 +00001772 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001773 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001774
1775 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001776 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001777 return 1; // which take more than 1 char to form a wchar_t
1778 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001779}
1780
1781bool
Louis Dionne65358e12021-03-01 12:09:45 -05001782codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001783{
1784 return false;
1785}
1786
1787int
1788codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1789 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1790{
1791 int nbytes = 0;
1792 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1793 {
Ben Craig3756b922016-03-09 15:39:39 +00001794 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001795 switch (n)
1796 {
1797 case 0:
1798 ++nbytes;
1799 ++frm;
1800 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001801 case size_t(-1):
1802 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001803 return nbytes;
1804 default:
1805 nbytes += n;
1806 frm += n;
1807 break;
1808 }
1809 }
1810 return nbytes;
1811}
1812
1813int
Louis Dionne65358e12021-03-01 12:09:45 -05001814codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001815{
Ben Craig3756b922016-03-09 15:39:39 +00001816 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001817}
Louis Dionne89258142021-08-23 15:32:36 -04001818#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001819
1820// Valid UTF ranges
1821// UTF-32 UTF-16 UTF-8 # of code points
1822// first second first second third fourth
1823// 000000 - 00007F 0000 - 007F 00 - 7F 127
1824// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1825// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1826// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1827// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1828// 00D800 - 00DFFF invalid
1829// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1830// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1831// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1832// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1833
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001834static
1835codecvt_base::result
1836utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1837 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1838 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1839{
1840 frm_nxt = frm;
1841 to_nxt = to;
1842 if (mode & generate_header)
1843 {
1844 if (to_end-to_nxt < 3)
1845 return codecvt_base::partial;
1846 *to_nxt++ = static_cast<uint8_t>(0xEF);
1847 *to_nxt++ = static_cast<uint8_t>(0xBB);
1848 *to_nxt++ = static_cast<uint8_t>(0xBF);
1849 }
1850 for (; frm_nxt < frm_end; ++frm_nxt)
1851 {
1852 uint16_t wc1 = *frm_nxt;
1853 if (wc1 > Maxcode)
1854 return codecvt_base::error;
1855 if (wc1 < 0x0080)
1856 {
1857 if (to_end-to_nxt < 1)
1858 return codecvt_base::partial;
1859 *to_nxt++ = static_cast<uint8_t>(wc1);
1860 }
1861 else if (wc1 < 0x0800)
1862 {
1863 if (to_end-to_nxt < 2)
1864 return codecvt_base::partial;
1865 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1866 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1867 }
1868 else if (wc1 < 0xD800)
1869 {
1870 if (to_end-to_nxt < 3)
1871 return codecvt_base::partial;
1872 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1873 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1874 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1875 }
1876 else if (wc1 < 0xDC00)
1877 {
1878 if (frm_end-frm_nxt < 2)
1879 return codecvt_base::partial;
1880 uint16_t wc2 = frm_nxt[1];
1881 if ((wc2 & 0xFC00) != 0xDC00)
1882 return codecvt_base::error;
1883 if (to_end-to_nxt < 4)
1884 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001885 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1886 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001887 return codecvt_base::error;
1888 ++frm_nxt;
1889 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1890 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1891 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1892 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1893 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1894 }
1895 else if (wc1 < 0xE000)
1896 {
1897 return codecvt_base::error;
1898 }
1899 else
1900 {
1901 if (to_end-to_nxt < 3)
1902 return codecvt_base::partial;
1903 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1904 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1905 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1906 }
1907 }
1908 return codecvt_base::ok;
1909}
1910
1911static
1912codecvt_base::result
1913utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1914 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1915 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1916{
1917 frm_nxt = frm;
1918 to_nxt = to;
1919 if (mode & generate_header)
1920 {
1921 if (to_end-to_nxt < 3)
1922 return codecvt_base::partial;
1923 *to_nxt++ = static_cast<uint8_t>(0xEF);
1924 *to_nxt++ = static_cast<uint8_t>(0xBB);
1925 *to_nxt++ = static_cast<uint8_t>(0xBF);
1926 }
1927 for (; frm_nxt < frm_end; ++frm_nxt)
1928 {
1929 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1930 if (wc1 > Maxcode)
1931 return codecvt_base::error;
1932 if (wc1 < 0x0080)
1933 {
1934 if (to_end-to_nxt < 1)
1935 return codecvt_base::partial;
1936 *to_nxt++ = static_cast<uint8_t>(wc1);
1937 }
1938 else if (wc1 < 0x0800)
1939 {
1940 if (to_end-to_nxt < 2)
1941 return codecvt_base::partial;
1942 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1943 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1944 }
1945 else if (wc1 < 0xD800)
1946 {
1947 if (to_end-to_nxt < 3)
1948 return codecvt_base::partial;
1949 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1950 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1951 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1952 }
1953 else if (wc1 < 0xDC00)
1954 {
1955 if (frm_end-frm_nxt < 2)
1956 return codecvt_base::partial;
1957 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1958 if ((wc2 & 0xFC00) != 0xDC00)
1959 return codecvt_base::error;
1960 if (to_end-to_nxt < 4)
1961 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001962 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1963 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001964 return codecvt_base::error;
1965 ++frm_nxt;
1966 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1967 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1968 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1969 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1970 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1971 }
1972 else if (wc1 < 0xE000)
1973 {
1974 return codecvt_base::error;
1975 }
1976 else
1977 {
1978 if (to_end-to_nxt < 3)
1979 return codecvt_base::partial;
1980 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1981 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1982 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1983 }
1984 }
1985 return codecvt_base::ok;
1986}
1987
1988static
1989codecvt_base::result
1990utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1991 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1992 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1993{
1994 frm_nxt = frm;
1995 to_nxt = to;
1996 if (mode & consume_header)
1997 {
1998 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1999 frm_nxt[2] == 0xBF)
2000 frm_nxt += 3;
2001 }
2002 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2003 {
2004 uint8_t c1 = *frm_nxt;
2005 if (c1 > Maxcode)
2006 return codecvt_base::error;
2007 if (c1 < 0x80)
2008 {
2009 *to_nxt = static_cast<uint16_t>(c1);
2010 ++frm_nxt;
2011 }
2012 else if (c1 < 0xC2)
2013 {
2014 return codecvt_base::error;
2015 }
2016 else if (c1 < 0xE0)
2017 {
2018 if (frm_end-frm_nxt < 2)
2019 return codecvt_base::partial;
2020 uint8_t c2 = frm_nxt[1];
2021 if ((c2 & 0xC0) != 0x80)
2022 return codecvt_base::error;
2023 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2024 if (t > Maxcode)
2025 return codecvt_base::error;
2026 *to_nxt = t;
2027 frm_nxt += 2;
2028 }
2029 else if (c1 < 0xF0)
2030 {
2031 if (frm_end-frm_nxt < 3)
2032 return codecvt_base::partial;
2033 uint8_t c2 = frm_nxt[1];
2034 uint8_t c3 = frm_nxt[2];
2035 switch (c1)
2036 {
2037 case 0xE0:
2038 if ((c2 & 0xE0) != 0xA0)
2039 return codecvt_base::error;
2040 break;
2041 case 0xED:
2042 if ((c2 & 0xE0) != 0x80)
2043 return codecvt_base::error;
2044 break;
2045 default:
2046 if ((c2 & 0xC0) != 0x80)
2047 return codecvt_base::error;
2048 break;
2049 }
2050 if ((c3 & 0xC0) != 0x80)
2051 return codecvt_base::error;
2052 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2053 | ((c2 & 0x3F) << 6)
2054 | (c3 & 0x3F));
2055 if (t > Maxcode)
2056 return codecvt_base::error;
2057 *to_nxt = t;
2058 frm_nxt += 3;
2059 }
2060 else if (c1 < 0xF5)
2061 {
2062 if (frm_end-frm_nxt < 4)
2063 return codecvt_base::partial;
2064 uint8_t c2 = frm_nxt[1];
2065 uint8_t c3 = frm_nxt[2];
2066 uint8_t c4 = frm_nxt[3];
2067 switch (c1)
2068 {
2069 case 0xF0:
2070 if (!(0x90 <= c2 && c2 <= 0xBF))
2071 return codecvt_base::error;
2072 break;
2073 case 0xF4:
2074 if ((c2 & 0xF0) != 0x80)
2075 return codecvt_base::error;
2076 break;
2077 default:
2078 if ((c2 & 0xC0) != 0x80)
2079 return codecvt_base::error;
2080 break;
2081 }
2082 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2083 return codecvt_base::error;
2084 if (to_end-to_nxt < 2)
2085 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002086 if ((((c1 & 7UL) << 18) +
2087 ((c2 & 0x3FUL) << 12) +
2088 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002089 return codecvt_base::error;
2090 *to_nxt = static_cast<uint16_t>(
2091 0xD800
2092 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2093 | ((c2 & 0x0F) << 2)
2094 | ((c3 & 0x30) >> 4));
2095 *++to_nxt = static_cast<uint16_t>(
2096 0xDC00
2097 | ((c3 & 0x0F) << 6)
2098 | (c4 & 0x3F));
2099 frm_nxt += 4;
2100 }
2101 else
2102 {
2103 return codecvt_base::error;
2104 }
2105 }
2106 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2107}
2108
2109static
2110codecvt_base::result
2111utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2112 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2113 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2114{
2115 frm_nxt = frm;
2116 to_nxt = to;
2117 if (mode & consume_header)
2118 {
2119 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2120 frm_nxt[2] == 0xBF)
2121 frm_nxt += 3;
2122 }
2123 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2124 {
2125 uint8_t c1 = *frm_nxt;
2126 if (c1 > Maxcode)
2127 return codecvt_base::error;
2128 if (c1 < 0x80)
2129 {
2130 *to_nxt = static_cast<uint32_t>(c1);
2131 ++frm_nxt;
2132 }
2133 else if (c1 < 0xC2)
2134 {
2135 return codecvt_base::error;
2136 }
2137 else if (c1 < 0xE0)
2138 {
2139 if (frm_end-frm_nxt < 2)
2140 return codecvt_base::partial;
2141 uint8_t c2 = frm_nxt[1];
2142 if ((c2 & 0xC0) != 0x80)
2143 return codecvt_base::error;
2144 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2145 if (t > Maxcode)
2146 return codecvt_base::error;
2147 *to_nxt = static_cast<uint32_t>(t);
2148 frm_nxt += 2;
2149 }
2150 else if (c1 < 0xF0)
2151 {
2152 if (frm_end-frm_nxt < 3)
2153 return codecvt_base::partial;
2154 uint8_t c2 = frm_nxt[1];
2155 uint8_t c3 = frm_nxt[2];
2156 switch (c1)
2157 {
2158 case 0xE0:
2159 if ((c2 & 0xE0) != 0xA0)
2160 return codecvt_base::error;
2161 break;
2162 case 0xED:
2163 if ((c2 & 0xE0) != 0x80)
2164 return codecvt_base::error;
2165 break;
2166 default:
2167 if ((c2 & 0xC0) != 0x80)
2168 return codecvt_base::error;
2169 break;
2170 }
2171 if ((c3 & 0xC0) != 0x80)
2172 return codecvt_base::error;
2173 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2174 | ((c2 & 0x3F) << 6)
2175 | (c3 & 0x3F));
2176 if (t > Maxcode)
2177 return codecvt_base::error;
2178 *to_nxt = static_cast<uint32_t>(t);
2179 frm_nxt += 3;
2180 }
2181 else if (c1 < 0xF5)
2182 {
2183 if (frm_end-frm_nxt < 4)
2184 return codecvt_base::partial;
2185 uint8_t c2 = frm_nxt[1];
2186 uint8_t c3 = frm_nxt[2];
2187 uint8_t c4 = frm_nxt[3];
2188 switch (c1)
2189 {
2190 case 0xF0:
2191 if (!(0x90 <= c2 && c2 <= 0xBF))
2192 return codecvt_base::error;
2193 break;
2194 case 0xF4:
2195 if ((c2 & 0xF0) != 0x80)
2196 return codecvt_base::error;
2197 break;
2198 default:
2199 if ((c2 & 0xC0) != 0x80)
2200 return codecvt_base::error;
2201 break;
2202 }
2203 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2204 return codecvt_base::error;
2205 if (to_end-to_nxt < 2)
2206 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002207 if ((((c1 & 7UL) << 18) +
2208 ((c2 & 0x3FUL) << 12) +
2209 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002210 return codecvt_base::error;
2211 *to_nxt = static_cast<uint32_t>(
2212 0xD800
2213 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2214 | ((c2 & 0x0F) << 2)
2215 | ((c3 & 0x30) >> 4));
2216 *++to_nxt = static_cast<uint32_t>(
2217 0xDC00
2218 | ((c3 & 0x0F) << 6)
2219 | (c4 & 0x3F));
2220 frm_nxt += 4;
2221 }
2222 else
2223 {
2224 return codecvt_base::error;
2225 }
2226 }
2227 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2228}
2229
2230static
2231int
2232utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2233 size_t mx, unsigned long Maxcode = 0x10FFFF,
2234 codecvt_mode mode = codecvt_mode(0))
2235{
2236 const uint8_t* frm_nxt = frm;
2237 if (mode & consume_header)
2238 {
2239 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2240 frm_nxt[2] == 0xBF)
2241 frm_nxt += 3;
2242 }
2243 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2244 {
2245 uint8_t c1 = *frm_nxt;
2246 if (c1 > Maxcode)
2247 break;
2248 if (c1 < 0x80)
2249 {
2250 ++frm_nxt;
2251 }
2252 else if (c1 < 0xC2)
2253 {
2254 break;
2255 }
2256 else if (c1 < 0xE0)
2257 {
2258 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2259 break;
2260 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2261 if (t > Maxcode)
2262 break;
2263 frm_nxt += 2;
2264 }
2265 else if (c1 < 0xF0)
2266 {
2267 if (frm_end-frm_nxt < 3)
2268 break;
2269 uint8_t c2 = frm_nxt[1];
2270 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002271 switch (c1)
2272 {
2273 case 0xE0:
2274 if ((c2 & 0xE0) != 0xA0)
2275 return static_cast<int>(frm_nxt - frm);
2276 break;
2277 case 0xED:
2278 if ((c2 & 0xE0) != 0x80)
2279 return static_cast<int>(frm_nxt - frm);
2280 break;
2281 default:
2282 if ((c2 & 0xC0) != 0x80)
2283 return static_cast<int>(frm_nxt - frm);
2284 break;
2285 }
2286 if ((c3 & 0xC0) != 0x80)
2287 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002288 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002289 break;
2290 frm_nxt += 3;
2291 }
2292 else if (c1 < 0xF5)
2293 {
2294 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2295 break;
2296 uint8_t c2 = frm_nxt[1];
2297 uint8_t c3 = frm_nxt[2];
2298 uint8_t c4 = frm_nxt[3];
2299 switch (c1)
2300 {
2301 case 0xF0:
2302 if (!(0x90 <= c2 && c2 <= 0xBF))
2303 return static_cast<int>(frm_nxt - frm);
2304 break;
2305 case 0xF4:
2306 if ((c2 & 0xF0) != 0x80)
2307 return static_cast<int>(frm_nxt - frm);
2308 break;
2309 default:
2310 if ((c2 & 0xC0) != 0x80)
2311 return static_cast<int>(frm_nxt - frm);
2312 break;
2313 }
2314 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2315 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002316 if ((((c1 & 7UL) << 18) +
2317 ((c2 & 0x3FUL) << 12) +
2318 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002319 break;
2320 ++nchar16_t;
2321 frm_nxt += 4;
2322 }
2323 else
2324 {
2325 break;
2326 }
2327 }
2328 return static_cast<int>(frm_nxt - frm);
2329}
2330
2331static
2332codecvt_base::result
2333ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2334 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2335 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2336{
2337 frm_nxt = frm;
2338 to_nxt = to;
2339 if (mode & generate_header)
2340 {
2341 if (to_end-to_nxt < 3)
2342 return codecvt_base::partial;
2343 *to_nxt++ = static_cast<uint8_t>(0xEF);
2344 *to_nxt++ = static_cast<uint8_t>(0xBB);
2345 *to_nxt++ = static_cast<uint8_t>(0xBF);
2346 }
2347 for (; frm_nxt < frm_end; ++frm_nxt)
2348 {
2349 uint32_t wc = *frm_nxt;
2350 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2351 return codecvt_base::error;
2352 if (wc < 0x000080)
2353 {
2354 if (to_end-to_nxt < 1)
2355 return codecvt_base::partial;
2356 *to_nxt++ = static_cast<uint8_t>(wc);
2357 }
2358 else if (wc < 0x000800)
2359 {
2360 if (to_end-to_nxt < 2)
2361 return codecvt_base::partial;
2362 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2363 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2364 }
2365 else if (wc < 0x010000)
2366 {
2367 if (to_end-to_nxt < 3)
2368 return codecvt_base::partial;
2369 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2370 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2371 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2372 }
2373 else // if (wc < 0x110000)
2374 {
2375 if (to_end-to_nxt < 4)
2376 return codecvt_base::partial;
2377 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2378 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2379 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2380 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2381 }
2382 }
2383 return codecvt_base::ok;
2384}
2385
2386static
2387codecvt_base::result
2388utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2389 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2390 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2391{
2392 frm_nxt = frm;
2393 to_nxt = to;
2394 if (mode & consume_header)
2395 {
2396 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2397 frm_nxt[2] == 0xBF)
2398 frm_nxt += 3;
2399 }
2400 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2401 {
2402 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2403 if (c1 < 0x80)
2404 {
2405 if (c1 > Maxcode)
2406 return codecvt_base::error;
2407 *to_nxt = static_cast<uint32_t>(c1);
2408 ++frm_nxt;
2409 }
2410 else if (c1 < 0xC2)
2411 {
2412 return codecvt_base::error;
2413 }
2414 else if (c1 < 0xE0)
2415 {
2416 if (frm_end-frm_nxt < 2)
2417 return codecvt_base::partial;
2418 uint8_t c2 = frm_nxt[1];
2419 if ((c2 & 0xC0) != 0x80)
2420 return codecvt_base::error;
2421 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2422 | (c2 & 0x3F));
2423 if (t > Maxcode)
2424 return codecvt_base::error;
2425 *to_nxt = t;
2426 frm_nxt += 2;
2427 }
2428 else if (c1 < 0xF0)
2429 {
2430 if (frm_end-frm_nxt < 3)
2431 return codecvt_base::partial;
2432 uint8_t c2 = frm_nxt[1];
2433 uint8_t c3 = frm_nxt[2];
2434 switch (c1)
2435 {
2436 case 0xE0:
2437 if ((c2 & 0xE0) != 0xA0)
2438 return codecvt_base::error;
2439 break;
2440 case 0xED:
2441 if ((c2 & 0xE0) != 0x80)
2442 return codecvt_base::error;
2443 break;
2444 default:
2445 if ((c2 & 0xC0) != 0x80)
2446 return codecvt_base::error;
2447 break;
2448 }
2449 if ((c3 & 0xC0) != 0x80)
2450 return codecvt_base::error;
2451 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2452 | ((c2 & 0x3F) << 6)
2453 | (c3 & 0x3F));
2454 if (t > Maxcode)
2455 return codecvt_base::error;
2456 *to_nxt = t;
2457 frm_nxt += 3;
2458 }
2459 else if (c1 < 0xF5)
2460 {
2461 if (frm_end-frm_nxt < 4)
2462 return codecvt_base::partial;
2463 uint8_t c2 = frm_nxt[1];
2464 uint8_t c3 = frm_nxt[2];
2465 uint8_t c4 = frm_nxt[3];
2466 switch (c1)
2467 {
2468 case 0xF0:
2469 if (!(0x90 <= c2 && c2 <= 0xBF))
2470 return codecvt_base::error;
2471 break;
2472 case 0xF4:
2473 if ((c2 & 0xF0) != 0x80)
2474 return codecvt_base::error;
2475 break;
2476 default:
2477 if ((c2 & 0xC0) != 0x80)
2478 return codecvt_base::error;
2479 break;
2480 }
2481 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2482 return codecvt_base::error;
2483 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2484 | ((c2 & 0x3F) << 12)
2485 | ((c3 & 0x3F) << 6)
2486 | (c4 & 0x3F));
2487 if (t > Maxcode)
2488 return codecvt_base::error;
2489 *to_nxt = t;
2490 frm_nxt += 4;
2491 }
2492 else
2493 {
2494 return codecvt_base::error;
2495 }
2496 }
2497 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2498}
2499
2500static
2501int
2502utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2503 size_t mx, unsigned long Maxcode = 0x10FFFF,
2504 codecvt_mode mode = codecvt_mode(0))
2505{
2506 const uint8_t* frm_nxt = frm;
2507 if (mode & consume_header)
2508 {
2509 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2510 frm_nxt[2] == 0xBF)
2511 frm_nxt += 3;
2512 }
2513 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2514 {
2515 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2516 if (c1 < 0x80)
2517 {
2518 if (c1 > Maxcode)
2519 break;
2520 ++frm_nxt;
2521 }
2522 else if (c1 < 0xC2)
2523 {
2524 break;
2525 }
2526 else if (c1 < 0xE0)
2527 {
2528 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2529 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002530 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002531 break;
2532 frm_nxt += 2;
2533 }
2534 else if (c1 < 0xF0)
2535 {
2536 if (frm_end-frm_nxt < 3)
2537 break;
2538 uint8_t c2 = frm_nxt[1];
2539 uint8_t c3 = frm_nxt[2];
2540 switch (c1)
2541 {
2542 case 0xE0:
2543 if ((c2 & 0xE0) != 0xA0)
2544 return static_cast<int>(frm_nxt - frm);
2545 break;
2546 case 0xED:
2547 if ((c2 & 0xE0) != 0x80)
2548 return static_cast<int>(frm_nxt - frm);
2549 break;
2550 default:
2551 if ((c2 & 0xC0) != 0x80)
2552 return static_cast<int>(frm_nxt - frm);
2553 break;
2554 }
2555 if ((c3 & 0xC0) != 0x80)
2556 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002557 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002558 break;
2559 frm_nxt += 3;
2560 }
2561 else if (c1 < 0xF5)
2562 {
2563 if (frm_end-frm_nxt < 4)
2564 break;
2565 uint8_t c2 = frm_nxt[1];
2566 uint8_t c3 = frm_nxt[2];
2567 uint8_t c4 = frm_nxt[3];
2568 switch (c1)
2569 {
2570 case 0xF0:
2571 if (!(0x90 <= c2 && c2 <= 0xBF))
2572 return static_cast<int>(frm_nxt - frm);
2573 break;
2574 case 0xF4:
2575 if ((c2 & 0xF0) != 0x80)
2576 return static_cast<int>(frm_nxt - frm);
2577 break;
2578 default:
2579 if ((c2 & 0xC0) != 0x80)
2580 return static_cast<int>(frm_nxt - frm);
2581 break;
2582 }
2583 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2584 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002585 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2586 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002587 break;
2588 frm_nxt += 4;
2589 }
2590 else
2591 {
2592 break;
2593 }
2594 }
2595 return static_cast<int>(frm_nxt - frm);
2596}
2597
2598static
2599codecvt_base::result
2600ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2601 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2602 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2603{
2604 frm_nxt = frm;
2605 to_nxt = to;
2606 if (mode & generate_header)
2607 {
2608 if (to_end-to_nxt < 3)
2609 return codecvt_base::partial;
2610 *to_nxt++ = static_cast<uint8_t>(0xEF);
2611 *to_nxt++ = static_cast<uint8_t>(0xBB);
2612 *to_nxt++ = static_cast<uint8_t>(0xBF);
2613 }
2614 for (; frm_nxt < frm_end; ++frm_nxt)
2615 {
2616 uint16_t wc = *frm_nxt;
2617 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2618 return codecvt_base::error;
2619 if (wc < 0x0080)
2620 {
2621 if (to_end-to_nxt < 1)
2622 return codecvt_base::partial;
2623 *to_nxt++ = static_cast<uint8_t>(wc);
2624 }
2625 else if (wc < 0x0800)
2626 {
2627 if (to_end-to_nxt < 2)
2628 return codecvt_base::partial;
2629 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2630 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2631 }
2632 else // if (wc <= 0xFFFF)
2633 {
2634 if (to_end-to_nxt < 3)
2635 return codecvt_base::partial;
2636 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2637 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2638 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2639 }
2640 }
2641 return codecvt_base::ok;
2642}
2643
2644static
2645codecvt_base::result
2646utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2647 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2648 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2649{
2650 frm_nxt = frm;
2651 to_nxt = to;
2652 if (mode & consume_header)
2653 {
2654 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2655 frm_nxt[2] == 0xBF)
2656 frm_nxt += 3;
2657 }
2658 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2659 {
2660 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2661 if (c1 < 0x80)
2662 {
2663 if (c1 > Maxcode)
2664 return codecvt_base::error;
2665 *to_nxt = static_cast<uint16_t>(c1);
2666 ++frm_nxt;
2667 }
2668 else if (c1 < 0xC2)
2669 {
2670 return codecvt_base::error;
2671 }
2672 else if (c1 < 0xE0)
2673 {
2674 if (frm_end-frm_nxt < 2)
2675 return codecvt_base::partial;
2676 uint8_t c2 = frm_nxt[1];
2677 if ((c2 & 0xC0) != 0x80)
2678 return codecvt_base::error;
2679 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2680 | (c2 & 0x3F));
2681 if (t > Maxcode)
2682 return codecvt_base::error;
2683 *to_nxt = t;
2684 frm_nxt += 2;
2685 }
2686 else if (c1 < 0xF0)
2687 {
2688 if (frm_end-frm_nxt < 3)
2689 return codecvt_base::partial;
2690 uint8_t c2 = frm_nxt[1];
2691 uint8_t c3 = frm_nxt[2];
2692 switch (c1)
2693 {
2694 case 0xE0:
2695 if ((c2 & 0xE0) != 0xA0)
2696 return codecvt_base::error;
2697 break;
2698 case 0xED:
2699 if ((c2 & 0xE0) != 0x80)
2700 return codecvt_base::error;
2701 break;
2702 default:
2703 if ((c2 & 0xC0) != 0x80)
2704 return codecvt_base::error;
2705 break;
2706 }
2707 if ((c3 & 0xC0) != 0x80)
2708 return codecvt_base::error;
2709 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2710 | ((c2 & 0x3F) << 6)
2711 | (c3 & 0x3F));
2712 if (t > Maxcode)
2713 return codecvt_base::error;
2714 *to_nxt = t;
2715 frm_nxt += 3;
2716 }
2717 else
2718 {
2719 return codecvt_base::error;
2720 }
2721 }
2722 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2723}
2724
2725static
2726int
2727utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2728 size_t mx, unsigned long Maxcode = 0x10FFFF,
2729 codecvt_mode mode = codecvt_mode(0))
2730{
2731 const uint8_t* frm_nxt = frm;
2732 if (mode & consume_header)
2733 {
2734 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2735 frm_nxt[2] == 0xBF)
2736 frm_nxt += 3;
2737 }
2738 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2739 {
2740 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2741 if (c1 < 0x80)
2742 {
2743 if (c1 > Maxcode)
2744 break;
2745 ++frm_nxt;
2746 }
2747 else if (c1 < 0xC2)
2748 {
2749 break;
2750 }
2751 else if (c1 < 0xE0)
2752 {
2753 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2754 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002755 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002756 break;
2757 frm_nxt += 2;
2758 }
2759 else if (c1 < 0xF0)
2760 {
2761 if (frm_end-frm_nxt < 3)
2762 break;
2763 uint8_t c2 = frm_nxt[1];
2764 uint8_t c3 = frm_nxt[2];
2765 switch (c1)
2766 {
2767 case 0xE0:
2768 if ((c2 & 0xE0) != 0xA0)
2769 return static_cast<int>(frm_nxt - frm);
2770 break;
2771 case 0xED:
2772 if ((c2 & 0xE0) != 0x80)
2773 return static_cast<int>(frm_nxt - frm);
2774 break;
2775 default:
2776 if ((c2 & 0xC0) != 0x80)
2777 return static_cast<int>(frm_nxt - frm);
2778 break;
2779 }
2780 if ((c3 & 0xC0) != 0x80)
2781 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002782 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002783 break;
2784 frm_nxt += 3;
2785 }
2786 else
2787 {
2788 break;
2789 }
2790 }
2791 return static_cast<int>(frm_nxt - frm);
2792}
2793
2794static
2795codecvt_base::result
2796ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2797 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2798 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2799{
2800 frm_nxt = frm;
2801 to_nxt = to;
2802 if (mode & generate_header)
2803 {
2804 if (to_end-to_nxt < 2)
2805 return codecvt_base::partial;
2806 *to_nxt++ = static_cast<uint8_t>(0xFE);
2807 *to_nxt++ = static_cast<uint8_t>(0xFF);
2808 }
2809 for (; frm_nxt < frm_end; ++frm_nxt)
2810 {
2811 uint32_t wc = *frm_nxt;
2812 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2813 return codecvt_base::error;
2814 if (wc < 0x010000)
2815 {
2816 if (to_end-to_nxt < 2)
2817 return codecvt_base::partial;
2818 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2819 *to_nxt++ = static_cast<uint8_t>(wc);
2820 }
2821 else
2822 {
2823 if (to_end-to_nxt < 4)
2824 return codecvt_base::partial;
2825 uint16_t t = static_cast<uint16_t>(
2826 0xD800
2827 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2828 | ((wc & 0x00FC00) >> 10));
2829 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2830 *to_nxt++ = static_cast<uint8_t>(t);
2831 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2832 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2833 *to_nxt++ = static_cast<uint8_t>(t);
2834 }
2835 }
2836 return codecvt_base::ok;
2837}
2838
2839static
2840codecvt_base::result
2841utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2842 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2843 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2844{
2845 frm_nxt = frm;
2846 to_nxt = to;
2847 if (mode & consume_header)
2848 {
2849 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2850 frm_nxt += 2;
2851 }
2852 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2853 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002854 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002855 if ((c1 & 0xFC00) == 0xDC00)
2856 return codecvt_base::error;
2857 if ((c1 & 0xFC00) != 0xD800)
2858 {
2859 if (c1 > Maxcode)
2860 return codecvt_base::error;
2861 *to_nxt = static_cast<uint32_t>(c1);
2862 frm_nxt += 2;
2863 }
2864 else
2865 {
2866 if (frm_end-frm_nxt < 4)
2867 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002868 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002869 if ((c2 & 0xFC00) != 0xDC00)
2870 return codecvt_base::error;
2871 uint32_t t = static_cast<uint32_t>(
2872 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2873 | ((c1 & 0x003F) << 10)
2874 | (c2 & 0x03FF));
2875 if (t > Maxcode)
2876 return codecvt_base::error;
2877 *to_nxt = t;
2878 frm_nxt += 4;
2879 }
2880 }
2881 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2882}
2883
2884static
2885int
2886utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2887 size_t mx, unsigned long Maxcode = 0x10FFFF,
2888 codecvt_mode mode = codecvt_mode(0))
2889{
2890 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002891 if (mode & consume_header)
2892 {
2893 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2894 frm_nxt += 2;
2895 }
2896 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2897 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002898 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002899 if ((c1 & 0xFC00) == 0xDC00)
2900 break;
2901 if ((c1 & 0xFC00) != 0xD800)
2902 {
2903 if (c1 > Maxcode)
2904 break;
2905 frm_nxt += 2;
2906 }
2907 else
2908 {
2909 if (frm_end-frm_nxt < 4)
2910 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002911 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002912 if ((c2 & 0xFC00) != 0xDC00)
2913 break;
2914 uint32_t t = static_cast<uint32_t>(
2915 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2916 | ((c1 & 0x003F) << 10)
2917 | (c2 & 0x03FF));
2918 if (t > Maxcode)
2919 break;
2920 frm_nxt += 4;
2921 }
2922 }
2923 return static_cast<int>(frm_nxt - frm);
2924}
2925
2926static
2927codecvt_base::result
2928ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2929 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2930 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2931{
2932 frm_nxt = frm;
2933 to_nxt = to;
2934 if (mode & generate_header)
2935 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002936 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002937 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002938 *to_nxt++ = static_cast<uint8_t>(0xFF);
2939 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002940 }
2941 for (; frm_nxt < frm_end; ++frm_nxt)
2942 {
2943 uint32_t wc = *frm_nxt;
2944 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2945 return codecvt_base::error;
2946 if (wc < 0x010000)
2947 {
2948 if (to_end-to_nxt < 2)
2949 return codecvt_base::partial;
2950 *to_nxt++ = static_cast<uint8_t>(wc);
2951 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2952 }
2953 else
2954 {
2955 if (to_end-to_nxt < 4)
2956 return codecvt_base::partial;
2957 uint16_t t = static_cast<uint16_t>(
2958 0xD800
2959 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2960 | ((wc & 0x00FC00) >> 10));
2961 *to_nxt++ = static_cast<uint8_t>(t);
2962 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2963 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2964 *to_nxt++ = static_cast<uint8_t>(t);
2965 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2966 }
2967 }
2968 return codecvt_base::ok;
2969}
2970
2971static
2972codecvt_base::result
2973utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2974 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2975 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2976{
2977 frm_nxt = frm;
2978 to_nxt = to;
2979 if (mode & consume_header)
2980 {
2981 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2982 frm_nxt += 2;
2983 }
2984 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2985 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002986 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002987 if ((c1 & 0xFC00) == 0xDC00)
2988 return codecvt_base::error;
2989 if ((c1 & 0xFC00) != 0xD800)
2990 {
2991 if (c1 > Maxcode)
2992 return codecvt_base::error;
2993 *to_nxt = static_cast<uint32_t>(c1);
2994 frm_nxt += 2;
2995 }
2996 else
2997 {
2998 if (frm_end-frm_nxt < 4)
2999 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00003000 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003001 if ((c2 & 0xFC00) != 0xDC00)
3002 return codecvt_base::error;
3003 uint32_t t = static_cast<uint32_t>(
3004 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3005 | ((c1 & 0x003F) << 10)
3006 | (c2 & 0x03FF));
3007 if (t > Maxcode)
3008 return codecvt_base::error;
3009 *to_nxt = t;
3010 frm_nxt += 4;
3011 }
3012 }
3013 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3014}
3015
3016static
3017int
3018utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
3019 size_t mx, unsigned long Maxcode = 0x10FFFF,
3020 codecvt_mode mode = codecvt_mode(0))
3021{
3022 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003023 if (mode & consume_header)
3024 {
3025 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3026 frm_nxt += 2;
3027 }
3028 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3029 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003030 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003031 if ((c1 & 0xFC00) == 0xDC00)
3032 break;
3033 if ((c1 & 0xFC00) != 0xD800)
3034 {
3035 if (c1 > Maxcode)
3036 break;
3037 frm_nxt += 2;
3038 }
3039 else
3040 {
3041 if (frm_end-frm_nxt < 4)
3042 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00003043 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003044 if ((c2 & 0xFC00) != 0xDC00)
3045 break;
3046 uint32_t t = static_cast<uint32_t>(
3047 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3048 | ((c1 & 0x003F) << 10)
3049 | (c2 & 0x03FF));
3050 if (t > Maxcode)
3051 break;
3052 frm_nxt += 4;
3053 }
3054 }
3055 return static_cast<int>(frm_nxt - frm);
3056}
3057
3058static
3059codecvt_base::result
3060ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3061 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3062 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3063{
3064 frm_nxt = frm;
3065 to_nxt = to;
3066 if (mode & generate_header)
3067 {
3068 if (to_end-to_nxt < 2)
3069 return codecvt_base::partial;
3070 *to_nxt++ = static_cast<uint8_t>(0xFE);
3071 *to_nxt++ = static_cast<uint8_t>(0xFF);
3072 }
3073 for (; frm_nxt < frm_end; ++frm_nxt)
3074 {
3075 uint16_t wc = *frm_nxt;
3076 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3077 return codecvt_base::error;
3078 if (to_end-to_nxt < 2)
3079 return codecvt_base::partial;
3080 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3081 *to_nxt++ = static_cast<uint8_t>(wc);
3082 }
3083 return codecvt_base::ok;
3084}
3085
3086static
3087codecvt_base::result
3088utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3089 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3090 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3091{
3092 frm_nxt = frm;
3093 to_nxt = to;
3094 if (mode & consume_header)
3095 {
3096 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3097 frm_nxt += 2;
3098 }
3099 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3100 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003101 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003102 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3103 return codecvt_base::error;
3104 *to_nxt = c1;
3105 frm_nxt += 2;
3106 }
3107 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3108}
3109
3110static
3111int
3112utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3113 size_t mx, unsigned long Maxcode = 0x10FFFF,
3114 codecvt_mode mode = codecvt_mode(0))
3115{
3116 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003117 if (mode & consume_header)
3118 {
3119 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3120 frm_nxt += 2;
3121 }
3122 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3123 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003124 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003125 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3126 break;
3127 frm_nxt += 2;
3128 }
3129 return static_cast<int>(frm_nxt - frm);
3130}
3131
3132static
3133codecvt_base::result
3134ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3135 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3136 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3137{
3138 frm_nxt = frm;
3139 to_nxt = to;
3140 if (mode & generate_header)
3141 {
3142 if (to_end-to_nxt < 2)
3143 return codecvt_base::partial;
3144 *to_nxt++ = static_cast<uint8_t>(0xFF);
3145 *to_nxt++ = static_cast<uint8_t>(0xFE);
3146 }
3147 for (; frm_nxt < frm_end; ++frm_nxt)
3148 {
3149 uint16_t wc = *frm_nxt;
3150 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3151 return codecvt_base::error;
3152 if (to_end-to_nxt < 2)
3153 return codecvt_base::partial;
3154 *to_nxt++ = static_cast<uint8_t>(wc);
3155 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3156 }
3157 return codecvt_base::ok;
3158}
3159
3160static
3161codecvt_base::result
3162utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3163 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3164 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3165{
3166 frm_nxt = frm;
3167 to_nxt = to;
3168 if (mode & consume_header)
3169 {
3170 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3171 frm_nxt += 2;
3172 }
3173 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3174 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003175 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003176 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3177 return codecvt_base::error;
3178 *to_nxt = c1;
3179 frm_nxt += 2;
3180 }
3181 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3182}
3183
3184static
3185int
3186utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3187 size_t mx, unsigned long Maxcode = 0x10FFFF,
3188 codecvt_mode mode = codecvt_mode(0))
3189{
3190 const uint8_t* frm_nxt = frm;
3191 frm_nxt = frm;
3192 if (mode & consume_header)
3193 {
3194 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3195 frm_nxt += 2;
3196 }
3197 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3198 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003199 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003200 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3201 break;
3202 frm_nxt += 2;
3203 }
3204 return static_cast<int>(frm_nxt - frm);
3205}
3206
Howard Hinnantc51e1022010-05-11 19:42:16 +00003207// template <> class codecvt<char16_t, char, mbstate_t>
3208
Howard Hinnantffb308e2010-08-22 00:03:27 +00003209locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003210
3211codecvt<char16_t, char, mbstate_t>::~codecvt()
3212{
3213}
3214
3215codecvt<char16_t, char, mbstate_t>::result
3216codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003217 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003218 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3219{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003220 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3221 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3222 const uint16_t* _frm_nxt = _frm;
3223 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3224 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3225 uint8_t* _to_nxt = _to;
3226 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3227 frm_nxt = frm + (_frm_nxt - _frm);
3228 to_nxt = to + (_to_nxt - _to);
3229 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003230}
3231
3232codecvt<char16_t, char, mbstate_t>::result
3233codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003234 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003235 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3236{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003237 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3238 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3239 const uint8_t* _frm_nxt = _frm;
3240 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3241 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3242 uint16_t* _to_nxt = _to;
3243 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3244 frm_nxt = frm + (_frm_nxt - _frm);
3245 to_nxt = to + (_to_nxt - _to);
3246 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003247}
3248
3249codecvt<char16_t, char, mbstate_t>::result
3250codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3251 extern_type* to, extern_type*, extern_type*& to_nxt) const
3252{
3253 to_nxt = to;
3254 return noconv;
3255}
3256
3257int
Louis Dionne65358e12021-03-01 12:09:45 -05003258codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003259{
3260 return 0;
3261}
3262
3263bool
Louis Dionne65358e12021-03-01 12:09:45 -05003264codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003265{
3266 return false;
3267}
3268
3269int
3270codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3271 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3272{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003273 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3274 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3275 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003276}
3277
3278int
Louis Dionne65358e12021-03-01 12:09:45 -05003279codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003280{
3281 return 4;
3282}
3283
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003284#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003285
3286// template <> class codecvt<char16_t, char8_t, mbstate_t>
3287
3288locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3289
3290codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3291{
3292}
3293
3294codecvt<char16_t, char8_t, mbstate_t>::result
3295codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3296 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3297 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3298{
3299 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3300 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3301 const uint16_t* _frm_nxt = _frm;
3302 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3303 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3304 uint8_t* _to_nxt = _to;
3305 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3306 frm_nxt = frm + (_frm_nxt - _frm);
3307 to_nxt = to + (_to_nxt - _to);
3308 return r;
3309}
3310
3311codecvt<char16_t, char8_t, mbstate_t>::result
3312codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3313 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3314 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3315{
3316 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3317 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3318 const uint8_t* _frm_nxt = _frm;
3319 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3320 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3321 uint16_t* _to_nxt = _to;
3322 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3323 frm_nxt = frm + (_frm_nxt - _frm);
3324 to_nxt = to + (_to_nxt - _to);
3325 return r;
3326}
3327
3328codecvt<char16_t, char8_t, mbstate_t>::result
3329codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3330 extern_type* to, extern_type*, extern_type*& to_nxt) const
3331{
3332 to_nxt = to;
3333 return noconv;
3334}
3335
3336int
Louis Dionne65358e12021-03-01 12:09:45 -05003337codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003338{
3339 return 0;
3340}
3341
3342bool
Louis Dionne65358e12021-03-01 12:09:45 -05003343codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003344{
3345 return false;
3346}
3347
3348int
3349codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3350 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3351{
3352 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3353 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3354 return utf8_to_utf16_length(_frm, _frm_end, mx);
3355}
3356
3357int
Louis Dionne65358e12021-03-01 12:09:45 -05003358codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003359{
3360 return 4;
3361}
3362
3363#endif
3364
Howard Hinnantc51e1022010-05-11 19:42:16 +00003365// template <> class codecvt<char32_t, char, mbstate_t>
3366
Howard Hinnantffb308e2010-08-22 00:03:27 +00003367locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003368
3369codecvt<char32_t, char, mbstate_t>::~codecvt()
3370{
3371}
3372
3373codecvt<char32_t, char, mbstate_t>::result
3374codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003375 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003376 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3377{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003378 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3379 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3380 const uint32_t* _frm_nxt = _frm;
3381 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3382 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3383 uint8_t* _to_nxt = _to;
3384 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3385 frm_nxt = frm + (_frm_nxt - _frm);
3386 to_nxt = to + (_to_nxt - _to);
3387 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003388}
3389
3390codecvt<char32_t, char, mbstate_t>::result
3391codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003392 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003393 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3394{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003395 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3396 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3397 const uint8_t* _frm_nxt = _frm;
3398 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3399 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3400 uint32_t* _to_nxt = _to;
3401 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3402 frm_nxt = frm + (_frm_nxt - _frm);
3403 to_nxt = to + (_to_nxt - _to);
3404 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003405}
3406
3407codecvt<char32_t, char, mbstate_t>::result
3408codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3409 extern_type* to, extern_type*, extern_type*& to_nxt) const
3410{
3411 to_nxt = to;
3412 return noconv;
3413}
3414
3415int
Louis Dionne65358e12021-03-01 12:09:45 -05003416codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003417{
3418 return 0;
3419}
3420
3421bool
Louis Dionne65358e12021-03-01 12:09:45 -05003422codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003423{
3424 return false;
3425}
3426
3427int
3428codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3429 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3430{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003431 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3432 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3433 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003434}
3435
3436int
Louis Dionne65358e12021-03-01 12:09:45 -05003437codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003438{
3439 return 4;
3440}
3441
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003442#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003443
3444// template <> class codecvt<char32_t, char8_t, mbstate_t>
3445
3446locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3447
3448codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3449{
3450}
3451
3452codecvt<char32_t, char8_t, mbstate_t>::result
3453codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3454 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3455 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3456{
3457 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3458 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3459 const uint32_t* _frm_nxt = _frm;
3460 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3461 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3462 uint8_t* _to_nxt = _to;
3463 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3464 frm_nxt = frm + (_frm_nxt - _frm);
3465 to_nxt = to + (_to_nxt - _to);
3466 return r;
3467}
3468
3469codecvt<char32_t, char8_t, mbstate_t>::result
3470codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3471 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3472 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3473{
3474 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3475 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3476 const uint8_t* _frm_nxt = _frm;
3477 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3478 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3479 uint32_t* _to_nxt = _to;
3480 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3481 frm_nxt = frm + (_frm_nxt - _frm);
3482 to_nxt = to + (_to_nxt - _to);
3483 return r;
3484}
3485
3486codecvt<char32_t, char8_t, mbstate_t>::result
3487codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3488 extern_type* to, extern_type*, extern_type*& to_nxt) const
3489{
3490 to_nxt = to;
3491 return noconv;
3492}
3493
3494int
Louis Dionne65358e12021-03-01 12:09:45 -05003495codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003496{
3497 return 0;
3498}
3499
3500bool
Louis Dionne65358e12021-03-01 12:09:45 -05003501codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003502{
3503 return false;
3504}
3505
3506int
3507codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3508 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3509{
3510 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3511 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3512 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3513}
3514
3515int
Louis Dionne65358e12021-03-01 12:09:45 -05003516codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003517{
3518 return 4;
3519}
3520
3521#endif
3522
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003523// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003524
Louis Dionne89258142021-08-23 15:32:36 -04003525#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003526__codecvt_utf8<wchar_t>::result
3527__codecvt_utf8<wchar_t>::do_out(state_type&,
3528 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003529 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3530{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003531#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003532 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3533 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3534 const uint16_t* _frm_nxt = _frm;
3535#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003536 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3537 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3538 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003539#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003540 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3541 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3542 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003543#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003544 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3545 _Maxcode_, _Mode_);
3546#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003547 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3548 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003549#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003550 frm_nxt = frm + (_frm_nxt - _frm);
3551 to_nxt = to + (_to_nxt - _to);
3552 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003553}
3554
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003555__codecvt_utf8<wchar_t>::result
3556__codecvt_utf8<wchar_t>::do_in(state_type&,
3557 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003558 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3559{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003560 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3561 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3562 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003563#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003564 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3565 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3566 uint16_t* _to_nxt = _to;
3567 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3568 _Maxcode_, _Mode_);
3569#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003570 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3571 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3572 uint32_t* _to_nxt = _to;
3573 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3574 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003575#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003576 frm_nxt = frm + (_frm_nxt - _frm);
3577 to_nxt = to + (_to_nxt - _to);
3578 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003579}
3580
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003581__codecvt_utf8<wchar_t>::result
3582__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003583 extern_type* to, extern_type*, extern_type*& to_nxt) const
3584{
3585 to_nxt = to;
3586 return noconv;
3587}
3588
3589int
Louis Dionne65358e12021-03-01 12:09:45 -05003590__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003591{
3592 return 0;
3593}
3594
3595bool
Louis Dionne65358e12021-03-01 12:09:45 -05003596__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003597{
3598 return false;
3599}
3600
3601int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003602__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003603 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3604{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003605 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3606 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003607#if defined(_LIBCPP_SHORT_WCHAR)
3608 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3609#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003610 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003611#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003612}
3613
3614int
Louis Dionne65358e12021-03-01 12:09:45 -05003615__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003616{
Xing Xue50b0eb42021-09-09 16:20:36 -04003617#if defined(_LIBCPP_SHORT_WCHAR)
3618 if (_Mode_ & consume_header)
3619 return 6;
3620 return 3;
3621#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003622 if (_Mode_ & consume_header)
3623 return 7;
3624 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003625#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003626}
Louis Dionne89258142021-08-23 15:32:36 -04003627#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003628
3629// __codecvt_utf8<char16_t>
3630
3631__codecvt_utf8<char16_t>::result
3632__codecvt_utf8<char16_t>::do_out(state_type&,
3633 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3634 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3635{
3636 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3637 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3638 const uint16_t* _frm_nxt = _frm;
3639 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3640 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3641 uint8_t* _to_nxt = _to;
3642 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3643 _Maxcode_, _Mode_);
3644 frm_nxt = frm + (_frm_nxt - _frm);
3645 to_nxt = to + (_to_nxt - _to);
3646 return r;
3647}
3648
3649__codecvt_utf8<char16_t>::result
3650__codecvt_utf8<char16_t>::do_in(state_type&,
3651 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3652 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3653{
3654 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3655 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3656 const uint8_t* _frm_nxt = _frm;
3657 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3658 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3659 uint16_t* _to_nxt = _to;
3660 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3661 _Maxcode_, _Mode_);
3662 frm_nxt = frm + (_frm_nxt - _frm);
3663 to_nxt = to + (_to_nxt - _to);
3664 return r;
3665}
3666
3667__codecvt_utf8<char16_t>::result
3668__codecvt_utf8<char16_t>::do_unshift(state_type&,
3669 extern_type* to, extern_type*, extern_type*& to_nxt) const
3670{
3671 to_nxt = to;
3672 return noconv;
3673}
3674
3675int
Louis Dionne65358e12021-03-01 12:09:45 -05003676__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003677{
3678 return 0;
3679}
3680
3681bool
Louis Dionne65358e12021-03-01 12:09:45 -05003682__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003683{
3684 return false;
3685}
3686
3687int
3688__codecvt_utf8<char16_t>::do_length(state_type&,
3689 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3690{
3691 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3692 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3693 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3694}
3695
3696int
Louis Dionne65358e12021-03-01 12:09:45 -05003697__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003698{
3699 if (_Mode_ & consume_header)
3700 return 6;
3701 return 3;
3702}
3703
3704// __codecvt_utf8<char32_t>
3705
3706__codecvt_utf8<char32_t>::result
3707__codecvt_utf8<char32_t>::do_out(state_type&,
3708 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3709 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3710{
3711 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3712 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3713 const uint32_t* _frm_nxt = _frm;
3714 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3715 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3716 uint8_t* _to_nxt = _to;
3717 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3718 _Maxcode_, _Mode_);
3719 frm_nxt = frm + (_frm_nxt - _frm);
3720 to_nxt = to + (_to_nxt - _to);
3721 return r;
3722}
3723
3724__codecvt_utf8<char32_t>::result
3725__codecvt_utf8<char32_t>::do_in(state_type&,
3726 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3727 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3728{
3729 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3730 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3731 const uint8_t* _frm_nxt = _frm;
3732 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3733 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3734 uint32_t* _to_nxt = _to;
3735 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3736 _Maxcode_, _Mode_);
3737 frm_nxt = frm + (_frm_nxt - _frm);
3738 to_nxt = to + (_to_nxt - _to);
3739 return r;
3740}
3741
3742__codecvt_utf8<char32_t>::result
3743__codecvt_utf8<char32_t>::do_unshift(state_type&,
3744 extern_type* to, extern_type*, extern_type*& to_nxt) const
3745{
3746 to_nxt = to;
3747 return noconv;
3748}
3749
3750int
Louis Dionne65358e12021-03-01 12:09:45 -05003751__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003752{
3753 return 0;
3754}
3755
3756bool
Louis Dionne65358e12021-03-01 12:09:45 -05003757__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003758{
3759 return false;
3760}
3761
3762int
3763__codecvt_utf8<char32_t>::do_length(state_type&,
3764 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3765{
3766 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3767 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3768 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3769}
3770
3771int
Louis Dionne65358e12021-03-01 12:09:45 -05003772__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003773{
3774 if (_Mode_ & consume_header)
3775 return 7;
3776 return 4;
3777}
3778
3779// __codecvt_utf16<wchar_t, false>
3780
Louis Dionne89258142021-08-23 15:32:36 -04003781#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003782__codecvt_utf16<wchar_t, false>::result
3783__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3784 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3785 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3786{
Xing Xue50b0eb42021-09-09 16:20:36 -04003787#if defined(_LIBCPP_SHORT_WCHAR)
3788 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3789 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3790 const uint16_t* _frm_nxt = _frm;
3791#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003792 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3793 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3794 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003795#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003796 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3797 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3798 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003799#if defined(_LIBCPP_SHORT_WCHAR)
3800 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3801 _Maxcode_, _Mode_);
3802#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003803 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3804 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003805#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003806 frm_nxt = frm + (_frm_nxt - _frm);
3807 to_nxt = to + (_to_nxt - _to);
3808 return r;
3809}
3810
3811__codecvt_utf16<wchar_t, false>::result
3812__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3813 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3814 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3815{
3816 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3817 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3818 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003819#if defined(_LIBCPP_SHORT_WCHAR)
3820 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3821 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3822 uint16_t* _to_nxt = _to;
3823 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3824 _Maxcode_, _Mode_);
3825#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003826 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3827 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3828 uint32_t* _to_nxt = _to;
3829 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3830 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003831#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003832 frm_nxt = frm + (_frm_nxt - _frm);
3833 to_nxt = to + (_to_nxt - _to);
3834 return r;
3835}
3836
3837__codecvt_utf16<wchar_t, false>::result
3838__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3839 extern_type* to, extern_type*, extern_type*& to_nxt) const
3840{
3841 to_nxt = to;
3842 return noconv;
3843}
3844
3845int
Louis Dionne65358e12021-03-01 12:09:45 -05003846__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003847{
3848 return 0;
3849}
3850
3851bool
Louis Dionne65358e12021-03-01 12:09:45 -05003852__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003853{
3854 return false;
3855}
3856
3857int
3858__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3859 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3860{
3861 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3862 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003863#if defined(_LIBCPP_SHORT_WCHAR)
3864 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3865#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003866 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003867#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003868}
3869
3870int
Louis Dionne65358e12021-03-01 12:09:45 -05003871__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003872{
Xing Xue50b0eb42021-09-09 16:20:36 -04003873#if defined(_LIBCPP_SHORT_WCHAR)
3874 if (_Mode_ & consume_header)
3875 return 4;
3876 return 2;
3877#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003878 if (_Mode_ & consume_header)
3879 return 6;
3880 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003881#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003882}
3883
3884// __codecvt_utf16<wchar_t, true>
3885
3886__codecvt_utf16<wchar_t, true>::result
3887__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3888 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3889 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3890{
Xing Xue50b0eb42021-09-09 16:20:36 -04003891#if defined(_LIBCPP_SHORT_WCHAR)
3892 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3893 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3894 const uint16_t* _frm_nxt = _frm;
3895#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003896 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3897 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3898 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003899#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003900 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3901 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3902 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003903#if defined(_LIBCPP_SHORT_WCHAR)
3904 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3905 _Maxcode_, _Mode_);
3906#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003907 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3908 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003909#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003910 frm_nxt = frm + (_frm_nxt - _frm);
3911 to_nxt = to + (_to_nxt - _to);
3912 return r;
3913}
3914
3915__codecvt_utf16<wchar_t, true>::result
3916__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3917 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3918 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3919{
3920 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3921 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3922 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003923#if defined(_LIBCPP_SHORT_WCHAR)
3924 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3925 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3926 uint16_t* _to_nxt = _to;
3927 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3928 _Maxcode_, _Mode_);
3929#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003930 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3931 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3932 uint32_t* _to_nxt = _to;
3933 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3934 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003935#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003936 frm_nxt = frm + (_frm_nxt - _frm);
3937 to_nxt = to + (_to_nxt - _to);
3938 return r;
3939}
3940
3941__codecvt_utf16<wchar_t, true>::result
3942__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3943 extern_type* to, extern_type*, extern_type*& to_nxt) const
3944{
3945 to_nxt = to;
3946 return noconv;
3947}
3948
3949int
Louis Dionne65358e12021-03-01 12:09:45 -05003950__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003951{
3952 return 0;
3953}
3954
3955bool
Louis Dionne65358e12021-03-01 12:09:45 -05003956__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003957{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003958 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003959}
3960
3961int
3962__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3963 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3964{
3965 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3966 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003967#if defined(_LIBCPP_SHORT_WCHAR)
3968 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3969#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003970 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003971#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003972}
3973
3974int
Louis Dionne65358e12021-03-01 12:09:45 -05003975__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003976{
Xing Xue50b0eb42021-09-09 16:20:36 -04003977#if defined(_LIBCPP_SHORT_WCHAR)
3978 if (_Mode_ & consume_header)
3979 return 4;
3980 return 2;
3981#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003982 if (_Mode_ & consume_header)
3983 return 6;
3984 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003985#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003986}
Louis Dionne89258142021-08-23 15:32:36 -04003987#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003988
3989// __codecvt_utf16<char16_t, false>
3990
3991__codecvt_utf16<char16_t, false>::result
3992__codecvt_utf16<char16_t, false>::do_out(state_type&,
3993 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3994 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3995{
3996 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3997 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3998 const uint16_t* _frm_nxt = _frm;
3999 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4000 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4001 uint8_t* _to_nxt = _to;
4002 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4003 _Maxcode_, _Mode_);
4004 frm_nxt = frm + (_frm_nxt - _frm);
4005 to_nxt = to + (_to_nxt - _to);
4006 return r;
4007}
4008
4009__codecvt_utf16<char16_t, false>::result
4010__codecvt_utf16<char16_t, false>::do_in(state_type&,
4011 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4012 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4013{
4014 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4015 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4016 const uint8_t* _frm_nxt = _frm;
4017 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4018 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4019 uint16_t* _to_nxt = _to;
4020 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4021 _Maxcode_, _Mode_);
4022 frm_nxt = frm + (_frm_nxt - _frm);
4023 to_nxt = to + (_to_nxt - _to);
4024 return r;
4025}
4026
4027__codecvt_utf16<char16_t, false>::result
4028__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4029 extern_type* to, extern_type*, extern_type*& to_nxt) const
4030{
4031 to_nxt = to;
4032 return noconv;
4033}
4034
4035int
Louis Dionne65358e12021-03-01 12:09:45 -05004036__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004037{
4038 return 0;
4039}
4040
4041bool
Louis Dionne65358e12021-03-01 12:09:45 -05004042__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004043{
4044 return false;
4045}
4046
4047int
4048__codecvt_utf16<char16_t, false>::do_length(state_type&,
4049 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4050{
4051 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4052 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4053 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4054}
4055
4056int
Louis Dionne65358e12021-03-01 12:09:45 -05004057__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004058{
4059 if (_Mode_ & consume_header)
4060 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004061 return 2;
4062}
4063
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004064// __codecvt_utf16<char16_t, true>
4065
4066__codecvt_utf16<char16_t, true>::result
4067__codecvt_utf16<char16_t, true>::do_out(state_type&,
4068 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4069 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4070{
4071 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4072 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4073 const uint16_t* _frm_nxt = _frm;
4074 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4075 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4076 uint8_t* _to_nxt = _to;
4077 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4078 _Maxcode_, _Mode_);
4079 frm_nxt = frm + (_frm_nxt - _frm);
4080 to_nxt = to + (_to_nxt - _to);
4081 return r;
4082}
4083
4084__codecvt_utf16<char16_t, true>::result
4085__codecvt_utf16<char16_t, true>::do_in(state_type&,
4086 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4087 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4088{
4089 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4090 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4091 const uint8_t* _frm_nxt = _frm;
4092 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4093 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4094 uint16_t* _to_nxt = _to;
4095 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4096 _Maxcode_, _Mode_);
4097 frm_nxt = frm + (_frm_nxt - _frm);
4098 to_nxt = to + (_to_nxt - _to);
4099 return r;
4100}
4101
4102__codecvt_utf16<char16_t, true>::result
4103__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4104 extern_type* to, extern_type*, extern_type*& to_nxt) const
4105{
4106 to_nxt = to;
4107 return noconv;
4108}
4109
4110int
Louis Dionne65358e12021-03-01 12:09:45 -05004111__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004112{
4113 return 0;
4114}
4115
4116bool
Louis Dionne65358e12021-03-01 12:09:45 -05004117__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004118{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004119 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004120}
4121
4122int
4123__codecvt_utf16<char16_t, true>::do_length(state_type&,
4124 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4125{
4126 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4127 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4128 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4129}
4130
4131int
Louis Dionne65358e12021-03-01 12:09:45 -05004132__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004133{
4134 if (_Mode_ & consume_header)
4135 return 4;
4136 return 2;
4137}
4138
4139// __codecvt_utf16<char32_t, false>
4140
4141__codecvt_utf16<char32_t, false>::result
4142__codecvt_utf16<char32_t, false>::do_out(state_type&,
4143 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4144 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4145{
4146 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4147 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4148 const uint32_t* _frm_nxt = _frm;
4149 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4150 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4151 uint8_t* _to_nxt = _to;
4152 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4153 _Maxcode_, _Mode_);
4154 frm_nxt = frm + (_frm_nxt - _frm);
4155 to_nxt = to + (_to_nxt - _to);
4156 return r;
4157}
4158
4159__codecvt_utf16<char32_t, false>::result
4160__codecvt_utf16<char32_t, false>::do_in(state_type&,
4161 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4162 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4163{
4164 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4165 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4166 const uint8_t* _frm_nxt = _frm;
4167 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4168 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4169 uint32_t* _to_nxt = _to;
4170 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4171 _Maxcode_, _Mode_);
4172 frm_nxt = frm + (_frm_nxt - _frm);
4173 to_nxt = to + (_to_nxt - _to);
4174 return r;
4175}
4176
4177__codecvt_utf16<char32_t, false>::result
4178__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4179 extern_type* to, extern_type*, extern_type*& to_nxt) const
4180{
4181 to_nxt = to;
4182 return noconv;
4183}
4184
4185int
Louis Dionne65358e12021-03-01 12:09:45 -05004186__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004187{
4188 return 0;
4189}
4190
4191bool
Louis Dionne65358e12021-03-01 12:09:45 -05004192__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004193{
4194 return false;
4195}
4196
4197int
4198__codecvt_utf16<char32_t, false>::do_length(state_type&,
4199 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4200{
4201 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4202 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4203 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4204}
4205
4206int
Louis Dionne65358e12021-03-01 12:09:45 -05004207__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004208{
4209 if (_Mode_ & consume_header)
4210 return 6;
4211 return 4;
4212}
4213
4214// __codecvt_utf16<char32_t, true>
4215
4216__codecvt_utf16<char32_t, true>::result
4217__codecvt_utf16<char32_t, true>::do_out(state_type&,
4218 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4219 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4220{
4221 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4222 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4223 const uint32_t* _frm_nxt = _frm;
4224 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4225 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4226 uint8_t* _to_nxt = _to;
4227 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4228 _Maxcode_, _Mode_);
4229 frm_nxt = frm + (_frm_nxt - _frm);
4230 to_nxt = to + (_to_nxt - _to);
4231 return r;
4232}
4233
4234__codecvt_utf16<char32_t, true>::result
4235__codecvt_utf16<char32_t, true>::do_in(state_type&,
4236 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4237 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4238{
4239 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4240 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4241 const uint8_t* _frm_nxt = _frm;
4242 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4243 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4244 uint32_t* _to_nxt = _to;
4245 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4246 _Maxcode_, _Mode_);
4247 frm_nxt = frm + (_frm_nxt - _frm);
4248 to_nxt = to + (_to_nxt - _to);
4249 return r;
4250}
4251
4252__codecvt_utf16<char32_t, true>::result
4253__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4254 extern_type* to, extern_type*, extern_type*& to_nxt) const
4255{
4256 to_nxt = to;
4257 return noconv;
4258}
4259
4260int
Louis Dionne65358e12021-03-01 12:09:45 -05004261__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004262{
4263 return 0;
4264}
4265
4266bool
Louis Dionne65358e12021-03-01 12:09:45 -05004267__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004268{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004269 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004270}
4271
4272int
4273__codecvt_utf16<char32_t, true>::do_length(state_type&,
4274 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4275{
4276 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4277 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4278 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4279}
4280
4281int
Louis Dionne65358e12021-03-01 12:09:45 -05004282__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004283{
4284 if (_Mode_ & consume_header)
4285 return 6;
4286 return 4;
4287}
4288
4289// __codecvt_utf8_utf16<wchar_t>
4290
Louis Dionne89258142021-08-23 15:32:36 -04004291#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004292__codecvt_utf8_utf16<wchar_t>::result
4293__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4294 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4295 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4296{
Xing Xue50b0eb42021-09-09 16:20:36 -04004297#if defined(_LIBCPP_SHORT_WCHAR)
4298 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4299 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4300 const uint16_t* _frm_nxt = _frm;
4301#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004302 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4303 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4304 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004305#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004306 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4307 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4308 uint8_t* _to_nxt = _to;
4309 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4310 _Maxcode_, _Mode_);
4311 frm_nxt = frm + (_frm_nxt - _frm);
4312 to_nxt = to + (_to_nxt - _to);
4313 return r;
4314}
4315
4316__codecvt_utf8_utf16<wchar_t>::result
4317__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4318 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4319 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4320{
4321 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4322 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4323 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004324#if defined(_LIBCPP_SHORT_WCHAR)
4325 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4326 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4327 uint16_t* _to_nxt = _to;
4328#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004329 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4330 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4331 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004332#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004333 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4334 _Maxcode_, _Mode_);
4335 frm_nxt = frm + (_frm_nxt - _frm);
4336 to_nxt = to + (_to_nxt - _to);
4337 return r;
4338}
4339
4340__codecvt_utf8_utf16<wchar_t>::result
4341__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4342 extern_type* to, extern_type*, extern_type*& to_nxt) const
4343{
4344 to_nxt = to;
4345 return noconv;
4346}
4347
4348int
Louis Dionne65358e12021-03-01 12:09:45 -05004349__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004350{
4351 return 0;
4352}
4353
4354bool
Louis Dionne65358e12021-03-01 12:09:45 -05004355__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004356{
4357 return false;
4358}
4359
4360int
4361__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4362 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4363{
4364 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4365 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4366 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4367}
4368
4369int
Louis Dionne65358e12021-03-01 12:09:45 -05004370__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004371{
4372 if (_Mode_ & consume_header)
4373 return 7;
4374 return 4;
4375}
Louis Dionne89258142021-08-23 15:32:36 -04004376#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004377
4378// __codecvt_utf8_utf16<char16_t>
4379
4380__codecvt_utf8_utf16<char16_t>::result
4381__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4382 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4383 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4384{
4385 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4386 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4387 const uint16_t* _frm_nxt = _frm;
4388 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4389 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4390 uint8_t* _to_nxt = _to;
4391 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4392 _Maxcode_, _Mode_);
4393 frm_nxt = frm + (_frm_nxt - _frm);
4394 to_nxt = to + (_to_nxt - _to);
4395 return r;
4396}
4397
4398__codecvt_utf8_utf16<char16_t>::result
4399__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4400 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4401 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4402{
4403 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4404 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4405 const uint8_t* _frm_nxt = _frm;
4406 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4407 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4408 uint16_t* _to_nxt = _to;
4409 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4410 _Maxcode_, _Mode_);
4411 frm_nxt = frm + (_frm_nxt - _frm);
4412 to_nxt = to + (_to_nxt - _to);
4413 return r;
4414}
4415
4416__codecvt_utf8_utf16<char16_t>::result
4417__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4418 extern_type* to, extern_type*, extern_type*& to_nxt) const
4419{
4420 to_nxt = to;
4421 return noconv;
4422}
4423
4424int
Louis Dionne65358e12021-03-01 12:09:45 -05004425__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004426{
4427 return 0;
4428}
4429
4430bool
Louis Dionne65358e12021-03-01 12:09:45 -05004431__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004432{
4433 return false;
4434}
4435
4436int
4437__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4438 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4439{
4440 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4441 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4442 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4443}
4444
4445int
Louis Dionne65358e12021-03-01 12:09:45 -05004446__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004447{
4448 if (_Mode_ & consume_header)
4449 return 7;
4450 return 4;
4451}
4452
4453// __codecvt_utf8_utf16<char32_t>
4454
4455__codecvt_utf8_utf16<char32_t>::result
4456__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4457 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4458 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4459{
4460 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4461 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4462 const uint32_t* _frm_nxt = _frm;
4463 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4464 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4465 uint8_t* _to_nxt = _to;
4466 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4467 _Maxcode_, _Mode_);
4468 frm_nxt = frm + (_frm_nxt - _frm);
4469 to_nxt = to + (_to_nxt - _to);
4470 return r;
4471}
4472
4473__codecvt_utf8_utf16<char32_t>::result
4474__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4475 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4476 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4477{
4478 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4479 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4480 const uint8_t* _frm_nxt = _frm;
4481 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4482 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4483 uint32_t* _to_nxt = _to;
4484 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4485 _Maxcode_, _Mode_);
4486 frm_nxt = frm + (_frm_nxt - _frm);
4487 to_nxt = to + (_to_nxt - _to);
4488 return r;
4489}
4490
4491__codecvt_utf8_utf16<char32_t>::result
4492__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4493 extern_type* to, extern_type*, extern_type*& to_nxt) const
4494{
4495 to_nxt = to;
4496 return noconv;
4497}
4498
4499int
Louis Dionne65358e12021-03-01 12:09:45 -05004500__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004501{
4502 return 0;
4503}
4504
4505bool
Louis Dionne65358e12021-03-01 12:09:45 -05004506__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004507{
4508 return false;
4509}
4510
4511int
4512__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4513 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4514{
4515 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4516 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4517 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4518}
4519
4520int
Louis Dionne65358e12021-03-01 12:09:45 -05004521__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004522{
4523 if (_Mode_ & consume_header)
4524 return 7;
4525 return 4;
4526}
4527
Howard Hinnantc51e1022010-05-11 19:42:16 +00004528// __narrow_to_utf8<16>
4529
4530__narrow_to_utf8<16>::~__narrow_to_utf8()
4531{
4532}
4533
4534// __narrow_to_utf8<32>
4535
4536__narrow_to_utf8<32>::~__narrow_to_utf8()
4537{
4538}
4539
4540// __widen_from_utf8<16>
4541
4542__widen_from_utf8<16>::~__widen_from_utf8()
4543{
4544}
4545
4546// __widen_from_utf8<32>
4547
4548__widen_from_utf8<32>::~__widen_from_utf8()
4549{
4550}
4551
Louis Dionne89258142021-08-23 15:32:36 -04004552#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004553static bool checked_string_to_wchar_convert(wchar_t& dest,
4554 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004555 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004556 if (*ptr == '\0')
4557 return false;
4558 mbstate_t mb = {};
4559 wchar_t out;
4560 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4561 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4562 return false;
4563 }
4564 dest = out;
4565 return true;
4566}
Louis Dionne89258142021-08-23 15:32:36 -04004567#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004568
Mark de Weverffed1402021-11-03 19:25:20 +01004569#ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4570static bool is_narrow_non_breaking_space(const char* ptr) {
4571 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4572 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4573}
4574
4575static bool is_non_breaking_space(const char* ptr) {
4576 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4577 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4578}
4579#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4580
Eric Fiselierbf945a22016-12-11 00:20:59 +00004581static bool checked_string_to_char_convert(char& dest,
4582 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004583 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004584 if (*ptr == '\0')
4585 return false;
4586 if (!ptr[1]) {
4587 dest = *ptr;
4588 return true;
4589 }
Louis Dionne89258142021-08-23 15:32:36 -04004590
4591#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004592 // First convert the MBS into a wide char then attempt to narrow it using
4593 // wctob_l.
4594 wchar_t wout;
4595 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4596 return false;
4597 int res;
4598 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4599 dest = res;
4600 return true;
4601 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004602 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004603 // translate into a different single byte.
4604 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004605 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004606 case L'\u00A0': // non-breaking space
4607 dest = ' ';
4608 return true;
4609 default:
4610 return false;
4611 }
Louis Dionne89258142021-08-23 15:32:36 -04004612#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverffed1402021-11-03 19:25:20 +01004613 // FIXME: Work around specific multibyte sequences that we can reasonably
4614 // translate into a different single byte.
4615 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4616 dest = ' ';
4617 return true;
4618 }
4619
Louis Dionne89258142021-08-23 15:32:36 -04004620 return false;
4621#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Nikolas Klausercfe21472022-02-14 18:26:02 +01004622 __libcpp_unreachable();
Eric Fiselierbf945a22016-12-11 00:20:59 +00004623}
4624
4625
Howard Hinnantc51e1022010-05-11 19:42:16 +00004626// numpunct<char> && numpunct<wchar_t>
4627
4628locale::id numpunct< char >::id;
Louis Dionne89258142021-08-23 15:32:36 -04004629#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004630locale::id numpunct<wchar_t>::id;
Louis Dionne89258142021-08-23 15:32:36 -04004631#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004632
4633numpunct<char>::numpunct(size_t refs)
4634 : locale::facet(refs),
4635 __decimal_point_('.'),
4636 __thousands_sep_(',')
4637{
4638}
4639
Louis Dionne89258142021-08-23 15:32:36 -04004640#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004641numpunct<wchar_t>::numpunct(size_t refs)
4642 : locale::facet(refs),
4643 __decimal_point_(L'.'),
4644 __thousands_sep_(L',')
4645{
4646}
Louis Dionne89258142021-08-23 15:32:36 -04004647#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004648
4649numpunct<char>::~numpunct()
4650{
4651}
4652
Louis Dionne89258142021-08-23 15:32:36 -04004653#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004654numpunct<wchar_t>::~numpunct()
4655{
4656}
Louis Dionne89258142021-08-23 15:32:36 -04004657#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004658
4659 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004660#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004661wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004662#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004663
4664 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004665#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004666wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004667#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004668
4669string numpunct< char >::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004670#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004671string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004672#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004673
4674 string numpunct< char >::do_truename() const {return "true";}
Louis Dionne89258142021-08-23 15:32:36 -04004675#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004676wstring numpunct<wchar_t>::do_truename() const {return L"true";}
Louis Dionne89258142021-08-23 15:32:36 -04004677#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004678
4679 string numpunct< char >::do_falsename() const {return "false";}
Louis Dionne89258142021-08-23 15:32:36 -04004680#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004681wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
Louis Dionne89258142021-08-23 15:32:36 -04004682#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004683
4684// numpunct_byname<char>
4685
4686numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4687 : numpunct<char>(refs)
4688{
4689 __init(nm);
4690}
4691
4692numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4693 : numpunct<char>(refs)
4694{
4695 __init(nm.c_str());
4696}
4697
4698numpunct_byname<char>::~numpunct_byname()
4699{
4700}
4701
4702void
4703numpunct_byname<char>::__init(const char* nm)
4704{
Louis Dionne89258142021-08-23 15:32:36 -04004705 typedef numpunct<char> base;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004706 if (strcmp(nm, "C") != 0)
4707 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004708 __libcpp_unique_locale loc(nm);
4709 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004710 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004711 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004712
Ben Craig3756b922016-03-09 15:39:39 +00004713 lconv* lc = __libcpp_localeconv_l(loc.get());
Louis Dionne89258142021-08-23 15:32:36 -04004714 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4715 loc.get()))
4716 __decimal_point_ = base::do_decimal_point();
4717 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4718 loc.get()))
4719 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00004720 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004721 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004722 }
4723}
4724
4725// numpunct_byname<wchar_t>
4726
Louis Dionne89258142021-08-23 15:32:36 -04004727#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004728numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4729 : numpunct<wchar_t>(refs)
4730{
4731 __init(nm);
4732}
4733
4734numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4735 : numpunct<wchar_t>(refs)
4736{
4737 __init(nm.c_str());
4738}
4739
4740numpunct_byname<wchar_t>::~numpunct_byname()
4741{
4742}
4743
4744void
4745numpunct_byname<wchar_t>::__init(const char* nm)
4746{
4747 if (strcmp(nm, "C") != 0)
4748 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004749 __libcpp_unique_locale loc(nm);
4750 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004751 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004752 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004753
Ben Craig3756b922016-03-09 15:39:39 +00004754 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004755 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4756 loc.get());
4757 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4758 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004759 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004760 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004761 }
4762}
Louis Dionne89258142021-08-23 15:32:36 -04004763#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004764
4765// num_get helpers
4766
4767int
4768__num_get_base::__get_base(ios_base& iob)
4769{
4770 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4771 if (__basefield == ios_base::oct)
4772 return 8;
4773 else if (__basefield == ios_base::hex)
4774 return 16;
4775 else if (__basefield == 0)
4776 return 0;
4777 return 10;
4778}
4779
4780const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4781
4782void
4783__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4784 ios_base::iostate& __err)
4785{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004786// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4787// 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 +00004788 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004789 {
4790 reverse(__g, __g_end);
4791 const char* __ig = __grouping.data();
4792 const char* __eg = __ig + __grouping.size();
4793 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4794 {
4795 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4796 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004797 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004798 {
4799 __err = ios_base::failbit;
4800 return;
4801 }
4802 }
4803 if (__eg - __ig > 1)
4804 ++__ig;
4805 }
4806 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4807 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004808 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004809 __err = ios_base::failbit;
4810 }
4811 }
4812}
4813
4814void
4815__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4816 ios_base::fmtflags __flags)
4817{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004818 if ((__flags & ios_base::showpos) &&
4819 (__flags & ios_base::basefield) != ios_base::oct &&
4820 (__flags & ios_base::basefield) != ios_base::hex &&
4821 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004822 *__fmtp++ = '+';
4823 if (__flags & ios_base::showbase)
4824 *__fmtp++ = '#';
4825 while(*__len)
4826 *__fmtp++ = *__len++;
4827 if ((__flags & ios_base::basefield) == ios_base::oct)
4828 *__fmtp = 'o';
4829 else if ((__flags & ios_base::basefield) == ios_base::hex)
4830 {
4831 if (__flags & ios_base::uppercase)
4832 *__fmtp = 'X';
4833 else
4834 *__fmtp = 'x';
4835 }
4836 else if (__signd)
4837 *__fmtp = 'd';
4838 else
4839 *__fmtp = 'u';
4840}
4841
4842bool
4843__num_put_base::__format_float(char* __fmtp, const char* __len,
4844 ios_base::fmtflags __flags)
4845{
4846 bool specify_precision = true;
4847 if (__flags & ios_base::showpos)
4848 *__fmtp++ = '+';
4849 if (__flags & ios_base::showpoint)
4850 *__fmtp++ = '#';
4851 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004852 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004853 if (floatfield == (ios_base::fixed | ios_base::scientific))
4854 specify_precision = false;
4855 else
4856 {
4857 *__fmtp++ = '.';
4858 *__fmtp++ = '*';
4859 }
4860 while(*__len)
4861 *__fmtp++ = *__len++;
4862 if (floatfield == ios_base::fixed)
4863 {
4864 if (uppercase)
4865 *__fmtp = 'F';
4866 else
4867 *__fmtp = 'f';
4868 }
4869 else if (floatfield == ios_base::scientific)
4870 {
4871 if (uppercase)
4872 *__fmtp = 'E';
4873 else
4874 *__fmtp = 'e';
4875 }
4876 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4877 {
4878 if (uppercase)
4879 *__fmtp = 'A';
4880 else
4881 *__fmtp = 'a';
4882 }
4883 else
4884 {
4885 if (uppercase)
4886 *__fmtp = 'G';
4887 else
4888 *__fmtp = 'g';
4889 }
4890 return specify_precision;
4891}
4892
4893char*
4894__num_put_base::__identify_padding(char* __nb, char* __ne,
4895 const ios_base& __iob)
4896{
4897 switch (__iob.flags() & ios_base::adjustfield)
4898 {
4899 case ios_base::internal:
4900 if (__nb[0] == '-' || __nb[0] == '+')
4901 return __nb+1;
4902 if (__ne - __nb >= 2 && __nb[0] == '0'
4903 && (__nb[1] == 'x' || __nb[1] == 'X'))
4904 return __nb+2;
4905 break;
4906 case ios_base::left:
4907 return __ne;
4908 case ios_base::right:
4909 default:
4910 break;
4911 }
4912 return __nb;
4913}
4914
4915// time_get
4916
4917static
4918string*
4919init_weeks()
4920{
4921 static string weeks[14];
4922 weeks[0] = "Sunday";
4923 weeks[1] = "Monday";
4924 weeks[2] = "Tuesday";
4925 weeks[3] = "Wednesday";
4926 weeks[4] = "Thursday";
4927 weeks[5] = "Friday";
4928 weeks[6] = "Saturday";
4929 weeks[7] = "Sun";
4930 weeks[8] = "Mon";
4931 weeks[9] = "Tue";
4932 weeks[10] = "Wed";
4933 weeks[11] = "Thu";
4934 weeks[12] = "Fri";
4935 weeks[13] = "Sat";
4936 return weeks;
4937}
4938
Louis Dionne89258142021-08-23 15:32:36 -04004939#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004940static
4941wstring*
4942init_wweeks()
4943{
4944 static wstring weeks[14];
4945 weeks[0] = L"Sunday";
4946 weeks[1] = L"Monday";
4947 weeks[2] = L"Tuesday";
4948 weeks[3] = L"Wednesday";
4949 weeks[4] = L"Thursday";
4950 weeks[5] = L"Friday";
4951 weeks[6] = L"Saturday";
4952 weeks[7] = L"Sun";
4953 weeks[8] = L"Mon";
4954 weeks[9] = L"Tue";
4955 weeks[10] = L"Wed";
4956 weeks[11] = L"Thu";
4957 weeks[12] = L"Fri";
4958 weeks[13] = L"Sat";
4959 return weeks;
4960}
Louis Dionne89258142021-08-23 15:32:36 -04004961#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004962
4963template <>
4964const string*
4965__time_get_c_storage<char>::__weeks() const
4966{
4967 static const string* weeks = init_weeks();
4968 return weeks;
4969}
4970
Louis Dionne89258142021-08-23 15:32:36 -04004971#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004972template <>
4973const wstring*
4974__time_get_c_storage<wchar_t>::__weeks() const
4975{
4976 static const wstring* weeks = init_wweeks();
4977 return weeks;
4978}
Louis Dionne89258142021-08-23 15:32:36 -04004979#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004980
4981static
4982string*
4983init_months()
4984{
4985 static string months[24];
4986 months[0] = "January";
4987 months[1] = "February";
4988 months[2] = "March";
4989 months[3] = "April";
4990 months[4] = "May";
4991 months[5] = "June";
4992 months[6] = "July";
4993 months[7] = "August";
4994 months[8] = "September";
4995 months[9] = "October";
4996 months[10] = "November";
4997 months[11] = "December";
4998 months[12] = "Jan";
4999 months[13] = "Feb";
5000 months[14] = "Mar";
5001 months[15] = "Apr";
5002 months[16] = "May";
5003 months[17] = "Jun";
5004 months[18] = "Jul";
5005 months[19] = "Aug";
5006 months[20] = "Sep";
5007 months[21] = "Oct";
5008 months[22] = "Nov";
5009 months[23] = "Dec";
5010 return months;
5011}
5012
Louis Dionne89258142021-08-23 15:32:36 -04005013#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005014static
5015wstring*
5016init_wmonths()
5017{
5018 static wstring months[24];
5019 months[0] = L"January";
5020 months[1] = L"February";
5021 months[2] = L"March";
5022 months[3] = L"April";
5023 months[4] = L"May";
5024 months[5] = L"June";
5025 months[6] = L"July";
5026 months[7] = L"August";
5027 months[8] = L"September";
5028 months[9] = L"October";
5029 months[10] = L"November";
5030 months[11] = L"December";
5031 months[12] = L"Jan";
5032 months[13] = L"Feb";
5033 months[14] = L"Mar";
5034 months[15] = L"Apr";
5035 months[16] = L"May";
5036 months[17] = L"Jun";
5037 months[18] = L"Jul";
5038 months[19] = L"Aug";
5039 months[20] = L"Sep";
5040 months[21] = L"Oct";
5041 months[22] = L"Nov";
5042 months[23] = L"Dec";
5043 return months;
5044}
Louis Dionne89258142021-08-23 15:32:36 -04005045#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005046
5047template <>
5048const string*
5049__time_get_c_storage<char>::__months() const
5050{
5051 static const string* months = init_months();
5052 return months;
5053}
5054
Louis Dionne89258142021-08-23 15:32:36 -04005055#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005056template <>
5057const wstring*
5058__time_get_c_storage<wchar_t>::__months() const
5059{
5060 static const wstring* months = init_wmonths();
5061 return months;
5062}
Louis Dionne89258142021-08-23 15:32:36 -04005063#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005064
5065static
5066string*
5067init_am_pm()
5068{
Marshall Clow5cc04922018-01-11 17:16:52 +00005069 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005070 am_pm[0] = "AM";
5071 am_pm[1] = "PM";
5072 return am_pm;
5073}
5074
Louis Dionne89258142021-08-23 15:32:36 -04005075#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005076static
5077wstring*
5078init_wam_pm()
5079{
Marshall Clow5cc04922018-01-11 17:16:52 +00005080 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005081 am_pm[0] = L"AM";
5082 am_pm[1] = L"PM";
5083 return am_pm;
5084}
Louis Dionne89258142021-08-23 15:32:36 -04005085#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005086
5087template <>
5088const string*
5089__time_get_c_storage<char>::__am_pm() const
5090{
5091 static const string* am_pm = init_am_pm();
5092 return am_pm;
5093}
5094
Louis Dionne89258142021-08-23 15:32:36 -04005095#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005096template <>
5097const wstring*
5098__time_get_c_storage<wchar_t>::__am_pm() const
5099{
5100 static const wstring* am_pm = init_wam_pm();
5101 return am_pm;
5102}
Louis Dionne89258142021-08-23 15:32:36 -04005103#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005104
5105template <>
5106const string&
5107__time_get_c_storage<char>::__x() const
5108{
5109 static string s("%m/%d/%y");
5110 return s;
5111}
5112
Louis Dionne89258142021-08-23 15:32:36 -04005113#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005114template <>
5115const wstring&
5116__time_get_c_storage<wchar_t>::__x() const
5117{
5118 static wstring s(L"%m/%d/%y");
5119 return s;
5120}
Louis Dionne89258142021-08-23 15:32:36 -04005121#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005122
5123template <>
5124const string&
5125__time_get_c_storage<char>::__X() const
5126{
5127 static string s("%H:%M:%S");
5128 return s;
5129}
5130
Louis Dionne89258142021-08-23 15:32:36 -04005131#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005132template <>
5133const wstring&
5134__time_get_c_storage<wchar_t>::__X() const
5135{
5136 static wstring s(L"%H:%M:%S");
5137 return s;
5138}
Louis Dionne89258142021-08-23 15:32:36 -04005139#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005140
5141template <>
5142const string&
5143__time_get_c_storage<char>::__c() const
5144{
5145 static string s("%a %b %d %H:%M:%S %Y");
5146 return s;
5147}
5148
Louis Dionne89258142021-08-23 15:32:36 -04005149#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005150template <>
5151const wstring&
5152__time_get_c_storage<wchar_t>::__c() const
5153{
5154 static wstring s(L"%a %b %d %H:%M:%S %Y");
5155 return s;
5156}
Louis Dionne89258142021-08-23 15:32:36 -04005157#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005158
5159template <>
5160const string&
5161__time_get_c_storage<char>::__r() const
5162{
5163 static string s("%I:%M:%S %p");
5164 return s;
5165}
5166
Louis Dionne89258142021-08-23 15:32:36 -04005167#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005168template <>
5169const wstring&
5170__time_get_c_storage<wchar_t>::__r() const
5171{
5172 static wstring s(L"%I:%M:%S %p");
5173 return s;
5174}
Louis Dionne89258142021-08-23 15:32:36 -04005175#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005176
5177// time_get_byname
5178
5179__time_get::__time_get(const char* nm)
5180 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5181{
5182 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005183 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005184 " failed to construct for " + string(nm));
5185}
5186
5187__time_get::__time_get(const string& nm)
5188 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5189{
5190 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005191 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005192 " failed to construct for " + nm);
5193}
5194
5195__time_get::~__time_get()
5196{
5197 freelocale(__loc_);
5198}
Nikolas Klauser41c59762022-02-14 18:52:28 +01005199
5200_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005201
Howard Hinnantc51e1022010-05-11 19:42:16 +00005202template <>
5203string
5204__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5205{
Howard Hinnant990207c2012-02-19 14:55:32 +00005206 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005207 t.tm_sec = 59;
5208 t.tm_min = 55;
5209 t.tm_hour = 23;
5210 t.tm_mday = 31;
5211 t.tm_mon = 11;
5212 t.tm_year = 161;
5213 t.tm_wday = 6;
5214 t.tm_yday = 364;
5215 t.tm_isdst = -1;
5216 char buf[100];
5217 char f[3] = {0};
5218 f[0] = '%';
5219 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005220 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005221 char* bb = buf;
5222 char* be = buf + n;
5223 string result;
5224 while (bb != be)
5225 {
5226 if (ct.is(ctype_base::space, *bb))
5227 {
5228 result.push_back(' ');
5229 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5230 ;
5231 continue;
5232 }
5233 char* w = bb;
5234 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005235 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005236 ct, err, false)
5237 - this->__weeks_;
5238 if (i < 14)
5239 {
5240 result.push_back('%');
5241 if (i < 7)
5242 result.push_back('A');
5243 else
5244 result.push_back('a');
5245 bb = w;
5246 continue;
5247 }
5248 w = bb;
5249 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5250 ct, err, false)
5251 - this->__months_;
5252 if (i < 24)
5253 {
5254 result.push_back('%');
5255 if (i < 12)
5256 result.push_back('B');
5257 else
5258 result.push_back('b');
5259 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5260 result.back() = 'm';
5261 bb = w;
5262 continue;
5263 }
5264 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5265 {
5266 w = bb;
5267 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5268 ct, err, false) - this->__am_pm_;
5269 if (i < 2)
5270 {
5271 result.push_back('%');
5272 result.push_back('p');
5273 bb = w;
5274 continue;
5275 }
5276 }
5277 w = bb;
5278 if (ct.is(ctype_base::digit, *bb))
5279 {
5280 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5281 {
5282 case 6:
5283 result.push_back('%');
5284 result.push_back('w');
5285 break;
5286 case 7:
5287 result.push_back('%');
5288 result.push_back('u');
5289 break;
5290 case 11:
5291 result.push_back('%');
5292 result.push_back('I');
5293 break;
5294 case 12:
5295 result.push_back('%');
5296 result.push_back('m');
5297 break;
5298 case 23:
5299 result.push_back('%');
5300 result.push_back('H');
5301 break;
5302 case 31:
5303 result.push_back('%');
5304 result.push_back('d');
5305 break;
5306 case 55:
5307 result.push_back('%');
5308 result.push_back('M');
5309 break;
5310 case 59:
5311 result.push_back('%');
5312 result.push_back('S');
5313 break;
5314 case 61:
5315 result.push_back('%');
5316 result.push_back('y');
5317 break;
5318 case 364:
5319 result.push_back('%');
5320 result.push_back('j');
5321 break;
5322 case 2061:
5323 result.push_back('%');
5324 result.push_back('Y');
5325 break;
5326 default:
5327 for (; w != bb; ++w)
5328 result.push_back(*w);
5329 break;
5330 }
5331 continue;
5332 }
5333 if (*bb == '%')
5334 {
5335 result.push_back('%');
5336 result.push_back('%');
5337 ++bb;
5338 continue;
5339 }
5340 result.push_back(*bb);
5341 ++bb;
5342 }
5343 return result;
5344}
5345
Nikolas Klauser41c59762022-02-14 18:52:28 +01005346_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces")
Howard Hinnant28b24882011-12-01 20:21:04 +00005347
Louis Dionne89258142021-08-23 15:32:36 -04005348#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005349template <>
5350wstring
5351__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5352{
Howard Hinnant990207c2012-02-19 14:55:32 +00005353 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005354 t.tm_sec = 59;
5355 t.tm_min = 55;
5356 t.tm_hour = 23;
5357 t.tm_mday = 31;
5358 t.tm_mon = 11;
5359 t.tm_year = 161;
5360 t.tm_wday = 6;
5361 t.tm_yday = 364;
5362 t.tm_isdst = -1;
5363 char buf[100];
5364 char f[3] = {0};
5365 f[0] = '%';
5366 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005367 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005368 wchar_t wbuf[100];
5369 wchar_t* wbb = wbuf;
5370 mbstate_t mb = {0};
5371 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005372 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005373 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005374 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005375 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005376 wstring result;
5377 while (wbb != wbe)
5378 {
5379 if (ct.is(ctype_base::space, *wbb))
5380 {
5381 result.push_back(L' ');
5382 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5383 ;
5384 continue;
5385 }
5386 wchar_t* w = wbb;
5387 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005388 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005389 ct, err, false)
5390 - this->__weeks_;
5391 if (i < 14)
5392 {
5393 result.push_back(L'%');
5394 if (i < 7)
5395 result.push_back(L'A');
5396 else
5397 result.push_back(L'a');
5398 wbb = w;
5399 continue;
5400 }
5401 w = wbb;
5402 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5403 ct, err, false)
5404 - this->__months_;
5405 if (i < 24)
5406 {
5407 result.push_back(L'%');
5408 if (i < 12)
5409 result.push_back(L'B');
5410 else
5411 result.push_back(L'b');
5412 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5413 result.back() = L'm';
5414 wbb = w;
5415 continue;
5416 }
5417 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5418 {
5419 w = wbb;
5420 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5421 ct, err, false) - this->__am_pm_;
5422 if (i < 2)
5423 {
5424 result.push_back(L'%');
5425 result.push_back(L'p');
5426 wbb = w;
5427 continue;
5428 }
5429 }
5430 w = wbb;
5431 if (ct.is(ctype_base::digit, *wbb))
5432 {
5433 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5434 {
5435 case 6:
5436 result.push_back(L'%');
5437 result.push_back(L'w');
5438 break;
5439 case 7:
5440 result.push_back(L'%');
5441 result.push_back(L'u');
5442 break;
5443 case 11:
5444 result.push_back(L'%');
5445 result.push_back(L'I');
5446 break;
5447 case 12:
5448 result.push_back(L'%');
5449 result.push_back(L'm');
5450 break;
5451 case 23:
5452 result.push_back(L'%');
5453 result.push_back(L'H');
5454 break;
5455 case 31:
5456 result.push_back(L'%');
5457 result.push_back(L'd');
5458 break;
5459 case 55:
5460 result.push_back(L'%');
5461 result.push_back(L'M');
5462 break;
5463 case 59:
5464 result.push_back(L'%');
5465 result.push_back(L'S');
5466 break;
5467 case 61:
5468 result.push_back(L'%');
5469 result.push_back(L'y');
5470 break;
5471 case 364:
5472 result.push_back(L'%');
5473 result.push_back(L'j');
5474 break;
5475 case 2061:
5476 result.push_back(L'%');
5477 result.push_back(L'Y');
5478 break;
5479 default:
5480 for (; w != wbb; ++w)
5481 result.push_back(*w);
5482 break;
5483 }
5484 continue;
5485 }
5486 if (ct.narrow(*wbb, 0) == '%')
5487 {
5488 result.push_back(L'%');
5489 result.push_back(L'%');
5490 ++wbb;
5491 continue;
5492 }
5493 result.push_back(*wbb);
5494 ++wbb;
5495 }
5496 return result;
5497}
Louis Dionne89258142021-08-23 15:32:36 -04005498#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005499
5500template <>
5501void
5502__time_get_storage<char>::init(const ctype<char>& ct)
5503{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005504 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005505 char buf[100];
5506 // __weeks_
5507 for (int i = 0; i < 7; ++i)
5508 {
5509 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005510 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005511 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005512 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005513 __weeks_[i+7] = buf;
5514 }
5515 // __months_
5516 for (int i = 0; i < 12; ++i)
5517 {
5518 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005519 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005520 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005521 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005522 __months_[i+12] = buf;
5523 }
5524 // __am_pm_
5525 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005526 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005527 __am_pm_[0] = buf;
5528 t.tm_hour = 13;
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_[1] = buf;
5531 __c_ = __analyze('c', ct);
5532 __r_ = __analyze('r', ct);
5533 __x_ = __analyze('x', ct);
5534 __X_ = __analyze('X', ct);
5535}
5536
Louis Dionne89258142021-08-23 15:32:36 -04005537#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005538template <>
5539void
5540__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5541{
5542 tm t = {0};
5543 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005544 wchar_t wbuf[100];
5545 wchar_t* wbe;
5546 mbstate_t mb = {0};
5547 // __weeks_
5548 for (int i = 0; i < 7; ++i)
5549 {
5550 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005551 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005552 mb = mbstate_t();
5553 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005554 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005555 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005556 __throw_runtime_error("locale not supported");
5557 wbe = wbuf + j;
5558 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005559 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005560 mb = mbstate_t();
5561 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005562 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005563 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005564 __throw_runtime_error("locale not supported");
5565 wbe = wbuf + j;
5566 __weeks_[i+7].assign(wbuf, wbe);
5567 }
5568 // __months_
5569 for (int i = 0; i < 12; ++i)
5570 {
5571 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005572 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005573 mb = mbstate_t();
5574 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005575 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005576 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 __throw_runtime_error("locale not supported");
5578 wbe = wbuf + j;
5579 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005580 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005581 mb = mbstate_t();
5582 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005583 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005584 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005585 __throw_runtime_error("locale not supported");
5586 wbe = wbuf + j;
5587 __months_[i+12].assign(wbuf, wbe);
5588 }
5589 // __am_pm_
5590 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005591 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005592 mb = mbstate_t();
5593 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005594 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005595 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005596 __throw_runtime_error("locale not supported");
5597 wbe = wbuf + j;
5598 __am_pm_[0].assign(wbuf, wbe);
5599 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005600 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005601 mb = mbstate_t();
5602 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005603 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005604 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005605 __throw_runtime_error("locale not supported");
5606 wbe = wbuf + j;
5607 __am_pm_[1].assign(wbuf, wbe);
5608 __c_ = __analyze('c', ct);
5609 __r_ = __analyze('r', ct);
5610 __x_ = __analyze('x', ct);
5611 __X_ = __analyze('X', ct);
5612}
Louis Dionne89258142021-08-23 15:32:36 -04005613#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005614
5615template <class CharT>
5616struct _LIBCPP_HIDDEN __time_get_temp
5617 : public ctype_byname<CharT>
5618{
5619 explicit __time_get_temp(const char* nm)
5620 : ctype_byname<CharT>(nm, 1) {}
5621 explicit __time_get_temp(const string& nm)
5622 : ctype_byname<CharT>(nm, 1) {}
5623};
5624
5625template <>
5626__time_get_storage<char>::__time_get_storage(const char* __nm)
5627 : __time_get(__nm)
5628{
5629 const __time_get_temp<char> ct(__nm);
5630 init(ct);
5631}
5632
5633template <>
5634__time_get_storage<char>::__time_get_storage(const string& __nm)
5635 : __time_get(__nm)
5636{
5637 const __time_get_temp<char> ct(__nm);
5638 init(ct);
5639}
5640
Louis Dionne89258142021-08-23 15:32:36 -04005641#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005642template <>
5643__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5644 : __time_get(__nm)
5645{
5646 const __time_get_temp<wchar_t> ct(__nm);
5647 init(ct);
5648}
5649
5650template <>
5651__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5652 : __time_get(__nm)
5653{
5654 const __time_get_temp<wchar_t> ct(__nm);
5655 init(ct);
5656}
Louis Dionne89258142021-08-23 15:32:36 -04005657#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005658
5659template <>
5660time_base::dateorder
5661__time_get_storage<char>::__do_date_order() const
5662{
5663 unsigned i;
5664 for (i = 0; i < __x_.size(); ++i)
5665 if (__x_[i] == '%')
5666 break;
5667 ++i;
5668 switch (__x_[i])
5669 {
5670 case 'y':
5671 case 'Y':
5672 for (++i; i < __x_.size(); ++i)
5673 if (__x_[i] == '%')
5674 break;
5675 if (i == __x_.size())
5676 break;
5677 ++i;
5678 switch (__x_[i])
5679 {
5680 case 'm':
5681 for (++i; i < __x_.size(); ++i)
5682 if (__x_[i] == '%')
5683 break;
5684 if (i == __x_.size())
5685 break;
5686 ++i;
5687 if (__x_[i] == 'd')
5688 return time_base::ymd;
5689 break;
5690 case 'd':
5691 for (++i; i < __x_.size(); ++i)
5692 if (__x_[i] == '%')
5693 break;
5694 if (i == __x_.size())
5695 break;
5696 ++i;
5697 if (__x_[i] == 'm')
5698 return time_base::ydm;
5699 break;
5700 }
5701 break;
5702 case 'm':
5703 for (++i; i < __x_.size(); ++i)
5704 if (__x_[i] == '%')
5705 break;
5706 if (i == __x_.size())
5707 break;
5708 ++i;
5709 if (__x_[i] == 'd')
5710 {
5711 for (++i; i < __x_.size(); ++i)
5712 if (__x_[i] == '%')
5713 break;
5714 if (i == __x_.size())
5715 break;
5716 ++i;
5717 if (__x_[i] == 'y' || __x_[i] == 'Y')
5718 return time_base::mdy;
5719 break;
5720 }
5721 break;
5722 case 'd':
5723 for (++i; i < __x_.size(); ++i)
5724 if (__x_[i] == '%')
5725 break;
5726 if (i == __x_.size())
5727 break;
5728 ++i;
5729 if (__x_[i] == 'm')
5730 {
5731 for (++i; i < __x_.size(); ++i)
5732 if (__x_[i] == '%')
5733 break;
5734 if (i == __x_.size())
5735 break;
5736 ++i;
5737 if (__x_[i] == 'y' || __x_[i] == 'Y')
5738 return time_base::dmy;
5739 break;
5740 }
5741 break;
5742 }
5743 return time_base::no_order;
5744}
5745
Louis Dionne89258142021-08-23 15:32:36 -04005746#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005747template <>
5748time_base::dateorder
5749__time_get_storage<wchar_t>::__do_date_order() const
5750{
5751 unsigned i;
5752 for (i = 0; i < __x_.size(); ++i)
5753 if (__x_[i] == L'%')
5754 break;
5755 ++i;
5756 switch (__x_[i])
5757 {
5758 case L'y':
5759 case L'Y':
5760 for (++i; i < __x_.size(); ++i)
5761 if (__x_[i] == L'%')
5762 break;
5763 if (i == __x_.size())
5764 break;
5765 ++i;
5766 switch (__x_[i])
5767 {
5768 case L'm':
5769 for (++i; i < __x_.size(); ++i)
5770 if (__x_[i] == L'%')
5771 break;
5772 if (i == __x_.size())
5773 break;
5774 ++i;
5775 if (__x_[i] == L'd')
5776 return time_base::ymd;
5777 break;
5778 case L'd':
5779 for (++i; i < __x_.size(); ++i)
5780 if (__x_[i] == L'%')
5781 break;
5782 if (i == __x_.size())
5783 break;
5784 ++i;
5785 if (__x_[i] == L'm')
5786 return time_base::ydm;
5787 break;
5788 }
5789 break;
5790 case L'm':
5791 for (++i; i < __x_.size(); ++i)
5792 if (__x_[i] == L'%')
5793 break;
5794 if (i == __x_.size())
5795 break;
5796 ++i;
5797 if (__x_[i] == L'd')
5798 {
5799 for (++i; i < __x_.size(); ++i)
5800 if (__x_[i] == L'%')
5801 break;
5802 if (i == __x_.size())
5803 break;
5804 ++i;
5805 if (__x_[i] == L'y' || __x_[i] == L'Y')
5806 return time_base::mdy;
5807 break;
5808 }
5809 break;
5810 case L'd':
5811 for (++i; i < __x_.size(); ++i)
5812 if (__x_[i] == L'%')
5813 break;
5814 if (i == __x_.size())
5815 break;
5816 ++i;
5817 if (__x_[i] == L'm')
5818 {
5819 for (++i; i < __x_.size(); ++i)
5820 if (__x_[i] == L'%')
5821 break;
5822 if (i == __x_.size())
5823 break;
5824 ++i;
5825 if (__x_[i] == L'y' || __x_[i] == L'Y')
5826 return time_base::dmy;
5827 break;
5828 }
5829 break;
5830 }
5831 return time_base::no_order;
5832}
Louis Dionne89258142021-08-23 15:32:36 -04005833#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005834
5835// time_put
5836
5837__time_put::__time_put(const char* nm)
5838 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5839{
5840 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005841 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005842 " failed to construct for " + string(nm));
5843}
5844
5845__time_put::__time_put(const string& nm)
5846 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5847{
5848 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005849 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005850 " failed to construct for " + nm);
5851}
5852
5853__time_put::~__time_put()
5854{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005855 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005856 freelocale(__loc_);
5857}
5858
5859void
5860__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5861 char __fmt, char __mod) const
5862{
5863 char fmt[] = {'%', __fmt, __mod, 0};
5864 if (__mod != 0)
5865 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005866 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005867 __ne = __nb + n;
5868}
5869
Louis Dionne89258142021-08-23 15:32:36 -04005870#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005871void
5872__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5873 char __fmt, char __mod) const
5874{
5875 char __nar[100];
5876 char* __ne = __nar + 100;
5877 __do_put(__nar, __ne, __tm, __fmt, __mod);
5878 mbstate_t mb = {0};
5879 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005880 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005881 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005882 __throw_runtime_error("locale not supported");
5883 __we = __wb + j;
5884}
Louis Dionne89258142021-08-23 15:32:36 -04005885#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005886
5887// moneypunct_byname
5888
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005889template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005890static
5891void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005892__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5893 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5894 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005895{
5896 const char sign = static_cast<char>(money_base::sign);
5897 const char space = static_cast<char>(money_base::space);
5898 const char none = static_cast<char>(money_base::none);
5899 const char symbol = static_cast<char>(money_base::symbol);
5900 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005901 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5902
5903 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5904 // function'. "Space between sign and symbol or value" means that
5905 // if the sign is adjacent to the symbol, there's a space between
5906 // them, and otherwise there's a space between the sign and value.
5907 //
5908 // C11's localeconv specifies that the fourth character of an
5909 // international curr_symbol is used to separate the sign and
5910 // value when sep_by_space says to do so. C++ can't represent
5911 // that, so we just use a space. When sep_by_space says to
5912 // separate the symbol and value-or-sign with a space, we rearrange the
5913 // curr_symbol to put its spacing character on the correct side of
5914 // the symbol.
5915 //
5916 // We also need to avoid adding an extra space between the sign
5917 // and value when the currency symbol is suppressed (by not
5918 // setting showbase). We match glibc's strfmon by interpreting
5919 // sep_by_space==1 as "omit the space when the currency symbol is
5920 // absent".
5921 //
5922 // Users who want to get this right should use ICU instead.
5923
Howard Hinnantc51e1022010-05-11 19:42:16 +00005924 switch (cs_precedes)
5925 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005926 case 0: // value before curr_symbol
5927 if (symbol_contains_sep) {
5928 // Move the separator to before the symbol, to place it
5929 // between the value and symbol.
5930 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5931 __curr_symbol_.end());
5932 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005933 switch (sign_posn)
5934 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005935 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005936 pat.field[0] = sign;
5937 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005938 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005939 pat.field[3] = symbol;
5940 switch (sep_by_space)
5941 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005942 case 0: // No space separates the currency symbol and value.
5943 // This case may have changed between C99 and C11;
5944 // assume the currency symbol matches the intention.
5945 case 2: // Space between sign and currency or value.
5946 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005948 case 1: // Space between currency-and-sign or currency and value.
5949 if (!symbol_contains_sep) {
5950 // We insert the space into the symbol instead of
5951 // setting pat.field[2]=space so that when
5952 // showbase is not set, the space goes away too.
5953 __curr_symbol_.insert(0, 1, space_char);
5954 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005955 return;
5956 default:
5957 break;
5958 }
5959 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005960 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005961 pat.field[0] = sign;
5962 pat.field[3] = symbol;
5963 switch (sep_by_space)
5964 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005965 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005966 pat.field[1] = value;
5967 pat.field[2] = none;
5968 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005969 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005970 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005971 pat.field[2] = none;
5972 if (!symbol_contains_sep) {
5973 // We insert the space into the symbol instead of
5974 // setting pat.field[2]=space so that when
5975 // showbase is not set, the space goes away too.
5976 __curr_symbol_.insert(0, 1, space_char);
5977 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005978 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005979 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005980 pat.field[1] = space;
5981 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005982 if (symbol_contains_sep) {
5983 // Remove the separator from the symbol, since it
5984 // has already appeared after the sign.
5985 __curr_symbol_.erase(__curr_symbol_.begin());
5986 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005987 return;
5988 default:
5989 break;
5990 }
5991 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005992 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005993 pat.field[0] = value;
5994 pat.field[3] = sign;
5995 switch (sep_by_space)
5996 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005997 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005998 pat.field[1] = none;
5999 pat.field[2] = symbol;
6000 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006001 case 1: // Space between currency-and-sign or currency and value.
6002 if (!symbol_contains_sep) {
6003 // We insert the space into the symbol instead of
6004 // setting pat.field[1]=space so that when
6005 // showbase is not set, the space goes away too.
6006 __curr_symbol_.insert(0, 1, space_char);
6007 }
6008 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006009 pat.field[2] = symbol;
6010 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006011 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006012 pat.field[1] = symbol;
6013 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006014 if (symbol_contains_sep) {
6015 // Remove the separator from the symbol, since it
6016 // should not be removed if showbase is absent.
6017 __curr_symbol_.erase(__curr_symbol_.begin());
6018 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006019 return;
6020 default:
6021 break;
6022 }
6023 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006024 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006025 pat.field[0] = value;
6026 pat.field[3] = symbol;
6027 switch (sep_by_space)
6028 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006029 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006030 pat.field[1] = none;
6031 pat.field[2] = sign;
6032 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006033 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006034 pat.field[1] = space;
6035 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006036 if (symbol_contains_sep) {
6037 // Remove the separator from the symbol, since it
6038 // has already appeared before the sign.
6039 __curr_symbol_.erase(__curr_symbol_.begin());
6040 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006041 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006042 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006043 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006044 pat.field[2] = none;
6045 if (!symbol_contains_sep) {
6046 // We insert the space into the symbol instead of
6047 // setting pat.field[2]=space so that when
6048 // showbase is not set, the space goes away too.
6049 __curr_symbol_.insert(0, 1, space_char);
6050 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006051 return;
6052 default:
6053 break;
6054 }
6055 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006056 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006057 pat.field[0] = value;
6058 pat.field[3] = sign;
6059 switch (sep_by_space)
6060 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006061 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006062 pat.field[1] = none;
6063 pat.field[2] = symbol;
6064 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006065 case 1: // Space between currency-and-sign or currency and value.
6066 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006067 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006068 if (!symbol_contains_sep) {
6069 // We insert the space into the symbol instead of
6070 // setting pat.field[1]=space so that when
6071 // showbase is not set, the space goes away too.
6072 __curr_symbol_.insert(0, 1, space_char);
6073 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006074 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006075 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006076 pat.field[1] = symbol;
6077 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006078 if (symbol_contains_sep) {
6079 // Remove the separator from the symbol, since it
6080 // should not disappear when showbase is absent.
6081 __curr_symbol_.erase(__curr_symbol_.begin());
6082 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006083 return;
6084 default:
6085 break;
6086 }
6087 break;
6088 default:
6089 break;
6090 }
6091 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006092 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00006093 switch (sign_posn)
6094 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006095 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006096 pat.field[0] = sign;
6097 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006098 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006099 pat.field[3] = value;
6100 switch (sep_by_space)
6101 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006102 case 0: // No space separates the currency symbol and value.
6103 // This case may have changed between C99 and C11;
6104 // assume the currency symbol matches the intention.
6105 case 2: // Space between sign and currency or value.
6106 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006107 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006108 case 1: // Space between currency-and-sign or currency and value.
6109 if (!symbol_contains_sep) {
6110 // We insert the space into the symbol instead of
6111 // setting pat.field[2]=space so that when
6112 // showbase is not set, the space goes away too.
6113 __curr_symbol_.insert(0, 1, space_char);
6114 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006115 return;
6116 default:
6117 break;
6118 }
6119 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006120 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006121 pat.field[0] = sign;
6122 pat.field[3] = value;
6123 switch (sep_by_space)
6124 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006125 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006126 pat.field[1] = symbol;
6127 pat.field[2] = none;
6128 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006129 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006130 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006131 pat.field[2] = none;
6132 if (!symbol_contains_sep) {
6133 // We insert the space into the symbol instead of
6134 // setting pat.field[2]=space so that when
6135 // showbase is not set, the space goes away too.
6136 __curr_symbol_.push_back(space_char);
6137 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006138 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006139 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006140 pat.field[1] = space;
6141 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006142 if (symbol_contains_sep) {
6143 // Remove the separator from the symbol, since it
6144 // has already appeared after the sign.
6145 __curr_symbol_.pop_back();
6146 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006147 return;
6148 default:
6149 break;
6150 }
6151 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006152 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006153 pat.field[0] = symbol;
6154 pat.field[3] = sign;
6155 switch (sep_by_space)
6156 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006157 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006158 pat.field[1] = none;
6159 pat.field[2] = value;
6160 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006161 case 1: // Space between currency-and-sign or currency and value.
6162 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006163 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006164 if (!symbol_contains_sep) {
6165 // We insert the space into the symbol instead of
6166 // setting pat.field[1]=space so that when
6167 // showbase is not set, the space goes away too.
6168 __curr_symbol_.push_back(space_char);
6169 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006170 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006171 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006172 pat.field[1] = value;
6173 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006174 if (symbol_contains_sep) {
6175 // Remove the separator from the symbol, since it
6176 // will appear before the sign.
6177 __curr_symbol_.pop_back();
6178 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006179 return;
6180 default:
6181 break;
6182 }
6183 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006184 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006185 pat.field[0] = sign;
6186 pat.field[3] = value;
6187 switch (sep_by_space)
6188 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006189 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006190 pat.field[1] = symbol;
6191 pat.field[2] = none;
6192 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006193 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006194 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006195 pat.field[2] = none;
6196 if (!symbol_contains_sep) {
6197 // We insert the space into the symbol instead of
6198 // setting pat.field[2]=space so that when
6199 // showbase is not set, the space goes away too.
6200 __curr_symbol_.push_back(space_char);
6201 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006202 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006203 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006204 pat.field[1] = space;
6205 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006206 if (symbol_contains_sep) {
6207 // Remove the separator from the symbol, since it
6208 // has already appeared after the sign.
6209 __curr_symbol_.pop_back();
6210 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006211 return;
6212 default:
6213 break;
6214 }
6215 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006216 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006217 pat.field[0] = symbol;
6218 pat.field[3] = value;
6219 switch (sep_by_space)
6220 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006221 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006222 pat.field[1] = sign;
6223 pat.field[2] = none;
6224 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006225 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006226 pat.field[1] = sign;
6227 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006228 if (symbol_contains_sep) {
6229 // Remove the separator from the symbol, since it
6230 // should not disappear when showbase is absent.
6231 __curr_symbol_.pop_back();
6232 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006233 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006234 case 2: // Space between sign and currency or value.
6235 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006236 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006237 if (!symbol_contains_sep) {
6238 // We insert the space into the symbol instead of
6239 // setting pat.field[1]=space so that when
6240 // showbase is not set, the space goes away too.
6241 __curr_symbol_.push_back(space_char);
6242 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006243 return;
6244 default:
6245 break;
6246 }
6247 break;
6248 default:
6249 break;
6250 }
6251 break;
6252 default:
6253 break;
6254 }
6255 pat.field[0] = symbol;
6256 pat.field[1] = sign;
6257 pat.field[2] = none;
6258 pat.field[3] = value;
6259}
6260
6261template<>
6262void
6263moneypunct_byname<char, false>::init(const char* nm)
6264{
6265 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006266 __libcpp_unique_locale loc(nm);
6267 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006268 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006269 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006270
Ben Craig3756b922016-03-09 15:39:39 +00006271 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006272 if (!checked_string_to_char_convert(__decimal_point_,
6273 lc->mon_decimal_point,
6274 loc.get()))
6275 __decimal_point_ = base::do_decimal_point();
6276 if (!checked_string_to_char_convert(__thousands_sep_,
6277 lc->mon_thousands_sep,
6278 loc.get()))
6279 __thousands_sep_ = base::do_thousands_sep();
6280
Howard Hinnantc51e1022010-05-11 19:42:16 +00006281 __grouping_ = lc->mon_grouping;
6282 __curr_symbol_ = lc->currency_symbol;
6283 if (lc->frac_digits != CHAR_MAX)
6284 __frac_digits_ = lc->frac_digits;
6285 else
6286 __frac_digits_ = base::do_frac_digits();
6287 if (lc->p_sign_posn == 0)
6288 __positive_sign_ = "()";
6289 else
6290 __positive_sign_ = lc->positive_sign;
6291 if (lc->n_sign_posn == 0)
6292 __negative_sign_ = "()";
6293 else
6294 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006295 // Assume the positive and negative formats will want spaces in
6296 // the same places in curr_symbol since there's no way to
6297 // represent anything else.
6298 string_type __dummy_curr_symbol = __curr_symbol_;
6299 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6300 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6301 __init_pat(__neg_format_, __curr_symbol_, false,
6302 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006303}
6304
6305template<>
6306void
6307moneypunct_byname<char, true>::init(const char* nm)
6308{
6309 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006310 __libcpp_unique_locale loc(nm);
6311 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006312 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006313 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006314
Ben Craig3756b922016-03-09 15:39:39 +00006315 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006316 if (!checked_string_to_char_convert(__decimal_point_,
6317 lc->mon_decimal_point,
6318 loc.get()))
6319 __decimal_point_ = base::do_decimal_point();
6320 if (!checked_string_to_char_convert(__thousands_sep_,
6321 lc->mon_thousands_sep,
6322 loc.get()))
6323 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006324 __grouping_ = lc->mon_grouping;
6325 __curr_symbol_ = lc->int_curr_symbol;
6326 if (lc->int_frac_digits != CHAR_MAX)
6327 __frac_digits_ = lc->int_frac_digits;
6328 else
6329 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006330#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006331 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006332#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006333 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006334#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006335 __positive_sign_ = "()";
6336 else
6337 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006338#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006339 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006340#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006341 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006342#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006343 __negative_sign_ = "()";
6344 else
6345 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006346 // Assume the positive and negative formats will want spaces in
6347 // the same places in curr_symbol since there's no way to
6348 // represent anything else.
6349 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006350#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006351 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6352 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6353 __init_pat(__neg_format_, __curr_symbol_, true,
6354 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006355#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006356 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6357 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6358 lc->int_p_sign_posn, ' ');
6359 __init_pat(__neg_format_, __curr_symbol_, true,
6360 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6361 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006362#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006363}
6364
Louis Dionne89258142021-08-23 15:32:36 -04006365#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006366template<>
6367void
6368moneypunct_byname<wchar_t, false>::init(const char* nm)
6369{
6370 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006371 __libcpp_unique_locale loc(nm);
6372 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006373 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006374 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006375 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006376 if (!checked_string_to_wchar_convert(__decimal_point_,
6377 lc->mon_decimal_point,
6378 loc.get()))
6379 __decimal_point_ = base::do_decimal_point();
6380 if (!checked_string_to_wchar_convert(__thousands_sep_,
6381 lc->mon_thousands_sep,
6382 loc.get()))
6383 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006384 __grouping_ = lc->mon_grouping;
6385 wchar_t wbuf[100];
6386 mbstate_t mb = {0};
6387 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006388 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006389 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006390 __throw_runtime_error("locale not supported");
6391 wchar_t* wbe = wbuf + j;
6392 __curr_symbol_.assign(wbuf, wbe);
6393 if (lc->frac_digits != CHAR_MAX)
6394 __frac_digits_ = lc->frac_digits;
6395 else
6396 __frac_digits_ = base::do_frac_digits();
6397 if (lc->p_sign_posn == 0)
6398 __positive_sign_ = L"()";
6399 else
6400 {
6401 mb = mbstate_t();
6402 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006403 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006404 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006405 __throw_runtime_error("locale not supported");
6406 wbe = wbuf + j;
6407 __positive_sign_.assign(wbuf, wbe);
6408 }
6409 if (lc->n_sign_posn == 0)
6410 __negative_sign_ = L"()";
6411 else
6412 {
6413 mb = mbstate_t();
6414 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006415 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006416 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006417 __throw_runtime_error("locale not supported");
6418 wbe = wbuf + j;
6419 __negative_sign_.assign(wbuf, wbe);
6420 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006421 // Assume the positive and negative formats will want spaces in
6422 // the same places in curr_symbol since there's no way to
6423 // represent anything else.
6424 string_type __dummy_curr_symbol = __curr_symbol_;
6425 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6426 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6427 __init_pat(__neg_format_, __curr_symbol_, false,
6428 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006429}
6430
6431template<>
6432void
6433moneypunct_byname<wchar_t, true>::init(const char* nm)
6434{
6435 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006436 __libcpp_unique_locale loc(nm);
6437 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006438 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006439 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006440
Ben Craig3756b922016-03-09 15:39:39 +00006441 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006442 if (!checked_string_to_wchar_convert(__decimal_point_,
6443 lc->mon_decimal_point,
6444 loc.get()))
6445 __decimal_point_ = base::do_decimal_point();
6446 if (!checked_string_to_wchar_convert(__thousands_sep_,
6447 lc->mon_thousands_sep,
6448 loc.get()))
6449 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006450 __grouping_ = lc->mon_grouping;
6451 wchar_t wbuf[100];
6452 mbstate_t mb = {0};
6453 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006454 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006455 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006456 __throw_runtime_error("locale not supported");
6457 wchar_t* wbe = wbuf + j;
6458 __curr_symbol_.assign(wbuf, wbe);
6459 if (lc->int_frac_digits != CHAR_MAX)
6460 __frac_digits_ = lc->int_frac_digits;
6461 else
6462 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006463#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006464 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006465#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006466 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006467#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006468 __positive_sign_ = L"()";
6469 else
6470 {
6471 mb = mbstate_t();
6472 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006473 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006474 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006475 __throw_runtime_error("locale not supported");
6476 wbe = wbuf + j;
6477 __positive_sign_.assign(wbuf, wbe);
6478 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006479#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006480 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006481#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006482 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006483#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006484 __negative_sign_ = L"()";
6485 else
6486 {
6487 mb = mbstate_t();
6488 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006489 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006490 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006491 __throw_runtime_error("locale not supported");
6492 wbe = wbuf + j;
6493 __negative_sign_.assign(wbuf, wbe);
6494 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006495 // Assume the positive and negative formats will want spaces in
6496 // the same places in curr_symbol since there's no way to
6497 // represent anything else.
6498 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006499#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006500 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6501 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6502 __init_pat(__neg_format_, __curr_symbol_, true,
6503 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006504#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006505 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6506 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6507 lc->int_p_sign_posn, L' ');
6508 __init_pat(__neg_format_, __curr_symbol_, true,
6509 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6510 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006511#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006512}
Louis Dionne89258142021-08-23 15:32:36 -04006513#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006514
6515void __do_nothing(void*) {}
6516
6517void __throw_runtime_error(const char* msg)
6518{
Howard Hinnant72f73582010-08-11 17:04:31 +00006519#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006520 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006521#else
6522 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006523 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006524#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006525}
6526
Louis Dionne89258142021-08-23 15:32:36 -04006527 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6528_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006529
Louis Dionne89258142021-08-23 15:32:36 -04006530 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6531_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006532
Louis Dionne89258142021-08-23 15:32:36 -04006533 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6534_LIBCPP_IF_WIDE_CHARACTERS(template struct _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 class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6537_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006538
Louis Dionne89258142021-08-23 15:32:36 -04006539 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6540_LIBCPP_IF_WIDE_CHARACTERS(template struct _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 class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6543_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<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_byname<char>;
6546_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<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_put<char>;
6549_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<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_byname<char>;
6552_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<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 moneypunct<char, false>;
6555 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6556_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6557_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006558
Louis Dionne89258142021-08-23 15:32:36 -04006559 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6560 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6561_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6562_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006563
Louis Dionne89258142021-08-23 15:32:36 -04006564 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6565_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006566
Louis Dionne89258142021-08-23 15:32:36 -04006567 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __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_put<char>;
6571_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<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 messages<char>;
6577_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<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_byname<char>;
6580_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<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 codecvt_byname<char, char, mbstate_t>;
6583_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 -08006584template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6585template 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 -04006586#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006587template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6588template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6589#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006590
Howard Hinnantc51e1022010-05-11 19:42:16 +00006591_LIBCPP_END_NAMESPACE_STD
Arthur O'Dwyercf9bf392022-02-11 13:00:39 -05006592
6593_LIBCPP_POP_MACROS