blob: a45dcbf2d8dd86743995886e5235fb9dce849003 [file] [log] [blame]
Louis Dionne9bd93882021-11-17 16:25:01 -05001//===----------------------------------------------------------------------===//
Howard Hinnantc51e1022010-05-11 19:42:16 +00002//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantc51e1022010-05-11 19:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
David Chisnall8074c342012-02-29 13:05:08 +00009// On Solaris, we need to define something to make the C99 parts of localeconv
10// visible.
11#ifdef __sun__
12#define _LCONV_C99
13#endif
14
Nikolas Klausercfe21472022-02-14 18:26:02 +010015#include <__utility/unreachable.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +000016#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000017#include "clocale"
Louis Dionneafc98402021-09-09 13:52:38 -040018#include "codecvt"
19#include "cstdio"
20#include "cstdlib"
Howard Hinnantc51e1022010-05-11 19:42:16 +000021#include "cstring"
Louis Dionneafc98402021-09-09 13:52:38 -040022#include "locale"
23#include "string"
24#include "type_traits"
25#include "typeinfo"
26#include "vector"
27
Louis Dionne89258142021-08-23 15:32:36 -040028#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
29# include "cwctype"
30#endif
31
David Tenty725f16e2021-10-12 11:53:12 -040032#if defined(_AIX)
33# include <sys/localedef.h> // for __lc_ctype_ptr
34#endif
35
Louis Dionneafc98402021-09-09 13:52:38 -040036#if defined(_LIBCPP_MSVCRT)
37# define _CTYPE_DISABLE_MACROS
Marshall Clow3477ec92014-07-10 15:20:28 +000038#endif
Louis Dionneafc98402021-09-09 13:52:38 -040039
40#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
41# include "__support/win32/locale_win32.h"
42#elif !defined(__BIONIC__) && !defined(__NuttX__)
43# include <langinfo.h>
44#endif
45
Weiming Zhaob613db72017-09-19 23:18:03 +000046#include "include/atomic_support.h"
Arthur O'Dwyerf5c4bb02021-04-26 09:56:50 -040047#include "include/sso_allocator.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000048#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000049
Marshall Clowab9c1772013-02-07 17:20:56 +000050// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070051// lots of noise in the build log, but no bugs that I know of.
Nikolas Klauser41c59762022-02-14 18:52:28 +010052_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wsign-conversion")
Marshall Clowab9c1772013-02-07 17:20:56 +000053
Howard Hinnantc51e1022010-05-11 19:42:16 +000054_LIBCPP_BEGIN_NAMESPACE_STD
55
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000056struct __libcpp_unique_locale {
57 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
58
59 ~__libcpp_unique_locale() {
60 if (__loc_)
61 freelocale(__loc_);
62 }
63
64 explicit operator bool() const { return __loc_; }
65
66 locale_t& get() { return __loc_; }
67
68 locale_t __loc_;
69private:
70 __libcpp_unique_locale(__libcpp_unique_locale const&);
71 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
72};
73
Howard Hinnantf312e3e2011-09-28 23:39:33 +000074#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000075locale_t __cloc() {
76 // In theory this could create a race condition. In practice
77 // the race condition is non-fatal since it will just create
78 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000079 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
80 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000081}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000082#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000083
Howard Hinnantc51e1022010-05-11 19:42:16 +000084namespace {
85
86struct release
87{
88 void operator()(locale::facet* p) {p->__release_shared();}
89};
90
Louis Dionne6e41a152021-08-09 13:26:04 -040091template <class T, class ...Args>
92T& make(Args ...args)
Howard Hinnantc51e1022010-05-11 19:42:16 +000093{
94 static typename aligned_storage<sizeof(T)>::type buf;
Louis Dionne6e41a152021-08-09 13:26:04 -040095 auto *obj = ::new (&buf) T(args...);
Eric Fiselier4db80032017-05-05 20:32:26 +000096 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000097}
98
Howard Hinnant3d2417c2012-12-27 21:17:53 +000099template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000100inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000101_LIBCPP_CONSTEXPR
102size_t
103countof(const T (&)[N])
104{
105 return N;
106}
107
108template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000109inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000110_LIBCPP_CONSTEXPR
111size_t
112countof(const T * const begin, const T * const end)
113{
114 return static_cast<size_t>(end - begin);
115}
116
Marshall Clow8fea1612016-08-25 15:09:01 +0000117_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
118{
119#ifndef _LIBCPP_NO_EXCEPTIONS
120 throw runtime_error(msg);
121#else
122 (void)msg;
123 _VSTD::abort();
124#endif
125}
126
Howard Hinnantc51e1022010-05-11 19:42:16 +0000127}
128
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000129const locale::category locale::none;
130const locale::category locale::collate;
131const locale::category locale::ctype;
132const locale::category locale::monetary;
133const locale::category locale::numeric;
134const locale::category locale::time;
135const locale::category locale::messages;
136const locale::category locale::all;
137
Howard Hinnantc51e1022010-05-11 19:42:16 +0000138class _LIBCPP_HIDDEN locale::__imp
139 : public facet
140{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100141 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000142#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000143// FIXME: MSVC doesn't support aligned parameters by value.
144// I can't get the __sso_allocator to work here
145// for MSVC I think for this reason.
146 vector<facet*> facets_;
147#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000148 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000149#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000150 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000151public:
152 explicit __imp(size_t refs = 0);
153 explicit __imp(const string& name, size_t refs = 0);
154 __imp(const __imp&);
155 __imp(const __imp&, const string&, locale::category c);
156 __imp(const __imp& other, const __imp& one, locale::category c);
157 __imp(const __imp&, facet* f, long id);
158 ~__imp();
159
160 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000161 bool has_facet(long id) const
162 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000163 const locale::facet* use_facet(long id) const;
164
165 static const locale& make_classic();
166 static locale& make_global();
167private:
168 void install(facet* f, long id);
169 template <class F> void install(F* f) {install(f, f->id.__get());}
170 template <class F> void install_from(const __imp& other);
171};
172
173locale::__imp::__imp(size_t refs)
174 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000175 facets_(N),
176 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000177{
178 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000179 install(&make<_VSTD::collate<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400180#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000181 install(&make<_VSTD::collate<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400182#endif
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000183 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Louis Dionne89258142021-08-23 15:32:36 -0400184#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000185 install(&make<_VSTD::ctype<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400186#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000187 install(&make<codecvt<char, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400188#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000189 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400190#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100191_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000192 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
193 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100194_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400195#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100196 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
197 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
198#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000199 install(&make<numpunct<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400200#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000201 install(&make<numpunct<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400202#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000203 install(&make<num_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400204#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000205 install(&make<num_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400206#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000207 install(&make<num_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400208#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000209 install(&make<num_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400210#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000211 install(&make<moneypunct<char, false> >(1u));
212 install(&make<moneypunct<char, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400213#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000214 install(&make<moneypunct<wchar_t, false> >(1u));
215 install(&make<moneypunct<wchar_t, true> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400216#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000217 install(&make<money_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400218#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000219 install(&make<money_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400220#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000221 install(&make<money_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400222#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000223 install(&make<money_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400224#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000225 install(&make<time_get<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400226#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000227 install(&make<time_get<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400228#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000229 install(&make<time_put<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400230#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000231 install(&make<time_put<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400232#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000233 install(&make<_VSTD::messages<char> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400234#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant28b24882011-12-01 20:21:04 +0000235 install(&make<_VSTD::messages<wchar_t> >(1u));
Louis Dionne89258142021-08-23 15:32:36 -0400236#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000237}
238
239locale::__imp::__imp(const string& name, size_t refs)
240 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000241 facets_(N),
242 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000243{
Howard Hinnant72f73582010-08-11 17:04:31 +0000244#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000245 try
246 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400247#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000248 facets_ = locale::classic().__locale_->facets_;
249 for (unsigned i = 0; i < facets_.size(); ++i)
250 if (facets_[i])
251 facets_[i]->__add_shared();
252 install(new collate_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400253#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000254 install(new collate_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400255#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000256 install(new ctype_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400257#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000258 install(new ctype_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400259#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000260 install(new codecvt_byname<char, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400261#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400263#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100264_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000265 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
266 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100267_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400268#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100269 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
270 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
271#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000272 install(new numpunct_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400273#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000274 install(new numpunct_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400275#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276 install(new moneypunct_byname<char, false>(name_));
277 install(new moneypunct_byname<char, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400278#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000279 install(new moneypunct_byname<wchar_t, false>(name_));
280 install(new moneypunct_byname<wchar_t, true>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400281#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000282 install(new time_get_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400283#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284 install(new time_get_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400285#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000286 install(new time_put_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400287#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288 install(new time_put_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400289#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000290 install(new messages_byname<char>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400291#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000292 install(new messages_byname<wchar_t>(name_));
Louis Dionne89258142021-08-23 15:32:36 -0400293#endif
Howard Hinnant72f73582010-08-11 17:04:31 +0000294#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000295 }
296 catch (...)
297 {
298 for (unsigned i = 0; i < facets_.size(); ++i)
299 if (facets_[i])
300 facets_[i]->__release_shared();
301 throw;
302 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400303#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000304}
305
306locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000307 : facets_(max<size_t>(N, other.facets_.size())),
308 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000309{
310 facets_ = other.facets_;
311 for (unsigned i = 0; i < facets_.size(); ++i)
312 if (facets_[i])
313 facets_[i]->__add_shared();
314}
315
316locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000317 : facets_(N),
318 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000319{
320 facets_ = other.facets_;
321 for (unsigned i = 0; i < facets_.size(); ++i)
322 if (facets_[i])
323 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000324#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000325 try
326 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400327#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000328 if (c & locale::collate)
329 {
330 install(new collate_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400331#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000332 install(new collate_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400333#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000334 }
335 if (c & locale::ctype)
336 {
337 install(new ctype_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400338#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000339 install(new ctype_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400340#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000341 install(new codecvt_byname<char, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400342#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000343 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400344#endif
Marek Kurdej718b62c2020-12-02 08:57:02 +0100345_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000346 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
347 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100348_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400349#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100350 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
351 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
352#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000353 }
354 if (c & locale::monetary)
355 {
356 install(new moneypunct_byname<char, false>(name));
357 install(new moneypunct_byname<char, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400358#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000359 install(new moneypunct_byname<wchar_t, false>(name));
360 install(new moneypunct_byname<wchar_t, true>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400361#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000362 }
363 if (c & locale::numeric)
364 {
365 install(new numpunct_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400366#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000367 install(new numpunct_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400368#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000369 }
370 if (c & locale::time)
371 {
372 install(new time_get_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400373#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000374 install(new time_get_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400375#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000376 install(new time_put_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400377#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000378 install(new time_put_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400379#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000380 }
381 if (c & locale::messages)
382 {
383 install(new messages_byname<char>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400384#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000385 install(new messages_byname<wchar_t>(name));
Louis Dionne89258142021-08-23 15:32:36 -0400386#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000387 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000388#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000389 }
390 catch (...)
391 {
392 for (unsigned i = 0; i < facets_.size(); ++i)
393 if (facets_[i])
394 facets_[i]->__release_shared();
395 throw;
396 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400397#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000398}
399
400template<class F>
401inline
402void
403locale::__imp::install_from(const locale::__imp& one)
404{
405 long id = F::id.__get();
406 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
407}
408
409locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000410 : facets_(N),
411 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000412{
413 facets_ = other.facets_;
414 for (unsigned i = 0; i < facets_.size(); ++i)
415 if (facets_[i])
416 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000417#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000418 try
419 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400420#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000421 if (c & locale::collate)
422 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000423 install_from<_VSTD::collate<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400424#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000425 install_from<_VSTD::collate<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400426#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000427 }
428 if (c & locale::ctype)
429 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000430 install_from<_VSTD::ctype<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400431#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000432 install_from<_VSTD::ctype<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400433#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000434 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100435_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000436 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
437 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100438_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400439#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100440 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
441 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
442#endif
Louis Dionne89258142021-08-23 15:32:36 -0400443#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000444 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400445#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000446 }
447 if (c & locale::monetary)
448 {
449 install_from<moneypunct<char, false> >(one);
450 install_from<moneypunct<char, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400451#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000452 install_from<moneypunct<wchar_t, false> >(one);
453 install_from<moneypunct<wchar_t, true> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400454#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000455 install_from<money_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400456#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000457 install_from<money_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400458#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000459 install_from<money_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400460#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000461 install_from<money_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400462#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000463 }
464 if (c & locale::numeric)
465 {
466 install_from<numpunct<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400467#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000468 install_from<numpunct<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400469#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000470 install_from<num_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400471#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000472 install_from<num_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400473#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000474 install_from<num_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400475#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000476 install_from<num_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400477#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000478 }
479 if (c & locale::time)
480 {
481 install_from<time_get<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400482#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000483 install_from<time_get<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400484#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000485 install_from<time_put<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400486#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000487 install_from<time_put<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400488#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000489 }
490 if (c & locale::messages)
491 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000492 install_from<_VSTD::messages<char> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400493#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000494 install_from<_VSTD::messages<wchar_t> >(one);
Louis Dionne89258142021-08-23 15:32:36 -0400495#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000496 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000497#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000498 }
499 catch (...)
500 {
501 for (unsigned i = 0; i < facets_.size(); ++i)
502 if (facets_[i])
503 facets_[i]->__release_shared();
504 throw;
505 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400506#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000507}
508
509locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000510 : facets_(max<size_t>(N, other.facets_.size()+1)),
511 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000512{
513 f->__add_shared();
514 unique_ptr<facet, release> hold(f);
515 facets_ = other.facets_;
516 for (unsigned i = 0; i < other.facets_.size(); ++i)
517 if (facets_[i])
518 facets_[i]->__add_shared();
519 install(hold.get(), id);
520}
521
522locale::__imp::~__imp()
523{
524 for (unsigned i = 0; i < facets_.size(); ++i)
525 if (facets_[i])
526 facets_[i]->__release_shared();
527}
528
529void
530locale::__imp::install(facet* f, long id)
531{
532 f->__add_shared();
533 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000534 if (static_cast<size_t>(id) >= facets_.size())
535 facets_.resize(static_cast<size_t>(id+1));
536 if (facets_[static_cast<size_t>(id)])
537 facets_[static_cast<size_t>(id)]->__release_shared();
538 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000539}
540
541const locale::facet*
542locale::__imp::use_facet(long id) const
543{
544 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000545 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000546 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000547}
548
549// locale
550
551const locale&
552locale::__imp::make_classic()
553{
554 // only one thread can get in here and it only gets in once
555 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000556 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000557 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000558 return *c;
559}
560
561const locale&
562locale::classic()
563{
564 static const locale& c = __imp::make_classic();
565 return c;
566}
567
568locale&
569locale::__imp::make_global()
570{
571 // only one thread can get in here and it only gets in once
572 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000573 auto *obj = ::new (&buf) locale(locale::classic());
574 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000575}
576
577locale&
578locale::__global()
579{
580 static locale& g = __imp::make_global();
581 return g;
582}
583
Louis Dionne65358e12021-03-01 12:09:45 -0500584locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000585 : __locale_(__global().__locale_)
586{
587 __locale_->__add_shared();
588}
589
Louis Dionne65358e12021-03-01 12:09:45 -0500590locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000591 : __locale_(l.__locale_)
592{
593 __locale_->__add_shared();
594}
595
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000596locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000597{
598 __locale_->__release_shared();
599}
600
601const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500602locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000603{
604 other.__locale_->__add_shared();
605 __locale_->__release_shared();
606 __locale_ = other.__locale_;
607 return *this;
608}
609
610locale::locale(const char* name)
611 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100612 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000613{
614 __locale_->__add_shared();
615}
616
617locale::locale(const string& name)
618 : __locale_(new __imp(name))
619{
620 __locale_->__add_shared();
621}
622
623locale::locale(const locale& other, const char* name, category c)
624 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100625 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000626{
627 __locale_->__add_shared();
628}
629
630locale::locale(const locale& other, const string& name, category c)
631 : __locale_(new __imp(*other.__locale_, name, c))
632{
633 __locale_->__add_shared();
634}
635
636locale::locale(const locale& other, const locale& one, category c)
637 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
638{
639 __locale_->__add_shared();
640}
641
642string
643locale::name() const
644{
645 return __locale_->name();
646}
647
648void
649locale::__install_ctor(const locale& other, facet* f, long id)
650{
651 if (f)
652 __locale_ = new __imp(*other.__locale_, f, id);
653 else
654 __locale_ = other.__locale_;
655 __locale_->__add_shared();
656}
657
658locale
659locale::global(const locale& loc)
660{
661 locale& g = __global();
662 locale r = g;
663 g = loc;
664 if (g.name() != "*")
665 setlocale(LC_ALL, g.name().c_str());
666 return r;
667}
668
669bool
670locale::has_facet(id& x) const
671{
672 return __locale_->has_facet(x.__get());
673}
674
675const locale::facet*
676locale::use_facet(id& x) const
677{
678 return __locale_->use_facet(x.__get());
679}
680
681bool
682locale::operator==(const locale& y) const
683{
684 return (__locale_ == y.__locale_)
685 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
686}
687
688// locale::facet
689
690locale::facet::~facet()
691{
692}
693
694void
Louis Dionne65358e12021-03-01 12:09:45 -0500695locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000696{
697 delete this;
698}
699
700// locale::id
701
702int32_t locale::id::__next_id = 0;
703
704namespace
705{
706
707class __fake_bind
708{
709 locale::id* id_;
710 void (locale::id::* pmf_)();
711public:
712 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
713 : id_(id), pmf_(pmf) {}
714
715 void operator()() const
716 {
717 (id_->*pmf_)();
718 }
719};
720
721}
722
723long
724locale::id::__get()
725{
726 call_once(__flag_, __fake_bind(&locale::id::__init, this));
727 return __id_ - 1;
728}
729
730void
731locale::id::__init()
732{
Weiming Zhaob613db72017-09-19 23:18:03 +0000733 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000734}
735
736// template <> class collate_byname<char>
737
738collate_byname<char>::collate_byname(const char* n, size_t refs)
739 : collate<char>(refs),
740 __l(newlocale(LC_ALL_MASK, n, 0))
741{
742 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000743 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000744 " failed to construct for " + string(n));
745}
746
747collate_byname<char>::collate_byname(const string& name, size_t refs)
748 : collate<char>(refs),
749 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
750{
751 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000752 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000753 " failed to construct for " + name);
754}
755
756collate_byname<char>::~collate_byname()
757{
758 freelocale(__l);
759}
760
761int
762collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
763 const char_type* __lo2, const char_type* __hi2) const
764{
765 string_type lhs(__lo1, __hi1);
766 string_type rhs(__lo2, __hi2);
767 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
768 if (r < 0)
769 return -1;
770 if (r > 0)
771 return 1;
772 return r;
773}
774
775collate_byname<char>::string_type
776collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
777{
778 const string_type in(lo, hi);
779 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
780 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
781 return out;
782}
783
784// template <> class collate_byname<wchar_t>
785
Louis Dionne89258142021-08-23 15:32:36 -0400786#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000787collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
788 : collate<wchar_t>(refs),
789 __l(newlocale(LC_ALL_MASK, n, 0))
790{
791 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000792 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000793 " failed to construct for " + string(n));
794}
795
796collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
797 : collate<wchar_t>(refs),
798 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
799{
800 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000801 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000802 " failed to construct for " + name);
803}
804
805collate_byname<wchar_t>::~collate_byname()
806{
807 freelocale(__l);
808}
809
810int
811collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
812 const char_type* __lo2, const char_type* __hi2) const
813{
814 string_type lhs(__lo1, __hi1);
815 string_type rhs(__lo2, __hi2);
816 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
817 if (r < 0)
818 return -1;
819 if (r > 0)
820 return 1;
821 return r;
822}
823
824collate_byname<wchar_t>::string_type
825collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
826{
827 const string_type in(lo, hi);
828 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
829 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
830 return out;
831}
Louis Dionne89258142021-08-23 15:32:36 -0400832#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000833
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000834const ctype_base::mask ctype_base::space;
835const ctype_base::mask ctype_base::print;
836const ctype_base::mask ctype_base::cntrl;
837const ctype_base::mask ctype_base::upper;
838const ctype_base::mask ctype_base::lower;
839const ctype_base::mask ctype_base::alpha;
840const ctype_base::mask ctype_base::digit;
841const ctype_base::mask ctype_base::punct;
842const ctype_base::mask ctype_base::xdigit;
843const ctype_base::mask ctype_base::blank;
844const ctype_base::mask ctype_base::alnum;
845const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700846
Louis Dionne945f8682021-09-09 13:29:24 -0400847// template <> class ctype<wchar_t>;
848
Louis Dionne89258142021-08-23 15:32:36 -0400849#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000850locale::id ctype<wchar_t>::id;
851
852ctype<wchar_t>::~ctype()
853{
854}
855
856bool
857ctype<wchar_t>::do_is(mask m, char_type c) const
858{
Marshall Clowd920eea2013-10-21 15:07:28 +0000859 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000860}
861
862const wchar_t*
863ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
864{
865 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000866 *vec = static_cast<mask>(isascii(*low) ?
867 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000868 return low;
869}
870
871const wchar_t*
872ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
873{
874 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000875 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000876 break;
877 return low;
878}
879
880const wchar_t*
881ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
882{
883 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000884 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000885 break;
886 return low;
887}
888
889wchar_t
890ctype<wchar_t>::do_toupper(char_type c) const
891{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000892#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
893 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000894#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500895 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000896 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000897#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000898 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000899#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000900}
901
902const wchar_t*
903ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
904{
905 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000906#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
907 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000908#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500909 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000910 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
911 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000912#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000913 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000914#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000915 return low;
916}
917
918wchar_t
919ctype<wchar_t>::do_tolower(char_type c) const
920{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000921#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
922 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000923#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500924 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000925 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000926#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000927 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000928#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000929}
930
931const wchar_t*
932ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
933{
934 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000935#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
936 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000937#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Muiez Ahmed38aa7872022-01-14 11:35:53 -0500938 defined(__NetBSD__) || defined(__MVS__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000939 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
940 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000941#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000942 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000943#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000944 return low;
945}
946
947wchar_t
948ctype<wchar_t>::do_widen(char c) const
949{
950 return c;
951}
952
953const char*
954ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
955{
956 for (; low != high; ++low, ++dest)
957 *dest = *low;
958 return low;
959}
960
961char
962ctype<wchar_t>::do_narrow(char_type c, char dfault) const
963{
964 if (isascii(c))
965 return static_cast<char>(c);
966 return dfault;
967}
968
969const wchar_t*
970ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
971{
972 for (; low != high; ++low, ++dest)
973 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000974 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000975 else
976 *dest = dfault;
977 return low;
978}
Louis Dionne89258142021-08-23 15:32:36 -0400979#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000980
981// template <> class ctype<char>;
982
983locale::id ctype<char>::id;
984
Muiez Ahmedc98adb12021-11-18 15:49:45 -0500985const size_t ctype<char>::table_size;
986
Howard Hinnantc51e1022010-05-11 19:42:16 +0000987ctype<char>::ctype(const mask* tab, bool del, size_t refs)
988 : locale::facet(refs),
989 __tab_(tab),
990 __del_(del)
991{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000992 if (__tab_ == 0)
993 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000994}
995
996ctype<char>::~ctype()
997{
998 if (__tab_ && __del_)
999 delete [] __tab_;
1000}
1001
1002char
1003ctype<char>::do_toupper(char_type c) const
1004{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001005#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001006 return isascii(c) ?
1007 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001008#elif defined(__NetBSD__)
1009 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001010#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +00001011 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001012 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001013#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001014 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001015#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001016}
1017
1018const char*
1019ctype<char>::do_toupper(char_type* low, const char_type* high) const
1020{
1021 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001022#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001023 *low = isascii(*low) ?
1024 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001025#elif defined(__NetBSD__)
1026 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001027#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001028 *low = isascii(*low) ?
1029 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001030#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001031 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001032#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001033 return low;
1034}
1035
1036char
1037ctype<char>::do_tolower(char_type c) const
1038{
Howard Hinnantd7a78632011-09-29 13:33:15 +00001039#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001040 return isascii(c) ?
1041 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001042#elif defined(__NetBSD__)
1043 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001044#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001045 return isascii(c) ?
1046 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001047#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001048 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001049#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001050}
1051
1052const char*
1053ctype<char>::do_tolower(char_type* low, const char_type* high) const
1054{
1055 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001056#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001057 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001058#elif defined(__NetBSD__)
1059 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001060#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__MVS__)
Marshall Clowada0f732013-02-07 14:22:51 +00001061 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001062#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001063 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001064#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001065 return low;
1066}
1067
1068char
1069ctype<char>::do_widen(char c) const
1070{
1071 return c;
1072}
1073
1074const char*
1075ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1076{
1077 for (; low != high; ++low, ++dest)
1078 *dest = *low;
1079 return low;
1080}
1081
1082char
1083ctype<char>::do_narrow(char_type c, char dfault) const
1084{
1085 if (isascii(c))
1086 return static_cast<char>(c);
1087 return dfault;
1088}
1089
1090const char*
1091ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1092{
1093 for (; low != high; ++low, ++dest)
1094 if (isascii(*low))
1095 *dest = *low;
1096 else
1097 *dest = dfault;
1098 return low;
1099}
1100
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001101#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001102extern "C" const unsigned short ** __ctype_b_loc();
1103extern "C" const int ** __ctype_tolower_loc();
1104extern "C" const int ** __ctype_toupper_loc();
1105#endif
1106
Marshall Clow8f870232015-03-04 16:50:02 +00001107#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001108const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001109ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001110{
1111 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1112 cntrl, cntrl,
1113 cntrl, cntrl,
1114 cntrl, cntrl,
1115 cntrl, cntrl,
1116 cntrl, cntrl | space | blank,
1117 cntrl | space, cntrl | space,
1118 cntrl | space, cntrl | space,
1119 cntrl, cntrl,
1120 cntrl, cntrl,
1121 cntrl, cntrl,
1122 cntrl, cntrl,
1123 cntrl, cntrl,
1124 cntrl, cntrl,
1125 cntrl, cntrl,
1126 cntrl, cntrl,
1127 cntrl, cntrl,
1128 space | blank | print, punct | print,
1129 punct | print, punct | print,
1130 punct | 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 digit | print | xdigit, digit | print | xdigit,
1137 digit | print | xdigit, digit | print | xdigit,
1138 digit | print | xdigit, digit | print | xdigit,
1139 digit | print | xdigit, digit | print | xdigit,
1140 digit | print | xdigit, digit | print | xdigit,
1141 punct | print, punct | print,
1142 punct | print, punct | print,
1143 punct | print, punct | print,
1144 punct | print, upper | xdigit | print | alpha,
1145 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1146 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1147 upper | xdigit | print | alpha, upper | print | alpha,
1148 upper | print | alpha, upper | print | alpha,
1149 upper | 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, punct | print,
1158 punct | print, punct | print,
1159 punct | print, punct | print,
1160 punct | print, lower | xdigit | print | alpha,
1161 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1162 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1163 lower | xdigit | print | alpha, lower | print | alpha,
1164 lower | print | alpha, lower | print | alpha,
1165 lower | 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, punct | print,
1174 punct | print, punct | print,
1175 punct | print, cntrl,
1176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 };
1185 return builtin_table;
1186}
1187#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001188const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001189ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001190{
David Chisnall1d581062011-09-21 08:39:44 +00001191#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001192 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001193#elif defined(__NetBSD__)
1194 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001195#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001196 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001197#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001198 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001199#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001200 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001201#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001202 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001203#elif defined(_NEWLIB_VERSION)
1204 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1205 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001206#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001207 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001208#elif defined(__MVS__)
1209# if defined(__NATIVE_ASCII_F)
1210 return const_cast<const ctype<char>::mask*> (__OBJ_DATA(__lc_ctype_a)->mask);
1211# else
1212 return const_cast<const ctype<char>::mask*> (__ctypec);
1213# endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001214#else
David Chisnall8074c342012-02-29 13:05:08 +00001215 // Platform not supported: abort so the person doing the port knows what to
1216 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001217# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001218 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001219 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001220 return NULL;
1221#endif
1222}
Marshall Clowb3f62842015-03-04 16:10:14 +00001223#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001224
Howard Hinnantd7a78632011-09-29 13:33:15 +00001225#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001226const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001227ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001228{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001229 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001230}
1231
1232const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001233ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001234{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001235 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001236}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001237#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001238const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001239ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001240{
1241 return _C_tolower_tab_ + 1;
1242}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001243
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001244const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001245ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001246{
1247 return _C_toupper_tab_ + 1;
1248}
1249
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001250#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001251const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001252ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001253{
1254 return *__ctype_tolower_loc();
1255}
1256
1257const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001258ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001259{
1260 return *__ctype_toupper_loc();
1261}
Muiez Ahmed38aa7872022-01-14 11:35:53 -05001262#elif defined(__MVS__)
1263const unsigned short*
1264ctype<char>::__classic_lower_table() _NOEXCEPT
1265{
1266# if defined(__NATIVE_ASCII_F)
1267 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->lower);
1268# else
1269 return const_cast<const unsigned short*>(__ctype + __TOLOWER_INDEX);
1270# endif
1271}
1272const unsigned short *
1273ctype<char>::__classic_upper_table() _NOEXCEPT
1274{
1275# if defined(__NATIVE_ASCII_F)
1276 return const_cast<const unsigned short*>(__OBJ_DATA(__lc_ctype_a)->upper);
1277# else
1278 return const_cast<const unsigned short*>(__ctype + __TOUPPER_INDEX);
1279# endif
1280}
1281#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || __MVS__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001282
Howard Hinnantc51e1022010-05-11 19:42:16 +00001283// template <> class ctype_byname<char>
1284
1285ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1286 : ctype<char>(0, false, refs),
1287 __l(newlocale(LC_ALL_MASK, name, 0))
1288{
1289 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001290 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001291 " failed to construct for " + string(name));
1292}
1293
1294ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1295 : ctype<char>(0, false, refs),
1296 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1297{
1298 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001299 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 " failed to construct for " + name);
1301}
1302
1303ctype_byname<char>::~ctype_byname()
1304{
1305 freelocale(__l);
1306}
1307
1308char
1309ctype_byname<char>::do_toupper(char_type c) const
1310{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001311 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001312}
1313
1314const char*
1315ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1316{
1317 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001318 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001319 return low;
1320}
1321
1322char
1323ctype_byname<char>::do_tolower(char_type c) const
1324{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001325 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001326}
1327
1328const char*
1329ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1330{
1331 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001332 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001333 return low;
1334}
1335
1336// template <> class ctype_byname<wchar_t>
1337
Louis Dionne89258142021-08-23 15:32:36 -04001338#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001339ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1340 : ctype<wchar_t>(refs),
1341 __l(newlocale(LC_ALL_MASK, name, 0))
1342{
1343 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001344 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345 " failed to construct for " + string(name));
1346}
1347
1348ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1349 : ctype<wchar_t>(refs),
1350 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1351{
1352 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001353 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001354 " failed to construct for " + name);
1355}
1356
1357ctype_byname<wchar_t>::~ctype_byname()
1358{
1359 freelocale(__l);
1360}
1361
1362bool
1363ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1364{
Alexis Huntc2017f12011-07-09 03:40:04 +00001365#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001366 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001367#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001368 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001369 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001370 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1371 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1372 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1373 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1374 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1375 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1376 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1377 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1378 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1379 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001380 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001381#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001382}
1383
1384const wchar_t*
1385ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1386{
1387 for (; low != high; ++low, ++vec)
1388 {
1389 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001390 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001391 else
1392 {
1393 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001394 wint_t ch = static_cast<wint_t>(*low);
1395 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001396 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001397#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001398 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001399 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001400#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001401 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001402 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001403 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001405 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001406 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001407#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001408 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001409 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001410#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001411 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001412 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001413 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001414 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001415#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001416 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001417 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001418#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001419#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001420 if (iswblank_l(ch, __l))
1421 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001422#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001423 }
1424 }
1425 return low;
1426}
1427
1428const wchar_t*
1429ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1430{
1431 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001432 {
1433#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001434 if (iswctype_l(*low, m, __l))
1435 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001436#else
Marshall Clowada0f732013-02-07 14:22:51 +00001437 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001438 if ((m & space) == space && iswspace_l(ch, __l)) break;
1439 if ((m & print) == print && iswprint_l(ch, __l)) break;
1440 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1441 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1442 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1443 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1444 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1445 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1446 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1447 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001448#endif
1449 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001450 return low;
1451}
1452
1453const wchar_t*
1454ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1455{
1456 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001457 {
1458#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001459 if (!iswctype_l(*low, m, __l))
1460 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001461#else
Marshall Clowada0f732013-02-07 14:22:51 +00001462 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001463 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1464 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1465 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1466 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1467 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1468 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1469 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1470 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1471 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1472 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001473 break;
1474#endif
1475 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001476 return low;
1477}
1478
1479wchar_t
1480ctype_byname<wchar_t>::do_toupper(char_type c) const
1481{
1482 return towupper_l(c, __l);
1483}
1484
1485const wchar_t*
1486ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1487{
1488 for (; low != high; ++low)
1489 *low = towupper_l(*low, __l);
1490 return low;
1491}
1492
1493wchar_t
1494ctype_byname<wchar_t>::do_tolower(char_type c) const
1495{
1496 return towlower_l(c, __l);
1497}
1498
1499const wchar_t*
1500ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1501{
1502 for (; low != high; ++low)
1503 *low = towlower_l(*low, __l);
1504 return low;
1505}
1506
1507wchar_t
1508ctype_byname<wchar_t>::do_widen(char c) const
1509{
Ben Craig3756b922016-03-09 15:39:39 +00001510 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001511}
1512
1513const char*
1514ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1515{
1516 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001517 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001518 return low;
1519}
1520
1521char
1522ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1523{
Ben Craig3756b922016-03-09 15:39:39 +00001524 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001525 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526}
1527
1528const wchar_t*
1529ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1530{
1531 for (; low != high; ++low, ++dest)
1532 {
Ben Craig3756b922016-03-09 15:39:39 +00001533 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001534 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001535 }
1536 return low;
1537}
Louis Dionne89258142021-08-23 15:32:36 -04001538#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001539
1540// template <> class codecvt<char, char, mbstate_t>
1541
Howard Hinnantffb308e2010-08-22 00:03:27 +00001542locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001543
1544codecvt<char, char, mbstate_t>::~codecvt()
1545{
1546}
1547
1548codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001549codecvt<char, char, mbstate_t>::do_out(state_type&,
1550 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001551 extern_type* to, extern_type*, extern_type*& to_nxt) const
1552{
1553 frm_nxt = frm;
1554 to_nxt = to;
1555 return noconv;
1556}
1557
1558codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001559codecvt<char, char, mbstate_t>::do_in(state_type&,
1560 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001561 intern_type* to, intern_type*, intern_type*& to_nxt) const
1562{
1563 frm_nxt = frm;
1564 to_nxt = to;
1565 return noconv;
1566}
1567
1568codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001569codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001570 extern_type* to, extern_type*, extern_type*& to_nxt) const
1571{
1572 to_nxt = to;
1573 return noconv;
1574}
1575
1576int
Louis Dionne65358e12021-03-01 12:09:45 -05001577codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001578{
1579 return 1;
1580}
1581
1582bool
Louis Dionne65358e12021-03-01 12:09:45 -05001583codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001584{
1585 return true;
1586}
1587
1588int
1589codecvt<char, char, mbstate_t>::do_length(state_type&,
1590 const extern_type* frm, const extern_type* end, size_t mx) const
1591{
Howard Hinnant28b24882011-12-01 20:21:04 +00001592 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001593}
1594
1595int
Louis Dionne65358e12021-03-01 12:09:45 -05001596codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001597{
1598 return 1;
1599}
1600
1601// template <> class codecvt<wchar_t, char, mbstate_t>
1602
Louis Dionne89258142021-08-23 15:32:36 -04001603#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantffb308e2010-08-22 00:03:27 +00001604locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001605
1606codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1607 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001608 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001609{
1610}
1611
1612codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1613 : locale::facet(refs),
1614 __l(newlocale(LC_ALL_MASK, nm, 0))
1615{
1616 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001617 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001618 " failed to construct for " + string(nm));
1619}
1620
1621codecvt<wchar_t, char, mbstate_t>::~codecvt()
1622{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001623 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001624 freelocale(__l);
1625}
1626
1627codecvt<wchar_t, char, mbstate_t>::result
1628codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001629 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001630 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1631{
1632 // look for first internal null in frm
1633 const intern_type* fend = frm;
1634 for (; fend != frm_end; ++fend)
1635 if (*fend == 0)
1636 break;
1637 // loop over all null-terminated sequences in frm
1638 to_nxt = to;
1639 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1640 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001641 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001642 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001643 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1644 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001645 if (n == size_t(-1))
1646 {
1647 // need to recover to_nxt
1648 for (to_nxt = to; frm != frm_nxt; ++frm)
1649 {
Ben Craig3756b922016-03-09 15:39:39 +00001650 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001651 if (n == size_t(-1))
1652 break;
1653 to_nxt += n;
1654 }
1655 frm_nxt = frm;
1656 return error;
1657 }
1658 if (n == 0)
1659 return partial;
1660 to_nxt += n;
1661 if (to_nxt == to_end)
1662 break;
1663 if (fend != frm_end) // set up next null terminated sequence
1664 {
1665 // Try to write the terminating null
1666 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001667 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001668 if (n == size_t(-1)) // on error
1669 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001670 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001671 return partial;
1672 for (extern_type* p = tmp; n; --n) // write it
1673 *to_nxt++ = *p++;
1674 ++frm_nxt;
1675 // look for next null in frm
1676 for (fend = frm_nxt; fend != frm_end; ++fend)
1677 if (*fend == 0)
1678 break;
1679 }
1680 }
1681 return frm_nxt == frm_end ? ok : partial;
1682}
1683
1684codecvt<wchar_t, char, mbstate_t>::result
1685codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001686 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001687 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1688{
1689 // look for first internal null in frm
1690 const extern_type* fend = frm;
1691 for (; fend != frm_end; ++fend)
1692 if (*fend == 0)
1693 break;
1694 // loop over all null-terminated sequences in frm
1695 to_nxt = to;
1696 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1697 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001698 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001699 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001700 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1701 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001702 if (n == size_t(-1))
1703 {
1704 // need to recover to_nxt
1705 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1706 {
Ben Craig3756b922016-03-09 15:39:39 +00001707 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1708 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001709 switch (n)
1710 {
1711 case 0:
1712 ++frm;
1713 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001714 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001715 frm_nxt = frm;
1716 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001717 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001718 frm_nxt = frm;
1719 return partial;
1720 default:
1721 frm += n;
1722 break;
1723 }
1724 }
1725 frm_nxt = frm;
1726 return frm_nxt == frm_end ? ok : partial;
1727 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001728 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001729 return error;
1730 to_nxt += n;
1731 if (to_nxt == to_end)
1732 break;
1733 if (fend != frm_end) // set up next null terminated sequence
1734 {
1735 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001736 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001737 if (n != 0) // on error
1738 return error;
1739 ++to_nxt;
1740 ++frm_nxt;
1741 // look for next null in frm
1742 for (fend = frm_nxt; fend != frm_end; ++fend)
1743 if (*fend == 0)
1744 break;
1745 }
1746 }
1747 return frm_nxt == frm_end ? ok : partial;
1748}
1749
1750codecvt<wchar_t, char, mbstate_t>::result
1751codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1752 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1753{
1754 to_nxt = to;
1755 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001756 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001757 if (n == size_t(-1) || n == 0) // on error
1758 return error;
1759 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001760 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001761 return partial;
1762 for (extern_type* p = tmp; n; --n) // write it
1763 *to_nxt++ = *p++;
1764 return ok;
1765}
1766
1767int
Louis Dionne65358e12021-03-01 12:09:45 -05001768codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001769{
Ben Craig3756b922016-03-09 15:39:39 +00001770 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001771 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001772
1773 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001774 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001775 return 1; // which take more than 1 char to form a wchar_t
1776 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001777}
1778
1779bool
Louis Dionne65358e12021-03-01 12:09:45 -05001780codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001781{
1782 return false;
1783}
1784
1785int
1786codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1787 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1788{
1789 int nbytes = 0;
1790 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1791 {
Ben Craig3756b922016-03-09 15:39:39 +00001792 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001793 switch (n)
1794 {
1795 case 0:
1796 ++nbytes;
1797 ++frm;
1798 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001799 case size_t(-1):
1800 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001801 return nbytes;
1802 default:
1803 nbytes += n;
1804 frm += n;
1805 break;
1806 }
1807 }
1808 return nbytes;
1809}
1810
1811int
Louis Dionne65358e12021-03-01 12:09:45 -05001812codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001813{
Ben Craig3756b922016-03-09 15:39:39 +00001814 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001815}
Louis Dionne89258142021-08-23 15:32:36 -04001816#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001817
1818// Valid UTF ranges
1819// UTF-32 UTF-16 UTF-8 # of code points
1820// first second first second third fourth
1821// 000000 - 00007F 0000 - 007F 00 - 7F 127
1822// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1823// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1824// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1825// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1826// 00D800 - 00DFFF invalid
1827// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1828// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1829// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1830// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1831
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001832static
1833codecvt_base::result
1834utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1835 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1836 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1837{
1838 frm_nxt = frm;
1839 to_nxt = to;
1840 if (mode & generate_header)
1841 {
1842 if (to_end-to_nxt < 3)
1843 return codecvt_base::partial;
1844 *to_nxt++ = static_cast<uint8_t>(0xEF);
1845 *to_nxt++ = static_cast<uint8_t>(0xBB);
1846 *to_nxt++ = static_cast<uint8_t>(0xBF);
1847 }
1848 for (; frm_nxt < frm_end; ++frm_nxt)
1849 {
1850 uint16_t wc1 = *frm_nxt;
1851 if (wc1 > Maxcode)
1852 return codecvt_base::error;
1853 if (wc1 < 0x0080)
1854 {
1855 if (to_end-to_nxt < 1)
1856 return codecvt_base::partial;
1857 *to_nxt++ = static_cast<uint8_t>(wc1);
1858 }
1859 else if (wc1 < 0x0800)
1860 {
1861 if (to_end-to_nxt < 2)
1862 return codecvt_base::partial;
1863 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1864 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1865 }
1866 else if (wc1 < 0xD800)
1867 {
1868 if (to_end-to_nxt < 3)
1869 return codecvt_base::partial;
1870 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1871 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1872 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1873 }
1874 else if (wc1 < 0xDC00)
1875 {
1876 if (frm_end-frm_nxt < 2)
1877 return codecvt_base::partial;
1878 uint16_t wc2 = frm_nxt[1];
1879 if ((wc2 & 0xFC00) != 0xDC00)
1880 return codecvt_base::error;
1881 if (to_end-to_nxt < 4)
1882 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001883 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1884 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001885 return codecvt_base::error;
1886 ++frm_nxt;
1887 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1888 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1889 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1890 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1891 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1892 }
1893 else if (wc1 < 0xE000)
1894 {
1895 return codecvt_base::error;
1896 }
1897 else
1898 {
1899 if (to_end-to_nxt < 3)
1900 return codecvt_base::partial;
1901 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1902 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1903 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1904 }
1905 }
1906 return codecvt_base::ok;
1907}
1908
1909static
1910codecvt_base::result
1911utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1912 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1913 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1914{
1915 frm_nxt = frm;
1916 to_nxt = to;
1917 if (mode & generate_header)
1918 {
1919 if (to_end-to_nxt < 3)
1920 return codecvt_base::partial;
1921 *to_nxt++ = static_cast<uint8_t>(0xEF);
1922 *to_nxt++ = static_cast<uint8_t>(0xBB);
1923 *to_nxt++ = static_cast<uint8_t>(0xBF);
1924 }
1925 for (; frm_nxt < frm_end; ++frm_nxt)
1926 {
1927 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1928 if (wc1 > Maxcode)
1929 return codecvt_base::error;
1930 if (wc1 < 0x0080)
1931 {
1932 if (to_end-to_nxt < 1)
1933 return codecvt_base::partial;
1934 *to_nxt++ = static_cast<uint8_t>(wc1);
1935 }
1936 else if (wc1 < 0x0800)
1937 {
1938 if (to_end-to_nxt < 2)
1939 return codecvt_base::partial;
1940 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1941 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1942 }
1943 else if (wc1 < 0xD800)
1944 {
1945 if (to_end-to_nxt < 3)
1946 return codecvt_base::partial;
1947 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1948 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1949 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1950 }
1951 else if (wc1 < 0xDC00)
1952 {
1953 if (frm_end-frm_nxt < 2)
1954 return codecvt_base::partial;
1955 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1956 if ((wc2 & 0xFC00) != 0xDC00)
1957 return codecvt_base::error;
1958 if (to_end-to_nxt < 4)
1959 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001960 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1961 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001962 return codecvt_base::error;
1963 ++frm_nxt;
1964 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1965 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1966 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1967 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1968 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1969 }
1970 else if (wc1 < 0xE000)
1971 {
1972 return codecvt_base::error;
1973 }
1974 else
1975 {
1976 if (to_end-to_nxt < 3)
1977 return codecvt_base::partial;
1978 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1979 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1980 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1981 }
1982 }
1983 return codecvt_base::ok;
1984}
1985
1986static
1987codecvt_base::result
1988utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1989 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1990 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1991{
1992 frm_nxt = frm;
1993 to_nxt = to;
1994 if (mode & consume_header)
1995 {
1996 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1997 frm_nxt[2] == 0xBF)
1998 frm_nxt += 3;
1999 }
2000 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2001 {
2002 uint8_t c1 = *frm_nxt;
2003 if (c1 > Maxcode)
2004 return codecvt_base::error;
2005 if (c1 < 0x80)
2006 {
2007 *to_nxt = static_cast<uint16_t>(c1);
2008 ++frm_nxt;
2009 }
2010 else if (c1 < 0xC2)
2011 {
2012 return codecvt_base::error;
2013 }
2014 else if (c1 < 0xE0)
2015 {
2016 if (frm_end-frm_nxt < 2)
2017 return codecvt_base::partial;
2018 uint8_t c2 = frm_nxt[1];
2019 if ((c2 & 0xC0) != 0x80)
2020 return codecvt_base::error;
2021 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2022 if (t > Maxcode)
2023 return codecvt_base::error;
2024 *to_nxt = t;
2025 frm_nxt += 2;
2026 }
2027 else if (c1 < 0xF0)
2028 {
2029 if (frm_end-frm_nxt < 3)
2030 return codecvt_base::partial;
2031 uint8_t c2 = frm_nxt[1];
2032 uint8_t c3 = frm_nxt[2];
2033 switch (c1)
2034 {
2035 case 0xE0:
2036 if ((c2 & 0xE0) != 0xA0)
2037 return codecvt_base::error;
2038 break;
2039 case 0xED:
2040 if ((c2 & 0xE0) != 0x80)
2041 return codecvt_base::error;
2042 break;
2043 default:
2044 if ((c2 & 0xC0) != 0x80)
2045 return codecvt_base::error;
2046 break;
2047 }
2048 if ((c3 & 0xC0) != 0x80)
2049 return codecvt_base::error;
2050 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2051 | ((c2 & 0x3F) << 6)
2052 | (c3 & 0x3F));
2053 if (t > Maxcode)
2054 return codecvt_base::error;
2055 *to_nxt = t;
2056 frm_nxt += 3;
2057 }
2058 else if (c1 < 0xF5)
2059 {
2060 if (frm_end-frm_nxt < 4)
2061 return codecvt_base::partial;
2062 uint8_t c2 = frm_nxt[1];
2063 uint8_t c3 = frm_nxt[2];
2064 uint8_t c4 = frm_nxt[3];
2065 switch (c1)
2066 {
2067 case 0xF0:
2068 if (!(0x90 <= c2 && c2 <= 0xBF))
2069 return codecvt_base::error;
2070 break;
2071 case 0xF4:
2072 if ((c2 & 0xF0) != 0x80)
2073 return codecvt_base::error;
2074 break;
2075 default:
2076 if ((c2 & 0xC0) != 0x80)
2077 return codecvt_base::error;
2078 break;
2079 }
2080 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2081 return codecvt_base::error;
2082 if (to_end-to_nxt < 2)
2083 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002084 if ((((c1 & 7UL) << 18) +
2085 ((c2 & 0x3FUL) << 12) +
2086 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002087 return codecvt_base::error;
2088 *to_nxt = static_cast<uint16_t>(
2089 0xD800
2090 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2091 | ((c2 & 0x0F) << 2)
2092 | ((c3 & 0x30) >> 4));
2093 *++to_nxt = static_cast<uint16_t>(
2094 0xDC00
2095 | ((c3 & 0x0F) << 6)
2096 | (c4 & 0x3F));
2097 frm_nxt += 4;
2098 }
2099 else
2100 {
2101 return codecvt_base::error;
2102 }
2103 }
2104 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2105}
2106
2107static
2108codecvt_base::result
2109utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2110 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2111 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2112{
2113 frm_nxt = frm;
2114 to_nxt = to;
2115 if (mode & consume_header)
2116 {
2117 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2118 frm_nxt[2] == 0xBF)
2119 frm_nxt += 3;
2120 }
2121 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2122 {
2123 uint8_t c1 = *frm_nxt;
2124 if (c1 > Maxcode)
2125 return codecvt_base::error;
2126 if (c1 < 0x80)
2127 {
2128 *to_nxt = static_cast<uint32_t>(c1);
2129 ++frm_nxt;
2130 }
2131 else if (c1 < 0xC2)
2132 {
2133 return codecvt_base::error;
2134 }
2135 else if (c1 < 0xE0)
2136 {
2137 if (frm_end-frm_nxt < 2)
2138 return codecvt_base::partial;
2139 uint8_t c2 = frm_nxt[1];
2140 if ((c2 & 0xC0) != 0x80)
2141 return codecvt_base::error;
2142 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2143 if (t > Maxcode)
2144 return codecvt_base::error;
2145 *to_nxt = static_cast<uint32_t>(t);
2146 frm_nxt += 2;
2147 }
2148 else if (c1 < 0xF0)
2149 {
2150 if (frm_end-frm_nxt < 3)
2151 return codecvt_base::partial;
2152 uint8_t c2 = frm_nxt[1];
2153 uint8_t c3 = frm_nxt[2];
2154 switch (c1)
2155 {
2156 case 0xE0:
2157 if ((c2 & 0xE0) != 0xA0)
2158 return codecvt_base::error;
2159 break;
2160 case 0xED:
2161 if ((c2 & 0xE0) != 0x80)
2162 return codecvt_base::error;
2163 break;
2164 default:
2165 if ((c2 & 0xC0) != 0x80)
2166 return codecvt_base::error;
2167 break;
2168 }
2169 if ((c3 & 0xC0) != 0x80)
2170 return codecvt_base::error;
2171 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2172 | ((c2 & 0x3F) << 6)
2173 | (c3 & 0x3F));
2174 if (t > Maxcode)
2175 return codecvt_base::error;
2176 *to_nxt = static_cast<uint32_t>(t);
2177 frm_nxt += 3;
2178 }
2179 else if (c1 < 0xF5)
2180 {
2181 if (frm_end-frm_nxt < 4)
2182 return codecvt_base::partial;
2183 uint8_t c2 = frm_nxt[1];
2184 uint8_t c3 = frm_nxt[2];
2185 uint8_t c4 = frm_nxt[3];
2186 switch (c1)
2187 {
2188 case 0xF0:
2189 if (!(0x90 <= c2 && c2 <= 0xBF))
2190 return codecvt_base::error;
2191 break;
2192 case 0xF4:
2193 if ((c2 & 0xF0) != 0x80)
2194 return codecvt_base::error;
2195 break;
2196 default:
2197 if ((c2 & 0xC0) != 0x80)
2198 return codecvt_base::error;
2199 break;
2200 }
2201 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2202 return codecvt_base::error;
2203 if (to_end-to_nxt < 2)
2204 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002205 if ((((c1 & 7UL) << 18) +
2206 ((c2 & 0x3FUL) << 12) +
2207 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002208 return codecvt_base::error;
2209 *to_nxt = static_cast<uint32_t>(
2210 0xD800
2211 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2212 | ((c2 & 0x0F) << 2)
2213 | ((c3 & 0x30) >> 4));
2214 *++to_nxt = static_cast<uint32_t>(
2215 0xDC00
2216 | ((c3 & 0x0F) << 6)
2217 | (c4 & 0x3F));
2218 frm_nxt += 4;
2219 }
2220 else
2221 {
2222 return codecvt_base::error;
2223 }
2224 }
2225 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2226}
2227
2228static
2229int
2230utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2231 size_t mx, unsigned long Maxcode = 0x10FFFF,
2232 codecvt_mode mode = codecvt_mode(0))
2233{
2234 const uint8_t* frm_nxt = frm;
2235 if (mode & consume_header)
2236 {
2237 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2238 frm_nxt[2] == 0xBF)
2239 frm_nxt += 3;
2240 }
2241 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2242 {
2243 uint8_t c1 = *frm_nxt;
2244 if (c1 > Maxcode)
2245 break;
2246 if (c1 < 0x80)
2247 {
2248 ++frm_nxt;
2249 }
2250 else if (c1 < 0xC2)
2251 {
2252 break;
2253 }
2254 else if (c1 < 0xE0)
2255 {
2256 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2257 break;
2258 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2259 if (t > Maxcode)
2260 break;
2261 frm_nxt += 2;
2262 }
2263 else if (c1 < 0xF0)
2264 {
2265 if (frm_end-frm_nxt < 3)
2266 break;
2267 uint8_t c2 = frm_nxt[1];
2268 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002269 switch (c1)
2270 {
2271 case 0xE0:
2272 if ((c2 & 0xE0) != 0xA0)
2273 return static_cast<int>(frm_nxt - frm);
2274 break;
2275 case 0xED:
2276 if ((c2 & 0xE0) != 0x80)
2277 return static_cast<int>(frm_nxt - frm);
2278 break;
2279 default:
2280 if ((c2 & 0xC0) != 0x80)
2281 return static_cast<int>(frm_nxt - frm);
2282 break;
2283 }
2284 if ((c3 & 0xC0) != 0x80)
2285 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002286 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002287 break;
2288 frm_nxt += 3;
2289 }
2290 else if (c1 < 0xF5)
2291 {
2292 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2293 break;
2294 uint8_t c2 = frm_nxt[1];
2295 uint8_t c3 = frm_nxt[2];
2296 uint8_t c4 = frm_nxt[3];
2297 switch (c1)
2298 {
2299 case 0xF0:
2300 if (!(0x90 <= c2 && c2 <= 0xBF))
2301 return static_cast<int>(frm_nxt - frm);
2302 break;
2303 case 0xF4:
2304 if ((c2 & 0xF0) != 0x80)
2305 return static_cast<int>(frm_nxt - frm);
2306 break;
2307 default:
2308 if ((c2 & 0xC0) != 0x80)
2309 return static_cast<int>(frm_nxt - frm);
2310 break;
2311 }
2312 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2313 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002314 if ((((c1 & 7UL) << 18) +
2315 ((c2 & 0x3FUL) << 12) +
2316 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002317 break;
2318 ++nchar16_t;
2319 frm_nxt += 4;
2320 }
2321 else
2322 {
2323 break;
2324 }
2325 }
2326 return static_cast<int>(frm_nxt - frm);
2327}
2328
2329static
2330codecvt_base::result
2331ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2332 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2333 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2334{
2335 frm_nxt = frm;
2336 to_nxt = to;
2337 if (mode & generate_header)
2338 {
2339 if (to_end-to_nxt < 3)
2340 return codecvt_base::partial;
2341 *to_nxt++ = static_cast<uint8_t>(0xEF);
2342 *to_nxt++ = static_cast<uint8_t>(0xBB);
2343 *to_nxt++ = static_cast<uint8_t>(0xBF);
2344 }
2345 for (; frm_nxt < frm_end; ++frm_nxt)
2346 {
2347 uint32_t wc = *frm_nxt;
2348 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2349 return codecvt_base::error;
2350 if (wc < 0x000080)
2351 {
2352 if (to_end-to_nxt < 1)
2353 return codecvt_base::partial;
2354 *to_nxt++ = static_cast<uint8_t>(wc);
2355 }
2356 else if (wc < 0x000800)
2357 {
2358 if (to_end-to_nxt < 2)
2359 return codecvt_base::partial;
2360 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2361 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2362 }
2363 else if (wc < 0x010000)
2364 {
2365 if (to_end-to_nxt < 3)
2366 return codecvt_base::partial;
2367 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2368 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2369 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2370 }
2371 else // if (wc < 0x110000)
2372 {
2373 if (to_end-to_nxt < 4)
2374 return codecvt_base::partial;
2375 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2376 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2377 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2378 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2379 }
2380 }
2381 return codecvt_base::ok;
2382}
2383
2384static
2385codecvt_base::result
2386utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2387 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2388 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2389{
2390 frm_nxt = frm;
2391 to_nxt = to;
2392 if (mode & consume_header)
2393 {
2394 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2395 frm_nxt[2] == 0xBF)
2396 frm_nxt += 3;
2397 }
2398 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2399 {
2400 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2401 if (c1 < 0x80)
2402 {
2403 if (c1 > Maxcode)
2404 return codecvt_base::error;
2405 *to_nxt = static_cast<uint32_t>(c1);
2406 ++frm_nxt;
2407 }
2408 else if (c1 < 0xC2)
2409 {
2410 return codecvt_base::error;
2411 }
2412 else if (c1 < 0xE0)
2413 {
2414 if (frm_end-frm_nxt < 2)
2415 return codecvt_base::partial;
2416 uint8_t c2 = frm_nxt[1];
2417 if ((c2 & 0xC0) != 0x80)
2418 return codecvt_base::error;
2419 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2420 | (c2 & 0x3F));
2421 if (t > Maxcode)
2422 return codecvt_base::error;
2423 *to_nxt = t;
2424 frm_nxt += 2;
2425 }
2426 else if (c1 < 0xF0)
2427 {
2428 if (frm_end-frm_nxt < 3)
2429 return codecvt_base::partial;
2430 uint8_t c2 = frm_nxt[1];
2431 uint8_t c3 = frm_nxt[2];
2432 switch (c1)
2433 {
2434 case 0xE0:
2435 if ((c2 & 0xE0) != 0xA0)
2436 return codecvt_base::error;
2437 break;
2438 case 0xED:
2439 if ((c2 & 0xE0) != 0x80)
2440 return codecvt_base::error;
2441 break;
2442 default:
2443 if ((c2 & 0xC0) != 0x80)
2444 return codecvt_base::error;
2445 break;
2446 }
2447 if ((c3 & 0xC0) != 0x80)
2448 return codecvt_base::error;
2449 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2450 | ((c2 & 0x3F) << 6)
2451 | (c3 & 0x3F));
2452 if (t > Maxcode)
2453 return codecvt_base::error;
2454 *to_nxt = t;
2455 frm_nxt += 3;
2456 }
2457 else if (c1 < 0xF5)
2458 {
2459 if (frm_end-frm_nxt < 4)
2460 return codecvt_base::partial;
2461 uint8_t c2 = frm_nxt[1];
2462 uint8_t c3 = frm_nxt[2];
2463 uint8_t c4 = frm_nxt[3];
2464 switch (c1)
2465 {
2466 case 0xF0:
2467 if (!(0x90 <= c2 && c2 <= 0xBF))
2468 return codecvt_base::error;
2469 break;
2470 case 0xF4:
2471 if ((c2 & 0xF0) != 0x80)
2472 return codecvt_base::error;
2473 break;
2474 default:
2475 if ((c2 & 0xC0) != 0x80)
2476 return codecvt_base::error;
2477 break;
2478 }
2479 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2480 return codecvt_base::error;
2481 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2482 | ((c2 & 0x3F) << 12)
2483 | ((c3 & 0x3F) << 6)
2484 | (c4 & 0x3F));
2485 if (t > Maxcode)
2486 return codecvt_base::error;
2487 *to_nxt = t;
2488 frm_nxt += 4;
2489 }
2490 else
2491 {
2492 return codecvt_base::error;
2493 }
2494 }
2495 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2496}
2497
2498static
2499int
2500utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2501 size_t mx, unsigned long Maxcode = 0x10FFFF,
2502 codecvt_mode mode = codecvt_mode(0))
2503{
2504 const uint8_t* frm_nxt = frm;
2505 if (mode & consume_header)
2506 {
2507 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2508 frm_nxt[2] == 0xBF)
2509 frm_nxt += 3;
2510 }
2511 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2512 {
2513 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2514 if (c1 < 0x80)
2515 {
2516 if (c1 > Maxcode)
2517 break;
2518 ++frm_nxt;
2519 }
2520 else if (c1 < 0xC2)
2521 {
2522 break;
2523 }
2524 else if (c1 < 0xE0)
2525 {
2526 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2527 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002528 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002529 break;
2530 frm_nxt += 2;
2531 }
2532 else if (c1 < 0xF0)
2533 {
2534 if (frm_end-frm_nxt < 3)
2535 break;
2536 uint8_t c2 = frm_nxt[1];
2537 uint8_t c3 = frm_nxt[2];
2538 switch (c1)
2539 {
2540 case 0xE0:
2541 if ((c2 & 0xE0) != 0xA0)
2542 return static_cast<int>(frm_nxt - frm);
2543 break;
2544 case 0xED:
2545 if ((c2 & 0xE0) != 0x80)
2546 return static_cast<int>(frm_nxt - frm);
2547 break;
2548 default:
2549 if ((c2 & 0xC0) != 0x80)
2550 return static_cast<int>(frm_nxt - frm);
2551 break;
2552 }
2553 if ((c3 & 0xC0) != 0x80)
2554 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002555 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002556 break;
2557 frm_nxt += 3;
2558 }
2559 else if (c1 < 0xF5)
2560 {
2561 if (frm_end-frm_nxt < 4)
2562 break;
2563 uint8_t c2 = frm_nxt[1];
2564 uint8_t c3 = frm_nxt[2];
2565 uint8_t c4 = frm_nxt[3];
2566 switch (c1)
2567 {
2568 case 0xF0:
2569 if (!(0x90 <= c2 && c2 <= 0xBF))
2570 return static_cast<int>(frm_nxt - frm);
2571 break;
2572 case 0xF4:
2573 if ((c2 & 0xF0) != 0x80)
2574 return static_cast<int>(frm_nxt - frm);
2575 break;
2576 default:
2577 if ((c2 & 0xC0) != 0x80)
2578 return static_cast<int>(frm_nxt - frm);
2579 break;
2580 }
2581 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2582 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002583 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2584 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002585 break;
2586 frm_nxt += 4;
2587 }
2588 else
2589 {
2590 break;
2591 }
2592 }
2593 return static_cast<int>(frm_nxt - frm);
2594}
2595
2596static
2597codecvt_base::result
2598ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2599 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2600 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2601{
2602 frm_nxt = frm;
2603 to_nxt = to;
2604 if (mode & generate_header)
2605 {
2606 if (to_end-to_nxt < 3)
2607 return codecvt_base::partial;
2608 *to_nxt++ = static_cast<uint8_t>(0xEF);
2609 *to_nxt++ = static_cast<uint8_t>(0xBB);
2610 *to_nxt++ = static_cast<uint8_t>(0xBF);
2611 }
2612 for (; frm_nxt < frm_end; ++frm_nxt)
2613 {
2614 uint16_t wc = *frm_nxt;
2615 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2616 return codecvt_base::error;
2617 if (wc < 0x0080)
2618 {
2619 if (to_end-to_nxt < 1)
2620 return codecvt_base::partial;
2621 *to_nxt++ = static_cast<uint8_t>(wc);
2622 }
2623 else if (wc < 0x0800)
2624 {
2625 if (to_end-to_nxt < 2)
2626 return codecvt_base::partial;
2627 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2628 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2629 }
2630 else // if (wc <= 0xFFFF)
2631 {
2632 if (to_end-to_nxt < 3)
2633 return codecvt_base::partial;
2634 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2635 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2636 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2637 }
2638 }
2639 return codecvt_base::ok;
2640}
2641
2642static
2643codecvt_base::result
2644utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2645 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2646 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2647{
2648 frm_nxt = frm;
2649 to_nxt = to;
2650 if (mode & consume_header)
2651 {
2652 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2653 frm_nxt[2] == 0xBF)
2654 frm_nxt += 3;
2655 }
2656 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2657 {
2658 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2659 if (c1 < 0x80)
2660 {
2661 if (c1 > Maxcode)
2662 return codecvt_base::error;
2663 *to_nxt = static_cast<uint16_t>(c1);
2664 ++frm_nxt;
2665 }
2666 else if (c1 < 0xC2)
2667 {
2668 return codecvt_base::error;
2669 }
2670 else if (c1 < 0xE0)
2671 {
2672 if (frm_end-frm_nxt < 2)
2673 return codecvt_base::partial;
2674 uint8_t c2 = frm_nxt[1];
2675 if ((c2 & 0xC0) != 0x80)
2676 return codecvt_base::error;
2677 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2678 | (c2 & 0x3F));
2679 if (t > Maxcode)
2680 return codecvt_base::error;
2681 *to_nxt = t;
2682 frm_nxt += 2;
2683 }
2684 else if (c1 < 0xF0)
2685 {
2686 if (frm_end-frm_nxt < 3)
2687 return codecvt_base::partial;
2688 uint8_t c2 = frm_nxt[1];
2689 uint8_t c3 = frm_nxt[2];
2690 switch (c1)
2691 {
2692 case 0xE0:
2693 if ((c2 & 0xE0) != 0xA0)
2694 return codecvt_base::error;
2695 break;
2696 case 0xED:
2697 if ((c2 & 0xE0) != 0x80)
2698 return codecvt_base::error;
2699 break;
2700 default:
2701 if ((c2 & 0xC0) != 0x80)
2702 return codecvt_base::error;
2703 break;
2704 }
2705 if ((c3 & 0xC0) != 0x80)
2706 return codecvt_base::error;
2707 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2708 | ((c2 & 0x3F) << 6)
2709 | (c3 & 0x3F));
2710 if (t > Maxcode)
2711 return codecvt_base::error;
2712 *to_nxt = t;
2713 frm_nxt += 3;
2714 }
2715 else
2716 {
2717 return codecvt_base::error;
2718 }
2719 }
2720 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2721}
2722
2723static
2724int
2725utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2726 size_t mx, unsigned long Maxcode = 0x10FFFF,
2727 codecvt_mode mode = codecvt_mode(0))
2728{
2729 const uint8_t* frm_nxt = frm;
2730 if (mode & consume_header)
2731 {
2732 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2733 frm_nxt[2] == 0xBF)
2734 frm_nxt += 3;
2735 }
2736 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2737 {
2738 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2739 if (c1 < 0x80)
2740 {
2741 if (c1 > Maxcode)
2742 break;
2743 ++frm_nxt;
2744 }
2745 else if (c1 < 0xC2)
2746 {
2747 break;
2748 }
2749 else if (c1 < 0xE0)
2750 {
2751 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2752 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002753 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002754 break;
2755 frm_nxt += 2;
2756 }
2757 else if (c1 < 0xF0)
2758 {
2759 if (frm_end-frm_nxt < 3)
2760 break;
2761 uint8_t c2 = frm_nxt[1];
2762 uint8_t c3 = frm_nxt[2];
2763 switch (c1)
2764 {
2765 case 0xE0:
2766 if ((c2 & 0xE0) != 0xA0)
2767 return static_cast<int>(frm_nxt - frm);
2768 break;
2769 case 0xED:
2770 if ((c2 & 0xE0) != 0x80)
2771 return static_cast<int>(frm_nxt - frm);
2772 break;
2773 default:
2774 if ((c2 & 0xC0) != 0x80)
2775 return static_cast<int>(frm_nxt - frm);
2776 break;
2777 }
2778 if ((c3 & 0xC0) != 0x80)
2779 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002780 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002781 break;
2782 frm_nxt += 3;
2783 }
2784 else
2785 {
2786 break;
2787 }
2788 }
2789 return static_cast<int>(frm_nxt - frm);
2790}
2791
2792static
2793codecvt_base::result
2794ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2795 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2796 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2797{
2798 frm_nxt = frm;
2799 to_nxt = to;
2800 if (mode & generate_header)
2801 {
2802 if (to_end-to_nxt < 2)
2803 return codecvt_base::partial;
2804 *to_nxt++ = static_cast<uint8_t>(0xFE);
2805 *to_nxt++ = static_cast<uint8_t>(0xFF);
2806 }
2807 for (; frm_nxt < frm_end; ++frm_nxt)
2808 {
2809 uint32_t wc = *frm_nxt;
2810 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2811 return codecvt_base::error;
2812 if (wc < 0x010000)
2813 {
2814 if (to_end-to_nxt < 2)
2815 return codecvt_base::partial;
2816 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2817 *to_nxt++ = static_cast<uint8_t>(wc);
2818 }
2819 else
2820 {
2821 if (to_end-to_nxt < 4)
2822 return codecvt_base::partial;
2823 uint16_t t = static_cast<uint16_t>(
2824 0xD800
2825 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2826 | ((wc & 0x00FC00) >> 10));
2827 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2828 *to_nxt++ = static_cast<uint8_t>(t);
2829 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2830 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2831 *to_nxt++ = static_cast<uint8_t>(t);
2832 }
2833 }
2834 return codecvt_base::ok;
2835}
2836
2837static
2838codecvt_base::result
2839utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2840 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2841 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2842{
2843 frm_nxt = frm;
2844 to_nxt = to;
2845 if (mode & consume_header)
2846 {
2847 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2848 frm_nxt += 2;
2849 }
2850 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2851 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002852 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002853 if ((c1 & 0xFC00) == 0xDC00)
2854 return codecvt_base::error;
2855 if ((c1 & 0xFC00) != 0xD800)
2856 {
2857 if (c1 > Maxcode)
2858 return codecvt_base::error;
2859 *to_nxt = static_cast<uint32_t>(c1);
2860 frm_nxt += 2;
2861 }
2862 else
2863 {
2864 if (frm_end-frm_nxt < 4)
2865 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002866 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002867 if ((c2 & 0xFC00) != 0xDC00)
2868 return codecvt_base::error;
2869 uint32_t t = static_cast<uint32_t>(
2870 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2871 | ((c1 & 0x003F) << 10)
2872 | (c2 & 0x03FF));
2873 if (t > Maxcode)
2874 return codecvt_base::error;
2875 *to_nxt = t;
2876 frm_nxt += 4;
2877 }
2878 }
2879 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2880}
2881
2882static
2883int
2884utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2885 size_t mx, unsigned long Maxcode = 0x10FFFF,
2886 codecvt_mode mode = codecvt_mode(0))
2887{
2888 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002889 if (mode & consume_header)
2890 {
2891 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2892 frm_nxt += 2;
2893 }
2894 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2895 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002896 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002897 if ((c1 & 0xFC00) == 0xDC00)
2898 break;
2899 if ((c1 & 0xFC00) != 0xD800)
2900 {
2901 if (c1 > Maxcode)
2902 break;
2903 frm_nxt += 2;
2904 }
2905 else
2906 {
2907 if (frm_end-frm_nxt < 4)
2908 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002909 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002910 if ((c2 & 0xFC00) != 0xDC00)
2911 break;
2912 uint32_t t = static_cast<uint32_t>(
2913 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2914 | ((c1 & 0x003F) << 10)
2915 | (c2 & 0x03FF));
2916 if (t > Maxcode)
2917 break;
2918 frm_nxt += 4;
2919 }
2920 }
2921 return static_cast<int>(frm_nxt - frm);
2922}
2923
2924static
2925codecvt_base::result
2926ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2927 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2928 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2929{
2930 frm_nxt = frm;
2931 to_nxt = to;
2932 if (mode & generate_header)
2933 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002934 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002935 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002936 *to_nxt++ = static_cast<uint8_t>(0xFF);
2937 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002938 }
2939 for (; frm_nxt < frm_end; ++frm_nxt)
2940 {
2941 uint32_t wc = *frm_nxt;
2942 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2943 return codecvt_base::error;
2944 if (wc < 0x010000)
2945 {
2946 if (to_end-to_nxt < 2)
2947 return codecvt_base::partial;
2948 *to_nxt++ = static_cast<uint8_t>(wc);
2949 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2950 }
2951 else
2952 {
2953 if (to_end-to_nxt < 4)
2954 return codecvt_base::partial;
2955 uint16_t t = static_cast<uint16_t>(
2956 0xD800
2957 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2958 | ((wc & 0x00FC00) >> 10));
2959 *to_nxt++ = static_cast<uint8_t>(t);
2960 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2961 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2962 *to_nxt++ = static_cast<uint8_t>(t);
2963 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2964 }
2965 }
2966 return codecvt_base::ok;
2967}
2968
2969static
2970codecvt_base::result
2971utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2972 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2973 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2974{
2975 frm_nxt = frm;
2976 to_nxt = to;
2977 if (mode & consume_header)
2978 {
2979 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2980 frm_nxt += 2;
2981 }
2982 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2983 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002984 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002985 if ((c1 & 0xFC00) == 0xDC00)
2986 return codecvt_base::error;
2987 if ((c1 & 0xFC00) != 0xD800)
2988 {
2989 if (c1 > Maxcode)
2990 return codecvt_base::error;
2991 *to_nxt = static_cast<uint32_t>(c1);
2992 frm_nxt += 2;
2993 }
2994 else
2995 {
2996 if (frm_end-frm_nxt < 4)
2997 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002998 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002999 if ((c2 & 0xFC00) != 0xDC00)
3000 return codecvt_base::error;
3001 uint32_t t = static_cast<uint32_t>(
3002 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3003 | ((c1 & 0x003F) << 10)
3004 | (c2 & 0x03FF));
3005 if (t > Maxcode)
3006 return codecvt_base::error;
3007 *to_nxt = t;
3008 frm_nxt += 4;
3009 }
3010 }
3011 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3012}
3013
3014static
3015int
3016utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
3017 size_t mx, unsigned long Maxcode = 0x10FFFF,
3018 codecvt_mode mode = codecvt_mode(0))
3019{
3020 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003021 if (mode & consume_header)
3022 {
3023 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3024 frm_nxt += 2;
3025 }
3026 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
3027 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003028 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003029 if ((c1 & 0xFC00) == 0xDC00)
3030 break;
3031 if ((c1 & 0xFC00) != 0xD800)
3032 {
3033 if (c1 > Maxcode)
3034 break;
3035 frm_nxt += 2;
3036 }
3037 else
3038 {
3039 if (frm_end-frm_nxt < 4)
3040 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00003041 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003042 if ((c2 & 0xFC00) != 0xDC00)
3043 break;
3044 uint32_t t = static_cast<uint32_t>(
3045 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3046 | ((c1 & 0x003F) << 10)
3047 | (c2 & 0x03FF));
3048 if (t > Maxcode)
3049 break;
3050 frm_nxt += 4;
3051 }
3052 }
3053 return static_cast<int>(frm_nxt - frm);
3054}
3055
3056static
3057codecvt_base::result
3058ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3059 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3060 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3061{
3062 frm_nxt = frm;
3063 to_nxt = to;
3064 if (mode & generate_header)
3065 {
3066 if (to_end-to_nxt < 2)
3067 return codecvt_base::partial;
3068 *to_nxt++ = static_cast<uint8_t>(0xFE);
3069 *to_nxt++ = static_cast<uint8_t>(0xFF);
3070 }
3071 for (; frm_nxt < frm_end; ++frm_nxt)
3072 {
3073 uint16_t wc = *frm_nxt;
3074 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3075 return codecvt_base::error;
3076 if (to_end-to_nxt < 2)
3077 return codecvt_base::partial;
3078 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3079 *to_nxt++ = static_cast<uint8_t>(wc);
3080 }
3081 return codecvt_base::ok;
3082}
3083
3084static
3085codecvt_base::result
3086utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3087 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3088 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3089{
3090 frm_nxt = frm;
3091 to_nxt = to;
3092 if (mode & consume_header)
3093 {
3094 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3095 frm_nxt += 2;
3096 }
3097 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3098 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003099 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003100 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3101 return codecvt_base::error;
3102 *to_nxt = c1;
3103 frm_nxt += 2;
3104 }
3105 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3106}
3107
3108static
3109int
3110utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3111 size_t mx, unsigned long Maxcode = 0x10FFFF,
3112 codecvt_mode mode = codecvt_mode(0))
3113{
3114 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003115 if (mode & consume_header)
3116 {
3117 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3118 frm_nxt += 2;
3119 }
3120 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3121 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003122 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003123 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3124 break;
3125 frm_nxt += 2;
3126 }
3127 return static_cast<int>(frm_nxt - frm);
3128}
3129
3130static
3131codecvt_base::result
3132ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3133 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3134 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3135{
3136 frm_nxt = frm;
3137 to_nxt = to;
3138 if (mode & generate_header)
3139 {
3140 if (to_end-to_nxt < 2)
3141 return codecvt_base::partial;
3142 *to_nxt++ = static_cast<uint8_t>(0xFF);
3143 *to_nxt++ = static_cast<uint8_t>(0xFE);
3144 }
3145 for (; frm_nxt < frm_end; ++frm_nxt)
3146 {
3147 uint16_t wc = *frm_nxt;
3148 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3149 return codecvt_base::error;
3150 if (to_end-to_nxt < 2)
3151 return codecvt_base::partial;
3152 *to_nxt++ = static_cast<uint8_t>(wc);
3153 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3154 }
3155 return codecvt_base::ok;
3156}
3157
3158static
3159codecvt_base::result
3160utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3161 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3162 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3163{
3164 frm_nxt = frm;
3165 to_nxt = to;
3166 if (mode & consume_header)
3167 {
3168 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3169 frm_nxt += 2;
3170 }
3171 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3172 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003173 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003174 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3175 return codecvt_base::error;
3176 *to_nxt = c1;
3177 frm_nxt += 2;
3178 }
3179 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3180}
3181
3182static
3183int
3184utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3185 size_t mx, unsigned long Maxcode = 0x10FFFF,
3186 codecvt_mode mode = codecvt_mode(0))
3187{
3188 const uint8_t* frm_nxt = frm;
3189 frm_nxt = frm;
3190 if (mode & consume_header)
3191 {
3192 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3193 frm_nxt += 2;
3194 }
3195 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3196 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003197 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003198 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3199 break;
3200 frm_nxt += 2;
3201 }
3202 return static_cast<int>(frm_nxt - frm);
3203}
3204
Howard Hinnantc51e1022010-05-11 19:42:16 +00003205// template <> class codecvt<char16_t, char, mbstate_t>
3206
Howard Hinnantffb308e2010-08-22 00:03:27 +00003207locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003208
3209codecvt<char16_t, char, mbstate_t>::~codecvt()
3210{
3211}
3212
3213codecvt<char16_t, char, mbstate_t>::result
3214codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003215 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003216 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3217{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003218 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3219 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3220 const uint16_t* _frm_nxt = _frm;
3221 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3222 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3223 uint8_t* _to_nxt = _to;
3224 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3225 frm_nxt = frm + (_frm_nxt - _frm);
3226 to_nxt = to + (_to_nxt - _to);
3227 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003228}
3229
3230codecvt<char16_t, char, mbstate_t>::result
3231codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003232 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003233 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3234{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003235 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3236 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3237 const uint8_t* _frm_nxt = _frm;
3238 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3239 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3240 uint16_t* _to_nxt = _to;
3241 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3242 frm_nxt = frm + (_frm_nxt - _frm);
3243 to_nxt = to + (_to_nxt - _to);
3244 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003245}
3246
3247codecvt<char16_t, char, mbstate_t>::result
3248codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3249 extern_type* to, extern_type*, extern_type*& to_nxt) const
3250{
3251 to_nxt = to;
3252 return noconv;
3253}
3254
3255int
Louis Dionne65358e12021-03-01 12:09:45 -05003256codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003257{
3258 return 0;
3259}
3260
3261bool
Louis Dionne65358e12021-03-01 12:09:45 -05003262codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003263{
3264 return false;
3265}
3266
3267int
3268codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3269 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3270{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003271 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3272 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3273 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003274}
3275
3276int
Louis Dionne65358e12021-03-01 12:09:45 -05003277codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003278{
3279 return 4;
3280}
3281
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003282#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003283
3284// template <> class codecvt<char16_t, char8_t, mbstate_t>
3285
3286locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3287
3288codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3289{
3290}
3291
3292codecvt<char16_t, char8_t, mbstate_t>::result
3293codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3294 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3295 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3296{
3297 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3298 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3299 const uint16_t* _frm_nxt = _frm;
3300 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3301 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3302 uint8_t* _to_nxt = _to;
3303 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3304 frm_nxt = frm + (_frm_nxt - _frm);
3305 to_nxt = to + (_to_nxt - _to);
3306 return r;
3307}
3308
3309codecvt<char16_t, char8_t, mbstate_t>::result
3310codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3311 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3312 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3313{
3314 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3315 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3316 const uint8_t* _frm_nxt = _frm;
3317 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3318 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3319 uint16_t* _to_nxt = _to;
3320 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3321 frm_nxt = frm + (_frm_nxt - _frm);
3322 to_nxt = to + (_to_nxt - _to);
3323 return r;
3324}
3325
3326codecvt<char16_t, char8_t, mbstate_t>::result
3327codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3328 extern_type* to, extern_type*, extern_type*& to_nxt) const
3329{
3330 to_nxt = to;
3331 return noconv;
3332}
3333
3334int
Louis Dionne65358e12021-03-01 12:09:45 -05003335codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003336{
3337 return 0;
3338}
3339
3340bool
Louis Dionne65358e12021-03-01 12:09:45 -05003341codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003342{
3343 return false;
3344}
3345
3346int
3347codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3348 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3349{
3350 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3351 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3352 return utf8_to_utf16_length(_frm, _frm_end, mx);
3353}
3354
3355int
Louis Dionne65358e12021-03-01 12:09:45 -05003356codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003357{
3358 return 4;
3359}
3360
3361#endif
3362
Howard Hinnantc51e1022010-05-11 19:42:16 +00003363// template <> class codecvt<char32_t, char, mbstate_t>
3364
Howard Hinnantffb308e2010-08-22 00:03:27 +00003365locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003366
3367codecvt<char32_t, char, mbstate_t>::~codecvt()
3368{
3369}
3370
3371codecvt<char32_t, char, mbstate_t>::result
3372codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003373 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003374 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3375{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003376 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3377 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3378 const uint32_t* _frm_nxt = _frm;
3379 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3380 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3381 uint8_t* _to_nxt = _to;
3382 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3383 frm_nxt = frm + (_frm_nxt - _frm);
3384 to_nxt = to + (_to_nxt - _to);
3385 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003386}
3387
3388codecvt<char32_t, char, mbstate_t>::result
3389codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003390 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003391 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3392{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003393 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3394 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3395 const uint8_t* _frm_nxt = _frm;
3396 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3397 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3398 uint32_t* _to_nxt = _to;
3399 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3400 frm_nxt = frm + (_frm_nxt - _frm);
3401 to_nxt = to + (_to_nxt - _to);
3402 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003403}
3404
3405codecvt<char32_t, char, mbstate_t>::result
3406codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3407 extern_type* to, extern_type*, extern_type*& to_nxt) const
3408{
3409 to_nxt = to;
3410 return noconv;
3411}
3412
3413int
Louis Dionne65358e12021-03-01 12:09:45 -05003414codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003415{
3416 return 0;
3417}
3418
3419bool
Louis Dionne65358e12021-03-01 12:09:45 -05003420codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003421{
3422 return false;
3423}
3424
3425int
3426codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3427 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3428{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003429 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3430 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3431 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003432}
3433
3434int
Louis Dionne65358e12021-03-01 12:09:45 -05003435codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003436{
3437 return 4;
3438}
3439
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003440#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003441
3442// template <> class codecvt<char32_t, char8_t, mbstate_t>
3443
3444locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3445
3446codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3447{
3448}
3449
3450codecvt<char32_t, char8_t, mbstate_t>::result
3451codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3452 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3453 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3454{
3455 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3456 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3457 const uint32_t* _frm_nxt = _frm;
3458 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3459 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3460 uint8_t* _to_nxt = _to;
3461 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3462 frm_nxt = frm + (_frm_nxt - _frm);
3463 to_nxt = to + (_to_nxt - _to);
3464 return r;
3465}
3466
3467codecvt<char32_t, char8_t, mbstate_t>::result
3468codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3469 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3470 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3471{
3472 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3473 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3474 const uint8_t* _frm_nxt = _frm;
3475 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3476 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3477 uint32_t* _to_nxt = _to;
3478 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3479 frm_nxt = frm + (_frm_nxt - _frm);
3480 to_nxt = to + (_to_nxt - _to);
3481 return r;
3482}
3483
3484codecvt<char32_t, char8_t, mbstate_t>::result
3485codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3486 extern_type* to, extern_type*, extern_type*& to_nxt) const
3487{
3488 to_nxt = to;
3489 return noconv;
3490}
3491
3492int
Louis Dionne65358e12021-03-01 12:09:45 -05003493codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003494{
3495 return 0;
3496}
3497
3498bool
Louis Dionne65358e12021-03-01 12:09:45 -05003499codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003500{
3501 return false;
3502}
3503
3504int
3505codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3506 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3507{
3508 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3509 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3510 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3511}
3512
3513int
Louis Dionne65358e12021-03-01 12:09:45 -05003514codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003515{
3516 return 4;
3517}
3518
3519#endif
3520
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003521// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003522
Louis Dionne89258142021-08-23 15:32:36 -04003523#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003524__codecvt_utf8<wchar_t>::result
3525__codecvt_utf8<wchar_t>::do_out(state_type&,
3526 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003527 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3528{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003529#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003530 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3531 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3532 const uint16_t* _frm_nxt = _frm;
3533#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003534 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3535 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3536 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003537#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003538 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3539 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3540 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003541#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003542 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3543 _Maxcode_, _Mode_);
3544#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003545 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3546 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003547#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003548 frm_nxt = frm + (_frm_nxt - _frm);
3549 to_nxt = to + (_to_nxt - _to);
3550 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003551}
3552
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003553__codecvt_utf8<wchar_t>::result
3554__codecvt_utf8<wchar_t>::do_in(state_type&,
3555 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003556 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3557{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003558 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3559 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3560 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003561#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003562 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3563 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3564 uint16_t* _to_nxt = _to;
3565 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3566 _Maxcode_, _Mode_);
3567#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003568 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3569 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3570 uint32_t* _to_nxt = _to;
3571 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3572 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003573#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003574 frm_nxt = frm + (_frm_nxt - _frm);
3575 to_nxt = to + (_to_nxt - _to);
3576 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003577}
3578
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003579__codecvt_utf8<wchar_t>::result
3580__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003581 extern_type* to, extern_type*, extern_type*& to_nxt) const
3582{
3583 to_nxt = to;
3584 return noconv;
3585}
3586
3587int
Louis Dionne65358e12021-03-01 12:09:45 -05003588__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003589{
3590 return 0;
3591}
3592
3593bool
Louis Dionne65358e12021-03-01 12:09:45 -05003594__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003595{
3596 return false;
3597}
3598
3599int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003600__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003601 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3602{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003603 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3604 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003605#if defined(_LIBCPP_SHORT_WCHAR)
3606 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3607#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003608 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003609#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003610}
3611
3612int
Louis Dionne65358e12021-03-01 12:09:45 -05003613__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003614{
Xing Xue50b0eb42021-09-09 16:20:36 -04003615#if defined(_LIBCPP_SHORT_WCHAR)
3616 if (_Mode_ & consume_header)
3617 return 6;
3618 return 3;
3619#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003620 if (_Mode_ & consume_header)
3621 return 7;
3622 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003623#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003624}
Louis Dionne89258142021-08-23 15:32:36 -04003625#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003626
3627// __codecvt_utf8<char16_t>
3628
3629__codecvt_utf8<char16_t>::result
3630__codecvt_utf8<char16_t>::do_out(state_type&,
3631 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3632 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3633{
3634 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3635 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3636 const uint16_t* _frm_nxt = _frm;
3637 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3638 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3639 uint8_t* _to_nxt = _to;
3640 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3641 _Maxcode_, _Mode_);
3642 frm_nxt = frm + (_frm_nxt - _frm);
3643 to_nxt = to + (_to_nxt - _to);
3644 return r;
3645}
3646
3647__codecvt_utf8<char16_t>::result
3648__codecvt_utf8<char16_t>::do_in(state_type&,
3649 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3650 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3651{
3652 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3653 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3654 const uint8_t* _frm_nxt = _frm;
3655 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3656 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3657 uint16_t* _to_nxt = _to;
3658 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3659 _Maxcode_, _Mode_);
3660 frm_nxt = frm + (_frm_nxt - _frm);
3661 to_nxt = to + (_to_nxt - _to);
3662 return r;
3663}
3664
3665__codecvt_utf8<char16_t>::result
3666__codecvt_utf8<char16_t>::do_unshift(state_type&,
3667 extern_type* to, extern_type*, extern_type*& to_nxt) const
3668{
3669 to_nxt = to;
3670 return noconv;
3671}
3672
3673int
Louis Dionne65358e12021-03-01 12:09:45 -05003674__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003675{
3676 return 0;
3677}
3678
3679bool
Louis Dionne65358e12021-03-01 12:09:45 -05003680__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003681{
3682 return false;
3683}
3684
3685int
3686__codecvt_utf8<char16_t>::do_length(state_type&,
3687 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3688{
3689 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3690 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3691 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3692}
3693
3694int
Louis Dionne65358e12021-03-01 12:09:45 -05003695__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003696{
3697 if (_Mode_ & consume_header)
3698 return 6;
3699 return 3;
3700}
3701
3702// __codecvt_utf8<char32_t>
3703
3704__codecvt_utf8<char32_t>::result
3705__codecvt_utf8<char32_t>::do_out(state_type&,
3706 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3707 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3708{
3709 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3710 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3711 const uint32_t* _frm_nxt = _frm;
3712 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3713 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3714 uint8_t* _to_nxt = _to;
3715 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3716 _Maxcode_, _Mode_);
3717 frm_nxt = frm + (_frm_nxt - _frm);
3718 to_nxt = to + (_to_nxt - _to);
3719 return r;
3720}
3721
3722__codecvt_utf8<char32_t>::result
3723__codecvt_utf8<char32_t>::do_in(state_type&,
3724 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3725 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3726{
3727 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3728 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3729 const uint8_t* _frm_nxt = _frm;
3730 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3731 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3732 uint32_t* _to_nxt = _to;
3733 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3734 _Maxcode_, _Mode_);
3735 frm_nxt = frm + (_frm_nxt - _frm);
3736 to_nxt = to + (_to_nxt - _to);
3737 return r;
3738}
3739
3740__codecvt_utf8<char32_t>::result
3741__codecvt_utf8<char32_t>::do_unshift(state_type&,
3742 extern_type* to, extern_type*, extern_type*& to_nxt) const
3743{
3744 to_nxt = to;
3745 return noconv;
3746}
3747
3748int
Louis Dionne65358e12021-03-01 12:09:45 -05003749__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003750{
3751 return 0;
3752}
3753
3754bool
Louis Dionne65358e12021-03-01 12:09:45 -05003755__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003756{
3757 return false;
3758}
3759
3760int
3761__codecvt_utf8<char32_t>::do_length(state_type&,
3762 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3763{
3764 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3765 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3766 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3767}
3768
3769int
Louis Dionne65358e12021-03-01 12:09:45 -05003770__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003771{
3772 if (_Mode_ & consume_header)
3773 return 7;
3774 return 4;
3775}
3776
3777// __codecvt_utf16<wchar_t, false>
3778
Louis Dionne89258142021-08-23 15:32:36 -04003779#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003780__codecvt_utf16<wchar_t, false>::result
3781__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3782 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3783 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3784{
Xing Xue50b0eb42021-09-09 16:20:36 -04003785#if defined(_LIBCPP_SHORT_WCHAR)
3786 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3787 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3788 const uint16_t* _frm_nxt = _frm;
3789#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003790 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3791 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3792 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003793#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003794 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3795 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3796 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003797#if defined(_LIBCPP_SHORT_WCHAR)
3798 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3799 _Maxcode_, _Mode_);
3800#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003801 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3802 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003803#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003804 frm_nxt = frm + (_frm_nxt - _frm);
3805 to_nxt = to + (_to_nxt - _to);
3806 return r;
3807}
3808
3809__codecvt_utf16<wchar_t, false>::result
3810__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3811 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3812 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3813{
3814 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3815 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3816 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003817#if defined(_LIBCPP_SHORT_WCHAR)
3818 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3819 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3820 uint16_t* _to_nxt = _to;
3821 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3822 _Maxcode_, _Mode_);
3823#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003824 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3825 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3826 uint32_t* _to_nxt = _to;
3827 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3828 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003829#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003830 frm_nxt = frm + (_frm_nxt - _frm);
3831 to_nxt = to + (_to_nxt - _to);
3832 return r;
3833}
3834
3835__codecvt_utf16<wchar_t, false>::result
3836__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3837 extern_type* to, extern_type*, extern_type*& to_nxt) const
3838{
3839 to_nxt = to;
3840 return noconv;
3841}
3842
3843int
Louis Dionne65358e12021-03-01 12:09:45 -05003844__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003845{
3846 return 0;
3847}
3848
3849bool
Louis Dionne65358e12021-03-01 12:09:45 -05003850__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003851{
3852 return false;
3853}
3854
3855int
3856__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3857 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3858{
3859 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3860 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003861#if defined(_LIBCPP_SHORT_WCHAR)
3862 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3863#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003864 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003865#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003866}
3867
3868int
Louis Dionne65358e12021-03-01 12:09:45 -05003869__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003870{
Xing Xue50b0eb42021-09-09 16:20:36 -04003871#if defined(_LIBCPP_SHORT_WCHAR)
3872 if (_Mode_ & consume_header)
3873 return 4;
3874 return 2;
3875#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003876 if (_Mode_ & consume_header)
3877 return 6;
3878 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003879#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003880}
3881
3882// __codecvt_utf16<wchar_t, true>
3883
3884__codecvt_utf16<wchar_t, true>::result
3885__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3886 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3887 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3888{
Xing Xue50b0eb42021-09-09 16:20:36 -04003889#if defined(_LIBCPP_SHORT_WCHAR)
3890 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3891 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3892 const uint16_t* _frm_nxt = _frm;
3893#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003894 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3895 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3896 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003897#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003898 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3899 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3900 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003901#if defined(_LIBCPP_SHORT_WCHAR)
3902 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3903 _Maxcode_, _Mode_);
3904#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003905 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3906 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003907#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003908 frm_nxt = frm + (_frm_nxt - _frm);
3909 to_nxt = to + (_to_nxt - _to);
3910 return r;
3911}
3912
3913__codecvt_utf16<wchar_t, true>::result
3914__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3915 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3916 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3917{
3918 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3919 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3920 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003921#if defined(_LIBCPP_SHORT_WCHAR)
3922 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3923 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3924 uint16_t* _to_nxt = _to;
3925 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3926 _Maxcode_, _Mode_);
3927#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003928 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3929 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3930 uint32_t* _to_nxt = _to;
3931 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3932 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003933#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003934 frm_nxt = frm + (_frm_nxt - _frm);
3935 to_nxt = to + (_to_nxt - _to);
3936 return r;
3937}
3938
3939__codecvt_utf16<wchar_t, true>::result
3940__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3941 extern_type* to, extern_type*, extern_type*& to_nxt) const
3942{
3943 to_nxt = to;
3944 return noconv;
3945}
3946
3947int
Louis Dionne65358e12021-03-01 12:09:45 -05003948__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003949{
3950 return 0;
3951}
3952
3953bool
Louis Dionne65358e12021-03-01 12:09:45 -05003954__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003955{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003956 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003957}
3958
3959int
3960__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3961 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3962{
3963 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3964 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003965#if defined(_LIBCPP_SHORT_WCHAR)
3966 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3967#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003968 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003969#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003970}
3971
3972int
Louis Dionne65358e12021-03-01 12:09:45 -05003973__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003974{
Xing Xue50b0eb42021-09-09 16:20:36 -04003975#if defined(_LIBCPP_SHORT_WCHAR)
3976 if (_Mode_ & consume_header)
3977 return 4;
3978 return 2;
3979#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003980 if (_Mode_ & consume_header)
3981 return 6;
3982 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003983#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003984}
Louis Dionne89258142021-08-23 15:32:36 -04003985#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003986
3987// __codecvt_utf16<char16_t, false>
3988
3989__codecvt_utf16<char16_t, false>::result
3990__codecvt_utf16<char16_t, false>::do_out(state_type&,
3991 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3992 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3993{
3994 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3995 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3996 const uint16_t* _frm_nxt = _frm;
3997 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3998 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3999 uint8_t* _to_nxt = _to;
4000 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4001 _Maxcode_, _Mode_);
4002 frm_nxt = frm + (_frm_nxt - _frm);
4003 to_nxt = to + (_to_nxt - _to);
4004 return r;
4005}
4006
4007__codecvt_utf16<char16_t, false>::result
4008__codecvt_utf16<char16_t, false>::do_in(state_type&,
4009 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4010 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4011{
4012 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4013 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4014 const uint8_t* _frm_nxt = _frm;
4015 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4016 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4017 uint16_t* _to_nxt = _to;
4018 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4019 _Maxcode_, _Mode_);
4020 frm_nxt = frm + (_frm_nxt - _frm);
4021 to_nxt = to + (_to_nxt - _to);
4022 return r;
4023}
4024
4025__codecvt_utf16<char16_t, false>::result
4026__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
4027 extern_type* to, extern_type*, extern_type*& to_nxt) const
4028{
4029 to_nxt = to;
4030 return noconv;
4031}
4032
4033int
Louis Dionne65358e12021-03-01 12:09:45 -05004034__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004035{
4036 return 0;
4037}
4038
4039bool
Louis Dionne65358e12021-03-01 12:09:45 -05004040__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004041{
4042 return false;
4043}
4044
4045int
4046__codecvt_utf16<char16_t, false>::do_length(state_type&,
4047 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4048{
4049 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4050 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4051 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4052}
4053
4054int
Louis Dionne65358e12021-03-01 12:09:45 -05004055__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004056{
4057 if (_Mode_ & consume_header)
4058 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004059 return 2;
4060}
4061
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004062// __codecvt_utf16<char16_t, true>
4063
4064__codecvt_utf16<char16_t, true>::result
4065__codecvt_utf16<char16_t, true>::do_out(state_type&,
4066 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4067 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4068{
4069 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4070 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4071 const uint16_t* _frm_nxt = _frm;
4072 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4073 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4074 uint8_t* _to_nxt = _to;
4075 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4076 _Maxcode_, _Mode_);
4077 frm_nxt = frm + (_frm_nxt - _frm);
4078 to_nxt = to + (_to_nxt - _to);
4079 return r;
4080}
4081
4082__codecvt_utf16<char16_t, true>::result
4083__codecvt_utf16<char16_t, true>::do_in(state_type&,
4084 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4085 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4086{
4087 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4088 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4089 const uint8_t* _frm_nxt = _frm;
4090 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4091 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4092 uint16_t* _to_nxt = _to;
4093 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4094 _Maxcode_, _Mode_);
4095 frm_nxt = frm + (_frm_nxt - _frm);
4096 to_nxt = to + (_to_nxt - _to);
4097 return r;
4098}
4099
4100__codecvt_utf16<char16_t, true>::result
4101__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
4102 extern_type* to, extern_type*, extern_type*& to_nxt) const
4103{
4104 to_nxt = to;
4105 return noconv;
4106}
4107
4108int
Louis Dionne65358e12021-03-01 12:09:45 -05004109__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004110{
4111 return 0;
4112}
4113
4114bool
Louis Dionne65358e12021-03-01 12:09:45 -05004115__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004116{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004117 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004118}
4119
4120int
4121__codecvt_utf16<char16_t, true>::do_length(state_type&,
4122 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4123{
4124 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4125 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4126 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4127}
4128
4129int
Louis Dionne65358e12021-03-01 12:09:45 -05004130__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004131{
4132 if (_Mode_ & consume_header)
4133 return 4;
4134 return 2;
4135}
4136
4137// __codecvt_utf16<char32_t, false>
4138
4139__codecvt_utf16<char32_t, false>::result
4140__codecvt_utf16<char32_t, false>::do_out(state_type&,
4141 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4142 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4143{
4144 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4145 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4146 const uint32_t* _frm_nxt = _frm;
4147 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4148 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4149 uint8_t* _to_nxt = _to;
4150 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4151 _Maxcode_, _Mode_);
4152 frm_nxt = frm + (_frm_nxt - _frm);
4153 to_nxt = to + (_to_nxt - _to);
4154 return r;
4155}
4156
4157__codecvt_utf16<char32_t, false>::result
4158__codecvt_utf16<char32_t, false>::do_in(state_type&,
4159 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4160 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4161{
4162 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4163 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4164 const uint8_t* _frm_nxt = _frm;
4165 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4166 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4167 uint32_t* _to_nxt = _to;
4168 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4169 _Maxcode_, _Mode_);
4170 frm_nxt = frm + (_frm_nxt - _frm);
4171 to_nxt = to + (_to_nxt - _to);
4172 return r;
4173}
4174
4175__codecvt_utf16<char32_t, false>::result
4176__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4177 extern_type* to, extern_type*, extern_type*& to_nxt) const
4178{
4179 to_nxt = to;
4180 return noconv;
4181}
4182
4183int
Louis Dionne65358e12021-03-01 12:09:45 -05004184__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004185{
4186 return 0;
4187}
4188
4189bool
Louis Dionne65358e12021-03-01 12:09:45 -05004190__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004191{
4192 return false;
4193}
4194
4195int
4196__codecvt_utf16<char32_t, false>::do_length(state_type&,
4197 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4198{
4199 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4200 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4201 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4202}
4203
4204int
Louis Dionne65358e12021-03-01 12:09:45 -05004205__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004206{
4207 if (_Mode_ & consume_header)
4208 return 6;
4209 return 4;
4210}
4211
4212// __codecvt_utf16<char32_t, true>
4213
4214__codecvt_utf16<char32_t, true>::result
4215__codecvt_utf16<char32_t, true>::do_out(state_type&,
4216 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4217 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4218{
4219 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4220 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4221 const uint32_t* _frm_nxt = _frm;
4222 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4223 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4224 uint8_t* _to_nxt = _to;
4225 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4226 _Maxcode_, _Mode_);
4227 frm_nxt = frm + (_frm_nxt - _frm);
4228 to_nxt = to + (_to_nxt - _to);
4229 return r;
4230}
4231
4232__codecvt_utf16<char32_t, true>::result
4233__codecvt_utf16<char32_t, true>::do_in(state_type&,
4234 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4235 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4236{
4237 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4238 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4239 const uint8_t* _frm_nxt = _frm;
4240 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4241 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4242 uint32_t* _to_nxt = _to;
4243 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4244 _Maxcode_, _Mode_);
4245 frm_nxt = frm + (_frm_nxt - _frm);
4246 to_nxt = to + (_to_nxt - _to);
4247 return r;
4248}
4249
4250__codecvt_utf16<char32_t, true>::result
4251__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4252 extern_type* to, extern_type*, extern_type*& to_nxt) const
4253{
4254 to_nxt = to;
4255 return noconv;
4256}
4257
4258int
Louis Dionne65358e12021-03-01 12:09:45 -05004259__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004260{
4261 return 0;
4262}
4263
4264bool
Louis Dionne65358e12021-03-01 12:09:45 -05004265__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004266{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004267 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004268}
4269
4270int
4271__codecvt_utf16<char32_t, true>::do_length(state_type&,
4272 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4273{
4274 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4275 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4276 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4277}
4278
4279int
Louis Dionne65358e12021-03-01 12:09:45 -05004280__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004281{
4282 if (_Mode_ & consume_header)
4283 return 6;
4284 return 4;
4285}
4286
4287// __codecvt_utf8_utf16<wchar_t>
4288
Louis Dionne89258142021-08-23 15:32:36 -04004289#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004290__codecvt_utf8_utf16<wchar_t>::result
4291__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4292 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4293 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4294{
Xing Xue50b0eb42021-09-09 16:20:36 -04004295#if defined(_LIBCPP_SHORT_WCHAR)
4296 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4297 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4298 const uint16_t* _frm_nxt = _frm;
4299#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004300 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4301 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4302 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004303#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004304 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4305 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4306 uint8_t* _to_nxt = _to;
4307 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4308 _Maxcode_, _Mode_);
4309 frm_nxt = frm + (_frm_nxt - _frm);
4310 to_nxt = to + (_to_nxt - _to);
4311 return r;
4312}
4313
4314__codecvt_utf8_utf16<wchar_t>::result
4315__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4316 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4317 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4318{
4319 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4320 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4321 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004322#if defined(_LIBCPP_SHORT_WCHAR)
4323 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4324 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4325 uint16_t* _to_nxt = _to;
4326#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004327 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4328 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4329 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004330#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004331 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4332 _Maxcode_, _Mode_);
4333 frm_nxt = frm + (_frm_nxt - _frm);
4334 to_nxt = to + (_to_nxt - _to);
4335 return r;
4336}
4337
4338__codecvt_utf8_utf16<wchar_t>::result
4339__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4340 extern_type* to, extern_type*, extern_type*& to_nxt) const
4341{
4342 to_nxt = to;
4343 return noconv;
4344}
4345
4346int
Louis Dionne65358e12021-03-01 12:09:45 -05004347__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004348{
4349 return 0;
4350}
4351
4352bool
Louis Dionne65358e12021-03-01 12:09:45 -05004353__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004354{
4355 return false;
4356}
4357
4358int
4359__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4360 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4361{
4362 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4363 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4364 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4365}
4366
4367int
Louis Dionne65358e12021-03-01 12:09:45 -05004368__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004369{
4370 if (_Mode_ & consume_header)
4371 return 7;
4372 return 4;
4373}
Louis Dionne89258142021-08-23 15:32:36 -04004374#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004375
4376// __codecvt_utf8_utf16<char16_t>
4377
4378__codecvt_utf8_utf16<char16_t>::result
4379__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4380 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4381 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4382{
4383 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4384 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4385 const uint16_t* _frm_nxt = _frm;
4386 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4387 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4388 uint8_t* _to_nxt = _to;
4389 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4390 _Maxcode_, _Mode_);
4391 frm_nxt = frm + (_frm_nxt - _frm);
4392 to_nxt = to + (_to_nxt - _to);
4393 return r;
4394}
4395
4396__codecvt_utf8_utf16<char16_t>::result
4397__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4398 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4399 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4400{
4401 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4402 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4403 const uint8_t* _frm_nxt = _frm;
4404 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4405 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4406 uint16_t* _to_nxt = _to;
4407 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4408 _Maxcode_, _Mode_);
4409 frm_nxt = frm + (_frm_nxt - _frm);
4410 to_nxt = to + (_to_nxt - _to);
4411 return r;
4412}
4413
4414__codecvt_utf8_utf16<char16_t>::result
4415__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4416 extern_type* to, extern_type*, extern_type*& to_nxt) const
4417{
4418 to_nxt = to;
4419 return noconv;
4420}
4421
4422int
Louis Dionne65358e12021-03-01 12:09:45 -05004423__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004424{
4425 return 0;
4426}
4427
4428bool
Louis Dionne65358e12021-03-01 12:09:45 -05004429__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004430{
4431 return false;
4432}
4433
4434int
4435__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4436 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4437{
4438 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4439 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4440 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4441}
4442
4443int
Louis Dionne65358e12021-03-01 12:09:45 -05004444__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004445{
4446 if (_Mode_ & consume_header)
4447 return 7;
4448 return 4;
4449}
4450
4451// __codecvt_utf8_utf16<char32_t>
4452
4453__codecvt_utf8_utf16<char32_t>::result
4454__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4455 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4456 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4457{
4458 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4459 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4460 const uint32_t* _frm_nxt = _frm;
4461 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4462 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4463 uint8_t* _to_nxt = _to;
4464 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4465 _Maxcode_, _Mode_);
4466 frm_nxt = frm + (_frm_nxt - _frm);
4467 to_nxt = to + (_to_nxt - _to);
4468 return r;
4469}
4470
4471__codecvt_utf8_utf16<char32_t>::result
4472__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4473 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4474 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4475{
4476 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4477 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4478 const uint8_t* _frm_nxt = _frm;
4479 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4480 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4481 uint32_t* _to_nxt = _to;
4482 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4483 _Maxcode_, _Mode_);
4484 frm_nxt = frm + (_frm_nxt - _frm);
4485 to_nxt = to + (_to_nxt - _to);
4486 return r;
4487}
4488
4489__codecvt_utf8_utf16<char32_t>::result
4490__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4491 extern_type* to, extern_type*, extern_type*& to_nxt) const
4492{
4493 to_nxt = to;
4494 return noconv;
4495}
4496
4497int
Louis Dionne65358e12021-03-01 12:09:45 -05004498__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004499{
4500 return 0;
4501}
4502
4503bool
Louis Dionne65358e12021-03-01 12:09:45 -05004504__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004505{
4506 return false;
4507}
4508
4509int
4510__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4511 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4512{
4513 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4514 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4515 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4516}
4517
4518int
Louis Dionne65358e12021-03-01 12:09:45 -05004519__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004520{
4521 if (_Mode_ & consume_header)
4522 return 7;
4523 return 4;
4524}
4525
Howard Hinnantc51e1022010-05-11 19:42:16 +00004526// __narrow_to_utf8<16>
4527
4528__narrow_to_utf8<16>::~__narrow_to_utf8()
4529{
4530}
4531
4532// __narrow_to_utf8<32>
4533
4534__narrow_to_utf8<32>::~__narrow_to_utf8()
4535{
4536}
4537
4538// __widen_from_utf8<16>
4539
4540__widen_from_utf8<16>::~__widen_from_utf8()
4541{
4542}
4543
4544// __widen_from_utf8<32>
4545
4546__widen_from_utf8<32>::~__widen_from_utf8()
4547{
4548}
4549
Louis Dionne89258142021-08-23 15:32:36 -04004550#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004551static bool checked_string_to_wchar_convert(wchar_t& dest,
4552 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004553 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004554 if (*ptr == '\0')
4555 return false;
4556 mbstate_t mb = {};
4557 wchar_t out;
4558 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4559 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4560 return false;
4561 }
4562 dest = out;
4563 return true;
4564}
Louis Dionne89258142021-08-23 15:32:36 -04004565#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004566
Mark de Weverffed1402021-11-03 19:25:20 +01004567#ifdef _LIBCPP_HAS_NO_WIDE_CHARACTERS
4568static bool is_narrow_non_breaking_space(const char* ptr) {
4569 // https://www.fileformat.info/info/unicode/char/202f/index.htm
4570 return ptr[0] == '\xe2' && ptr[1] == '\x80' && ptr[2] == '\xaf';
4571}
4572
4573static bool is_non_breaking_space(const char* ptr) {
4574 // https://www.fileformat.info/info/unicode/char/0a/index.htm
4575 return ptr[0] == '\xc2' && ptr[1] == '\xa0';
4576}
4577#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
4578
Eric Fiselierbf945a22016-12-11 00:20:59 +00004579static bool checked_string_to_char_convert(char& dest,
4580 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004581 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004582 if (*ptr == '\0')
4583 return false;
4584 if (!ptr[1]) {
4585 dest = *ptr;
4586 return true;
4587 }
Louis Dionne89258142021-08-23 15:32:36 -04004588
4589#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierbf945a22016-12-11 00:20:59 +00004590 // First convert the MBS into a wide char then attempt to narrow it using
4591 // wctob_l.
4592 wchar_t wout;
4593 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4594 return false;
4595 int res;
4596 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4597 dest = res;
4598 return true;
4599 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004600 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004601 // translate into a different single byte.
4602 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004603 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004604 case L'\u00A0': // non-breaking space
4605 dest = ' ';
4606 return true;
4607 default:
4608 return false;
4609 }
Louis Dionne89258142021-08-23 15:32:36 -04004610#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Mark de Weverffed1402021-11-03 19:25:20 +01004611 // FIXME: Work around specific multibyte sequences that we can reasonably
4612 // translate into a different single byte.
4613 if (is_narrow_non_breaking_space(ptr) || is_non_breaking_space(ptr)) {
4614 dest = ' ';
4615 return true;
4616 }
4617
Louis Dionne89258142021-08-23 15:32:36 -04004618 return false;
4619#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Nikolas Klausercfe21472022-02-14 18:26:02 +01004620 __libcpp_unreachable();
Eric Fiselierbf945a22016-12-11 00:20:59 +00004621}
4622
4623
Howard Hinnantc51e1022010-05-11 19:42:16 +00004624// numpunct<char> && numpunct<wchar_t>
4625
4626locale::id numpunct< char >::id;
Louis Dionne89258142021-08-23 15:32:36 -04004627#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004628locale::id numpunct<wchar_t>::id;
Louis Dionne89258142021-08-23 15:32:36 -04004629#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004630
4631numpunct<char>::numpunct(size_t refs)
4632 : locale::facet(refs),
4633 __decimal_point_('.'),
4634 __thousands_sep_(',')
4635{
4636}
4637
Louis Dionne89258142021-08-23 15:32:36 -04004638#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004639numpunct<wchar_t>::numpunct(size_t refs)
4640 : locale::facet(refs),
4641 __decimal_point_(L'.'),
4642 __thousands_sep_(L',')
4643{
4644}
Louis Dionne89258142021-08-23 15:32:36 -04004645#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004646
4647numpunct<char>::~numpunct()
4648{
4649}
4650
Louis Dionne89258142021-08-23 15:32:36 -04004651#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004652numpunct<wchar_t>::~numpunct()
4653{
4654}
Louis Dionne89258142021-08-23 15:32:36 -04004655#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004656
4657 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004658#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004659wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
Louis Dionne89258142021-08-23 15:32:36 -04004660#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004661
4662 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004663#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004664wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
Louis Dionne89258142021-08-23 15:32:36 -04004665#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004666
4667string numpunct< char >::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004668#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004669string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
Louis Dionne89258142021-08-23 15:32:36 -04004670#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004671
4672 string numpunct< char >::do_truename() const {return "true";}
Louis Dionne89258142021-08-23 15:32:36 -04004673#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004674wstring numpunct<wchar_t>::do_truename() const {return L"true";}
Louis Dionne89258142021-08-23 15:32:36 -04004675#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004676
4677 string numpunct< char >::do_falsename() const {return "false";}
Louis Dionne89258142021-08-23 15:32:36 -04004678#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004679wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
Louis Dionne89258142021-08-23 15:32:36 -04004680#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004681
4682// numpunct_byname<char>
4683
4684numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4685 : numpunct<char>(refs)
4686{
4687 __init(nm);
4688}
4689
4690numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4691 : numpunct<char>(refs)
4692{
4693 __init(nm.c_str());
4694}
4695
4696numpunct_byname<char>::~numpunct_byname()
4697{
4698}
4699
4700void
4701numpunct_byname<char>::__init(const char* nm)
4702{
Louis Dionne89258142021-08-23 15:32:36 -04004703 typedef numpunct<char> base;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004704 if (strcmp(nm, "C") != 0)
4705 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004706 __libcpp_unique_locale loc(nm);
4707 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004708 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004709 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004710
Ben Craig3756b922016-03-09 15:39:39 +00004711 lconv* lc = __libcpp_localeconv_l(loc.get());
Louis Dionne89258142021-08-23 15:32:36 -04004712 if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4713 loc.get()))
4714 __decimal_point_ = base::do_decimal_point();
4715 if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4716 loc.get()))
4717 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00004718 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004719 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004720 }
4721}
4722
4723// numpunct_byname<wchar_t>
4724
Louis Dionne89258142021-08-23 15:32:36 -04004725#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004726numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4727 : numpunct<wchar_t>(refs)
4728{
4729 __init(nm);
4730}
4731
4732numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4733 : numpunct<wchar_t>(refs)
4734{
4735 __init(nm.c_str());
4736}
4737
4738numpunct_byname<wchar_t>::~numpunct_byname()
4739{
4740}
4741
4742void
4743numpunct_byname<wchar_t>::__init(const char* nm)
4744{
4745 if (strcmp(nm, "C") != 0)
4746 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004747 __libcpp_unique_locale loc(nm);
4748 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004749 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004750 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004751
Ben Craig3756b922016-03-09 15:39:39 +00004752 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004753 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4754 loc.get());
4755 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4756 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004757 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004758 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004759 }
4760}
Louis Dionne89258142021-08-23 15:32:36 -04004761#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004762
4763// num_get helpers
4764
4765int
4766__num_get_base::__get_base(ios_base& iob)
4767{
4768 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4769 if (__basefield == ios_base::oct)
4770 return 8;
4771 else if (__basefield == ios_base::hex)
4772 return 16;
4773 else if (__basefield == 0)
4774 return 0;
4775 return 10;
4776}
4777
4778const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4779
4780void
4781__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4782 ios_base::iostate& __err)
4783{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004784// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4785// 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 +00004786 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004787 {
4788 reverse(__g, __g_end);
4789 const char* __ig = __grouping.data();
4790 const char* __eg = __ig + __grouping.size();
4791 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4792 {
4793 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4794 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004795 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004796 {
4797 __err = ios_base::failbit;
4798 return;
4799 }
4800 }
4801 if (__eg - __ig > 1)
4802 ++__ig;
4803 }
4804 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4805 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004806 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004807 __err = ios_base::failbit;
4808 }
4809 }
4810}
4811
4812void
4813__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4814 ios_base::fmtflags __flags)
4815{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004816 if ((__flags & ios_base::showpos) &&
4817 (__flags & ios_base::basefield) != ios_base::oct &&
4818 (__flags & ios_base::basefield) != ios_base::hex &&
4819 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004820 *__fmtp++ = '+';
4821 if (__flags & ios_base::showbase)
4822 *__fmtp++ = '#';
4823 while(*__len)
4824 *__fmtp++ = *__len++;
4825 if ((__flags & ios_base::basefield) == ios_base::oct)
4826 *__fmtp = 'o';
4827 else if ((__flags & ios_base::basefield) == ios_base::hex)
4828 {
4829 if (__flags & ios_base::uppercase)
4830 *__fmtp = 'X';
4831 else
4832 *__fmtp = 'x';
4833 }
4834 else if (__signd)
4835 *__fmtp = 'd';
4836 else
4837 *__fmtp = 'u';
4838}
4839
4840bool
4841__num_put_base::__format_float(char* __fmtp, const char* __len,
4842 ios_base::fmtflags __flags)
4843{
4844 bool specify_precision = true;
4845 if (__flags & ios_base::showpos)
4846 *__fmtp++ = '+';
4847 if (__flags & ios_base::showpoint)
4848 *__fmtp++ = '#';
4849 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004850 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004851 if (floatfield == (ios_base::fixed | ios_base::scientific))
4852 specify_precision = false;
4853 else
4854 {
4855 *__fmtp++ = '.';
4856 *__fmtp++ = '*';
4857 }
4858 while(*__len)
4859 *__fmtp++ = *__len++;
4860 if (floatfield == ios_base::fixed)
4861 {
4862 if (uppercase)
4863 *__fmtp = 'F';
4864 else
4865 *__fmtp = 'f';
4866 }
4867 else if (floatfield == ios_base::scientific)
4868 {
4869 if (uppercase)
4870 *__fmtp = 'E';
4871 else
4872 *__fmtp = 'e';
4873 }
4874 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4875 {
4876 if (uppercase)
4877 *__fmtp = 'A';
4878 else
4879 *__fmtp = 'a';
4880 }
4881 else
4882 {
4883 if (uppercase)
4884 *__fmtp = 'G';
4885 else
4886 *__fmtp = 'g';
4887 }
4888 return specify_precision;
4889}
4890
4891char*
4892__num_put_base::__identify_padding(char* __nb, char* __ne,
4893 const ios_base& __iob)
4894{
4895 switch (__iob.flags() & ios_base::adjustfield)
4896 {
4897 case ios_base::internal:
4898 if (__nb[0] == '-' || __nb[0] == '+')
4899 return __nb+1;
4900 if (__ne - __nb >= 2 && __nb[0] == '0'
4901 && (__nb[1] == 'x' || __nb[1] == 'X'))
4902 return __nb+2;
4903 break;
4904 case ios_base::left:
4905 return __ne;
4906 case ios_base::right:
4907 default:
4908 break;
4909 }
4910 return __nb;
4911}
4912
4913// time_get
4914
4915static
4916string*
4917init_weeks()
4918{
4919 static string weeks[14];
4920 weeks[0] = "Sunday";
4921 weeks[1] = "Monday";
4922 weeks[2] = "Tuesday";
4923 weeks[3] = "Wednesday";
4924 weeks[4] = "Thursday";
4925 weeks[5] = "Friday";
4926 weeks[6] = "Saturday";
4927 weeks[7] = "Sun";
4928 weeks[8] = "Mon";
4929 weeks[9] = "Tue";
4930 weeks[10] = "Wed";
4931 weeks[11] = "Thu";
4932 weeks[12] = "Fri";
4933 weeks[13] = "Sat";
4934 return weeks;
4935}
4936
Louis Dionne89258142021-08-23 15:32:36 -04004937#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004938static
4939wstring*
4940init_wweeks()
4941{
4942 static wstring weeks[14];
4943 weeks[0] = L"Sunday";
4944 weeks[1] = L"Monday";
4945 weeks[2] = L"Tuesday";
4946 weeks[3] = L"Wednesday";
4947 weeks[4] = L"Thursday";
4948 weeks[5] = L"Friday";
4949 weeks[6] = L"Saturday";
4950 weeks[7] = L"Sun";
4951 weeks[8] = L"Mon";
4952 weeks[9] = L"Tue";
4953 weeks[10] = L"Wed";
4954 weeks[11] = L"Thu";
4955 weeks[12] = L"Fri";
4956 weeks[13] = L"Sat";
4957 return weeks;
4958}
Louis Dionne89258142021-08-23 15:32:36 -04004959#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004960
4961template <>
4962const string*
4963__time_get_c_storage<char>::__weeks() const
4964{
4965 static const string* weeks = init_weeks();
4966 return weeks;
4967}
4968
Louis Dionne89258142021-08-23 15:32:36 -04004969#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004970template <>
4971const wstring*
4972__time_get_c_storage<wchar_t>::__weeks() const
4973{
4974 static const wstring* weeks = init_wweeks();
4975 return weeks;
4976}
Louis Dionne89258142021-08-23 15:32:36 -04004977#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004978
4979static
4980string*
4981init_months()
4982{
4983 static string months[24];
4984 months[0] = "January";
4985 months[1] = "February";
4986 months[2] = "March";
4987 months[3] = "April";
4988 months[4] = "May";
4989 months[5] = "June";
4990 months[6] = "July";
4991 months[7] = "August";
4992 months[8] = "September";
4993 months[9] = "October";
4994 months[10] = "November";
4995 months[11] = "December";
4996 months[12] = "Jan";
4997 months[13] = "Feb";
4998 months[14] = "Mar";
4999 months[15] = "Apr";
5000 months[16] = "May";
5001 months[17] = "Jun";
5002 months[18] = "Jul";
5003 months[19] = "Aug";
5004 months[20] = "Sep";
5005 months[21] = "Oct";
5006 months[22] = "Nov";
5007 months[23] = "Dec";
5008 return months;
5009}
5010
Louis Dionne89258142021-08-23 15:32:36 -04005011#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005012static
5013wstring*
5014init_wmonths()
5015{
5016 static wstring months[24];
5017 months[0] = L"January";
5018 months[1] = L"February";
5019 months[2] = L"March";
5020 months[3] = L"April";
5021 months[4] = L"May";
5022 months[5] = L"June";
5023 months[6] = L"July";
5024 months[7] = L"August";
5025 months[8] = L"September";
5026 months[9] = L"October";
5027 months[10] = L"November";
5028 months[11] = L"December";
5029 months[12] = L"Jan";
5030 months[13] = L"Feb";
5031 months[14] = L"Mar";
5032 months[15] = L"Apr";
5033 months[16] = L"May";
5034 months[17] = L"Jun";
5035 months[18] = L"Jul";
5036 months[19] = L"Aug";
5037 months[20] = L"Sep";
5038 months[21] = L"Oct";
5039 months[22] = L"Nov";
5040 months[23] = L"Dec";
5041 return months;
5042}
Louis Dionne89258142021-08-23 15:32:36 -04005043#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005044
5045template <>
5046const string*
5047__time_get_c_storage<char>::__months() const
5048{
5049 static const string* months = init_months();
5050 return months;
5051}
5052
Louis Dionne89258142021-08-23 15:32:36 -04005053#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005054template <>
5055const wstring*
5056__time_get_c_storage<wchar_t>::__months() const
5057{
5058 static const wstring* months = init_wmonths();
5059 return months;
5060}
Louis Dionne89258142021-08-23 15:32:36 -04005061#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005062
5063static
5064string*
5065init_am_pm()
5066{
Marshall Clow5cc04922018-01-11 17:16:52 +00005067 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005068 am_pm[0] = "AM";
5069 am_pm[1] = "PM";
5070 return am_pm;
5071}
5072
Louis Dionne89258142021-08-23 15:32:36 -04005073#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005074static
5075wstring*
5076init_wam_pm()
5077{
Marshall Clow5cc04922018-01-11 17:16:52 +00005078 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005079 am_pm[0] = L"AM";
5080 am_pm[1] = L"PM";
5081 return am_pm;
5082}
Louis Dionne89258142021-08-23 15:32:36 -04005083#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005084
5085template <>
5086const string*
5087__time_get_c_storage<char>::__am_pm() const
5088{
5089 static const string* am_pm = init_am_pm();
5090 return am_pm;
5091}
5092
Louis Dionne89258142021-08-23 15:32:36 -04005093#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005094template <>
5095const wstring*
5096__time_get_c_storage<wchar_t>::__am_pm() const
5097{
5098 static const wstring* am_pm = init_wam_pm();
5099 return am_pm;
5100}
Louis Dionne89258142021-08-23 15:32:36 -04005101#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005102
5103template <>
5104const string&
5105__time_get_c_storage<char>::__x() const
5106{
5107 static string s("%m/%d/%y");
5108 return s;
5109}
5110
Louis Dionne89258142021-08-23 15:32:36 -04005111#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005112template <>
5113const wstring&
5114__time_get_c_storage<wchar_t>::__x() const
5115{
5116 static wstring s(L"%m/%d/%y");
5117 return s;
5118}
Louis Dionne89258142021-08-23 15:32:36 -04005119#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005120
5121template <>
5122const string&
5123__time_get_c_storage<char>::__X() const
5124{
5125 static string s("%H:%M:%S");
5126 return s;
5127}
5128
Louis Dionne89258142021-08-23 15:32:36 -04005129#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005130template <>
5131const wstring&
5132__time_get_c_storage<wchar_t>::__X() const
5133{
5134 static wstring s(L"%H:%M:%S");
5135 return s;
5136}
Louis Dionne89258142021-08-23 15:32:36 -04005137#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005138
5139template <>
5140const string&
5141__time_get_c_storage<char>::__c() const
5142{
5143 static string s("%a %b %d %H:%M:%S %Y");
5144 return s;
5145}
5146
Louis Dionne89258142021-08-23 15:32:36 -04005147#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005148template <>
5149const wstring&
5150__time_get_c_storage<wchar_t>::__c() const
5151{
5152 static wstring s(L"%a %b %d %H:%M:%S %Y");
5153 return s;
5154}
Louis Dionne89258142021-08-23 15:32:36 -04005155#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005156
5157template <>
5158const string&
5159__time_get_c_storage<char>::__r() const
5160{
5161 static string s("%I:%M:%S %p");
5162 return s;
5163}
5164
Louis Dionne89258142021-08-23 15:32:36 -04005165#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005166template <>
5167const wstring&
5168__time_get_c_storage<wchar_t>::__r() const
5169{
5170 static wstring s(L"%I:%M:%S %p");
5171 return s;
5172}
Louis Dionne89258142021-08-23 15:32:36 -04005173#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005174
5175// time_get_byname
5176
5177__time_get::__time_get(const char* nm)
5178 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5179{
5180 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005181 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005182 " failed to construct for " + string(nm));
5183}
5184
5185__time_get::__time_get(const string& nm)
5186 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5187{
5188 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005189 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005190 " failed to construct for " + nm);
5191}
5192
5193__time_get::~__time_get()
5194{
5195 freelocale(__loc_);
5196}
Nikolas Klauser41c59762022-02-14 18:52:28 +01005197
5198_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-field-initializers")
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005199
Howard Hinnantc51e1022010-05-11 19:42:16 +00005200template <>
5201string
5202__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5203{
Howard Hinnant990207c2012-02-19 14:55:32 +00005204 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005205 t.tm_sec = 59;
5206 t.tm_min = 55;
5207 t.tm_hour = 23;
5208 t.tm_mday = 31;
5209 t.tm_mon = 11;
5210 t.tm_year = 161;
5211 t.tm_wday = 6;
5212 t.tm_yday = 364;
5213 t.tm_isdst = -1;
5214 char buf[100];
5215 char f[3] = {0};
5216 f[0] = '%';
5217 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005218 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005219 char* bb = buf;
5220 char* be = buf + n;
5221 string result;
5222 while (bb != be)
5223 {
5224 if (ct.is(ctype_base::space, *bb))
5225 {
5226 result.push_back(' ');
5227 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5228 ;
5229 continue;
5230 }
5231 char* w = bb;
5232 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005233 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005234 ct, err, false)
5235 - this->__weeks_;
5236 if (i < 14)
5237 {
5238 result.push_back('%');
5239 if (i < 7)
5240 result.push_back('A');
5241 else
5242 result.push_back('a');
5243 bb = w;
5244 continue;
5245 }
5246 w = bb;
5247 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5248 ct, err, false)
5249 - this->__months_;
5250 if (i < 24)
5251 {
5252 result.push_back('%');
5253 if (i < 12)
5254 result.push_back('B');
5255 else
5256 result.push_back('b');
5257 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5258 result.back() = 'm';
5259 bb = w;
5260 continue;
5261 }
5262 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5263 {
5264 w = bb;
5265 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5266 ct, err, false) - this->__am_pm_;
5267 if (i < 2)
5268 {
5269 result.push_back('%');
5270 result.push_back('p');
5271 bb = w;
5272 continue;
5273 }
5274 }
5275 w = bb;
5276 if (ct.is(ctype_base::digit, *bb))
5277 {
5278 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5279 {
5280 case 6:
5281 result.push_back('%');
5282 result.push_back('w');
5283 break;
5284 case 7:
5285 result.push_back('%');
5286 result.push_back('u');
5287 break;
5288 case 11:
5289 result.push_back('%');
5290 result.push_back('I');
5291 break;
5292 case 12:
5293 result.push_back('%');
5294 result.push_back('m');
5295 break;
5296 case 23:
5297 result.push_back('%');
5298 result.push_back('H');
5299 break;
5300 case 31:
5301 result.push_back('%');
5302 result.push_back('d');
5303 break;
5304 case 55:
5305 result.push_back('%');
5306 result.push_back('M');
5307 break;
5308 case 59:
5309 result.push_back('%');
5310 result.push_back('S');
5311 break;
5312 case 61:
5313 result.push_back('%');
5314 result.push_back('y');
5315 break;
5316 case 364:
5317 result.push_back('%');
5318 result.push_back('j');
5319 break;
5320 case 2061:
5321 result.push_back('%');
5322 result.push_back('Y');
5323 break;
5324 default:
5325 for (; w != bb; ++w)
5326 result.push_back(*w);
5327 break;
5328 }
5329 continue;
5330 }
5331 if (*bb == '%')
5332 {
5333 result.push_back('%');
5334 result.push_back('%');
5335 ++bb;
5336 continue;
5337 }
5338 result.push_back(*bb);
5339 ++bb;
5340 }
5341 return result;
5342}
5343
Nikolas Klauser41c59762022-02-14 18:52:28 +01005344_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wmissing-braces")
Howard Hinnant28b24882011-12-01 20:21:04 +00005345
Louis Dionne89258142021-08-23 15:32:36 -04005346#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005347template <>
5348wstring
5349__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5350{
Howard Hinnant990207c2012-02-19 14:55:32 +00005351 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005352 t.tm_sec = 59;
5353 t.tm_min = 55;
5354 t.tm_hour = 23;
5355 t.tm_mday = 31;
5356 t.tm_mon = 11;
5357 t.tm_year = 161;
5358 t.tm_wday = 6;
5359 t.tm_yday = 364;
5360 t.tm_isdst = -1;
5361 char buf[100];
5362 char f[3] = {0};
5363 f[0] = '%';
5364 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005365 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005366 wchar_t wbuf[100];
5367 wchar_t* wbb = wbuf;
5368 mbstate_t mb = {0};
5369 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005370 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005371 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005372 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005373 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005374 wstring result;
5375 while (wbb != wbe)
5376 {
5377 if (ct.is(ctype_base::space, *wbb))
5378 {
5379 result.push_back(L' ');
5380 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5381 ;
5382 continue;
5383 }
5384 wchar_t* w = wbb;
5385 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005386 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005387 ct, err, false)
5388 - this->__weeks_;
5389 if (i < 14)
5390 {
5391 result.push_back(L'%');
5392 if (i < 7)
5393 result.push_back(L'A');
5394 else
5395 result.push_back(L'a');
5396 wbb = w;
5397 continue;
5398 }
5399 w = wbb;
5400 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5401 ct, err, false)
5402 - this->__months_;
5403 if (i < 24)
5404 {
5405 result.push_back(L'%');
5406 if (i < 12)
5407 result.push_back(L'B');
5408 else
5409 result.push_back(L'b');
5410 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5411 result.back() = L'm';
5412 wbb = w;
5413 continue;
5414 }
5415 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5416 {
5417 w = wbb;
5418 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5419 ct, err, false) - this->__am_pm_;
5420 if (i < 2)
5421 {
5422 result.push_back(L'%');
5423 result.push_back(L'p');
5424 wbb = w;
5425 continue;
5426 }
5427 }
5428 w = wbb;
5429 if (ct.is(ctype_base::digit, *wbb))
5430 {
5431 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5432 {
5433 case 6:
5434 result.push_back(L'%');
5435 result.push_back(L'w');
5436 break;
5437 case 7:
5438 result.push_back(L'%');
5439 result.push_back(L'u');
5440 break;
5441 case 11:
5442 result.push_back(L'%');
5443 result.push_back(L'I');
5444 break;
5445 case 12:
5446 result.push_back(L'%');
5447 result.push_back(L'm');
5448 break;
5449 case 23:
5450 result.push_back(L'%');
5451 result.push_back(L'H');
5452 break;
5453 case 31:
5454 result.push_back(L'%');
5455 result.push_back(L'd');
5456 break;
5457 case 55:
5458 result.push_back(L'%');
5459 result.push_back(L'M');
5460 break;
5461 case 59:
5462 result.push_back(L'%');
5463 result.push_back(L'S');
5464 break;
5465 case 61:
5466 result.push_back(L'%');
5467 result.push_back(L'y');
5468 break;
5469 case 364:
5470 result.push_back(L'%');
5471 result.push_back(L'j');
5472 break;
5473 case 2061:
5474 result.push_back(L'%');
5475 result.push_back(L'Y');
5476 break;
5477 default:
5478 for (; w != wbb; ++w)
5479 result.push_back(*w);
5480 break;
5481 }
5482 continue;
5483 }
5484 if (ct.narrow(*wbb, 0) == '%')
5485 {
5486 result.push_back(L'%');
5487 result.push_back(L'%');
5488 ++wbb;
5489 continue;
5490 }
5491 result.push_back(*wbb);
5492 ++wbb;
5493 }
5494 return result;
5495}
Louis Dionne89258142021-08-23 15:32:36 -04005496#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005497
5498template <>
5499void
5500__time_get_storage<char>::init(const ctype<char>& ct)
5501{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005502 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005503 char buf[100];
5504 // __weeks_
5505 for (int i = 0; i < 7; ++i)
5506 {
5507 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005508 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005509 __weeks_[i] = buf;
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+7] = buf;
5512 }
5513 // __months_
5514 for (int i = 0; i < 12; ++i)
5515 {
5516 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005517 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005518 __months_[i] = buf;
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+12] = buf;
5521 }
5522 // __am_pm_
5523 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005524 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005525 __am_pm_[0] = buf;
5526 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005527 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005528 __am_pm_[1] = buf;
5529 __c_ = __analyze('c', ct);
5530 __r_ = __analyze('r', ct);
5531 __x_ = __analyze('x', ct);
5532 __X_ = __analyze('X', ct);
5533}
5534
Louis Dionne89258142021-08-23 15:32:36 -04005535#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005536template <>
5537void
5538__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5539{
5540 tm t = {0};
5541 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005542 wchar_t wbuf[100];
5543 wchar_t* wbe;
5544 mbstate_t mb = {0};
5545 // __weeks_
5546 for (int i = 0; i < 7; ++i)
5547 {
5548 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005549 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005550 mb = mbstate_t();
5551 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005552 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005553 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005554 __throw_runtime_error("locale not supported");
5555 wbe = wbuf + j;
5556 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005557 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005558 mb = mbstate_t();
5559 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005560 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005561 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005562 __throw_runtime_error("locale not supported");
5563 wbe = wbuf + j;
5564 __weeks_[i+7].assign(wbuf, wbe);
5565 }
5566 // __months_
5567 for (int i = 0; i < 12; ++i)
5568 {
5569 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005570 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005571 mb = mbstate_t();
5572 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005573 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005574 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005575 __throw_runtime_error("locale not supported");
5576 wbe = wbuf + j;
5577 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005578 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005579 mb = mbstate_t();
5580 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005581 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005582 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005583 __throw_runtime_error("locale not supported");
5584 wbe = wbuf + j;
5585 __months_[i+12].assign(wbuf, wbe);
5586 }
5587 // __am_pm_
5588 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005589 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005590 mb = mbstate_t();
5591 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005592 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005593 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005594 __throw_runtime_error("locale not supported");
5595 wbe = wbuf + j;
5596 __am_pm_[0].assign(wbuf, wbe);
5597 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005598 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599 mb = mbstate_t();
5600 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005601 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005602 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005603 __throw_runtime_error("locale not supported");
5604 wbe = wbuf + j;
5605 __am_pm_[1].assign(wbuf, wbe);
5606 __c_ = __analyze('c', ct);
5607 __r_ = __analyze('r', ct);
5608 __x_ = __analyze('x', ct);
5609 __X_ = __analyze('X', ct);
5610}
Louis Dionne89258142021-08-23 15:32:36 -04005611#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005612
5613template <class CharT>
5614struct _LIBCPP_HIDDEN __time_get_temp
5615 : public ctype_byname<CharT>
5616{
5617 explicit __time_get_temp(const char* nm)
5618 : ctype_byname<CharT>(nm, 1) {}
5619 explicit __time_get_temp(const string& nm)
5620 : ctype_byname<CharT>(nm, 1) {}
5621};
5622
5623template <>
5624__time_get_storage<char>::__time_get_storage(const char* __nm)
5625 : __time_get(__nm)
5626{
5627 const __time_get_temp<char> ct(__nm);
5628 init(ct);
5629}
5630
5631template <>
5632__time_get_storage<char>::__time_get_storage(const string& __nm)
5633 : __time_get(__nm)
5634{
5635 const __time_get_temp<char> ct(__nm);
5636 init(ct);
5637}
5638
Louis Dionne89258142021-08-23 15:32:36 -04005639#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005640template <>
5641__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5642 : __time_get(__nm)
5643{
5644 const __time_get_temp<wchar_t> ct(__nm);
5645 init(ct);
5646}
5647
5648template <>
5649__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5650 : __time_get(__nm)
5651{
5652 const __time_get_temp<wchar_t> ct(__nm);
5653 init(ct);
5654}
Louis Dionne89258142021-08-23 15:32:36 -04005655#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005656
5657template <>
5658time_base::dateorder
5659__time_get_storage<char>::__do_date_order() const
5660{
5661 unsigned i;
5662 for (i = 0; i < __x_.size(); ++i)
5663 if (__x_[i] == '%')
5664 break;
5665 ++i;
5666 switch (__x_[i])
5667 {
5668 case 'y':
5669 case 'Y':
5670 for (++i; i < __x_.size(); ++i)
5671 if (__x_[i] == '%')
5672 break;
5673 if (i == __x_.size())
5674 break;
5675 ++i;
5676 switch (__x_[i])
5677 {
5678 case 'm':
5679 for (++i; i < __x_.size(); ++i)
5680 if (__x_[i] == '%')
5681 break;
5682 if (i == __x_.size())
5683 break;
5684 ++i;
5685 if (__x_[i] == 'd')
5686 return time_base::ymd;
5687 break;
5688 case 'd':
5689 for (++i; i < __x_.size(); ++i)
5690 if (__x_[i] == '%')
5691 break;
5692 if (i == __x_.size())
5693 break;
5694 ++i;
5695 if (__x_[i] == 'm')
5696 return time_base::ydm;
5697 break;
5698 }
5699 break;
5700 case 'm':
5701 for (++i; i < __x_.size(); ++i)
5702 if (__x_[i] == '%')
5703 break;
5704 if (i == __x_.size())
5705 break;
5706 ++i;
5707 if (__x_[i] == 'd')
5708 {
5709 for (++i; i < __x_.size(); ++i)
5710 if (__x_[i] == '%')
5711 break;
5712 if (i == __x_.size())
5713 break;
5714 ++i;
5715 if (__x_[i] == 'y' || __x_[i] == 'Y')
5716 return time_base::mdy;
5717 break;
5718 }
5719 break;
5720 case 'd':
5721 for (++i; i < __x_.size(); ++i)
5722 if (__x_[i] == '%')
5723 break;
5724 if (i == __x_.size())
5725 break;
5726 ++i;
5727 if (__x_[i] == 'm')
5728 {
5729 for (++i; i < __x_.size(); ++i)
5730 if (__x_[i] == '%')
5731 break;
5732 if (i == __x_.size())
5733 break;
5734 ++i;
5735 if (__x_[i] == 'y' || __x_[i] == 'Y')
5736 return time_base::dmy;
5737 break;
5738 }
5739 break;
5740 }
5741 return time_base::no_order;
5742}
5743
Louis Dionne89258142021-08-23 15:32:36 -04005744#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745template <>
5746time_base::dateorder
5747__time_get_storage<wchar_t>::__do_date_order() const
5748{
5749 unsigned i;
5750 for (i = 0; i < __x_.size(); ++i)
5751 if (__x_[i] == L'%')
5752 break;
5753 ++i;
5754 switch (__x_[i])
5755 {
5756 case L'y':
5757 case L'Y':
5758 for (++i; i < __x_.size(); ++i)
5759 if (__x_[i] == L'%')
5760 break;
5761 if (i == __x_.size())
5762 break;
5763 ++i;
5764 switch (__x_[i])
5765 {
5766 case L'm':
5767 for (++i; i < __x_.size(); ++i)
5768 if (__x_[i] == L'%')
5769 break;
5770 if (i == __x_.size())
5771 break;
5772 ++i;
5773 if (__x_[i] == L'd')
5774 return time_base::ymd;
5775 break;
5776 case L'd':
5777 for (++i; i < __x_.size(); ++i)
5778 if (__x_[i] == L'%')
5779 break;
5780 if (i == __x_.size())
5781 break;
5782 ++i;
5783 if (__x_[i] == L'm')
5784 return time_base::ydm;
5785 break;
5786 }
5787 break;
5788 case L'm':
5789 for (++i; i < __x_.size(); ++i)
5790 if (__x_[i] == L'%')
5791 break;
5792 if (i == __x_.size())
5793 break;
5794 ++i;
5795 if (__x_[i] == L'd')
5796 {
5797 for (++i; i < __x_.size(); ++i)
5798 if (__x_[i] == L'%')
5799 break;
5800 if (i == __x_.size())
5801 break;
5802 ++i;
5803 if (__x_[i] == L'y' || __x_[i] == L'Y')
5804 return time_base::mdy;
5805 break;
5806 }
5807 break;
5808 case L'd':
5809 for (++i; i < __x_.size(); ++i)
5810 if (__x_[i] == L'%')
5811 break;
5812 if (i == __x_.size())
5813 break;
5814 ++i;
5815 if (__x_[i] == L'm')
5816 {
5817 for (++i; i < __x_.size(); ++i)
5818 if (__x_[i] == L'%')
5819 break;
5820 if (i == __x_.size())
5821 break;
5822 ++i;
5823 if (__x_[i] == L'y' || __x_[i] == L'Y')
5824 return time_base::dmy;
5825 break;
5826 }
5827 break;
5828 }
5829 return time_base::no_order;
5830}
Louis Dionne89258142021-08-23 15:32:36 -04005831#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005832
5833// time_put
5834
5835__time_put::__time_put(const char* nm)
5836 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5837{
5838 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005839 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005840 " failed to construct for " + string(nm));
5841}
5842
5843__time_put::__time_put(const string& nm)
5844 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5845{
5846 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005847 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005848 " failed to construct for " + nm);
5849}
5850
5851__time_put::~__time_put()
5852{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005853 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005854 freelocale(__loc_);
5855}
5856
5857void
5858__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5859 char __fmt, char __mod) const
5860{
5861 char fmt[] = {'%', __fmt, __mod, 0};
5862 if (__mod != 0)
5863 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005864 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005865 __ne = __nb + n;
5866}
5867
Louis Dionne89258142021-08-23 15:32:36 -04005868#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005869void
5870__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5871 char __fmt, char __mod) const
5872{
5873 char __nar[100];
5874 char* __ne = __nar + 100;
5875 __do_put(__nar, __ne, __tm, __fmt, __mod);
5876 mbstate_t mb = {0};
5877 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005878 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005879 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005880 __throw_runtime_error("locale not supported");
5881 __we = __wb + j;
5882}
Louis Dionne89258142021-08-23 15:32:36 -04005883#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005884
5885// moneypunct_byname
5886
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005887template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005888static
5889void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005890__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5891 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5892 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005893{
5894 const char sign = static_cast<char>(money_base::sign);
5895 const char space = static_cast<char>(money_base::space);
5896 const char none = static_cast<char>(money_base::none);
5897 const char symbol = static_cast<char>(money_base::symbol);
5898 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005899 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5900
5901 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5902 // function'. "Space between sign and symbol or value" means that
5903 // if the sign is adjacent to the symbol, there's a space between
5904 // them, and otherwise there's a space between the sign and value.
5905 //
5906 // C11's localeconv specifies that the fourth character of an
5907 // international curr_symbol is used to separate the sign and
5908 // value when sep_by_space says to do so. C++ can't represent
5909 // that, so we just use a space. When sep_by_space says to
5910 // separate the symbol and value-or-sign with a space, we rearrange the
5911 // curr_symbol to put its spacing character on the correct side of
5912 // the symbol.
5913 //
5914 // We also need to avoid adding an extra space between the sign
5915 // and value when the currency symbol is suppressed (by not
5916 // setting showbase). We match glibc's strfmon by interpreting
5917 // sep_by_space==1 as "omit the space when the currency symbol is
5918 // absent".
5919 //
5920 // Users who want to get this right should use ICU instead.
5921
Howard Hinnantc51e1022010-05-11 19:42:16 +00005922 switch (cs_precedes)
5923 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005924 case 0: // value before curr_symbol
5925 if (symbol_contains_sep) {
5926 // Move the separator to before the symbol, to place it
5927 // between the value and symbol.
5928 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5929 __curr_symbol_.end());
5930 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005931 switch (sign_posn)
5932 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005933 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005934 pat.field[0] = sign;
5935 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005936 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005937 pat.field[3] = symbol;
5938 switch (sep_by_space)
5939 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005940 case 0: // No space separates the currency symbol and value.
5941 // This case may have changed between C99 and C11;
5942 // assume the currency symbol matches the intention.
5943 case 2: // Space between sign and currency or value.
5944 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005945 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005946 case 1: // Space between currency-and-sign or currency and value.
5947 if (!symbol_contains_sep) {
5948 // We insert the space into the symbol instead of
5949 // setting pat.field[2]=space so that when
5950 // showbase is not set, the space goes away too.
5951 __curr_symbol_.insert(0, 1, space_char);
5952 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005953 return;
5954 default:
5955 break;
5956 }
5957 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005958 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005959 pat.field[0] = sign;
5960 pat.field[3] = symbol;
5961 switch (sep_by_space)
5962 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005963 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005964 pat.field[1] = value;
5965 pat.field[2] = none;
5966 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005967 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005968 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005969 pat.field[2] = none;
5970 if (!symbol_contains_sep) {
5971 // We insert the space into the symbol instead of
5972 // setting pat.field[2]=space so that when
5973 // showbase is not set, the space goes away too.
5974 __curr_symbol_.insert(0, 1, space_char);
5975 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005976 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005977 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005978 pat.field[1] = space;
5979 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005980 if (symbol_contains_sep) {
5981 // Remove the separator from the symbol, since it
5982 // has already appeared after the sign.
5983 __curr_symbol_.erase(__curr_symbol_.begin());
5984 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005985 return;
5986 default:
5987 break;
5988 }
5989 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005990 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005991 pat.field[0] = value;
5992 pat.field[3] = sign;
5993 switch (sep_by_space)
5994 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005995 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005996 pat.field[1] = none;
5997 pat.field[2] = symbol;
5998 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005999 case 1: // Space between currency-and-sign or currency and value.
6000 if (!symbol_contains_sep) {
6001 // We insert the space into the symbol instead of
6002 // setting pat.field[1]=space so that when
6003 // showbase is not set, the space goes away too.
6004 __curr_symbol_.insert(0, 1, space_char);
6005 }
6006 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006007 pat.field[2] = symbol;
6008 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006009 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006010 pat.field[1] = symbol;
6011 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006012 if (symbol_contains_sep) {
6013 // Remove the separator from the symbol, since it
6014 // should not be removed if showbase is absent.
6015 __curr_symbol_.erase(__curr_symbol_.begin());
6016 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006017 return;
6018 default:
6019 break;
6020 }
6021 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006022 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006023 pat.field[0] = value;
6024 pat.field[3] = symbol;
6025 switch (sep_by_space)
6026 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006027 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006028 pat.field[1] = none;
6029 pat.field[2] = sign;
6030 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006031 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006032 pat.field[1] = space;
6033 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006034 if (symbol_contains_sep) {
6035 // Remove the separator from the symbol, since it
6036 // has already appeared before the sign.
6037 __curr_symbol_.erase(__curr_symbol_.begin());
6038 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006040 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006041 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006042 pat.field[2] = none;
6043 if (!symbol_contains_sep) {
6044 // We insert the space into the symbol instead of
6045 // setting pat.field[2]=space so that when
6046 // showbase is not set, the space goes away too.
6047 __curr_symbol_.insert(0, 1, space_char);
6048 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006049 return;
6050 default:
6051 break;
6052 }
6053 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006054 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006055 pat.field[0] = value;
6056 pat.field[3] = sign;
6057 switch (sep_by_space)
6058 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006059 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006060 pat.field[1] = none;
6061 pat.field[2] = symbol;
6062 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006063 case 1: // Space between currency-and-sign or currency and value.
6064 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006065 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006066 if (!symbol_contains_sep) {
6067 // We insert the space into the symbol instead of
6068 // setting pat.field[1]=space so that when
6069 // showbase is not set, the space goes away too.
6070 __curr_symbol_.insert(0, 1, space_char);
6071 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006072 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006073 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006074 pat.field[1] = symbol;
6075 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006076 if (symbol_contains_sep) {
6077 // Remove the separator from the symbol, since it
6078 // should not disappear when showbase is absent.
6079 __curr_symbol_.erase(__curr_symbol_.begin());
6080 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006081 return;
6082 default:
6083 break;
6084 }
6085 break;
6086 default:
6087 break;
6088 }
6089 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006090 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00006091 switch (sign_posn)
6092 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006093 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006094 pat.field[0] = sign;
6095 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006096 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006097 pat.field[3] = value;
6098 switch (sep_by_space)
6099 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006100 case 0: // No space separates the currency symbol and value.
6101 // This case may have changed between C99 and C11;
6102 // assume the currency symbol matches the intention.
6103 case 2: // Space between sign and currency or value.
6104 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006105 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006106 case 1: // Space between currency-and-sign or currency and value.
6107 if (!symbol_contains_sep) {
6108 // We insert the space into the symbol instead of
6109 // setting pat.field[2]=space so that when
6110 // showbase is not set, the space goes away too.
6111 __curr_symbol_.insert(0, 1, space_char);
6112 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006113 return;
6114 default:
6115 break;
6116 }
6117 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006118 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006119 pat.field[0] = sign;
6120 pat.field[3] = value;
6121 switch (sep_by_space)
6122 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006123 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006124 pat.field[1] = symbol;
6125 pat.field[2] = none;
6126 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006127 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006128 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006129 pat.field[2] = none;
6130 if (!symbol_contains_sep) {
6131 // We insert the space into the symbol instead of
6132 // setting pat.field[2]=space so that when
6133 // showbase is not set, the space goes away too.
6134 __curr_symbol_.push_back(space_char);
6135 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006136 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006137 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006138 pat.field[1] = space;
6139 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006140 if (symbol_contains_sep) {
6141 // Remove the separator from the symbol, since it
6142 // has already appeared after the sign.
6143 __curr_symbol_.pop_back();
6144 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006145 return;
6146 default:
6147 break;
6148 }
6149 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006150 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006151 pat.field[0] = symbol;
6152 pat.field[3] = sign;
6153 switch (sep_by_space)
6154 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006155 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006156 pat.field[1] = none;
6157 pat.field[2] = value;
6158 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006159 case 1: // Space between currency-and-sign or currency and value.
6160 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006161 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006162 if (!symbol_contains_sep) {
6163 // We insert the space into the symbol instead of
6164 // setting pat.field[1]=space so that when
6165 // showbase is not set, the space goes away too.
6166 __curr_symbol_.push_back(space_char);
6167 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006168 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006169 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006170 pat.field[1] = value;
6171 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006172 if (symbol_contains_sep) {
6173 // Remove the separator from the symbol, since it
6174 // will appear before the sign.
6175 __curr_symbol_.pop_back();
6176 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006177 return;
6178 default:
6179 break;
6180 }
6181 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006182 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006183 pat.field[0] = sign;
6184 pat.field[3] = value;
6185 switch (sep_by_space)
6186 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006187 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006188 pat.field[1] = symbol;
6189 pat.field[2] = none;
6190 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006191 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006192 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006193 pat.field[2] = none;
6194 if (!symbol_contains_sep) {
6195 // We insert the space into the symbol instead of
6196 // setting pat.field[2]=space so that when
6197 // showbase is not set, the space goes away too.
6198 __curr_symbol_.push_back(space_char);
6199 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006200 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006201 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006202 pat.field[1] = space;
6203 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006204 if (symbol_contains_sep) {
6205 // Remove the separator from the symbol, since it
6206 // has already appeared after the sign.
6207 __curr_symbol_.pop_back();
6208 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006209 return;
6210 default:
6211 break;
6212 }
6213 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006214 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006215 pat.field[0] = symbol;
6216 pat.field[3] = value;
6217 switch (sep_by_space)
6218 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006219 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006220 pat.field[1] = sign;
6221 pat.field[2] = none;
6222 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006223 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006224 pat.field[1] = sign;
6225 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006226 if (symbol_contains_sep) {
6227 // Remove the separator from the symbol, since it
6228 // should not disappear when showbase is absent.
6229 __curr_symbol_.pop_back();
6230 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006231 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006232 case 2: // Space between sign and currency or value.
6233 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006234 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006235 if (!symbol_contains_sep) {
6236 // We insert the space into the symbol instead of
6237 // setting pat.field[1]=space so that when
6238 // showbase is not set, the space goes away too.
6239 __curr_symbol_.push_back(space_char);
6240 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006241 return;
6242 default:
6243 break;
6244 }
6245 break;
6246 default:
6247 break;
6248 }
6249 break;
6250 default:
6251 break;
6252 }
6253 pat.field[0] = symbol;
6254 pat.field[1] = sign;
6255 pat.field[2] = none;
6256 pat.field[3] = value;
6257}
6258
6259template<>
6260void
6261moneypunct_byname<char, false>::init(const char* nm)
6262{
6263 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006264 __libcpp_unique_locale loc(nm);
6265 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006266 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006267 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006268
Ben Craig3756b922016-03-09 15:39:39 +00006269 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006270 if (!checked_string_to_char_convert(__decimal_point_,
6271 lc->mon_decimal_point,
6272 loc.get()))
6273 __decimal_point_ = base::do_decimal_point();
6274 if (!checked_string_to_char_convert(__thousands_sep_,
6275 lc->mon_thousands_sep,
6276 loc.get()))
6277 __thousands_sep_ = base::do_thousands_sep();
6278
Howard Hinnantc51e1022010-05-11 19:42:16 +00006279 __grouping_ = lc->mon_grouping;
6280 __curr_symbol_ = lc->currency_symbol;
6281 if (lc->frac_digits != CHAR_MAX)
6282 __frac_digits_ = lc->frac_digits;
6283 else
6284 __frac_digits_ = base::do_frac_digits();
6285 if (lc->p_sign_posn == 0)
6286 __positive_sign_ = "()";
6287 else
6288 __positive_sign_ = lc->positive_sign;
6289 if (lc->n_sign_posn == 0)
6290 __negative_sign_ = "()";
6291 else
6292 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006293 // Assume the positive and negative formats will want spaces in
6294 // the same places in curr_symbol since there's no way to
6295 // represent anything else.
6296 string_type __dummy_curr_symbol = __curr_symbol_;
6297 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6298 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6299 __init_pat(__neg_format_, __curr_symbol_, false,
6300 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006301}
6302
6303template<>
6304void
6305moneypunct_byname<char, true>::init(const char* nm)
6306{
6307 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006308 __libcpp_unique_locale loc(nm);
6309 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006310 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006311 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006312
Ben Craig3756b922016-03-09 15:39:39 +00006313 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006314 if (!checked_string_to_char_convert(__decimal_point_,
6315 lc->mon_decimal_point,
6316 loc.get()))
6317 __decimal_point_ = base::do_decimal_point();
6318 if (!checked_string_to_char_convert(__thousands_sep_,
6319 lc->mon_thousands_sep,
6320 loc.get()))
6321 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006322 __grouping_ = lc->mon_grouping;
6323 __curr_symbol_ = lc->int_curr_symbol;
6324 if (lc->int_frac_digits != CHAR_MAX)
6325 __frac_digits_ = lc->int_frac_digits;
6326 else
6327 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006328#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006329 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006330#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006331 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006332#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006333 __positive_sign_ = "()";
6334 else
6335 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006336#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006337 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006338#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006339 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006340#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006341 __negative_sign_ = "()";
6342 else
6343 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006344 // Assume the positive and negative formats will want spaces in
6345 // the same places in curr_symbol since there's no way to
6346 // represent anything else.
6347 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006348#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006349 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6350 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6351 __init_pat(__neg_format_, __curr_symbol_, true,
6352 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006353#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006354 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6355 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6356 lc->int_p_sign_posn, ' ');
6357 __init_pat(__neg_format_, __curr_symbol_, true,
6358 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6359 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006360#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006361}
6362
Louis Dionne89258142021-08-23 15:32:36 -04006363#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006364template<>
6365void
6366moneypunct_byname<wchar_t, false>::init(const char* nm)
6367{
6368 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006369 __libcpp_unique_locale loc(nm);
6370 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006371 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006372 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006373 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006374 if (!checked_string_to_wchar_convert(__decimal_point_,
6375 lc->mon_decimal_point,
6376 loc.get()))
6377 __decimal_point_ = base::do_decimal_point();
6378 if (!checked_string_to_wchar_convert(__thousands_sep_,
6379 lc->mon_thousands_sep,
6380 loc.get()))
6381 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006382 __grouping_ = lc->mon_grouping;
6383 wchar_t wbuf[100];
6384 mbstate_t mb = {0};
6385 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006386 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006387 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006388 __throw_runtime_error("locale not supported");
6389 wchar_t* wbe = wbuf + j;
6390 __curr_symbol_.assign(wbuf, wbe);
6391 if (lc->frac_digits != CHAR_MAX)
6392 __frac_digits_ = lc->frac_digits;
6393 else
6394 __frac_digits_ = base::do_frac_digits();
6395 if (lc->p_sign_posn == 0)
6396 __positive_sign_ = L"()";
6397 else
6398 {
6399 mb = mbstate_t();
6400 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006401 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006402 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006403 __throw_runtime_error("locale not supported");
6404 wbe = wbuf + j;
6405 __positive_sign_.assign(wbuf, wbe);
6406 }
6407 if (lc->n_sign_posn == 0)
6408 __negative_sign_ = L"()";
6409 else
6410 {
6411 mb = mbstate_t();
6412 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006413 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006414 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006415 __throw_runtime_error("locale not supported");
6416 wbe = wbuf + j;
6417 __negative_sign_.assign(wbuf, wbe);
6418 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006419 // Assume the positive and negative formats will want spaces in
6420 // the same places in curr_symbol since there's no way to
6421 // represent anything else.
6422 string_type __dummy_curr_symbol = __curr_symbol_;
6423 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6424 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6425 __init_pat(__neg_format_, __curr_symbol_, false,
6426 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006427}
6428
6429template<>
6430void
6431moneypunct_byname<wchar_t, true>::init(const char* nm)
6432{
6433 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006434 __libcpp_unique_locale loc(nm);
6435 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006436 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006437 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006438
Ben Craig3756b922016-03-09 15:39:39 +00006439 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006440 if (!checked_string_to_wchar_convert(__decimal_point_,
6441 lc->mon_decimal_point,
6442 loc.get()))
6443 __decimal_point_ = base::do_decimal_point();
6444 if (!checked_string_to_wchar_convert(__thousands_sep_,
6445 lc->mon_thousands_sep,
6446 loc.get()))
6447 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006448 __grouping_ = lc->mon_grouping;
6449 wchar_t wbuf[100];
6450 mbstate_t mb = {0};
6451 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006452 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006453 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006454 __throw_runtime_error("locale not supported");
6455 wchar_t* wbe = wbuf + j;
6456 __curr_symbol_.assign(wbuf, wbe);
6457 if (lc->int_frac_digits != CHAR_MAX)
6458 __frac_digits_ = lc->int_frac_digits;
6459 else
6460 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006461#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006462 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006463#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006464 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006465#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006466 __positive_sign_ = L"()";
6467 else
6468 {
6469 mb = mbstate_t();
6470 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006471 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006472 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006473 __throw_runtime_error("locale not supported");
6474 wbe = wbuf + j;
6475 __positive_sign_.assign(wbuf, wbe);
6476 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006477#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006478 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006479#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006480 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006481#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006482 __negative_sign_ = L"()";
6483 else
6484 {
6485 mb = mbstate_t();
6486 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006487 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006488 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006489 __throw_runtime_error("locale not supported");
6490 wbe = wbuf + j;
6491 __negative_sign_.assign(wbuf, wbe);
6492 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006493 // Assume the positive and negative formats will want spaces in
6494 // the same places in curr_symbol since there's no way to
6495 // represent anything else.
6496 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006497#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006498 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6499 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6500 __init_pat(__neg_format_, __curr_symbol_, true,
6501 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006502#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006503 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6504 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6505 lc->int_p_sign_posn, L' ');
6506 __init_pat(__neg_format_, __curr_symbol_, true,
6507 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6508 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006509#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006510}
Louis Dionne89258142021-08-23 15:32:36 -04006511#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006512
6513void __do_nothing(void*) {}
6514
6515void __throw_runtime_error(const char* msg)
6516{
Howard Hinnant72f73582010-08-11 17:04:31 +00006517#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006518 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006519#else
6520 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006521 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006522#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006523}
6524
Louis Dionne89258142021-08-23 15:32:36 -04006525 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6526_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006527
Louis Dionne89258142021-08-23 15:32:36 -04006528 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6529_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006530
Louis Dionne89258142021-08-23 15:32:36 -04006531 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6532_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006533
Louis Dionne89258142021-08-23 15:32:36 -04006534 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6535_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006536
Louis Dionne89258142021-08-23 15:32:36 -04006537 template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6538_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006539
Louis Dionne89258142021-08-23 15:32:36 -04006540 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6541_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006542
Louis Dionne89258142021-08-23 15:32:36 -04006543 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6544_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006545
Louis Dionne89258142021-08-23 15:32:36 -04006546 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6547_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006548
Louis Dionne89258142021-08-23 15:32:36 -04006549 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6550_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006551
Louis Dionne89258142021-08-23 15:32:36 -04006552 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6553 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6554_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;)
6555_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006556
Louis Dionne89258142021-08-23 15:32:36 -04006557 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6558 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6559_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;)
6560_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006561
Louis Dionne89258142021-08-23 15:32:36 -04006562 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6563_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006564
Louis Dionne89258142021-08-23 15:32:36 -04006565 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6566_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006567
Louis Dionne89258142021-08-23 15:32:36 -04006568 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6569_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006570
Louis Dionne89258142021-08-23 15:32:36 -04006571 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6572_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006573
Louis Dionne89258142021-08-23 15:32:36 -04006574 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6575_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006576
Louis Dionne89258142021-08-23 15:32:36 -04006577 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6578_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006579
Louis Dionne89258142021-08-23 15:32:36 -04006580 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6581_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 -08006582template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6583template 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 -04006584#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006585template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6586template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6587#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006588
Howard Hinnantc51e1022010-05-11 19:42:16 +00006589_LIBCPP_END_NAMESPACE_STD