blob: d5ab8fb3b8367c1ce0226fff40d96a878c79db5a [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantc51e1022010-05-11 19:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
David Chisnall8074c342012-02-29 13:05:08 +00009// On Solaris, we need to define something to make the C99 parts of localeconv
10// visible.
11#ifdef __sun__
12#define _LCONV_C99
13#endif
14
Howard Hinnantc51e1022010-05-11 19:42:16 +000015#include "string"
16#include "locale"
Howard Hinnant7282c5a2010-05-30 21:39:41 +000017#include "codecvt"
Howard Hinnantc51e1022010-05-11 19:42:16 +000018#include "vector"
19#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000020#include "typeinfo"
Howard Hinnant718dae32013-07-28 18:20:00 +000021#ifndef _LIBCPP_NO_EXCEPTIONS
22# include "type_traits"
23#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000024#include "clocale"
25#include "cstring"
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +000026#if defined(_LIBCPP_MSVCRT)
27#define _CTYPE_DISABLE_MACROS
28#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000029#include "cwctype"
Howard Hinnant8ad70912013-09-17 01:34:47 +000030#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Louis Dionne90a04492021-02-02 16:58:38 -050031#include "__support/win32/locale_win32.h"
Xiang Xiao85529232020-11-18 16:16:18 -050032#elif !defined(__BIONIC__) && !defined(__NuttX__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000033#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000034#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000035#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000036#include <stdio.h>
Weiming Zhaob613db72017-09-19 23:18:03 +000037#include "include/atomic_support.h"
Arthur O'Dwyerf5c4bb02021-04-26 09:56:50 -040038#include "include/sso_allocator.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000039#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000040
Marshall Clowab9c1772013-02-07 17:20:56 +000041// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070042// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000043#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000044#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000045#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000046
Howard Hinnantc51e1022010-05-11 19:42:16 +000047_LIBCPP_BEGIN_NAMESPACE_STD
48
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000049struct __libcpp_unique_locale {
50 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
51
52 ~__libcpp_unique_locale() {
53 if (__loc_)
54 freelocale(__loc_);
55 }
56
57 explicit operator bool() const { return __loc_; }
58
59 locale_t& get() { return __loc_; }
60
61 locale_t __loc_;
62private:
63 __libcpp_unique_locale(__libcpp_unique_locale const&);
64 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
65};
66
Howard Hinnantf312e3e2011-09-28 23:39:33 +000067#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000068locale_t __cloc() {
69 // In theory this could create a race condition. In practice
70 // the race condition is non-fatal since it will just create
71 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000072 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
73 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000074}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000075#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000076
Howard Hinnantc51e1022010-05-11 19:42:16 +000077namespace {
78
79struct release
80{
81 void operator()(locale::facet* p) {p->__release_shared();}
82};
83
84template <class T, class A0>
85inline
86T&
87make(A0 a0)
88{
89 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +000090 auto *obj = ::new (&buf) T(a0);
91 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000092}
93
94template <class T, class A0, class A1>
95inline
96T&
97make(A0 a0, A1 a1)
98{
99 static typename aligned_storage<sizeof(T)>::type buf;
100 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000101 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000102}
103
104template <class T, class A0, class A1, class A2>
105inline
106T&
107make(A0 a0, A1 a1, A2 a2)
108{
109 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000110 auto *obj = ::new (&buf) T(a0, a1, a2);
111 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000112}
113
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000114template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000115inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000116_LIBCPP_CONSTEXPR
117size_t
118countof(const T (&)[N])
119{
120 return N;
121}
122
123template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000124inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000125_LIBCPP_CONSTEXPR
126size_t
127countof(const T * const begin, const T * const end)
128{
129 return static_cast<size_t>(end - begin);
130}
131
Marshall Clow8fea1612016-08-25 15:09:01 +0000132_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
133{
134#ifndef _LIBCPP_NO_EXCEPTIONS
135 throw runtime_error(msg);
136#else
137 (void)msg;
138 _VSTD::abort();
139#endif
140}
141
Howard Hinnantc51e1022010-05-11 19:42:16 +0000142}
143
Howard Hinnantdd099492013-08-29 23:37:50 +0000144#if defined(_AIX)
145// Set priority to INT_MIN + 256 + 150
146# pragma priority ( -2147483242 )
147#endif
148
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000149const locale::category locale::none;
150const locale::category locale::collate;
151const locale::category locale::ctype;
152const locale::category locale::monetary;
153const locale::category locale::numeric;
154const locale::category locale::time;
155const locale::category locale::messages;
156const locale::category locale::all;
157
Howard Hinnantc51e1022010-05-11 19:42:16 +0000158class _LIBCPP_HIDDEN locale::__imp
159 : public facet
160{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100161 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000162#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000163// FIXME: MSVC doesn't support aligned parameters by value.
164// I can't get the __sso_allocator to work here
165// for MSVC I think for this reason.
166 vector<facet*> facets_;
167#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000168 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000169#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000170 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000171public:
172 explicit __imp(size_t refs = 0);
173 explicit __imp(const string& name, size_t refs = 0);
174 __imp(const __imp&);
175 __imp(const __imp&, const string&, locale::category c);
176 __imp(const __imp& other, const __imp& one, locale::category c);
177 __imp(const __imp&, facet* f, long id);
178 ~__imp();
179
180 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000181 bool has_facet(long id) const
182 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000183 const locale::facet* use_facet(long id) const;
184
185 static const locale& make_classic();
186 static locale& make_global();
187private:
188 void install(facet* f, long id);
189 template <class F> void install(F* f) {install(f, f->id.__get());}
190 template <class F> void install_from(const __imp& other);
191};
192
193locale::__imp::__imp(size_t refs)
194 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000195 facets_(N),
196 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000197{
198 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000199 install(&make<_VSTD::collate<char> >(1u));
200 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000201 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000202 install(&make<_VSTD::ctype<wchar_t> >(1u));
203 install(&make<codecvt<char, char, mbstate_t> >(1u));
204 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100205_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000206 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
207 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100208_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400209#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100210 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
211 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
212#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000213 install(&make<numpunct<char> >(1u));
214 install(&make<numpunct<wchar_t> >(1u));
215 install(&make<num_get<char> >(1u));
216 install(&make<num_get<wchar_t> >(1u));
217 install(&make<num_put<char> >(1u));
218 install(&make<num_put<wchar_t> >(1u));
219 install(&make<moneypunct<char, false> >(1u));
220 install(&make<moneypunct<char, true> >(1u));
221 install(&make<moneypunct<wchar_t, false> >(1u));
222 install(&make<moneypunct<wchar_t, true> >(1u));
223 install(&make<money_get<char> >(1u));
224 install(&make<money_get<wchar_t> >(1u));
225 install(&make<money_put<char> >(1u));
226 install(&make<money_put<wchar_t> >(1u));
227 install(&make<time_get<char> >(1u));
228 install(&make<time_get<wchar_t> >(1u));
229 install(&make<time_put<char> >(1u));
230 install(&make<time_put<wchar_t> >(1u));
231 install(&make<_VSTD::messages<char> >(1u));
232 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233}
234
235locale::__imp::__imp(const string& name, size_t refs)
236 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000237 facets_(N),
238 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000239{
Howard Hinnant72f73582010-08-11 17:04:31 +0000240#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000241 try
242 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400243#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000244 facets_ = locale::classic().__locale_->facets_;
245 for (unsigned i = 0; i < facets_.size(); ++i)
246 if (facets_[i])
247 facets_[i]->__add_shared();
248 install(new collate_byname<char>(name_));
249 install(new collate_byname<wchar_t>(name_));
250 install(new ctype_byname<char>(name_));
251 install(new ctype_byname<wchar_t>(name_));
252 install(new codecvt_byname<char, char, mbstate_t>(name_));
253 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100254_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000255 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
256 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100257_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400258#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100259 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
260 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
261#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262 install(new numpunct_byname<char>(name_));
263 install(new numpunct_byname<wchar_t>(name_));
264 install(new moneypunct_byname<char, false>(name_));
265 install(new moneypunct_byname<char, true>(name_));
266 install(new moneypunct_byname<wchar_t, false>(name_));
267 install(new moneypunct_byname<wchar_t, true>(name_));
268 install(new time_get_byname<char>(name_));
269 install(new time_get_byname<wchar_t>(name_));
270 install(new time_put_byname<char>(name_));
271 install(new time_put_byname<wchar_t>(name_));
272 install(new messages_byname<char>(name_));
273 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000274#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000275 }
276 catch (...)
277 {
278 for (unsigned i = 0; i < facets_.size(); ++i)
279 if (facets_[i])
280 facets_[i]->__release_shared();
281 throw;
282 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400283#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284}
285
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000286// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000287// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000288#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000289#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000290#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000291#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000292
Howard Hinnantc51e1022010-05-11 19:42:16 +0000293locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000294 : facets_(max<size_t>(N, other.facets_.size())),
295 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000296{
297 facets_ = other.facets_;
298 for (unsigned i = 0; i < facets_.size(); ++i)
299 if (facets_[i])
300 facets_[i]->__add_shared();
301}
302
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000303#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000304#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000305#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000306
Howard Hinnantc51e1022010-05-11 19:42:16 +0000307locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000308 : facets_(N),
309 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000310{
311 facets_ = other.facets_;
312 for (unsigned i = 0; i < facets_.size(); ++i)
313 if (facets_[i])
314 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000315#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000316 try
317 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400318#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000319 if (c & locale::collate)
320 {
321 install(new collate_byname<char>(name));
322 install(new collate_byname<wchar_t>(name));
323 }
324 if (c & locale::ctype)
325 {
326 install(new ctype_byname<char>(name));
327 install(new ctype_byname<wchar_t>(name));
328 install(new codecvt_byname<char, char, mbstate_t>(name));
329 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100330_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000331 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
332 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100333_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400334#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100335 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
336 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
337#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000338 }
339 if (c & locale::monetary)
340 {
341 install(new moneypunct_byname<char, false>(name));
342 install(new moneypunct_byname<char, true>(name));
343 install(new moneypunct_byname<wchar_t, false>(name));
344 install(new moneypunct_byname<wchar_t, true>(name));
345 }
346 if (c & locale::numeric)
347 {
348 install(new numpunct_byname<char>(name));
349 install(new numpunct_byname<wchar_t>(name));
350 }
351 if (c & locale::time)
352 {
353 install(new time_get_byname<char>(name));
354 install(new time_get_byname<wchar_t>(name));
355 install(new time_put_byname<char>(name));
356 install(new time_put_byname<wchar_t>(name));
357 }
358 if (c & locale::messages)
359 {
360 install(new messages_byname<char>(name));
361 install(new messages_byname<wchar_t>(name));
362 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000363#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000364 }
365 catch (...)
366 {
367 for (unsigned i = 0; i < facets_.size(); ++i)
368 if (facets_[i])
369 facets_[i]->__release_shared();
370 throw;
371 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400372#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000373}
374
375template<class F>
376inline
377void
378locale::__imp::install_from(const locale::__imp& one)
379{
380 long id = F::id.__get();
381 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
382}
383
384locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000385 : facets_(N),
386 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000387{
388 facets_ = other.facets_;
389 for (unsigned i = 0; i < facets_.size(); ++i)
390 if (facets_[i])
391 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000392#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000393 try
394 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400395#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000396 if (c & locale::collate)
397 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000398 install_from<_VSTD::collate<char> >(one);
399 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000400 }
401 if (c & locale::ctype)
402 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000403 install_from<_VSTD::ctype<char> >(one);
404 install_from<_VSTD::ctype<wchar_t> >(one);
405 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100406_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000407 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
408 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100409_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400410#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100411 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
412 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
413#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000414 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000415 }
416 if (c & locale::monetary)
417 {
418 install_from<moneypunct<char, false> >(one);
419 install_from<moneypunct<char, true> >(one);
420 install_from<moneypunct<wchar_t, false> >(one);
421 install_from<moneypunct<wchar_t, true> >(one);
422 install_from<money_get<char> >(one);
423 install_from<money_get<wchar_t> >(one);
424 install_from<money_put<char> >(one);
425 install_from<money_put<wchar_t> >(one);
426 }
427 if (c & locale::numeric)
428 {
429 install_from<numpunct<char> >(one);
430 install_from<numpunct<wchar_t> >(one);
431 install_from<num_get<char> >(one);
432 install_from<num_get<wchar_t> >(one);
433 install_from<num_put<char> >(one);
434 install_from<num_put<wchar_t> >(one);
435 }
436 if (c & locale::time)
437 {
438 install_from<time_get<char> >(one);
439 install_from<time_get<wchar_t> >(one);
440 install_from<time_put<char> >(one);
441 install_from<time_put<wchar_t> >(one);
442 }
443 if (c & locale::messages)
444 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000445 install_from<_VSTD::messages<char> >(one);
446 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000447 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000448#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000449 }
450 catch (...)
451 {
452 for (unsigned i = 0; i < facets_.size(); ++i)
453 if (facets_[i])
454 facets_[i]->__release_shared();
455 throw;
456 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400457#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000458}
459
460locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000461 : facets_(max<size_t>(N, other.facets_.size()+1)),
462 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000463{
464 f->__add_shared();
465 unique_ptr<facet, release> hold(f);
466 facets_ = other.facets_;
467 for (unsigned i = 0; i < other.facets_.size(); ++i)
468 if (facets_[i])
469 facets_[i]->__add_shared();
470 install(hold.get(), id);
471}
472
473locale::__imp::~__imp()
474{
475 for (unsigned i = 0; i < facets_.size(); ++i)
476 if (facets_[i])
477 facets_[i]->__release_shared();
478}
479
480void
481locale::__imp::install(facet* f, long id)
482{
483 f->__add_shared();
484 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000485 if (static_cast<size_t>(id) >= facets_.size())
486 facets_.resize(static_cast<size_t>(id+1));
487 if (facets_[static_cast<size_t>(id)])
488 facets_[static_cast<size_t>(id)]->__release_shared();
489 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000490}
491
492const locale::facet*
493locale::__imp::use_facet(long id) const
494{
495 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000496 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000497 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000498}
499
500// locale
501
502const locale&
503locale::__imp::make_classic()
504{
505 // only one thread can get in here and it only gets in once
506 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000507 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000508 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509 return *c;
510}
511
512const locale&
513locale::classic()
514{
515 static const locale& c = __imp::make_classic();
516 return c;
517}
518
519locale&
520locale::__imp::make_global()
521{
522 // only one thread can get in here and it only gets in once
523 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000524 auto *obj = ::new (&buf) locale(locale::classic());
525 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000526}
527
528locale&
529locale::__global()
530{
531 static locale& g = __imp::make_global();
532 return g;
533}
534
Louis Dionne65358e12021-03-01 12:09:45 -0500535locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000536 : __locale_(__global().__locale_)
537{
538 __locale_->__add_shared();
539}
540
Louis Dionne65358e12021-03-01 12:09:45 -0500541locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000542 : __locale_(l.__locale_)
543{
544 __locale_->__add_shared();
545}
546
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000547locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000548{
549 __locale_->__release_shared();
550}
551
552const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500553locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000554{
555 other.__locale_->__add_shared();
556 __locale_->__release_shared();
557 __locale_ = other.__locale_;
558 return *this;
559}
560
561locale::locale(const char* name)
562 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100563 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000564{
565 __locale_->__add_shared();
566}
567
568locale::locale(const string& name)
569 : __locale_(new __imp(name))
570{
571 __locale_->__add_shared();
572}
573
574locale::locale(const locale& other, const char* name, category c)
575 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100576 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000577{
578 __locale_->__add_shared();
579}
580
581locale::locale(const locale& other, const string& name, category c)
582 : __locale_(new __imp(*other.__locale_, name, c))
583{
584 __locale_->__add_shared();
585}
586
587locale::locale(const locale& other, const locale& one, category c)
588 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
589{
590 __locale_->__add_shared();
591}
592
593string
594locale::name() const
595{
596 return __locale_->name();
597}
598
599void
600locale::__install_ctor(const locale& other, facet* f, long id)
601{
602 if (f)
603 __locale_ = new __imp(*other.__locale_, f, id);
604 else
605 __locale_ = other.__locale_;
606 __locale_->__add_shared();
607}
608
609locale
610locale::global(const locale& loc)
611{
612 locale& g = __global();
613 locale r = g;
614 g = loc;
615 if (g.name() != "*")
616 setlocale(LC_ALL, g.name().c_str());
617 return r;
618}
619
620bool
621locale::has_facet(id& x) const
622{
623 return __locale_->has_facet(x.__get());
624}
625
626const locale::facet*
627locale::use_facet(id& x) const
628{
629 return __locale_->use_facet(x.__get());
630}
631
632bool
633locale::operator==(const locale& y) const
634{
635 return (__locale_ == y.__locale_)
636 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
637}
638
639// locale::facet
640
641locale::facet::~facet()
642{
643}
644
645void
Louis Dionne65358e12021-03-01 12:09:45 -0500646locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000647{
648 delete this;
649}
650
651// locale::id
652
653int32_t locale::id::__next_id = 0;
654
655namespace
656{
657
658class __fake_bind
659{
660 locale::id* id_;
661 void (locale::id::* pmf_)();
662public:
663 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
664 : id_(id), pmf_(pmf) {}
665
666 void operator()() const
667 {
668 (id_->*pmf_)();
669 }
670};
671
672}
673
674long
675locale::id::__get()
676{
677 call_once(__flag_, __fake_bind(&locale::id::__init, this));
678 return __id_ - 1;
679}
680
681void
682locale::id::__init()
683{
Weiming Zhaob613db72017-09-19 23:18:03 +0000684 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000685}
686
687// template <> class collate_byname<char>
688
689collate_byname<char>::collate_byname(const char* n, size_t refs)
690 : collate<char>(refs),
691 __l(newlocale(LC_ALL_MASK, n, 0))
692{
693 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000694 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000695 " failed to construct for " + string(n));
696}
697
698collate_byname<char>::collate_byname(const string& name, size_t refs)
699 : collate<char>(refs),
700 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
701{
702 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000703 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000704 " failed to construct for " + name);
705}
706
707collate_byname<char>::~collate_byname()
708{
709 freelocale(__l);
710}
711
712int
713collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
714 const char_type* __lo2, const char_type* __hi2) const
715{
716 string_type lhs(__lo1, __hi1);
717 string_type rhs(__lo2, __hi2);
718 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
719 if (r < 0)
720 return -1;
721 if (r > 0)
722 return 1;
723 return r;
724}
725
726collate_byname<char>::string_type
727collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
728{
729 const string_type in(lo, hi);
730 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
731 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
732 return out;
733}
734
735// template <> class collate_byname<wchar_t>
736
737collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
738 : collate<wchar_t>(refs),
739 __l(newlocale(LC_ALL_MASK, n, 0))
740{
741 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000742 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000743 " failed to construct for " + string(n));
744}
745
746collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
747 : collate<wchar_t>(refs),
748 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
749{
750 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000751 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000752 " failed to construct for " + name);
753}
754
755collate_byname<wchar_t>::~collate_byname()
756{
757 freelocale(__l);
758}
759
760int
761collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
762 const char_type* __lo2, const char_type* __hi2) const
763{
764 string_type lhs(__lo1, __hi1);
765 string_type rhs(__lo2, __hi2);
766 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
767 if (r < 0)
768 return -1;
769 if (r > 0)
770 return 1;
771 return r;
772}
773
774collate_byname<wchar_t>::string_type
775collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
776{
777 const string_type in(lo, hi);
778 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
779 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
780 return out;
781}
782
783// template <> class ctype<wchar_t>;
784
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000785const ctype_base::mask ctype_base::space;
786const ctype_base::mask ctype_base::print;
787const ctype_base::mask ctype_base::cntrl;
788const ctype_base::mask ctype_base::upper;
789const ctype_base::mask ctype_base::lower;
790const ctype_base::mask ctype_base::alpha;
791const ctype_base::mask ctype_base::digit;
792const ctype_base::mask ctype_base::punct;
793const ctype_base::mask ctype_base::xdigit;
794const ctype_base::mask ctype_base::blank;
795const ctype_base::mask ctype_base::alnum;
796const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700797
Howard Hinnantc51e1022010-05-11 19:42:16 +0000798locale::id ctype<wchar_t>::id;
799
800ctype<wchar_t>::~ctype()
801{
802}
803
804bool
805ctype<wchar_t>::do_is(mask m, char_type c) const
806{
Marshall Clowd920eea2013-10-21 15:07:28 +0000807 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000808}
809
810const wchar_t*
811ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
812{
813 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000814 *vec = static_cast<mask>(isascii(*low) ?
815 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000816 return low;
817}
818
819const wchar_t*
820ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
821{
822 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000823 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000824 break;
825 return low;
826}
827
828const wchar_t*
829ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
830{
831 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000832 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000833 break;
834 return low;
835}
836
837wchar_t
838ctype<wchar_t>::do_toupper(char_type c) const
839{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000840#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
841 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000842#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000843 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000844 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000845#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000846 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000847#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000848}
849
850const wchar_t*
851ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
852{
853 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000854#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
855 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000856#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000857 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000858 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
859 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000860#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000861 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000862#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000863 return low;
864}
865
866wchar_t
867ctype<wchar_t>::do_tolower(char_type c) const
868{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000869#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
870 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000871#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000872 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000873 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000874#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000875 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000876#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000877}
878
879const wchar_t*
880ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
881{
882 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000883#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
884 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000885#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000886 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000887 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
888 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000889#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000890 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000891#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000892 return low;
893}
894
895wchar_t
896ctype<wchar_t>::do_widen(char c) const
897{
898 return c;
899}
900
901const char*
902ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
903{
904 for (; low != high; ++low, ++dest)
905 *dest = *low;
906 return low;
907}
908
909char
910ctype<wchar_t>::do_narrow(char_type c, char dfault) const
911{
912 if (isascii(c))
913 return static_cast<char>(c);
914 return dfault;
915}
916
917const wchar_t*
918ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
919{
920 for (; low != high; ++low, ++dest)
921 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000922 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000923 else
924 *dest = dfault;
925 return low;
926}
927
928// template <> class ctype<char>;
929
930locale::id ctype<char>::id;
931
932ctype<char>::ctype(const mask* tab, bool del, size_t refs)
933 : locale::facet(refs),
934 __tab_(tab),
935 __del_(del)
936{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000937 if (__tab_ == 0)
938 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000939}
940
941ctype<char>::~ctype()
942{
943 if (__tab_ && __del_)
944 delete [] __tab_;
945}
946
947char
948ctype<char>::do_toupper(char_type c) const
949{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000950#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000951 return isascii(c) ?
952 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000953#elif defined(__NetBSD__)
954 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000955#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000956 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000957 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000958#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000959 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000960#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000961}
962
963const char*
964ctype<char>::do_toupper(char_type* low, const char_type* high) const
965{
966 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000967#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000968 *low = isascii(*low) ?
969 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000970#elif defined(__NetBSD__)
971 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000972#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000973 *low = isascii(*low) ?
974 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000975#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000976 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000977#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000978 return low;
979}
980
981char
982ctype<char>::do_tolower(char_type c) const
983{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000984#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000985 return isascii(c) ?
986 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000987#elif defined(__NetBSD__)
988 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000989#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000990 return isascii(c) ?
991 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000992#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000993 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000994#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000995}
996
997const char*
998ctype<char>::do_tolower(char_type* low, const char_type* high) const
999{
1000 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001001#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +00001002 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001003#elif defined(__NetBSD__)
1004 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001005#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +00001006 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001007#else
Ed Schouten7c54ead2015-07-06 15:37:40 +00001008 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +00001009#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001010 return low;
1011}
1012
1013char
1014ctype<char>::do_widen(char c) const
1015{
1016 return c;
1017}
1018
1019const char*
1020ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1021{
1022 for (; low != high; ++low, ++dest)
1023 *dest = *low;
1024 return low;
1025}
1026
1027char
1028ctype<char>::do_narrow(char_type c, char dfault) const
1029{
1030 if (isascii(c))
1031 return static_cast<char>(c);
1032 return dfault;
1033}
1034
1035const char*
1036ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1037{
1038 for (; low != high; ++low, ++dest)
1039 if (isascii(*low))
1040 *dest = *low;
1041 else
1042 *dest = dfault;
1043 return low;
1044}
1045
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001046#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001047extern "C" const unsigned short ** __ctype_b_loc();
1048extern "C" const int ** __ctype_tolower_loc();
1049extern "C" const int ** __ctype_toupper_loc();
1050#endif
1051
Marshall Clow8f870232015-03-04 16:50:02 +00001052#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001053const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001054ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001055{
1056 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1057 cntrl, cntrl,
1058 cntrl, cntrl,
1059 cntrl, cntrl,
1060 cntrl, cntrl,
1061 cntrl, cntrl | space | blank,
1062 cntrl | space, cntrl | space,
1063 cntrl | space, cntrl | space,
1064 cntrl, cntrl,
1065 cntrl, cntrl,
1066 cntrl, cntrl,
1067 cntrl, cntrl,
1068 cntrl, cntrl,
1069 cntrl, cntrl,
1070 cntrl, cntrl,
1071 cntrl, cntrl,
1072 cntrl, cntrl,
1073 space | blank | print, punct | print,
1074 punct | print, punct | print,
1075 punct | print, punct | print,
1076 punct | print, punct | print,
1077 punct | print, punct | print,
1078 punct | print, punct | print,
1079 punct | print, punct | print,
1080 punct | print, punct | print,
1081 digit | print | xdigit, digit | print | xdigit,
1082 digit | print | xdigit, digit | print | xdigit,
1083 digit | print | xdigit, digit | print | xdigit,
1084 digit | print | xdigit, digit | print | xdigit,
1085 digit | print | xdigit, digit | print | xdigit,
1086 punct | print, punct | print,
1087 punct | print, punct | print,
1088 punct | print, punct | print,
1089 punct | print, upper | xdigit | print | alpha,
1090 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1091 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1092 upper | xdigit | print | alpha, upper | print | alpha,
1093 upper | print | alpha, upper | print | alpha,
1094 upper | print | alpha, upper | print | alpha,
1095 upper | print | alpha, upper | print | alpha,
1096 upper | print | alpha, upper | print | alpha,
1097 upper | print | alpha, upper | print | alpha,
1098 upper | print | alpha, upper | print | alpha,
1099 upper | print | alpha, upper | print | alpha,
1100 upper | print | alpha, upper | print | alpha,
1101 upper | print | alpha, upper | print | alpha,
1102 upper | print | alpha, punct | print,
1103 punct | print, punct | print,
1104 punct | print, punct | print,
1105 punct | print, lower | xdigit | print | alpha,
1106 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1107 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1108 lower | xdigit | print | alpha, lower | print | alpha,
1109 lower | print | alpha, lower | print | alpha,
1110 lower | print | alpha, lower | print | alpha,
1111 lower | print | alpha, lower | print | alpha,
1112 lower | print | alpha, lower | print | alpha,
1113 lower | print | alpha, lower | print | alpha,
1114 lower | print | alpha, lower | print | alpha,
1115 lower | print | alpha, lower | print | alpha,
1116 lower | print | alpha, lower | print | alpha,
1117 lower | print | alpha, lower | print | alpha,
1118 lower | print | alpha, punct | print,
1119 punct | print, punct | print,
1120 punct | print, cntrl,
1121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1129 };
1130 return builtin_table;
1131}
1132#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001133const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001134ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001135{
David Chisnall1d581062011-09-21 08:39:44 +00001136#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001137 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001138#elif defined(__NetBSD__)
1139 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001140#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001141 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001142#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001143 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001144#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001145 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001146#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001147 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001148#elif defined(_NEWLIB_VERSION)
1149 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1150 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001151#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001152 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001153#else
David Chisnall8074c342012-02-29 13:05:08 +00001154 // Platform not supported: abort so the person doing the port knows what to
1155 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001156# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001157 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001158 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001159 return NULL;
1160#endif
1161}
Marshall Clowb3f62842015-03-04 16:10:14 +00001162#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001163
Howard Hinnantd7a78632011-09-29 13:33:15 +00001164#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001165const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001166ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001167{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001168 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001169}
1170
1171const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001172ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001173{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001174 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001175}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001176#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001177const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001178ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001179{
1180 return _C_tolower_tab_ + 1;
1181}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001182
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001183const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001184ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001185{
1186 return _C_toupper_tab_ + 1;
1187}
1188
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001189#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001190const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001191ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001192{
1193 return *__ctype_tolower_loc();
1194}
1195
1196const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001197ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001198{
1199 return *__ctype_toupper_loc();
1200}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001201#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001202
Howard Hinnantc51e1022010-05-11 19:42:16 +00001203// template <> class ctype_byname<char>
1204
1205ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1206 : ctype<char>(0, false, refs),
1207 __l(newlocale(LC_ALL_MASK, name, 0))
1208{
1209 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001210 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001211 " failed to construct for " + string(name));
1212}
1213
1214ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1215 : ctype<char>(0, false, refs),
1216 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1217{
1218 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001219 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001220 " failed to construct for " + name);
1221}
1222
1223ctype_byname<char>::~ctype_byname()
1224{
1225 freelocale(__l);
1226}
1227
1228char
1229ctype_byname<char>::do_toupper(char_type c) const
1230{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001231 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001232}
1233
1234const char*
1235ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1236{
1237 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001238 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001239 return low;
1240}
1241
1242char
1243ctype_byname<char>::do_tolower(char_type c) const
1244{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001245 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001246}
1247
1248const char*
1249ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1250{
1251 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001252 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001253 return low;
1254}
1255
1256// template <> class ctype_byname<wchar_t>
1257
1258ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1259 : ctype<wchar_t>(refs),
1260 __l(newlocale(LC_ALL_MASK, name, 0))
1261{
1262 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001263 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001264 " failed to construct for " + string(name));
1265}
1266
1267ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1268 : ctype<wchar_t>(refs),
1269 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1270{
1271 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001272 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001273 " failed to construct for " + name);
1274}
1275
1276ctype_byname<wchar_t>::~ctype_byname()
1277{
1278 freelocale(__l);
1279}
1280
1281bool
1282ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1283{
Alexis Huntc2017f12011-07-09 03:40:04 +00001284#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001285 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001286#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001287 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001288 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001289 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1290 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1291 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1292 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1293 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1294 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1295 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1296 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1297 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1298 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001299 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001300#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301}
1302
1303const wchar_t*
1304ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1305{
1306 for (; low != high; ++low, ++vec)
1307 {
1308 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001309 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001310 else
1311 {
1312 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001313 wint_t ch = static_cast<wint_t>(*low);
1314 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001315 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001316#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001317 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001318 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001319#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001320 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001322 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001323 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001324 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001325 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001326#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001327 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001328 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001329#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001330 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001331 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001332 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001333 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001334#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001335 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001336 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001337#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001338#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001339 if (iswblank_l(ch, __l))
1340 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001341#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001342 }
1343 }
1344 return low;
1345}
1346
1347const wchar_t*
1348ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1349{
1350 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001351 {
1352#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001353 if (iswctype_l(*low, m, __l))
1354 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001355#else
Marshall Clowada0f732013-02-07 14:22:51 +00001356 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001357 if ((m & space) == space && iswspace_l(ch, __l)) break;
1358 if ((m & print) == print && iswprint_l(ch, __l)) break;
1359 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1360 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1361 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1362 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1363 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1364 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1365 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1366 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001367#endif
1368 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001369 return low;
1370}
1371
1372const wchar_t*
1373ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1374{
1375 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001376 {
1377#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001378 if (!iswctype_l(*low, m, __l))
1379 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001380#else
Marshall Clowada0f732013-02-07 14:22:51 +00001381 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001382 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1383 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1384 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1385 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1386 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1387 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1388 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1389 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1390 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1391 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001392 break;
1393#endif
1394 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001395 return low;
1396}
1397
1398wchar_t
1399ctype_byname<wchar_t>::do_toupper(char_type c) const
1400{
1401 return towupper_l(c, __l);
1402}
1403
1404const wchar_t*
1405ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1406{
1407 for (; low != high; ++low)
1408 *low = towupper_l(*low, __l);
1409 return low;
1410}
1411
1412wchar_t
1413ctype_byname<wchar_t>::do_tolower(char_type c) const
1414{
1415 return towlower_l(c, __l);
1416}
1417
1418const wchar_t*
1419ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1420{
1421 for (; low != high; ++low)
1422 *low = towlower_l(*low, __l);
1423 return low;
1424}
1425
1426wchar_t
1427ctype_byname<wchar_t>::do_widen(char c) const
1428{
Ben Craig3756b922016-03-09 15:39:39 +00001429 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001430}
1431
1432const char*
1433ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1434{
1435 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001436 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001437 return low;
1438}
1439
1440char
1441ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1442{
Ben Craig3756b922016-03-09 15:39:39 +00001443 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001444 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001445}
1446
1447const wchar_t*
1448ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1449{
1450 for (; low != high; ++low, ++dest)
1451 {
Ben Craig3756b922016-03-09 15:39:39 +00001452 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001453 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001454 }
1455 return low;
1456}
1457
1458// template <> class codecvt<char, char, mbstate_t>
1459
Howard Hinnantffb308e2010-08-22 00:03:27 +00001460locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001461
1462codecvt<char, char, mbstate_t>::~codecvt()
1463{
1464}
1465
1466codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001467codecvt<char, char, mbstate_t>::do_out(state_type&,
1468 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001469 extern_type* to, extern_type*, extern_type*& to_nxt) const
1470{
1471 frm_nxt = frm;
1472 to_nxt = to;
1473 return noconv;
1474}
1475
1476codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001477codecvt<char, char, mbstate_t>::do_in(state_type&,
1478 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001479 intern_type* to, intern_type*, intern_type*& to_nxt) const
1480{
1481 frm_nxt = frm;
1482 to_nxt = to;
1483 return noconv;
1484}
1485
1486codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001487codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001488 extern_type* to, extern_type*, extern_type*& to_nxt) const
1489{
1490 to_nxt = to;
1491 return noconv;
1492}
1493
1494int
Louis Dionne65358e12021-03-01 12:09:45 -05001495codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001496{
1497 return 1;
1498}
1499
1500bool
Louis Dionne65358e12021-03-01 12:09:45 -05001501codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001502{
1503 return true;
1504}
1505
1506int
1507codecvt<char, char, mbstate_t>::do_length(state_type&,
1508 const extern_type* frm, const extern_type* end, size_t mx) const
1509{
Howard Hinnant28b24882011-12-01 20:21:04 +00001510 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001511}
1512
1513int
Louis Dionne65358e12021-03-01 12:09:45 -05001514codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001515{
1516 return 1;
1517}
1518
1519// template <> class codecvt<wchar_t, char, mbstate_t>
1520
Howard Hinnantffb308e2010-08-22 00:03:27 +00001521locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001522
1523codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1524 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001525 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526{
1527}
1528
1529codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1530 : locale::facet(refs),
1531 __l(newlocale(LC_ALL_MASK, nm, 0))
1532{
1533 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001534 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001535 " failed to construct for " + string(nm));
1536}
1537
1538codecvt<wchar_t, char, mbstate_t>::~codecvt()
1539{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001540 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001541 freelocale(__l);
1542}
1543
1544codecvt<wchar_t, char, mbstate_t>::result
1545codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001546 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001547 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1548{
1549 // look for first internal null in frm
1550 const intern_type* fend = frm;
1551 for (; fend != frm_end; ++fend)
1552 if (*fend == 0)
1553 break;
1554 // loop over all null-terminated sequences in frm
1555 to_nxt = to;
1556 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1557 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001558 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001559 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001560 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1561 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001562 if (n == size_t(-1))
1563 {
1564 // need to recover to_nxt
1565 for (to_nxt = to; frm != frm_nxt; ++frm)
1566 {
Ben Craig3756b922016-03-09 15:39:39 +00001567 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001568 if (n == size_t(-1))
1569 break;
1570 to_nxt += n;
1571 }
1572 frm_nxt = frm;
1573 return error;
1574 }
1575 if (n == 0)
1576 return partial;
1577 to_nxt += n;
1578 if (to_nxt == to_end)
1579 break;
1580 if (fend != frm_end) // set up next null terminated sequence
1581 {
1582 // Try to write the terminating null
1583 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001584 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001585 if (n == size_t(-1)) // on error
1586 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001587 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001588 return partial;
1589 for (extern_type* p = tmp; n; --n) // write it
1590 *to_nxt++ = *p++;
1591 ++frm_nxt;
1592 // look for next null in frm
1593 for (fend = frm_nxt; fend != frm_end; ++fend)
1594 if (*fend == 0)
1595 break;
1596 }
1597 }
1598 return frm_nxt == frm_end ? ok : partial;
1599}
1600
1601codecvt<wchar_t, char, mbstate_t>::result
1602codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001603 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001604 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1605{
1606 // look for first internal null in frm
1607 const extern_type* fend = frm;
1608 for (; fend != frm_end; ++fend)
1609 if (*fend == 0)
1610 break;
1611 // loop over all null-terminated sequences in frm
1612 to_nxt = to;
1613 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1614 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001615 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001616 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001617 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1618 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001619 if (n == size_t(-1))
1620 {
1621 // need to recover to_nxt
1622 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1623 {
Ben Craig3756b922016-03-09 15:39:39 +00001624 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1625 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001626 switch (n)
1627 {
1628 case 0:
1629 ++frm;
1630 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001631 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001632 frm_nxt = frm;
1633 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001634 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001635 frm_nxt = frm;
1636 return partial;
1637 default:
1638 frm += n;
1639 break;
1640 }
1641 }
1642 frm_nxt = frm;
1643 return frm_nxt == frm_end ? ok : partial;
1644 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001645 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001646 return error;
1647 to_nxt += n;
1648 if (to_nxt == to_end)
1649 break;
1650 if (fend != frm_end) // set up next null terminated sequence
1651 {
1652 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001653 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001654 if (n != 0) // on error
1655 return error;
1656 ++to_nxt;
1657 ++frm_nxt;
1658 // look for next null in frm
1659 for (fend = frm_nxt; fend != frm_end; ++fend)
1660 if (*fend == 0)
1661 break;
1662 }
1663 }
1664 return frm_nxt == frm_end ? ok : partial;
1665}
1666
1667codecvt<wchar_t, char, mbstate_t>::result
1668codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1669 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1670{
1671 to_nxt = to;
1672 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001673 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001674 if (n == size_t(-1) || n == 0) // on error
1675 return error;
1676 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001677 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001678 return partial;
1679 for (extern_type* p = tmp; n; --n) // write it
1680 *to_nxt++ = *p++;
1681 return ok;
1682}
1683
1684int
Louis Dionne65358e12021-03-01 12:09:45 -05001685codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001686{
Ben Craig3756b922016-03-09 15:39:39 +00001687 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001688 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001689
1690 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001691 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001692 return 1; // which take more than 1 char to form a wchar_t
1693 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001694}
1695
1696bool
Louis Dionne65358e12021-03-01 12:09:45 -05001697codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001698{
1699 return false;
1700}
1701
1702int
1703codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1704 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1705{
1706 int nbytes = 0;
1707 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1708 {
Ben Craig3756b922016-03-09 15:39:39 +00001709 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001710 switch (n)
1711 {
1712 case 0:
1713 ++nbytes;
1714 ++frm;
1715 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001716 case size_t(-1):
1717 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001718 return nbytes;
1719 default:
1720 nbytes += n;
1721 frm += n;
1722 break;
1723 }
1724 }
1725 return nbytes;
1726}
1727
1728int
Louis Dionne65358e12021-03-01 12:09:45 -05001729codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001730{
Ben Craig3756b922016-03-09 15:39:39 +00001731 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001732}
1733
1734// Valid UTF ranges
1735// UTF-32 UTF-16 UTF-8 # of code points
1736// first second first second third fourth
1737// 000000 - 00007F 0000 - 007F 00 - 7F 127
1738// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1739// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1740// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1741// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1742// 00D800 - 00DFFF invalid
1743// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1744// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1745// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1746// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1747
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001748static
1749codecvt_base::result
1750utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1751 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1752 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1753{
1754 frm_nxt = frm;
1755 to_nxt = to;
1756 if (mode & generate_header)
1757 {
1758 if (to_end-to_nxt < 3)
1759 return codecvt_base::partial;
1760 *to_nxt++ = static_cast<uint8_t>(0xEF);
1761 *to_nxt++ = static_cast<uint8_t>(0xBB);
1762 *to_nxt++ = static_cast<uint8_t>(0xBF);
1763 }
1764 for (; frm_nxt < frm_end; ++frm_nxt)
1765 {
1766 uint16_t wc1 = *frm_nxt;
1767 if (wc1 > Maxcode)
1768 return codecvt_base::error;
1769 if (wc1 < 0x0080)
1770 {
1771 if (to_end-to_nxt < 1)
1772 return codecvt_base::partial;
1773 *to_nxt++ = static_cast<uint8_t>(wc1);
1774 }
1775 else if (wc1 < 0x0800)
1776 {
1777 if (to_end-to_nxt < 2)
1778 return codecvt_base::partial;
1779 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1780 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1781 }
1782 else if (wc1 < 0xD800)
1783 {
1784 if (to_end-to_nxt < 3)
1785 return codecvt_base::partial;
1786 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1787 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1788 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1789 }
1790 else if (wc1 < 0xDC00)
1791 {
1792 if (frm_end-frm_nxt < 2)
1793 return codecvt_base::partial;
1794 uint16_t wc2 = frm_nxt[1];
1795 if ((wc2 & 0xFC00) != 0xDC00)
1796 return codecvt_base::error;
1797 if (to_end-to_nxt < 4)
1798 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001799 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1800 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001801 return codecvt_base::error;
1802 ++frm_nxt;
1803 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1804 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1805 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1806 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1807 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1808 }
1809 else if (wc1 < 0xE000)
1810 {
1811 return codecvt_base::error;
1812 }
1813 else
1814 {
1815 if (to_end-to_nxt < 3)
1816 return codecvt_base::partial;
1817 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1818 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1819 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1820 }
1821 }
1822 return codecvt_base::ok;
1823}
1824
1825static
1826codecvt_base::result
1827utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1828 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1829 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1830{
1831 frm_nxt = frm;
1832 to_nxt = to;
1833 if (mode & generate_header)
1834 {
1835 if (to_end-to_nxt < 3)
1836 return codecvt_base::partial;
1837 *to_nxt++ = static_cast<uint8_t>(0xEF);
1838 *to_nxt++ = static_cast<uint8_t>(0xBB);
1839 *to_nxt++ = static_cast<uint8_t>(0xBF);
1840 }
1841 for (; frm_nxt < frm_end; ++frm_nxt)
1842 {
1843 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1844 if (wc1 > Maxcode)
1845 return codecvt_base::error;
1846 if (wc1 < 0x0080)
1847 {
1848 if (to_end-to_nxt < 1)
1849 return codecvt_base::partial;
1850 *to_nxt++ = static_cast<uint8_t>(wc1);
1851 }
1852 else if (wc1 < 0x0800)
1853 {
1854 if (to_end-to_nxt < 2)
1855 return codecvt_base::partial;
1856 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1857 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1858 }
1859 else if (wc1 < 0xD800)
1860 {
1861 if (to_end-to_nxt < 3)
1862 return codecvt_base::partial;
1863 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1864 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1865 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1866 }
1867 else if (wc1 < 0xDC00)
1868 {
1869 if (frm_end-frm_nxt < 2)
1870 return codecvt_base::partial;
1871 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1872 if ((wc2 & 0xFC00) != 0xDC00)
1873 return codecvt_base::error;
1874 if (to_end-to_nxt < 4)
1875 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001876 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1877 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001878 return codecvt_base::error;
1879 ++frm_nxt;
1880 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1881 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1882 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1883 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1884 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1885 }
1886 else if (wc1 < 0xE000)
1887 {
1888 return codecvt_base::error;
1889 }
1890 else
1891 {
1892 if (to_end-to_nxt < 3)
1893 return codecvt_base::partial;
1894 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1895 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1896 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1897 }
1898 }
1899 return codecvt_base::ok;
1900}
1901
1902static
1903codecvt_base::result
1904utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1905 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1906 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1907{
1908 frm_nxt = frm;
1909 to_nxt = to;
1910 if (mode & consume_header)
1911 {
1912 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1913 frm_nxt[2] == 0xBF)
1914 frm_nxt += 3;
1915 }
1916 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1917 {
1918 uint8_t c1 = *frm_nxt;
1919 if (c1 > Maxcode)
1920 return codecvt_base::error;
1921 if (c1 < 0x80)
1922 {
1923 *to_nxt = static_cast<uint16_t>(c1);
1924 ++frm_nxt;
1925 }
1926 else if (c1 < 0xC2)
1927 {
1928 return codecvt_base::error;
1929 }
1930 else if (c1 < 0xE0)
1931 {
1932 if (frm_end-frm_nxt < 2)
1933 return codecvt_base::partial;
1934 uint8_t c2 = frm_nxt[1];
1935 if ((c2 & 0xC0) != 0x80)
1936 return codecvt_base::error;
1937 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1938 if (t > Maxcode)
1939 return codecvt_base::error;
1940 *to_nxt = t;
1941 frm_nxt += 2;
1942 }
1943 else if (c1 < 0xF0)
1944 {
1945 if (frm_end-frm_nxt < 3)
1946 return codecvt_base::partial;
1947 uint8_t c2 = frm_nxt[1];
1948 uint8_t c3 = frm_nxt[2];
1949 switch (c1)
1950 {
1951 case 0xE0:
1952 if ((c2 & 0xE0) != 0xA0)
1953 return codecvt_base::error;
1954 break;
1955 case 0xED:
1956 if ((c2 & 0xE0) != 0x80)
1957 return codecvt_base::error;
1958 break;
1959 default:
1960 if ((c2 & 0xC0) != 0x80)
1961 return codecvt_base::error;
1962 break;
1963 }
1964 if ((c3 & 0xC0) != 0x80)
1965 return codecvt_base::error;
1966 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1967 | ((c2 & 0x3F) << 6)
1968 | (c3 & 0x3F));
1969 if (t > Maxcode)
1970 return codecvt_base::error;
1971 *to_nxt = t;
1972 frm_nxt += 3;
1973 }
1974 else if (c1 < 0xF5)
1975 {
1976 if (frm_end-frm_nxt < 4)
1977 return codecvt_base::partial;
1978 uint8_t c2 = frm_nxt[1];
1979 uint8_t c3 = frm_nxt[2];
1980 uint8_t c4 = frm_nxt[3];
1981 switch (c1)
1982 {
1983 case 0xF0:
1984 if (!(0x90 <= c2 && c2 <= 0xBF))
1985 return codecvt_base::error;
1986 break;
1987 case 0xF4:
1988 if ((c2 & 0xF0) != 0x80)
1989 return codecvt_base::error;
1990 break;
1991 default:
1992 if ((c2 & 0xC0) != 0x80)
1993 return codecvt_base::error;
1994 break;
1995 }
1996 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1997 return codecvt_base::error;
1998 if (to_end-to_nxt < 2)
1999 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002000 if ((((c1 & 7UL) << 18) +
2001 ((c2 & 0x3FUL) << 12) +
2002 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002003 return codecvt_base::error;
2004 *to_nxt = static_cast<uint16_t>(
2005 0xD800
2006 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2007 | ((c2 & 0x0F) << 2)
2008 | ((c3 & 0x30) >> 4));
2009 *++to_nxt = static_cast<uint16_t>(
2010 0xDC00
2011 | ((c3 & 0x0F) << 6)
2012 | (c4 & 0x3F));
2013 frm_nxt += 4;
2014 }
2015 else
2016 {
2017 return codecvt_base::error;
2018 }
2019 }
2020 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2021}
2022
2023static
2024codecvt_base::result
2025utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2026 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2027 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2028{
2029 frm_nxt = frm;
2030 to_nxt = to;
2031 if (mode & consume_header)
2032 {
2033 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2034 frm_nxt[2] == 0xBF)
2035 frm_nxt += 3;
2036 }
2037 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2038 {
2039 uint8_t c1 = *frm_nxt;
2040 if (c1 > Maxcode)
2041 return codecvt_base::error;
2042 if (c1 < 0x80)
2043 {
2044 *to_nxt = static_cast<uint32_t>(c1);
2045 ++frm_nxt;
2046 }
2047 else if (c1 < 0xC2)
2048 {
2049 return codecvt_base::error;
2050 }
2051 else if (c1 < 0xE0)
2052 {
2053 if (frm_end-frm_nxt < 2)
2054 return codecvt_base::partial;
2055 uint8_t c2 = frm_nxt[1];
2056 if ((c2 & 0xC0) != 0x80)
2057 return codecvt_base::error;
2058 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2059 if (t > Maxcode)
2060 return codecvt_base::error;
2061 *to_nxt = static_cast<uint32_t>(t);
2062 frm_nxt += 2;
2063 }
2064 else if (c1 < 0xF0)
2065 {
2066 if (frm_end-frm_nxt < 3)
2067 return codecvt_base::partial;
2068 uint8_t c2 = frm_nxt[1];
2069 uint8_t c3 = frm_nxt[2];
2070 switch (c1)
2071 {
2072 case 0xE0:
2073 if ((c2 & 0xE0) != 0xA0)
2074 return codecvt_base::error;
2075 break;
2076 case 0xED:
2077 if ((c2 & 0xE0) != 0x80)
2078 return codecvt_base::error;
2079 break;
2080 default:
2081 if ((c2 & 0xC0) != 0x80)
2082 return codecvt_base::error;
2083 break;
2084 }
2085 if ((c3 & 0xC0) != 0x80)
2086 return codecvt_base::error;
2087 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2088 | ((c2 & 0x3F) << 6)
2089 | (c3 & 0x3F));
2090 if (t > Maxcode)
2091 return codecvt_base::error;
2092 *to_nxt = static_cast<uint32_t>(t);
2093 frm_nxt += 3;
2094 }
2095 else if (c1 < 0xF5)
2096 {
2097 if (frm_end-frm_nxt < 4)
2098 return codecvt_base::partial;
2099 uint8_t c2 = frm_nxt[1];
2100 uint8_t c3 = frm_nxt[2];
2101 uint8_t c4 = frm_nxt[3];
2102 switch (c1)
2103 {
2104 case 0xF0:
2105 if (!(0x90 <= c2 && c2 <= 0xBF))
2106 return codecvt_base::error;
2107 break;
2108 case 0xF4:
2109 if ((c2 & 0xF0) != 0x80)
2110 return codecvt_base::error;
2111 break;
2112 default:
2113 if ((c2 & 0xC0) != 0x80)
2114 return codecvt_base::error;
2115 break;
2116 }
2117 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2118 return codecvt_base::error;
2119 if (to_end-to_nxt < 2)
2120 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002121 if ((((c1 & 7UL) << 18) +
2122 ((c2 & 0x3FUL) << 12) +
2123 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002124 return codecvt_base::error;
2125 *to_nxt = static_cast<uint32_t>(
2126 0xD800
2127 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2128 | ((c2 & 0x0F) << 2)
2129 | ((c3 & 0x30) >> 4));
2130 *++to_nxt = static_cast<uint32_t>(
2131 0xDC00
2132 | ((c3 & 0x0F) << 6)
2133 | (c4 & 0x3F));
2134 frm_nxt += 4;
2135 }
2136 else
2137 {
2138 return codecvt_base::error;
2139 }
2140 }
2141 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2142}
2143
2144static
2145int
2146utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2147 size_t mx, unsigned long Maxcode = 0x10FFFF,
2148 codecvt_mode mode = codecvt_mode(0))
2149{
2150 const uint8_t* frm_nxt = frm;
2151 if (mode & consume_header)
2152 {
2153 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2154 frm_nxt[2] == 0xBF)
2155 frm_nxt += 3;
2156 }
2157 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2158 {
2159 uint8_t c1 = *frm_nxt;
2160 if (c1 > Maxcode)
2161 break;
2162 if (c1 < 0x80)
2163 {
2164 ++frm_nxt;
2165 }
2166 else if (c1 < 0xC2)
2167 {
2168 break;
2169 }
2170 else if (c1 < 0xE0)
2171 {
2172 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2173 break;
2174 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2175 if (t > Maxcode)
2176 break;
2177 frm_nxt += 2;
2178 }
2179 else if (c1 < 0xF0)
2180 {
2181 if (frm_end-frm_nxt < 3)
2182 break;
2183 uint8_t c2 = frm_nxt[1];
2184 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002185 switch (c1)
2186 {
2187 case 0xE0:
2188 if ((c2 & 0xE0) != 0xA0)
2189 return static_cast<int>(frm_nxt - frm);
2190 break;
2191 case 0xED:
2192 if ((c2 & 0xE0) != 0x80)
2193 return static_cast<int>(frm_nxt - frm);
2194 break;
2195 default:
2196 if ((c2 & 0xC0) != 0x80)
2197 return static_cast<int>(frm_nxt - frm);
2198 break;
2199 }
2200 if ((c3 & 0xC0) != 0x80)
2201 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002202 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002203 break;
2204 frm_nxt += 3;
2205 }
2206 else if (c1 < 0xF5)
2207 {
2208 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2209 break;
2210 uint8_t c2 = frm_nxt[1];
2211 uint8_t c3 = frm_nxt[2];
2212 uint8_t c4 = frm_nxt[3];
2213 switch (c1)
2214 {
2215 case 0xF0:
2216 if (!(0x90 <= c2 && c2 <= 0xBF))
2217 return static_cast<int>(frm_nxt - frm);
2218 break;
2219 case 0xF4:
2220 if ((c2 & 0xF0) != 0x80)
2221 return static_cast<int>(frm_nxt - frm);
2222 break;
2223 default:
2224 if ((c2 & 0xC0) != 0x80)
2225 return static_cast<int>(frm_nxt - frm);
2226 break;
2227 }
2228 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2229 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002230 if ((((c1 & 7UL) << 18) +
2231 ((c2 & 0x3FUL) << 12) +
2232 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002233 break;
2234 ++nchar16_t;
2235 frm_nxt += 4;
2236 }
2237 else
2238 {
2239 break;
2240 }
2241 }
2242 return static_cast<int>(frm_nxt - frm);
2243}
2244
2245static
2246codecvt_base::result
2247ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2248 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2249 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2250{
2251 frm_nxt = frm;
2252 to_nxt = to;
2253 if (mode & generate_header)
2254 {
2255 if (to_end-to_nxt < 3)
2256 return codecvt_base::partial;
2257 *to_nxt++ = static_cast<uint8_t>(0xEF);
2258 *to_nxt++ = static_cast<uint8_t>(0xBB);
2259 *to_nxt++ = static_cast<uint8_t>(0xBF);
2260 }
2261 for (; frm_nxt < frm_end; ++frm_nxt)
2262 {
2263 uint32_t wc = *frm_nxt;
2264 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2265 return codecvt_base::error;
2266 if (wc < 0x000080)
2267 {
2268 if (to_end-to_nxt < 1)
2269 return codecvt_base::partial;
2270 *to_nxt++ = static_cast<uint8_t>(wc);
2271 }
2272 else if (wc < 0x000800)
2273 {
2274 if (to_end-to_nxt < 2)
2275 return codecvt_base::partial;
2276 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2277 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2278 }
2279 else if (wc < 0x010000)
2280 {
2281 if (to_end-to_nxt < 3)
2282 return codecvt_base::partial;
2283 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2284 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2285 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2286 }
2287 else // if (wc < 0x110000)
2288 {
2289 if (to_end-to_nxt < 4)
2290 return codecvt_base::partial;
2291 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2292 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2293 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2294 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2295 }
2296 }
2297 return codecvt_base::ok;
2298}
2299
2300static
2301codecvt_base::result
2302utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2303 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2304 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2305{
2306 frm_nxt = frm;
2307 to_nxt = to;
2308 if (mode & consume_header)
2309 {
2310 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2311 frm_nxt[2] == 0xBF)
2312 frm_nxt += 3;
2313 }
2314 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2315 {
2316 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2317 if (c1 < 0x80)
2318 {
2319 if (c1 > Maxcode)
2320 return codecvt_base::error;
2321 *to_nxt = static_cast<uint32_t>(c1);
2322 ++frm_nxt;
2323 }
2324 else if (c1 < 0xC2)
2325 {
2326 return codecvt_base::error;
2327 }
2328 else if (c1 < 0xE0)
2329 {
2330 if (frm_end-frm_nxt < 2)
2331 return codecvt_base::partial;
2332 uint8_t c2 = frm_nxt[1];
2333 if ((c2 & 0xC0) != 0x80)
2334 return codecvt_base::error;
2335 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2336 | (c2 & 0x3F));
2337 if (t > Maxcode)
2338 return codecvt_base::error;
2339 *to_nxt = t;
2340 frm_nxt += 2;
2341 }
2342 else if (c1 < 0xF0)
2343 {
2344 if (frm_end-frm_nxt < 3)
2345 return codecvt_base::partial;
2346 uint8_t c2 = frm_nxt[1];
2347 uint8_t c3 = frm_nxt[2];
2348 switch (c1)
2349 {
2350 case 0xE0:
2351 if ((c2 & 0xE0) != 0xA0)
2352 return codecvt_base::error;
2353 break;
2354 case 0xED:
2355 if ((c2 & 0xE0) != 0x80)
2356 return codecvt_base::error;
2357 break;
2358 default:
2359 if ((c2 & 0xC0) != 0x80)
2360 return codecvt_base::error;
2361 break;
2362 }
2363 if ((c3 & 0xC0) != 0x80)
2364 return codecvt_base::error;
2365 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2366 | ((c2 & 0x3F) << 6)
2367 | (c3 & 0x3F));
2368 if (t > Maxcode)
2369 return codecvt_base::error;
2370 *to_nxt = t;
2371 frm_nxt += 3;
2372 }
2373 else if (c1 < 0xF5)
2374 {
2375 if (frm_end-frm_nxt < 4)
2376 return codecvt_base::partial;
2377 uint8_t c2 = frm_nxt[1];
2378 uint8_t c3 = frm_nxt[2];
2379 uint8_t c4 = frm_nxt[3];
2380 switch (c1)
2381 {
2382 case 0xF0:
2383 if (!(0x90 <= c2 && c2 <= 0xBF))
2384 return codecvt_base::error;
2385 break;
2386 case 0xF4:
2387 if ((c2 & 0xF0) != 0x80)
2388 return codecvt_base::error;
2389 break;
2390 default:
2391 if ((c2 & 0xC0) != 0x80)
2392 return codecvt_base::error;
2393 break;
2394 }
2395 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2396 return codecvt_base::error;
2397 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2398 | ((c2 & 0x3F) << 12)
2399 | ((c3 & 0x3F) << 6)
2400 | (c4 & 0x3F));
2401 if (t > Maxcode)
2402 return codecvt_base::error;
2403 *to_nxt = t;
2404 frm_nxt += 4;
2405 }
2406 else
2407 {
2408 return codecvt_base::error;
2409 }
2410 }
2411 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2412}
2413
2414static
2415int
2416utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2417 size_t mx, unsigned long Maxcode = 0x10FFFF,
2418 codecvt_mode mode = codecvt_mode(0))
2419{
2420 const uint8_t* frm_nxt = frm;
2421 if (mode & consume_header)
2422 {
2423 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2424 frm_nxt[2] == 0xBF)
2425 frm_nxt += 3;
2426 }
2427 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2428 {
2429 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2430 if (c1 < 0x80)
2431 {
2432 if (c1 > Maxcode)
2433 break;
2434 ++frm_nxt;
2435 }
2436 else if (c1 < 0xC2)
2437 {
2438 break;
2439 }
2440 else if (c1 < 0xE0)
2441 {
2442 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2443 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002444 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002445 break;
2446 frm_nxt += 2;
2447 }
2448 else if (c1 < 0xF0)
2449 {
2450 if (frm_end-frm_nxt < 3)
2451 break;
2452 uint8_t c2 = frm_nxt[1];
2453 uint8_t c3 = frm_nxt[2];
2454 switch (c1)
2455 {
2456 case 0xE0:
2457 if ((c2 & 0xE0) != 0xA0)
2458 return static_cast<int>(frm_nxt - frm);
2459 break;
2460 case 0xED:
2461 if ((c2 & 0xE0) != 0x80)
2462 return static_cast<int>(frm_nxt - frm);
2463 break;
2464 default:
2465 if ((c2 & 0xC0) != 0x80)
2466 return static_cast<int>(frm_nxt - frm);
2467 break;
2468 }
2469 if ((c3 & 0xC0) != 0x80)
2470 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002471 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002472 break;
2473 frm_nxt += 3;
2474 }
2475 else if (c1 < 0xF5)
2476 {
2477 if (frm_end-frm_nxt < 4)
2478 break;
2479 uint8_t c2 = frm_nxt[1];
2480 uint8_t c3 = frm_nxt[2];
2481 uint8_t c4 = frm_nxt[3];
2482 switch (c1)
2483 {
2484 case 0xF0:
2485 if (!(0x90 <= c2 && c2 <= 0xBF))
2486 return static_cast<int>(frm_nxt - frm);
2487 break;
2488 case 0xF4:
2489 if ((c2 & 0xF0) != 0x80)
2490 return static_cast<int>(frm_nxt - frm);
2491 break;
2492 default:
2493 if ((c2 & 0xC0) != 0x80)
2494 return static_cast<int>(frm_nxt - frm);
2495 break;
2496 }
2497 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2498 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002499 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2500 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002501 break;
2502 frm_nxt += 4;
2503 }
2504 else
2505 {
2506 break;
2507 }
2508 }
2509 return static_cast<int>(frm_nxt - frm);
2510}
2511
2512static
2513codecvt_base::result
2514ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2515 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2516 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2517{
2518 frm_nxt = frm;
2519 to_nxt = to;
2520 if (mode & generate_header)
2521 {
2522 if (to_end-to_nxt < 3)
2523 return codecvt_base::partial;
2524 *to_nxt++ = static_cast<uint8_t>(0xEF);
2525 *to_nxt++ = static_cast<uint8_t>(0xBB);
2526 *to_nxt++ = static_cast<uint8_t>(0xBF);
2527 }
2528 for (; frm_nxt < frm_end; ++frm_nxt)
2529 {
2530 uint16_t wc = *frm_nxt;
2531 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2532 return codecvt_base::error;
2533 if (wc < 0x0080)
2534 {
2535 if (to_end-to_nxt < 1)
2536 return codecvt_base::partial;
2537 *to_nxt++ = static_cast<uint8_t>(wc);
2538 }
2539 else if (wc < 0x0800)
2540 {
2541 if (to_end-to_nxt < 2)
2542 return codecvt_base::partial;
2543 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2544 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2545 }
2546 else // if (wc <= 0xFFFF)
2547 {
2548 if (to_end-to_nxt < 3)
2549 return codecvt_base::partial;
2550 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2551 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2552 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2553 }
2554 }
2555 return codecvt_base::ok;
2556}
2557
2558static
2559codecvt_base::result
2560utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2561 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2562 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2563{
2564 frm_nxt = frm;
2565 to_nxt = to;
2566 if (mode & consume_header)
2567 {
2568 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2569 frm_nxt[2] == 0xBF)
2570 frm_nxt += 3;
2571 }
2572 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2573 {
2574 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2575 if (c1 < 0x80)
2576 {
2577 if (c1 > Maxcode)
2578 return codecvt_base::error;
2579 *to_nxt = static_cast<uint16_t>(c1);
2580 ++frm_nxt;
2581 }
2582 else if (c1 < 0xC2)
2583 {
2584 return codecvt_base::error;
2585 }
2586 else if (c1 < 0xE0)
2587 {
2588 if (frm_end-frm_nxt < 2)
2589 return codecvt_base::partial;
2590 uint8_t c2 = frm_nxt[1];
2591 if ((c2 & 0xC0) != 0x80)
2592 return codecvt_base::error;
2593 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2594 | (c2 & 0x3F));
2595 if (t > Maxcode)
2596 return codecvt_base::error;
2597 *to_nxt = t;
2598 frm_nxt += 2;
2599 }
2600 else if (c1 < 0xF0)
2601 {
2602 if (frm_end-frm_nxt < 3)
2603 return codecvt_base::partial;
2604 uint8_t c2 = frm_nxt[1];
2605 uint8_t c3 = frm_nxt[2];
2606 switch (c1)
2607 {
2608 case 0xE0:
2609 if ((c2 & 0xE0) != 0xA0)
2610 return codecvt_base::error;
2611 break;
2612 case 0xED:
2613 if ((c2 & 0xE0) != 0x80)
2614 return codecvt_base::error;
2615 break;
2616 default:
2617 if ((c2 & 0xC0) != 0x80)
2618 return codecvt_base::error;
2619 break;
2620 }
2621 if ((c3 & 0xC0) != 0x80)
2622 return codecvt_base::error;
2623 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2624 | ((c2 & 0x3F) << 6)
2625 | (c3 & 0x3F));
2626 if (t > Maxcode)
2627 return codecvt_base::error;
2628 *to_nxt = t;
2629 frm_nxt += 3;
2630 }
2631 else
2632 {
2633 return codecvt_base::error;
2634 }
2635 }
2636 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2637}
2638
2639static
2640int
2641utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2642 size_t mx, unsigned long Maxcode = 0x10FFFF,
2643 codecvt_mode mode = codecvt_mode(0))
2644{
2645 const uint8_t* frm_nxt = frm;
2646 if (mode & consume_header)
2647 {
2648 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2649 frm_nxt[2] == 0xBF)
2650 frm_nxt += 3;
2651 }
2652 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2653 {
2654 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2655 if (c1 < 0x80)
2656 {
2657 if (c1 > Maxcode)
2658 break;
2659 ++frm_nxt;
2660 }
2661 else if (c1 < 0xC2)
2662 {
2663 break;
2664 }
2665 else if (c1 < 0xE0)
2666 {
2667 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2668 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002669 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002670 break;
2671 frm_nxt += 2;
2672 }
2673 else if (c1 < 0xF0)
2674 {
2675 if (frm_end-frm_nxt < 3)
2676 break;
2677 uint8_t c2 = frm_nxt[1];
2678 uint8_t c3 = frm_nxt[2];
2679 switch (c1)
2680 {
2681 case 0xE0:
2682 if ((c2 & 0xE0) != 0xA0)
2683 return static_cast<int>(frm_nxt - frm);
2684 break;
2685 case 0xED:
2686 if ((c2 & 0xE0) != 0x80)
2687 return static_cast<int>(frm_nxt - frm);
2688 break;
2689 default:
2690 if ((c2 & 0xC0) != 0x80)
2691 return static_cast<int>(frm_nxt - frm);
2692 break;
2693 }
2694 if ((c3 & 0xC0) != 0x80)
2695 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002696 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002697 break;
2698 frm_nxt += 3;
2699 }
2700 else
2701 {
2702 break;
2703 }
2704 }
2705 return static_cast<int>(frm_nxt - frm);
2706}
2707
2708static
2709codecvt_base::result
2710ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2711 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2712 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2713{
2714 frm_nxt = frm;
2715 to_nxt = to;
2716 if (mode & generate_header)
2717 {
2718 if (to_end-to_nxt < 2)
2719 return codecvt_base::partial;
2720 *to_nxt++ = static_cast<uint8_t>(0xFE);
2721 *to_nxt++ = static_cast<uint8_t>(0xFF);
2722 }
2723 for (; frm_nxt < frm_end; ++frm_nxt)
2724 {
2725 uint32_t wc = *frm_nxt;
2726 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2727 return codecvt_base::error;
2728 if (wc < 0x010000)
2729 {
2730 if (to_end-to_nxt < 2)
2731 return codecvt_base::partial;
2732 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2733 *to_nxt++ = static_cast<uint8_t>(wc);
2734 }
2735 else
2736 {
2737 if (to_end-to_nxt < 4)
2738 return codecvt_base::partial;
2739 uint16_t t = static_cast<uint16_t>(
2740 0xD800
2741 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2742 | ((wc & 0x00FC00) >> 10));
2743 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2744 *to_nxt++ = static_cast<uint8_t>(t);
2745 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2746 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2747 *to_nxt++ = static_cast<uint8_t>(t);
2748 }
2749 }
2750 return codecvt_base::ok;
2751}
2752
2753static
2754codecvt_base::result
2755utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2756 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2757 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2758{
2759 frm_nxt = frm;
2760 to_nxt = to;
2761 if (mode & consume_header)
2762 {
2763 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2764 frm_nxt += 2;
2765 }
2766 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2767 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002768 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002769 if ((c1 & 0xFC00) == 0xDC00)
2770 return codecvt_base::error;
2771 if ((c1 & 0xFC00) != 0xD800)
2772 {
2773 if (c1 > Maxcode)
2774 return codecvt_base::error;
2775 *to_nxt = static_cast<uint32_t>(c1);
2776 frm_nxt += 2;
2777 }
2778 else
2779 {
2780 if (frm_end-frm_nxt < 4)
2781 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002782 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002783 if ((c2 & 0xFC00) != 0xDC00)
2784 return codecvt_base::error;
2785 uint32_t t = static_cast<uint32_t>(
2786 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2787 | ((c1 & 0x003F) << 10)
2788 | (c2 & 0x03FF));
2789 if (t > Maxcode)
2790 return codecvt_base::error;
2791 *to_nxt = t;
2792 frm_nxt += 4;
2793 }
2794 }
2795 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2796}
2797
2798static
2799int
2800utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2801 size_t mx, unsigned long Maxcode = 0x10FFFF,
2802 codecvt_mode mode = codecvt_mode(0))
2803{
2804 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002805 if (mode & consume_header)
2806 {
2807 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2808 frm_nxt += 2;
2809 }
2810 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2811 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002812 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002813 if ((c1 & 0xFC00) == 0xDC00)
2814 break;
2815 if ((c1 & 0xFC00) != 0xD800)
2816 {
2817 if (c1 > Maxcode)
2818 break;
2819 frm_nxt += 2;
2820 }
2821 else
2822 {
2823 if (frm_end-frm_nxt < 4)
2824 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002825 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002826 if ((c2 & 0xFC00) != 0xDC00)
2827 break;
2828 uint32_t t = static_cast<uint32_t>(
2829 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2830 | ((c1 & 0x003F) << 10)
2831 | (c2 & 0x03FF));
2832 if (t > Maxcode)
2833 break;
2834 frm_nxt += 4;
2835 }
2836 }
2837 return static_cast<int>(frm_nxt - frm);
2838}
2839
2840static
2841codecvt_base::result
2842ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2843 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2844 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2845{
2846 frm_nxt = frm;
2847 to_nxt = to;
2848 if (mode & generate_header)
2849 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002850 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002851 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002852 *to_nxt++ = static_cast<uint8_t>(0xFF);
2853 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002854 }
2855 for (; frm_nxt < frm_end; ++frm_nxt)
2856 {
2857 uint32_t wc = *frm_nxt;
2858 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2859 return codecvt_base::error;
2860 if (wc < 0x010000)
2861 {
2862 if (to_end-to_nxt < 2)
2863 return codecvt_base::partial;
2864 *to_nxt++ = static_cast<uint8_t>(wc);
2865 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2866 }
2867 else
2868 {
2869 if (to_end-to_nxt < 4)
2870 return codecvt_base::partial;
2871 uint16_t t = static_cast<uint16_t>(
2872 0xD800
2873 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2874 | ((wc & 0x00FC00) >> 10));
2875 *to_nxt++ = static_cast<uint8_t>(t);
2876 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2877 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2878 *to_nxt++ = static_cast<uint8_t>(t);
2879 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2880 }
2881 }
2882 return codecvt_base::ok;
2883}
2884
2885static
2886codecvt_base::result
2887utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2888 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2889 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2890{
2891 frm_nxt = frm;
2892 to_nxt = to;
2893 if (mode & consume_header)
2894 {
2895 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2896 frm_nxt += 2;
2897 }
2898 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2899 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002900 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002901 if ((c1 & 0xFC00) == 0xDC00)
2902 return codecvt_base::error;
2903 if ((c1 & 0xFC00) != 0xD800)
2904 {
2905 if (c1 > Maxcode)
2906 return codecvt_base::error;
2907 *to_nxt = static_cast<uint32_t>(c1);
2908 frm_nxt += 2;
2909 }
2910 else
2911 {
2912 if (frm_end-frm_nxt < 4)
2913 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002914 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002915 if ((c2 & 0xFC00) != 0xDC00)
2916 return codecvt_base::error;
2917 uint32_t t = static_cast<uint32_t>(
2918 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2919 | ((c1 & 0x003F) << 10)
2920 | (c2 & 0x03FF));
2921 if (t > Maxcode)
2922 return codecvt_base::error;
2923 *to_nxt = t;
2924 frm_nxt += 4;
2925 }
2926 }
2927 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2928}
2929
2930static
2931int
2932utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2933 size_t mx, unsigned long Maxcode = 0x10FFFF,
2934 codecvt_mode mode = codecvt_mode(0))
2935{
2936 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002937 if (mode & consume_header)
2938 {
2939 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2940 frm_nxt += 2;
2941 }
2942 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2943 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002944 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002945 if ((c1 & 0xFC00) == 0xDC00)
2946 break;
2947 if ((c1 & 0xFC00) != 0xD800)
2948 {
2949 if (c1 > Maxcode)
2950 break;
2951 frm_nxt += 2;
2952 }
2953 else
2954 {
2955 if (frm_end-frm_nxt < 4)
2956 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002957 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002958 if ((c2 & 0xFC00) != 0xDC00)
2959 break;
2960 uint32_t t = static_cast<uint32_t>(
2961 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2962 | ((c1 & 0x003F) << 10)
2963 | (c2 & 0x03FF));
2964 if (t > Maxcode)
2965 break;
2966 frm_nxt += 4;
2967 }
2968 }
2969 return static_cast<int>(frm_nxt - frm);
2970}
2971
2972static
2973codecvt_base::result
2974ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2975 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2976 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2977{
2978 frm_nxt = frm;
2979 to_nxt = to;
2980 if (mode & generate_header)
2981 {
2982 if (to_end-to_nxt < 2)
2983 return codecvt_base::partial;
2984 *to_nxt++ = static_cast<uint8_t>(0xFE);
2985 *to_nxt++ = static_cast<uint8_t>(0xFF);
2986 }
2987 for (; frm_nxt < frm_end; ++frm_nxt)
2988 {
2989 uint16_t wc = *frm_nxt;
2990 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2991 return codecvt_base::error;
2992 if (to_end-to_nxt < 2)
2993 return codecvt_base::partial;
2994 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2995 *to_nxt++ = static_cast<uint8_t>(wc);
2996 }
2997 return codecvt_base::ok;
2998}
2999
3000static
3001codecvt_base::result
3002utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3003 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3004 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3005{
3006 frm_nxt = frm;
3007 to_nxt = to;
3008 if (mode & consume_header)
3009 {
3010 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3011 frm_nxt += 2;
3012 }
3013 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3014 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003015 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003016 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3017 return codecvt_base::error;
3018 *to_nxt = c1;
3019 frm_nxt += 2;
3020 }
3021 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3022}
3023
3024static
3025int
3026utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3027 size_t mx, unsigned long Maxcode = 0x10FFFF,
3028 codecvt_mode mode = codecvt_mode(0))
3029{
3030 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003031 if (mode & consume_header)
3032 {
3033 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3034 frm_nxt += 2;
3035 }
3036 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3037 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003038 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003039 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3040 break;
3041 frm_nxt += 2;
3042 }
3043 return static_cast<int>(frm_nxt - frm);
3044}
3045
3046static
3047codecvt_base::result
3048ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3049 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3050 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3051{
3052 frm_nxt = frm;
3053 to_nxt = to;
3054 if (mode & generate_header)
3055 {
3056 if (to_end-to_nxt < 2)
3057 return codecvt_base::partial;
3058 *to_nxt++ = static_cast<uint8_t>(0xFF);
3059 *to_nxt++ = static_cast<uint8_t>(0xFE);
3060 }
3061 for (; frm_nxt < frm_end; ++frm_nxt)
3062 {
3063 uint16_t wc = *frm_nxt;
3064 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3065 return codecvt_base::error;
3066 if (to_end-to_nxt < 2)
3067 return codecvt_base::partial;
3068 *to_nxt++ = static_cast<uint8_t>(wc);
3069 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3070 }
3071 return codecvt_base::ok;
3072}
3073
3074static
3075codecvt_base::result
3076utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3077 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3078 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3079{
3080 frm_nxt = frm;
3081 to_nxt = to;
3082 if (mode & consume_header)
3083 {
3084 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3085 frm_nxt += 2;
3086 }
3087 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3088 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003089 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003090 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3091 return codecvt_base::error;
3092 *to_nxt = c1;
3093 frm_nxt += 2;
3094 }
3095 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3096}
3097
3098static
3099int
3100utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3101 size_t mx, unsigned long Maxcode = 0x10FFFF,
3102 codecvt_mode mode = codecvt_mode(0))
3103{
3104 const uint8_t* frm_nxt = frm;
3105 frm_nxt = frm;
3106 if (mode & consume_header)
3107 {
3108 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3109 frm_nxt += 2;
3110 }
3111 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3112 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003113 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003114 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3115 break;
3116 frm_nxt += 2;
3117 }
3118 return static_cast<int>(frm_nxt - frm);
3119}
3120
Howard Hinnantc51e1022010-05-11 19:42:16 +00003121// template <> class codecvt<char16_t, char, mbstate_t>
3122
Howard Hinnantffb308e2010-08-22 00:03:27 +00003123locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003124
3125codecvt<char16_t, char, mbstate_t>::~codecvt()
3126{
3127}
3128
3129codecvt<char16_t, char, mbstate_t>::result
3130codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003131 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003132 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3133{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003134 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3135 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3136 const uint16_t* _frm_nxt = _frm;
3137 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3138 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3139 uint8_t* _to_nxt = _to;
3140 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3141 frm_nxt = frm + (_frm_nxt - _frm);
3142 to_nxt = to + (_to_nxt - _to);
3143 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003144}
3145
3146codecvt<char16_t, char, mbstate_t>::result
3147codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003148 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003149 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3150{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003151 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3152 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3153 const uint8_t* _frm_nxt = _frm;
3154 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3155 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3156 uint16_t* _to_nxt = _to;
3157 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3158 frm_nxt = frm + (_frm_nxt - _frm);
3159 to_nxt = to + (_to_nxt - _to);
3160 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003161}
3162
3163codecvt<char16_t, char, mbstate_t>::result
3164codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3165 extern_type* to, extern_type*, extern_type*& to_nxt) const
3166{
3167 to_nxt = to;
3168 return noconv;
3169}
3170
3171int
Louis Dionne65358e12021-03-01 12:09:45 -05003172codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003173{
3174 return 0;
3175}
3176
3177bool
Louis Dionne65358e12021-03-01 12:09:45 -05003178codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003179{
3180 return false;
3181}
3182
3183int
3184codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3185 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3186{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003187 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3188 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3189 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003190}
3191
3192int
Louis Dionne65358e12021-03-01 12:09:45 -05003193codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003194{
3195 return 4;
3196}
3197
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003198#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003199
3200// template <> class codecvt<char16_t, char8_t, mbstate_t>
3201
3202locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3203
3204codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3205{
3206}
3207
3208codecvt<char16_t, char8_t, mbstate_t>::result
3209codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3210 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3211 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3212{
3213 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3214 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3215 const uint16_t* _frm_nxt = _frm;
3216 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3217 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3218 uint8_t* _to_nxt = _to;
3219 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3220 frm_nxt = frm + (_frm_nxt - _frm);
3221 to_nxt = to + (_to_nxt - _to);
3222 return r;
3223}
3224
3225codecvt<char16_t, char8_t, mbstate_t>::result
3226codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3227 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3228 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3229{
3230 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3231 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3232 const uint8_t* _frm_nxt = _frm;
3233 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3234 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3235 uint16_t* _to_nxt = _to;
3236 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3237 frm_nxt = frm + (_frm_nxt - _frm);
3238 to_nxt = to + (_to_nxt - _to);
3239 return r;
3240}
3241
3242codecvt<char16_t, char8_t, mbstate_t>::result
3243codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3244 extern_type* to, extern_type*, extern_type*& to_nxt) const
3245{
3246 to_nxt = to;
3247 return noconv;
3248}
3249
3250int
Louis Dionne65358e12021-03-01 12:09:45 -05003251codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003252{
3253 return 0;
3254}
3255
3256bool
Louis Dionne65358e12021-03-01 12:09:45 -05003257codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003258{
3259 return false;
3260}
3261
3262int
3263codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3264 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3265{
3266 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3267 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3268 return utf8_to_utf16_length(_frm, _frm_end, mx);
3269}
3270
3271int
Louis Dionne65358e12021-03-01 12:09:45 -05003272codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003273{
3274 return 4;
3275}
3276
3277#endif
3278
Howard Hinnantc51e1022010-05-11 19:42:16 +00003279// template <> class codecvt<char32_t, char, mbstate_t>
3280
Howard Hinnantffb308e2010-08-22 00:03:27 +00003281locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003282
3283codecvt<char32_t, char, mbstate_t>::~codecvt()
3284{
3285}
3286
3287codecvt<char32_t, char, mbstate_t>::result
3288codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003289 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003290 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3291{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003292 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3293 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3294 const uint32_t* _frm_nxt = _frm;
3295 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3296 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3297 uint8_t* _to_nxt = _to;
3298 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3299 frm_nxt = frm + (_frm_nxt - _frm);
3300 to_nxt = to + (_to_nxt - _to);
3301 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003302}
3303
3304codecvt<char32_t, char, mbstate_t>::result
3305codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003306 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003307 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3308{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003309 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3310 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3311 const uint8_t* _frm_nxt = _frm;
3312 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3313 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3314 uint32_t* _to_nxt = _to;
3315 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3316 frm_nxt = frm + (_frm_nxt - _frm);
3317 to_nxt = to + (_to_nxt - _to);
3318 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003319}
3320
3321codecvt<char32_t, char, mbstate_t>::result
3322codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3323 extern_type* to, extern_type*, extern_type*& to_nxt) const
3324{
3325 to_nxt = to;
3326 return noconv;
3327}
3328
3329int
Louis Dionne65358e12021-03-01 12:09:45 -05003330codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003331{
3332 return 0;
3333}
3334
3335bool
Louis Dionne65358e12021-03-01 12:09:45 -05003336codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003337{
3338 return false;
3339}
3340
3341int
3342codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3343 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3344{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003345 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3346 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3347 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003348}
3349
3350int
Louis Dionne65358e12021-03-01 12:09:45 -05003351codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003352{
3353 return 4;
3354}
3355
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003356#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003357
3358// template <> class codecvt<char32_t, char8_t, mbstate_t>
3359
3360locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3361
3362codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3363{
3364}
3365
3366codecvt<char32_t, char8_t, mbstate_t>::result
3367codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3368 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3369 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3370{
3371 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3372 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3373 const uint32_t* _frm_nxt = _frm;
3374 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3375 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3376 uint8_t* _to_nxt = _to;
3377 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3378 frm_nxt = frm + (_frm_nxt - _frm);
3379 to_nxt = to + (_to_nxt - _to);
3380 return r;
3381}
3382
3383codecvt<char32_t, char8_t, mbstate_t>::result
3384codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3385 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3386 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3387{
3388 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3389 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3390 const uint8_t* _frm_nxt = _frm;
3391 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3392 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3393 uint32_t* _to_nxt = _to;
3394 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3395 frm_nxt = frm + (_frm_nxt - _frm);
3396 to_nxt = to + (_to_nxt - _to);
3397 return r;
3398}
3399
3400codecvt<char32_t, char8_t, mbstate_t>::result
3401codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3402 extern_type* to, extern_type*, extern_type*& to_nxt) const
3403{
3404 to_nxt = to;
3405 return noconv;
3406}
3407
3408int
Louis Dionne65358e12021-03-01 12:09:45 -05003409codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003410{
3411 return 0;
3412}
3413
3414bool
Louis Dionne65358e12021-03-01 12:09:45 -05003415codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003416{
3417 return false;
3418}
3419
3420int
3421codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3422 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3423{
3424 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3425 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3426 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3427}
3428
3429int
Louis Dionne65358e12021-03-01 12:09:45 -05003430codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003431{
3432 return 4;
3433}
3434
3435#endif
3436
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003437// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003438
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003439__codecvt_utf8<wchar_t>::result
3440__codecvt_utf8<wchar_t>::do_out(state_type&,
3441 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003442 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3443{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003444#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003445 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3446 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3447 const uint16_t* _frm_nxt = _frm;
3448#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003449 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3450 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3451 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003452#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003453 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3454 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3455 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003456#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003457 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3458 _Maxcode_, _Mode_);
3459#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003460 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3461 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003462#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003463 frm_nxt = frm + (_frm_nxt - _frm);
3464 to_nxt = to + (_to_nxt - _to);
3465 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003466}
3467
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003468__codecvt_utf8<wchar_t>::result
3469__codecvt_utf8<wchar_t>::do_in(state_type&,
3470 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003471 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3472{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003473 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3474 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3475 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003476#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003477 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3478 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3479 uint16_t* _to_nxt = _to;
3480 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3481 _Maxcode_, _Mode_);
3482#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003483 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3484 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3485 uint32_t* _to_nxt = _to;
3486 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3487 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003488#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003489 frm_nxt = frm + (_frm_nxt - _frm);
3490 to_nxt = to + (_to_nxt - _to);
3491 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003492}
3493
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003494__codecvt_utf8<wchar_t>::result
3495__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003496 extern_type* to, extern_type*, extern_type*& to_nxt) const
3497{
3498 to_nxt = to;
3499 return noconv;
3500}
3501
3502int
Louis Dionne65358e12021-03-01 12:09:45 -05003503__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003504{
3505 return 0;
3506}
3507
3508bool
Louis Dionne65358e12021-03-01 12:09:45 -05003509__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003510{
3511 return false;
3512}
3513
3514int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003515__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003516 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3517{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003518 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3519 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3520 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003521}
3522
3523int
Louis Dionne65358e12021-03-01 12:09:45 -05003524__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003525{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003526 if (_Mode_ & consume_header)
3527 return 7;
3528 return 4;
3529}
3530
3531// __codecvt_utf8<char16_t>
3532
3533__codecvt_utf8<char16_t>::result
3534__codecvt_utf8<char16_t>::do_out(state_type&,
3535 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3536 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3537{
3538 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3539 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3540 const uint16_t* _frm_nxt = _frm;
3541 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3542 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3543 uint8_t* _to_nxt = _to;
3544 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3545 _Maxcode_, _Mode_);
3546 frm_nxt = frm + (_frm_nxt - _frm);
3547 to_nxt = to + (_to_nxt - _to);
3548 return r;
3549}
3550
3551__codecvt_utf8<char16_t>::result
3552__codecvt_utf8<char16_t>::do_in(state_type&,
3553 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3554 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3555{
3556 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3557 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3558 const uint8_t* _frm_nxt = _frm;
3559 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3560 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3561 uint16_t* _to_nxt = _to;
3562 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3563 _Maxcode_, _Mode_);
3564 frm_nxt = frm + (_frm_nxt - _frm);
3565 to_nxt = to + (_to_nxt - _to);
3566 return r;
3567}
3568
3569__codecvt_utf8<char16_t>::result
3570__codecvt_utf8<char16_t>::do_unshift(state_type&,
3571 extern_type* to, extern_type*, extern_type*& to_nxt) const
3572{
3573 to_nxt = to;
3574 return noconv;
3575}
3576
3577int
Louis Dionne65358e12021-03-01 12:09:45 -05003578__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003579{
3580 return 0;
3581}
3582
3583bool
Louis Dionne65358e12021-03-01 12:09:45 -05003584__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003585{
3586 return false;
3587}
3588
3589int
3590__codecvt_utf8<char16_t>::do_length(state_type&,
3591 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3592{
3593 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3594 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3595 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3596}
3597
3598int
Louis Dionne65358e12021-03-01 12:09:45 -05003599__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003600{
3601 if (_Mode_ & consume_header)
3602 return 6;
3603 return 3;
3604}
3605
3606// __codecvt_utf8<char32_t>
3607
3608__codecvt_utf8<char32_t>::result
3609__codecvt_utf8<char32_t>::do_out(state_type&,
3610 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3611 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3612{
3613 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3614 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3615 const uint32_t* _frm_nxt = _frm;
3616 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3617 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3618 uint8_t* _to_nxt = _to;
3619 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3620 _Maxcode_, _Mode_);
3621 frm_nxt = frm + (_frm_nxt - _frm);
3622 to_nxt = to + (_to_nxt - _to);
3623 return r;
3624}
3625
3626__codecvt_utf8<char32_t>::result
3627__codecvt_utf8<char32_t>::do_in(state_type&,
3628 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3629 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3630{
3631 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3632 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3633 const uint8_t* _frm_nxt = _frm;
3634 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3635 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3636 uint32_t* _to_nxt = _to;
3637 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3638 _Maxcode_, _Mode_);
3639 frm_nxt = frm + (_frm_nxt - _frm);
3640 to_nxt = to + (_to_nxt - _to);
3641 return r;
3642}
3643
3644__codecvt_utf8<char32_t>::result
3645__codecvt_utf8<char32_t>::do_unshift(state_type&,
3646 extern_type* to, extern_type*, extern_type*& to_nxt) const
3647{
3648 to_nxt = to;
3649 return noconv;
3650}
3651
3652int
Louis Dionne65358e12021-03-01 12:09:45 -05003653__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003654{
3655 return 0;
3656}
3657
3658bool
Louis Dionne65358e12021-03-01 12:09:45 -05003659__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003660{
3661 return false;
3662}
3663
3664int
3665__codecvt_utf8<char32_t>::do_length(state_type&,
3666 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3667{
3668 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3669 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3670 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3671}
3672
3673int
Louis Dionne65358e12021-03-01 12:09:45 -05003674__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003675{
3676 if (_Mode_ & consume_header)
3677 return 7;
3678 return 4;
3679}
3680
3681// __codecvt_utf16<wchar_t, false>
3682
3683__codecvt_utf16<wchar_t, false>::result
3684__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3685 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3686 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3687{
3688 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3689 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3690 const uint32_t* _frm_nxt = _frm;
3691 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3692 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3693 uint8_t* _to_nxt = _to;
3694 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3695 _Maxcode_, _Mode_);
3696 frm_nxt = frm + (_frm_nxt - _frm);
3697 to_nxt = to + (_to_nxt - _to);
3698 return r;
3699}
3700
3701__codecvt_utf16<wchar_t, false>::result
3702__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3703 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3704 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3705{
3706 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3707 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3708 const uint8_t* _frm_nxt = _frm;
3709 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3710 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3711 uint32_t* _to_nxt = _to;
3712 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3713 _Maxcode_, _Mode_);
3714 frm_nxt = frm + (_frm_nxt - _frm);
3715 to_nxt = to + (_to_nxt - _to);
3716 return r;
3717}
3718
3719__codecvt_utf16<wchar_t, false>::result
3720__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3721 extern_type* to, extern_type*, extern_type*& to_nxt) const
3722{
3723 to_nxt = to;
3724 return noconv;
3725}
3726
3727int
Louis Dionne65358e12021-03-01 12:09:45 -05003728__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003729{
3730 return 0;
3731}
3732
3733bool
Louis Dionne65358e12021-03-01 12:09:45 -05003734__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003735{
3736 return false;
3737}
3738
3739int
3740__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3741 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3742{
3743 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3744 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3745 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3746}
3747
3748int
Louis Dionne65358e12021-03-01 12:09:45 -05003749__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003750{
3751 if (_Mode_ & consume_header)
3752 return 6;
3753 return 4;
3754}
3755
3756// __codecvt_utf16<wchar_t, true>
3757
3758__codecvt_utf16<wchar_t, true>::result
3759__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3760 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3761 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3762{
3763 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3764 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3765 const uint32_t* _frm_nxt = _frm;
3766 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3767 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3768 uint8_t* _to_nxt = _to;
3769 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3770 _Maxcode_, _Mode_);
3771 frm_nxt = frm + (_frm_nxt - _frm);
3772 to_nxt = to + (_to_nxt - _to);
3773 return r;
3774}
3775
3776__codecvt_utf16<wchar_t, true>::result
3777__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3778 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3779 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3780{
3781 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3782 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3783 const uint8_t* _frm_nxt = _frm;
3784 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3785 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3786 uint32_t* _to_nxt = _to;
3787 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3788 _Maxcode_, _Mode_);
3789 frm_nxt = frm + (_frm_nxt - _frm);
3790 to_nxt = to + (_to_nxt - _to);
3791 return r;
3792}
3793
3794__codecvt_utf16<wchar_t, true>::result
3795__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3796 extern_type* to, extern_type*, extern_type*& to_nxt) const
3797{
3798 to_nxt = to;
3799 return noconv;
3800}
3801
3802int
Louis Dionne65358e12021-03-01 12:09:45 -05003803__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003804{
3805 return 0;
3806}
3807
3808bool
Louis Dionne65358e12021-03-01 12:09:45 -05003809__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003810{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003811 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003812}
3813
3814int
3815__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3816 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3817{
3818 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3819 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3820 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3821}
3822
3823int
Louis Dionne65358e12021-03-01 12:09:45 -05003824__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003825{
3826 if (_Mode_ & consume_header)
3827 return 6;
3828 return 4;
3829}
3830
3831// __codecvt_utf16<char16_t, false>
3832
3833__codecvt_utf16<char16_t, false>::result
3834__codecvt_utf16<char16_t, false>::do_out(state_type&,
3835 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3836 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3837{
3838 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3839 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3840 const uint16_t* _frm_nxt = _frm;
3841 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3842 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3843 uint8_t* _to_nxt = _to;
3844 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3845 _Maxcode_, _Mode_);
3846 frm_nxt = frm + (_frm_nxt - _frm);
3847 to_nxt = to + (_to_nxt - _to);
3848 return r;
3849}
3850
3851__codecvt_utf16<char16_t, false>::result
3852__codecvt_utf16<char16_t, false>::do_in(state_type&,
3853 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3854 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3855{
3856 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3857 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3858 const uint8_t* _frm_nxt = _frm;
3859 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3860 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3861 uint16_t* _to_nxt = _to;
3862 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3863 _Maxcode_, _Mode_);
3864 frm_nxt = frm + (_frm_nxt - _frm);
3865 to_nxt = to + (_to_nxt - _to);
3866 return r;
3867}
3868
3869__codecvt_utf16<char16_t, false>::result
3870__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3871 extern_type* to, extern_type*, extern_type*& to_nxt) const
3872{
3873 to_nxt = to;
3874 return noconv;
3875}
3876
3877int
Louis Dionne65358e12021-03-01 12:09:45 -05003878__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003879{
3880 return 0;
3881}
3882
3883bool
Louis Dionne65358e12021-03-01 12:09:45 -05003884__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003885{
3886 return false;
3887}
3888
3889int
3890__codecvt_utf16<char16_t, false>::do_length(state_type&,
3891 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3892{
3893 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3894 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3895 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3896}
3897
3898int
Louis Dionne65358e12021-03-01 12:09:45 -05003899__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003900{
3901 if (_Mode_ & consume_header)
3902 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003903 return 2;
3904}
3905
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003906// __codecvt_utf16<char16_t, true>
3907
3908__codecvt_utf16<char16_t, true>::result
3909__codecvt_utf16<char16_t, true>::do_out(state_type&,
3910 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3911 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3912{
3913 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3914 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3915 const uint16_t* _frm_nxt = _frm;
3916 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3917 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3918 uint8_t* _to_nxt = _to;
3919 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3920 _Maxcode_, _Mode_);
3921 frm_nxt = frm + (_frm_nxt - _frm);
3922 to_nxt = to + (_to_nxt - _to);
3923 return r;
3924}
3925
3926__codecvt_utf16<char16_t, true>::result
3927__codecvt_utf16<char16_t, true>::do_in(state_type&,
3928 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3929 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3930{
3931 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3932 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3933 const uint8_t* _frm_nxt = _frm;
3934 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3935 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3936 uint16_t* _to_nxt = _to;
3937 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3938 _Maxcode_, _Mode_);
3939 frm_nxt = frm + (_frm_nxt - _frm);
3940 to_nxt = to + (_to_nxt - _to);
3941 return r;
3942}
3943
3944__codecvt_utf16<char16_t, true>::result
3945__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3946 extern_type* to, extern_type*, extern_type*& to_nxt) const
3947{
3948 to_nxt = to;
3949 return noconv;
3950}
3951
3952int
Louis Dionne65358e12021-03-01 12:09:45 -05003953__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003954{
3955 return 0;
3956}
3957
3958bool
Louis Dionne65358e12021-03-01 12:09:45 -05003959__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003960{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003961 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003962}
3963
3964int
3965__codecvt_utf16<char16_t, true>::do_length(state_type&,
3966 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3967{
3968 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3969 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3970 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3971}
3972
3973int
Louis Dionne65358e12021-03-01 12:09:45 -05003974__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003975{
3976 if (_Mode_ & consume_header)
3977 return 4;
3978 return 2;
3979}
3980
3981// __codecvt_utf16<char32_t, false>
3982
3983__codecvt_utf16<char32_t, false>::result
3984__codecvt_utf16<char32_t, false>::do_out(state_type&,
3985 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3986 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3987{
3988 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3989 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3990 const uint32_t* _frm_nxt = _frm;
3991 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3992 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3993 uint8_t* _to_nxt = _to;
3994 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3995 _Maxcode_, _Mode_);
3996 frm_nxt = frm + (_frm_nxt - _frm);
3997 to_nxt = to + (_to_nxt - _to);
3998 return r;
3999}
4000
4001__codecvt_utf16<char32_t, false>::result
4002__codecvt_utf16<char32_t, false>::do_in(state_type&,
4003 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4004 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4005{
4006 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4007 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4008 const uint8_t* _frm_nxt = _frm;
4009 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4010 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4011 uint32_t* _to_nxt = _to;
4012 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4013 _Maxcode_, _Mode_);
4014 frm_nxt = frm + (_frm_nxt - _frm);
4015 to_nxt = to + (_to_nxt - _to);
4016 return r;
4017}
4018
4019__codecvt_utf16<char32_t, false>::result
4020__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4021 extern_type* to, extern_type*, extern_type*& to_nxt) const
4022{
4023 to_nxt = to;
4024 return noconv;
4025}
4026
4027int
Louis Dionne65358e12021-03-01 12:09:45 -05004028__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004029{
4030 return 0;
4031}
4032
4033bool
Louis Dionne65358e12021-03-01 12:09:45 -05004034__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004035{
4036 return false;
4037}
4038
4039int
4040__codecvt_utf16<char32_t, false>::do_length(state_type&,
4041 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4042{
4043 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4044 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4045 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4046}
4047
4048int
Louis Dionne65358e12021-03-01 12:09:45 -05004049__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004050{
4051 if (_Mode_ & consume_header)
4052 return 6;
4053 return 4;
4054}
4055
4056// __codecvt_utf16<char32_t, true>
4057
4058__codecvt_utf16<char32_t, true>::result
4059__codecvt_utf16<char32_t, true>::do_out(state_type&,
4060 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4061 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4062{
4063 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4064 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4065 const uint32_t* _frm_nxt = _frm;
4066 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4067 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4068 uint8_t* _to_nxt = _to;
4069 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4070 _Maxcode_, _Mode_);
4071 frm_nxt = frm + (_frm_nxt - _frm);
4072 to_nxt = to + (_to_nxt - _to);
4073 return r;
4074}
4075
4076__codecvt_utf16<char32_t, true>::result
4077__codecvt_utf16<char32_t, true>::do_in(state_type&,
4078 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4079 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4080{
4081 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4082 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4083 const uint8_t* _frm_nxt = _frm;
4084 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4085 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4086 uint32_t* _to_nxt = _to;
4087 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4088 _Maxcode_, _Mode_);
4089 frm_nxt = frm + (_frm_nxt - _frm);
4090 to_nxt = to + (_to_nxt - _to);
4091 return r;
4092}
4093
4094__codecvt_utf16<char32_t, true>::result
4095__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4096 extern_type* to, extern_type*, extern_type*& to_nxt) const
4097{
4098 to_nxt = to;
4099 return noconv;
4100}
4101
4102int
Louis Dionne65358e12021-03-01 12:09:45 -05004103__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004104{
4105 return 0;
4106}
4107
4108bool
Louis Dionne65358e12021-03-01 12:09:45 -05004109__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004110{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004111 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004112}
4113
4114int
4115__codecvt_utf16<char32_t, true>::do_length(state_type&,
4116 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4117{
4118 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4119 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4120 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4121}
4122
4123int
Louis Dionne65358e12021-03-01 12:09:45 -05004124__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004125{
4126 if (_Mode_ & consume_header)
4127 return 6;
4128 return 4;
4129}
4130
4131// __codecvt_utf8_utf16<wchar_t>
4132
4133__codecvt_utf8_utf16<wchar_t>::result
4134__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4135 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4136 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4137{
4138 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4139 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4140 const uint32_t* _frm_nxt = _frm;
4141 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4142 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4143 uint8_t* _to_nxt = _to;
4144 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4145 _Maxcode_, _Mode_);
4146 frm_nxt = frm + (_frm_nxt - _frm);
4147 to_nxt = to + (_to_nxt - _to);
4148 return r;
4149}
4150
4151__codecvt_utf8_utf16<wchar_t>::result
4152__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4153 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4154 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4155{
4156 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4157 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4158 const uint8_t* _frm_nxt = _frm;
4159 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4160 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4161 uint32_t* _to_nxt = _to;
4162 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4163 _Maxcode_, _Mode_);
4164 frm_nxt = frm + (_frm_nxt - _frm);
4165 to_nxt = to + (_to_nxt - _to);
4166 return r;
4167}
4168
4169__codecvt_utf8_utf16<wchar_t>::result
4170__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4171 extern_type* to, extern_type*, extern_type*& to_nxt) const
4172{
4173 to_nxt = to;
4174 return noconv;
4175}
4176
4177int
Louis Dionne65358e12021-03-01 12:09:45 -05004178__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004179{
4180 return 0;
4181}
4182
4183bool
Louis Dionne65358e12021-03-01 12:09:45 -05004184__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004185{
4186 return false;
4187}
4188
4189int
4190__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4191 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4192{
4193 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4194 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4195 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4196}
4197
4198int
Louis Dionne65358e12021-03-01 12:09:45 -05004199__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004200{
4201 if (_Mode_ & consume_header)
4202 return 7;
4203 return 4;
4204}
4205
4206// __codecvt_utf8_utf16<char16_t>
4207
4208__codecvt_utf8_utf16<char16_t>::result
4209__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4210 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4211 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4212{
4213 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4214 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4215 const uint16_t* _frm_nxt = _frm;
4216 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4217 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4218 uint8_t* _to_nxt = _to;
4219 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4220 _Maxcode_, _Mode_);
4221 frm_nxt = frm + (_frm_nxt - _frm);
4222 to_nxt = to + (_to_nxt - _to);
4223 return r;
4224}
4225
4226__codecvt_utf8_utf16<char16_t>::result
4227__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4228 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4229 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4230{
4231 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4232 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4233 const uint8_t* _frm_nxt = _frm;
4234 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4235 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4236 uint16_t* _to_nxt = _to;
4237 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4238 _Maxcode_, _Mode_);
4239 frm_nxt = frm + (_frm_nxt - _frm);
4240 to_nxt = to + (_to_nxt - _to);
4241 return r;
4242}
4243
4244__codecvt_utf8_utf16<char16_t>::result
4245__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4246 extern_type* to, extern_type*, extern_type*& to_nxt) const
4247{
4248 to_nxt = to;
4249 return noconv;
4250}
4251
4252int
Louis Dionne65358e12021-03-01 12:09:45 -05004253__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004254{
4255 return 0;
4256}
4257
4258bool
Louis Dionne65358e12021-03-01 12:09:45 -05004259__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004260{
4261 return false;
4262}
4263
4264int
4265__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4266 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4267{
4268 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4269 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4270 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4271}
4272
4273int
Louis Dionne65358e12021-03-01 12:09:45 -05004274__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004275{
4276 if (_Mode_ & consume_header)
4277 return 7;
4278 return 4;
4279}
4280
4281// __codecvt_utf8_utf16<char32_t>
4282
4283__codecvt_utf8_utf16<char32_t>::result
4284__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4285 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4286 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4287{
4288 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4289 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4290 const uint32_t* _frm_nxt = _frm;
4291 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4292 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4293 uint8_t* _to_nxt = _to;
4294 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4295 _Maxcode_, _Mode_);
4296 frm_nxt = frm + (_frm_nxt - _frm);
4297 to_nxt = to + (_to_nxt - _to);
4298 return r;
4299}
4300
4301__codecvt_utf8_utf16<char32_t>::result
4302__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4303 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4304 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4305{
4306 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4307 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4308 const uint8_t* _frm_nxt = _frm;
4309 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4310 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4311 uint32_t* _to_nxt = _to;
4312 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4313 _Maxcode_, _Mode_);
4314 frm_nxt = frm + (_frm_nxt - _frm);
4315 to_nxt = to + (_to_nxt - _to);
4316 return r;
4317}
4318
4319__codecvt_utf8_utf16<char32_t>::result
4320__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4321 extern_type* to, extern_type*, extern_type*& to_nxt) const
4322{
4323 to_nxt = to;
4324 return noconv;
4325}
4326
4327int
Louis Dionne65358e12021-03-01 12:09:45 -05004328__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004329{
4330 return 0;
4331}
4332
4333bool
Louis Dionne65358e12021-03-01 12:09:45 -05004334__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004335{
4336 return false;
4337}
4338
4339int
4340__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4341 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4342{
4343 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4344 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4345 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4346}
4347
4348int
Louis Dionne65358e12021-03-01 12:09:45 -05004349__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004350{
4351 if (_Mode_ & consume_header)
4352 return 7;
4353 return 4;
4354}
4355
Howard Hinnantc51e1022010-05-11 19:42:16 +00004356// __narrow_to_utf8<16>
4357
4358__narrow_to_utf8<16>::~__narrow_to_utf8()
4359{
4360}
4361
4362// __narrow_to_utf8<32>
4363
4364__narrow_to_utf8<32>::~__narrow_to_utf8()
4365{
4366}
4367
4368// __widen_from_utf8<16>
4369
4370__widen_from_utf8<16>::~__widen_from_utf8()
4371{
4372}
4373
4374// __widen_from_utf8<32>
4375
4376__widen_from_utf8<32>::~__widen_from_utf8()
4377{
4378}
4379
Eric Fiselierbf945a22016-12-11 00:20:59 +00004380
4381static bool checked_string_to_wchar_convert(wchar_t& dest,
4382 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004383 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004384 if (*ptr == '\0')
4385 return false;
4386 mbstate_t mb = {};
4387 wchar_t out;
4388 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4389 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4390 return false;
4391 }
4392 dest = out;
4393 return true;
4394}
4395
4396static bool checked_string_to_char_convert(char& dest,
4397 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004398 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004399 if (*ptr == '\0')
4400 return false;
4401 if (!ptr[1]) {
4402 dest = *ptr;
4403 return true;
4404 }
4405 // First convert the MBS into a wide char then attempt to narrow it using
4406 // wctob_l.
4407 wchar_t wout;
4408 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4409 return false;
4410 int res;
4411 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4412 dest = res;
4413 return true;
4414 }
4415 // FIXME: Work around specific multibyte sequences that we can reasonable
4416 // translate into a different single byte.
4417 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004418 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004419 case L'\u00A0': // non-breaking space
4420 dest = ' ';
4421 return true;
4422 default:
4423 return false;
4424 }
4425 _LIBCPP_UNREACHABLE();
4426}
4427
4428
Howard Hinnantc51e1022010-05-11 19:42:16 +00004429// numpunct<char> && numpunct<wchar_t>
4430
4431locale::id numpunct< char >::id;
4432locale::id numpunct<wchar_t>::id;
4433
4434numpunct<char>::numpunct(size_t refs)
4435 : locale::facet(refs),
4436 __decimal_point_('.'),
4437 __thousands_sep_(',')
4438{
4439}
4440
4441numpunct<wchar_t>::numpunct(size_t refs)
4442 : locale::facet(refs),
4443 __decimal_point_(L'.'),
4444 __thousands_sep_(L',')
4445{
4446}
4447
4448numpunct<char>::~numpunct()
4449{
4450}
4451
4452numpunct<wchar_t>::~numpunct()
4453{
4454}
4455
4456 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4457wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4458
4459 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4460wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4461
4462string numpunct< char >::do_grouping() const {return __grouping_;}
4463string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4464
4465 string numpunct< char >::do_truename() const {return "true";}
4466wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4467
4468 string numpunct< char >::do_falsename() const {return "false";}
4469wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4470
4471// numpunct_byname<char>
4472
4473numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4474 : numpunct<char>(refs)
4475{
4476 __init(nm);
4477}
4478
4479numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4480 : numpunct<char>(refs)
4481{
4482 __init(nm.c_str());
4483}
4484
4485numpunct_byname<char>::~numpunct_byname()
4486{
4487}
4488
4489void
4490numpunct_byname<char>::__init(const char* nm)
4491{
4492 if (strcmp(nm, "C") != 0)
4493 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004494 __libcpp_unique_locale loc(nm);
4495 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004496 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004497 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004498
Ben Craig3756b922016-03-09 15:39:39 +00004499 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004500 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4501 loc.get());
4502 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4503 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004504 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004505 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004506 }
4507}
4508
4509// numpunct_byname<wchar_t>
4510
4511numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4512 : numpunct<wchar_t>(refs)
4513{
4514 __init(nm);
4515}
4516
4517numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4518 : numpunct<wchar_t>(refs)
4519{
4520 __init(nm.c_str());
4521}
4522
4523numpunct_byname<wchar_t>::~numpunct_byname()
4524{
4525}
4526
4527void
4528numpunct_byname<wchar_t>::__init(const char* nm)
4529{
4530 if (strcmp(nm, "C") != 0)
4531 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004532 __libcpp_unique_locale loc(nm);
4533 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004534 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004535 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004536
Ben Craig3756b922016-03-09 15:39:39 +00004537 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004538 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4539 loc.get());
4540 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4541 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004542 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004543 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004544 }
4545}
4546
4547// num_get helpers
4548
4549int
4550__num_get_base::__get_base(ios_base& iob)
4551{
4552 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4553 if (__basefield == ios_base::oct)
4554 return 8;
4555 else if (__basefield == ios_base::hex)
4556 return 16;
4557 else if (__basefield == 0)
4558 return 0;
4559 return 10;
4560}
4561
4562const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4563
4564void
4565__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4566 ios_base::iostate& __err)
4567{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004568// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4569// 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 +00004570 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004571 {
4572 reverse(__g, __g_end);
4573 const char* __ig = __grouping.data();
4574 const char* __eg = __ig + __grouping.size();
4575 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4576 {
4577 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4578 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004579 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004580 {
4581 __err = ios_base::failbit;
4582 return;
4583 }
4584 }
4585 if (__eg - __ig > 1)
4586 ++__ig;
4587 }
4588 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4589 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004590 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004591 __err = ios_base::failbit;
4592 }
4593 }
4594}
4595
4596void
4597__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4598 ios_base::fmtflags __flags)
4599{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004600 if ((__flags & ios_base::showpos) &&
4601 (__flags & ios_base::basefield) != ios_base::oct &&
4602 (__flags & ios_base::basefield) != ios_base::hex &&
4603 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004604 *__fmtp++ = '+';
4605 if (__flags & ios_base::showbase)
4606 *__fmtp++ = '#';
4607 while(*__len)
4608 *__fmtp++ = *__len++;
4609 if ((__flags & ios_base::basefield) == ios_base::oct)
4610 *__fmtp = 'o';
4611 else if ((__flags & ios_base::basefield) == ios_base::hex)
4612 {
4613 if (__flags & ios_base::uppercase)
4614 *__fmtp = 'X';
4615 else
4616 *__fmtp = 'x';
4617 }
4618 else if (__signd)
4619 *__fmtp = 'd';
4620 else
4621 *__fmtp = 'u';
4622}
4623
4624bool
4625__num_put_base::__format_float(char* __fmtp, const char* __len,
4626 ios_base::fmtflags __flags)
4627{
4628 bool specify_precision = true;
4629 if (__flags & ios_base::showpos)
4630 *__fmtp++ = '+';
4631 if (__flags & ios_base::showpoint)
4632 *__fmtp++ = '#';
4633 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004634 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004635 if (floatfield == (ios_base::fixed | ios_base::scientific))
4636 specify_precision = false;
4637 else
4638 {
4639 *__fmtp++ = '.';
4640 *__fmtp++ = '*';
4641 }
4642 while(*__len)
4643 *__fmtp++ = *__len++;
4644 if (floatfield == ios_base::fixed)
4645 {
4646 if (uppercase)
4647 *__fmtp = 'F';
4648 else
4649 *__fmtp = 'f';
4650 }
4651 else if (floatfield == ios_base::scientific)
4652 {
4653 if (uppercase)
4654 *__fmtp = 'E';
4655 else
4656 *__fmtp = 'e';
4657 }
4658 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4659 {
4660 if (uppercase)
4661 *__fmtp = 'A';
4662 else
4663 *__fmtp = 'a';
4664 }
4665 else
4666 {
4667 if (uppercase)
4668 *__fmtp = 'G';
4669 else
4670 *__fmtp = 'g';
4671 }
4672 return specify_precision;
4673}
4674
4675char*
4676__num_put_base::__identify_padding(char* __nb, char* __ne,
4677 const ios_base& __iob)
4678{
4679 switch (__iob.flags() & ios_base::adjustfield)
4680 {
4681 case ios_base::internal:
4682 if (__nb[0] == '-' || __nb[0] == '+')
4683 return __nb+1;
4684 if (__ne - __nb >= 2 && __nb[0] == '0'
4685 && (__nb[1] == 'x' || __nb[1] == 'X'))
4686 return __nb+2;
4687 break;
4688 case ios_base::left:
4689 return __ne;
4690 case ios_base::right:
4691 default:
4692 break;
4693 }
4694 return __nb;
4695}
4696
4697// time_get
4698
4699static
4700string*
4701init_weeks()
4702{
4703 static string weeks[14];
4704 weeks[0] = "Sunday";
4705 weeks[1] = "Monday";
4706 weeks[2] = "Tuesday";
4707 weeks[3] = "Wednesday";
4708 weeks[4] = "Thursday";
4709 weeks[5] = "Friday";
4710 weeks[6] = "Saturday";
4711 weeks[7] = "Sun";
4712 weeks[8] = "Mon";
4713 weeks[9] = "Tue";
4714 weeks[10] = "Wed";
4715 weeks[11] = "Thu";
4716 weeks[12] = "Fri";
4717 weeks[13] = "Sat";
4718 return weeks;
4719}
4720
4721static
4722wstring*
4723init_wweeks()
4724{
4725 static wstring weeks[14];
4726 weeks[0] = L"Sunday";
4727 weeks[1] = L"Monday";
4728 weeks[2] = L"Tuesday";
4729 weeks[3] = L"Wednesday";
4730 weeks[4] = L"Thursday";
4731 weeks[5] = L"Friday";
4732 weeks[6] = L"Saturday";
4733 weeks[7] = L"Sun";
4734 weeks[8] = L"Mon";
4735 weeks[9] = L"Tue";
4736 weeks[10] = L"Wed";
4737 weeks[11] = L"Thu";
4738 weeks[12] = L"Fri";
4739 weeks[13] = L"Sat";
4740 return weeks;
4741}
4742
4743template <>
4744const string*
4745__time_get_c_storage<char>::__weeks() const
4746{
4747 static const string* weeks = init_weeks();
4748 return weeks;
4749}
4750
4751template <>
4752const wstring*
4753__time_get_c_storage<wchar_t>::__weeks() const
4754{
4755 static const wstring* weeks = init_wweeks();
4756 return weeks;
4757}
4758
4759static
4760string*
4761init_months()
4762{
4763 static string months[24];
4764 months[0] = "January";
4765 months[1] = "February";
4766 months[2] = "March";
4767 months[3] = "April";
4768 months[4] = "May";
4769 months[5] = "June";
4770 months[6] = "July";
4771 months[7] = "August";
4772 months[8] = "September";
4773 months[9] = "October";
4774 months[10] = "November";
4775 months[11] = "December";
4776 months[12] = "Jan";
4777 months[13] = "Feb";
4778 months[14] = "Mar";
4779 months[15] = "Apr";
4780 months[16] = "May";
4781 months[17] = "Jun";
4782 months[18] = "Jul";
4783 months[19] = "Aug";
4784 months[20] = "Sep";
4785 months[21] = "Oct";
4786 months[22] = "Nov";
4787 months[23] = "Dec";
4788 return months;
4789}
4790
4791static
4792wstring*
4793init_wmonths()
4794{
4795 static wstring months[24];
4796 months[0] = L"January";
4797 months[1] = L"February";
4798 months[2] = L"March";
4799 months[3] = L"April";
4800 months[4] = L"May";
4801 months[5] = L"June";
4802 months[6] = L"July";
4803 months[7] = L"August";
4804 months[8] = L"September";
4805 months[9] = L"October";
4806 months[10] = L"November";
4807 months[11] = L"December";
4808 months[12] = L"Jan";
4809 months[13] = L"Feb";
4810 months[14] = L"Mar";
4811 months[15] = L"Apr";
4812 months[16] = L"May";
4813 months[17] = L"Jun";
4814 months[18] = L"Jul";
4815 months[19] = L"Aug";
4816 months[20] = L"Sep";
4817 months[21] = L"Oct";
4818 months[22] = L"Nov";
4819 months[23] = L"Dec";
4820 return months;
4821}
4822
4823template <>
4824const string*
4825__time_get_c_storage<char>::__months() const
4826{
4827 static const string* months = init_months();
4828 return months;
4829}
4830
4831template <>
4832const wstring*
4833__time_get_c_storage<wchar_t>::__months() const
4834{
4835 static const wstring* months = init_wmonths();
4836 return months;
4837}
4838
4839static
4840string*
4841init_am_pm()
4842{
Marshall Clow5cc04922018-01-11 17:16:52 +00004843 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004844 am_pm[0] = "AM";
4845 am_pm[1] = "PM";
4846 return am_pm;
4847}
4848
4849static
4850wstring*
4851init_wam_pm()
4852{
Marshall Clow5cc04922018-01-11 17:16:52 +00004853 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004854 am_pm[0] = L"AM";
4855 am_pm[1] = L"PM";
4856 return am_pm;
4857}
4858
4859template <>
4860const string*
4861__time_get_c_storage<char>::__am_pm() const
4862{
4863 static const string* am_pm = init_am_pm();
4864 return am_pm;
4865}
4866
4867template <>
4868const wstring*
4869__time_get_c_storage<wchar_t>::__am_pm() const
4870{
4871 static const wstring* am_pm = init_wam_pm();
4872 return am_pm;
4873}
4874
4875template <>
4876const string&
4877__time_get_c_storage<char>::__x() const
4878{
4879 static string s("%m/%d/%y");
4880 return s;
4881}
4882
4883template <>
4884const wstring&
4885__time_get_c_storage<wchar_t>::__x() const
4886{
4887 static wstring s(L"%m/%d/%y");
4888 return s;
4889}
4890
4891template <>
4892const string&
4893__time_get_c_storage<char>::__X() const
4894{
4895 static string s("%H:%M:%S");
4896 return s;
4897}
4898
4899template <>
4900const wstring&
4901__time_get_c_storage<wchar_t>::__X() const
4902{
4903 static wstring s(L"%H:%M:%S");
4904 return s;
4905}
4906
4907template <>
4908const string&
4909__time_get_c_storage<char>::__c() const
4910{
4911 static string s("%a %b %d %H:%M:%S %Y");
4912 return s;
4913}
4914
4915template <>
4916const wstring&
4917__time_get_c_storage<wchar_t>::__c() const
4918{
4919 static wstring s(L"%a %b %d %H:%M:%S %Y");
4920 return s;
4921}
4922
4923template <>
4924const string&
4925__time_get_c_storage<char>::__r() const
4926{
4927 static string s("%I:%M:%S %p");
4928 return s;
4929}
4930
4931template <>
4932const wstring&
4933__time_get_c_storage<wchar_t>::__r() const
4934{
4935 static wstring s(L"%I:%M:%S %p");
4936 return s;
4937}
4938
4939// time_get_byname
4940
4941__time_get::__time_get(const char* nm)
4942 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4943{
4944 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004945 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004946 " failed to construct for " + string(nm));
4947}
4948
4949__time_get::__time_get(const string& nm)
4950 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4951{
4952 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004953 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004954 " failed to construct for " + nm);
4955}
4956
4957__time_get::~__time_get()
4958{
4959 freelocale(__loc_);
4960}
Marshall Clowd920eea2013-10-21 15:07:28 +00004961#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004962#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004963#endif
4964#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004965#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004966#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004967
Howard Hinnantc51e1022010-05-11 19:42:16 +00004968template <>
4969string
4970__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4971{
Howard Hinnant990207c2012-02-19 14:55:32 +00004972 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004973 t.tm_sec = 59;
4974 t.tm_min = 55;
4975 t.tm_hour = 23;
4976 t.tm_mday = 31;
4977 t.tm_mon = 11;
4978 t.tm_year = 161;
4979 t.tm_wday = 6;
4980 t.tm_yday = 364;
4981 t.tm_isdst = -1;
4982 char buf[100];
4983 char f[3] = {0};
4984 f[0] = '%';
4985 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004986 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004987 char* bb = buf;
4988 char* be = buf + n;
4989 string result;
4990 while (bb != be)
4991 {
4992 if (ct.is(ctype_base::space, *bb))
4993 {
4994 result.push_back(' ');
4995 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4996 ;
4997 continue;
4998 }
4999 char* w = bb;
5000 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005001 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005002 ct, err, false)
5003 - this->__weeks_;
5004 if (i < 14)
5005 {
5006 result.push_back('%');
5007 if (i < 7)
5008 result.push_back('A');
5009 else
5010 result.push_back('a');
5011 bb = w;
5012 continue;
5013 }
5014 w = bb;
5015 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5016 ct, err, false)
5017 - this->__months_;
5018 if (i < 24)
5019 {
5020 result.push_back('%');
5021 if (i < 12)
5022 result.push_back('B');
5023 else
5024 result.push_back('b');
5025 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5026 result.back() = 'm';
5027 bb = w;
5028 continue;
5029 }
5030 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5031 {
5032 w = bb;
5033 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5034 ct, err, false) - this->__am_pm_;
5035 if (i < 2)
5036 {
5037 result.push_back('%');
5038 result.push_back('p');
5039 bb = w;
5040 continue;
5041 }
5042 }
5043 w = bb;
5044 if (ct.is(ctype_base::digit, *bb))
5045 {
5046 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5047 {
5048 case 6:
5049 result.push_back('%');
5050 result.push_back('w');
5051 break;
5052 case 7:
5053 result.push_back('%');
5054 result.push_back('u');
5055 break;
5056 case 11:
5057 result.push_back('%');
5058 result.push_back('I');
5059 break;
5060 case 12:
5061 result.push_back('%');
5062 result.push_back('m');
5063 break;
5064 case 23:
5065 result.push_back('%');
5066 result.push_back('H');
5067 break;
5068 case 31:
5069 result.push_back('%');
5070 result.push_back('d');
5071 break;
5072 case 55:
5073 result.push_back('%');
5074 result.push_back('M');
5075 break;
5076 case 59:
5077 result.push_back('%');
5078 result.push_back('S');
5079 break;
5080 case 61:
5081 result.push_back('%');
5082 result.push_back('y');
5083 break;
5084 case 364:
5085 result.push_back('%');
5086 result.push_back('j');
5087 break;
5088 case 2061:
5089 result.push_back('%');
5090 result.push_back('Y');
5091 break;
5092 default:
5093 for (; w != bb; ++w)
5094 result.push_back(*w);
5095 break;
5096 }
5097 continue;
5098 }
5099 if (*bb == '%')
5100 {
5101 result.push_back('%');
5102 result.push_back('%');
5103 ++bb;
5104 continue;
5105 }
5106 result.push_back(*bb);
5107 ++bb;
5108 }
5109 return result;
5110}
5111
Marshall Clowd920eea2013-10-21 15:07:28 +00005112#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005113#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005114#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005115
Howard Hinnantc51e1022010-05-11 19:42:16 +00005116template <>
5117wstring
5118__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5119{
Howard Hinnant990207c2012-02-19 14:55:32 +00005120 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005121 t.tm_sec = 59;
5122 t.tm_min = 55;
5123 t.tm_hour = 23;
5124 t.tm_mday = 31;
5125 t.tm_mon = 11;
5126 t.tm_year = 161;
5127 t.tm_wday = 6;
5128 t.tm_yday = 364;
5129 t.tm_isdst = -1;
5130 char buf[100];
5131 char f[3] = {0};
5132 f[0] = '%';
5133 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005134 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005135 wchar_t wbuf[100];
5136 wchar_t* wbb = wbuf;
5137 mbstate_t mb = {0};
5138 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005139 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005140 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005141 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005142 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005143 wstring result;
5144 while (wbb != wbe)
5145 {
5146 if (ct.is(ctype_base::space, *wbb))
5147 {
5148 result.push_back(L' ');
5149 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5150 ;
5151 continue;
5152 }
5153 wchar_t* w = wbb;
5154 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005155 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005156 ct, err, false)
5157 - this->__weeks_;
5158 if (i < 14)
5159 {
5160 result.push_back(L'%');
5161 if (i < 7)
5162 result.push_back(L'A');
5163 else
5164 result.push_back(L'a');
5165 wbb = w;
5166 continue;
5167 }
5168 w = wbb;
5169 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5170 ct, err, false)
5171 - this->__months_;
5172 if (i < 24)
5173 {
5174 result.push_back(L'%');
5175 if (i < 12)
5176 result.push_back(L'B');
5177 else
5178 result.push_back(L'b');
5179 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5180 result.back() = L'm';
5181 wbb = w;
5182 continue;
5183 }
5184 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5185 {
5186 w = wbb;
5187 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5188 ct, err, false) - this->__am_pm_;
5189 if (i < 2)
5190 {
5191 result.push_back(L'%');
5192 result.push_back(L'p');
5193 wbb = w;
5194 continue;
5195 }
5196 }
5197 w = wbb;
5198 if (ct.is(ctype_base::digit, *wbb))
5199 {
5200 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5201 {
5202 case 6:
5203 result.push_back(L'%');
5204 result.push_back(L'w');
5205 break;
5206 case 7:
5207 result.push_back(L'%');
5208 result.push_back(L'u');
5209 break;
5210 case 11:
5211 result.push_back(L'%');
5212 result.push_back(L'I');
5213 break;
5214 case 12:
5215 result.push_back(L'%');
5216 result.push_back(L'm');
5217 break;
5218 case 23:
5219 result.push_back(L'%');
5220 result.push_back(L'H');
5221 break;
5222 case 31:
5223 result.push_back(L'%');
5224 result.push_back(L'd');
5225 break;
5226 case 55:
5227 result.push_back(L'%');
5228 result.push_back(L'M');
5229 break;
5230 case 59:
5231 result.push_back(L'%');
5232 result.push_back(L'S');
5233 break;
5234 case 61:
5235 result.push_back(L'%');
5236 result.push_back(L'y');
5237 break;
5238 case 364:
5239 result.push_back(L'%');
5240 result.push_back(L'j');
5241 break;
5242 case 2061:
5243 result.push_back(L'%');
5244 result.push_back(L'Y');
5245 break;
5246 default:
5247 for (; w != wbb; ++w)
5248 result.push_back(*w);
5249 break;
5250 }
5251 continue;
5252 }
5253 if (ct.narrow(*wbb, 0) == '%')
5254 {
5255 result.push_back(L'%');
5256 result.push_back(L'%');
5257 ++wbb;
5258 continue;
5259 }
5260 result.push_back(*wbb);
5261 ++wbb;
5262 }
5263 return result;
5264}
5265
5266template <>
5267void
5268__time_get_storage<char>::init(const ctype<char>& ct)
5269{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005270 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005271 char buf[100];
5272 // __weeks_
5273 for (int i = 0; i < 7; ++i)
5274 {
5275 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005276 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005277 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005278 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005279 __weeks_[i+7] = buf;
5280 }
5281 // __months_
5282 for (int i = 0; i < 12; ++i)
5283 {
5284 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005285 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005286 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005287 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005288 __months_[i+12] = buf;
5289 }
5290 // __am_pm_
5291 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005292 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005293 __am_pm_[0] = buf;
5294 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005295 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005296 __am_pm_[1] = buf;
5297 __c_ = __analyze('c', ct);
5298 __r_ = __analyze('r', ct);
5299 __x_ = __analyze('x', ct);
5300 __X_ = __analyze('X', ct);
5301}
5302
5303template <>
5304void
5305__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5306{
5307 tm t = {0};
5308 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005309 wchar_t wbuf[100];
5310 wchar_t* wbe;
5311 mbstate_t mb = {0};
5312 // __weeks_
5313 for (int i = 0; i < 7; ++i)
5314 {
5315 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005316 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005317 mb = mbstate_t();
5318 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005319 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005320 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005321 __throw_runtime_error("locale not supported");
5322 wbe = wbuf + j;
5323 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005324 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005325 mb = mbstate_t();
5326 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005327 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005328 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005329 __throw_runtime_error("locale not supported");
5330 wbe = wbuf + j;
5331 __weeks_[i+7].assign(wbuf, wbe);
5332 }
5333 // __months_
5334 for (int i = 0; i < 12; ++i)
5335 {
5336 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005337 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005338 mb = mbstate_t();
5339 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005340 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005341 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005342 __throw_runtime_error("locale not supported");
5343 wbe = wbuf + j;
5344 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005345 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005346 mb = mbstate_t();
5347 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005348 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005349 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005350 __throw_runtime_error("locale not supported");
5351 wbe = wbuf + j;
5352 __months_[i+12].assign(wbuf, wbe);
5353 }
5354 // __am_pm_
5355 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005356 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005357 mb = mbstate_t();
5358 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005359 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005360 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005361 __throw_runtime_error("locale not supported");
5362 wbe = wbuf + j;
5363 __am_pm_[0].assign(wbuf, wbe);
5364 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005365 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005366 mb = mbstate_t();
5367 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005368 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005369 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005370 __throw_runtime_error("locale not supported");
5371 wbe = wbuf + j;
5372 __am_pm_[1].assign(wbuf, wbe);
5373 __c_ = __analyze('c', ct);
5374 __r_ = __analyze('r', ct);
5375 __x_ = __analyze('x', ct);
5376 __X_ = __analyze('X', ct);
5377}
5378
5379template <class CharT>
5380struct _LIBCPP_HIDDEN __time_get_temp
5381 : public ctype_byname<CharT>
5382{
5383 explicit __time_get_temp(const char* nm)
5384 : ctype_byname<CharT>(nm, 1) {}
5385 explicit __time_get_temp(const string& nm)
5386 : ctype_byname<CharT>(nm, 1) {}
5387};
5388
5389template <>
5390__time_get_storage<char>::__time_get_storage(const char* __nm)
5391 : __time_get(__nm)
5392{
5393 const __time_get_temp<char> ct(__nm);
5394 init(ct);
5395}
5396
5397template <>
5398__time_get_storage<char>::__time_get_storage(const string& __nm)
5399 : __time_get(__nm)
5400{
5401 const __time_get_temp<char> ct(__nm);
5402 init(ct);
5403}
5404
5405template <>
5406__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5407 : __time_get(__nm)
5408{
5409 const __time_get_temp<wchar_t> ct(__nm);
5410 init(ct);
5411}
5412
5413template <>
5414__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5415 : __time_get(__nm)
5416{
5417 const __time_get_temp<wchar_t> ct(__nm);
5418 init(ct);
5419}
5420
5421template <>
5422time_base::dateorder
5423__time_get_storage<char>::__do_date_order() const
5424{
5425 unsigned i;
5426 for (i = 0; i < __x_.size(); ++i)
5427 if (__x_[i] == '%')
5428 break;
5429 ++i;
5430 switch (__x_[i])
5431 {
5432 case 'y':
5433 case 'Y':
5434 for (++i; i < __x_.size(); ++i)
5435 if (__x_[i] == '%')
5436 break;
5437 if (i == __x_.size())
5438 break;
5439 ++i;
5440 switch (__x_[i])
5441 {
5442 case 'm':
5443 for (++i; i < __x_.size(); ++i)
5444 if (__x_[i] == '%')
5445 break;
5446 if (i == __x_.size())
5447 break;
5448 ++i;
5449 if (__x_[i] == 'd')
5450 return time_base::ymd;
5451 break;
5452 case 'd':
5453 for (++i; i < __x_.size(); ++i)
5454 if (__x_[i] == '%')
5455 break;
5456 if (i == __x_.size())
5457 break;
5458 ++i;
5459 if (__x_[i] == 'm')
5460 return time_base::ydm;
5461 break;
5462 }
5463 break;
5464 case 'm':
5465 for (++i; i < __x_.size(); ++i)
5466 if (__x_[i] == '%')
5467 break;
5468 if (i == __x_.size())
5469 break;
5470 ++i;
5471 if (__x_[i] == 'd')
5472 {
5473 for (++i; i < __x_.size(); ++i)
5474 if (__x_[i] == '%')
5475 break;
5476 if (i == __x_.size())
5477 break;
5478 ++i;
5479 if (__x_[i] == 'y' || __x_[i] == 'Y')
5480 return time_base::mdy;
5481 break;
5482 }
5483 break;
5484 case 'd':
5485 for (++i; i < __x_.size(); ++i)
5486 if (__x_[i] == '%')
5487 break;
5488 if (i == __x_.size())
5489 break;
5490 ++i;
5491 if (__x_[i] == 'm')
5492 {
5493 for (++i; i < __x_.size(); ++i)
5494 if (__x_[i] == '%')
5495 break;
5496 if (i == __x_.size())
5497 break;
5498 ++i;
5499 if (__x_[i] == 'y' || __x_[i] == 'Y')
5500 return time_base::dmy;
5501 break;
5502 }
5503 break;
5504 }
5505 return time_base::no_order;
5506}
5507
5508template <>
5509time_base::dateorder
5510__time_get_storage<wchar_t>::__do_date_order() const
5511{
5512 unsigned i;
5513 for (i = 0; i < __x_.size(); ++i)
5514 if (__x_[i] == L'%')
5515 break;
5516 ++i;
5517 switch (__x_[i])
5518 {
5519 case L'y':
5520 case L'Y':
5521 for (++i; i < __x_.size(); ++i)
5522 if (__x_[i] == L'%')
5523 break;
5524 if (i == __x_.size())
5525 break;
5526 ++i;
5527 switch (__x_[i])
5528 {
5529 case L'm':
5530 for (++i; i < __x_.size(); ++i)
5531 if (__x_[i] == L'%')
5532 break;
5533 if (i == __x_.size())
5534 break;
5535 ++i;
5536 if (__x_[i] == L'd')
5537 return time_base::ymd;
5538 break;
5539 case L'd':
5540 for (++i; i < __x_.size(); ++i)
5541 if (__x_[i] == L'%')
5542 break;
5543 if (i == __x_.size())
5544 break;
5545 ++i;
5546 if (__x_[i] == L'm')
5547 return time_base::ydm;
5548 break;
5549 }
5550 break;
5551 case L'm':
5552 for (++i; i < __x_.size(); ++i)
5553 if (__x_[i] == L'%')
5554 break;
5555 if (i == __x_.size())
5556 break;
5557 ++i;
5558 if (__x_[i] == L'd')
5559 {
5560 for (++i; i < __x_.size(); ++i)
5561 if (__x_[i] == L'%')
5562 break;
5563 if (i == __x_.size())
5564 break;
5565 ++i;
5566 if (__x_[i] == L'y' || __x_[i] == L'Y')
5567 return time_base::mdy;
5568 break;
5569 }
5570 break;
5571 case L'd':
5572 for (++i; i < __x_.size(); ++i)
5573 if (__x_[i] == L'%')
5574 break;
5575 if (i == __x_.size())
5576 break;
5577 ++i;
5578 if (__x_[i] == L'm')
5579 {
5580 for (++i; i < __x_.size(); ++i)
5581 if (__x_[i] == L'%')
5582 break;
5583 if (i == __x_.size())
5584 break;
5585 ++i;
5586 if (__x_[i] == L'y' || __x_[i] == L'Y')
5587 return time_base::dmy;
5588 break;
5589 }
5590 break;
5591 }
5592 return time_base::no_order;
5593}
5594
5595// time_put
5596
5597__time_put::__time_put(const char* nm)
5598 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5599{
5600 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005601 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602 " failed to construct for " + string(nm));
5603}
5604
5605__time_put::__time_put(const string& nm)
5606 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5607{
5608 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005609 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005610 " failed to construct for " + nm);
5611}
5612
5613__time_put::~__time_put()
5614{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005615 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005616 freelocale(__loc_);
5617}
5618
5619void
5620__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5621 char __fmt, char __mod) const
5622{
5623 char fmt[] = {'%', __fmt, __mod, 0};
5624 if (__mod != 0)
5625 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005626 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005627 __ne = __nb + n;
5628}
5629
5630void
5631__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5632 char __fmt, char __mod) const
5633{
5634 char __nar[100];
5635 char* __ne = __nar + 100;
5636 __do_put(__nar, __ne, __tm, __fmt, __mod);
5637 mbstate_t mb = {0};
5638 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005639 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005640 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005641 __throw_runtime_error("locale not supported");
5642 __we = __wb + j;
5643}
5644
5645// moneypunct_byname
5646
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005647template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005648static
5649void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005650__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5651 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5652 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005653{
5654 const char sign = static_cast<char>(money_base::sign);
5655 const char space = static_cast<char>(money_base::space);
5656 const char none = static_cast<char>(money_base::none);
5657 const char symbol = static_cast<char>(money_base::symbol);
5658 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005659 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5660
5661 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5662 // function'. "Space between sign and symbol or value" means that
5663 // if the sign is adjacent to the symbol, there's a space between
5664 // them, and otherwise there's a space between the sign and value.
5665 //
5666 // C11's localeconv specifies that the fourth character of an
5667 // international curr_symbol is used to separate the sign and
5668 // value when sep_by_space says to do so. C++ can't represent
5669 // that, so we just use a space. When sep_by_space says to
5670 // separate the symbol and value-or-sign with a space, we rearrange the
5671 // curr_symbol to put its spacing character on the correct side of
5672 // the symbol.
5673 //
5674 // We also need to avoid adding an extra space between the sign
5675 // and value when the currency symbol is suppressed (by not
5676 // setting showbase). We match glibc's strfmon by interpreting
5677 // sep_by_space==1 as "omit the space when the currency symbol is
5678 // absent".
5679 //
5680 // Users who want to get this right should use ICU instead.
5681
Howard Hinnantc51e1022010-05-11 19:42:16 +00005682 switch (cs_precedes)
5683 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005684 case 0: // value before curr_symbol
5685 if (symbol_contains_sep) {
5686 // Move the separator to before the symbol, to place it
5687 // between the value and symbol.
5688 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5689 __curr_symbol_.end());
5690 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005691 switch (sign_posn)
5692 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005693 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005694 pat.field[0] = sign;
5695 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005696 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005697 pat.field[3] = symbol;
5698 switch (sep_by_space)
5699 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005700 case 0: // No space separates the currency symbol and value.
5701 // This case may have changed between C99 and C11;
5702 // assume the currency symbol matches the intention.
5703 case 2: // Space between sign and currency or value.
5704 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005705 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005706 case 1: // Space between currency-and-sign or currency and value.
5707 if (!symbol_contains_sep) {
5708 // We insert the space into the symbol instead of
5709 // setting pat.field[2]=space so that when
5710 // showbase is not set, the space goes away too.
5711 __curr_symbol_.insert(0, 1, space_char);
5712 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005713 return;
5714 default:
5715 break;
5716 }
5717 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005718 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005719 pat.field[0] = sign;
5720 pat.field[3] = symbol;
5721 switch (sep_by_space)
5722 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005723 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005724 pat.field[1] = value;
5725 pat.field[2] = none;
5726 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005727 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005728 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005729 pat.field[2] = none;
5730 if (!symbol_contains_sep) {
5731 // We insert the space into the symbol instead of
5732 // setting pat.field[2]=space so that when
5733 // showbase is not set, the space goes away too.
5734 __curr_symbol_.insert(0, 1, space_char);
5735 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005736 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005737 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005738 pat.field[1] = space;
5739 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005740 if (symbol_contains_sep) {
5741 // Remove the separator from the symbol, since it
5742 // has already appeared after the sign.
5743 __curr_symbol_.erase(__curr_symbol_.begin());
5744 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 return;
5746 default:
5747 break;
5748 }
5749 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005750 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005751 pat.field[0] = value;
5752 pat.field[3] = sign;
5753 switch (sep_by_space)
5754 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005755 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005756 pat.field[1] = none;
5757 pat.field[2] = symbol;
5758 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005759 case 1: // Space between currency-and-sign or currency and value.
5760 if (!symbol_contains_sep) {
5761 // We insert the space into the symbol instead of
5762 // setting pat.field[1]=space so that when
5763 // showbase is not set, the space goes away too.
5764 __curr_symbol_.insert(0, 1, space_char);
5765 }
5766 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005767 pat.field[2] = symbol;
5768 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005769 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005770 pat.field[1] = symbol;
5771 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005772 if (symbol_contains_sep) {
5773 // Remove the separator from the symbol, since it
5774 // should not be removed if showbase is absent.
5775 __curr_symbol_.erase(__curr_symbol_.begin());
5776 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005777 return;
5778 default:
5779 break;
5780 }
5781 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005782 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005783 pat.field[0] = value;
5784 pat.field[3] = symbol;
5785 switch (sep_by_space)
5786 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005787 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005788 pat.field[1] = none;
5789 pat.field[2] = sign;
5790 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005791 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005792 pat.field[1] = space;
5793 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005794 if (symbol_contains_sep) {
5795 // Remove the separator from the symbol, since it
5796 // has already appeared before the sign.
5797 __curr_symbol_.erase(__curr_symbol_.begin());
5798 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005799 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005800 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005801 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005802 pat.field[2] = none;
5803 if (!symbol_contains_sep) {
5804 // We insert the space into the symbol instead of
5805 // setting pat.field[2]=space so that when
5806 // showbase is not set, the space goes away too.
5807 __curr_symbol_.insert(0, 1, space_char);
5808 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005809 return;
5810 default:
5811 break;
5812 }
5813 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005814 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005815 pat.field[0] = value;
5816 pat.field[3] = sign;
5817 switch (sep_by_space)
5818 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005819 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005820 pat.field[1] = none;
5821 pat.field[2] = symbol;
5822 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005823 case 1: // Space between currency-and-sign or currency and value.
5824 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005825 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005826 if (!symbol_contains_sep) {
5827 // We insert the space into the symbol instead of
5828 // setting pat.field[1]=space so that when
5829 // showbase is not set, the space goes away too.
5830 __curr_symbol_.insert(0, 1, space_char);
5831 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005832 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005833 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005834 pat.field[1] = symbol;
5835 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005836 if (symbol_contains_sep) {
5837 // Remove the separator from the symbol, since it
5838 // should not disappear when showbase is absent.
5839 __curr_symbol_.erase(__curr_symbol_.begin());
5840 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005841 return;
5842 default:
5843 break;
5844 }
5845 break;
5846 default:
5847 break;
5848 }
5849 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005850 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005851 switch (sign_posn)
5852 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005853 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005854 pat.field[0] = sign;
5855 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005856 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005857 pat.field[3] = value;
5858 switch (sep_by_space)
5859 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005860 case 0: // No space separates the currency symbol and value.
5861 // This case may have changed between C99 and C11;
5862 // assume the currency symbol matches the intention.
5863 case 2: // Space between sign and currency or value.
5864 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005865 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005866 case 1: // Space between currency-and-sign or currency and value.
5867 if (!symbol_contains_sep) {
5868 // We insert the space into the symbol instead of
5869 // setting pat.field[2]=space so that when
5870 // showbase is not set, the space goes away too.
5871 __curr_symbol_.insert(0, 1, space_char);
5872 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005873 return;
5874 default:
5875 break;
5876 }
5877 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005878 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005879 pat.field[0] = sign;
5880 pat.field[3] = value;
5881 switch (sep_by_space)
5882 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005883 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005884 pat.field[1] = symbol;
5885 pat.field[2] = none;
5886 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005887 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005888 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005889 pat.field[2] = none;
5890 if (!symbol_contains_sep) {
5891 // We insert the space into the symbol instead of
5892 // setting pat.field[2]=space so that when
5893 // showbase is not set, the space goes away too.
5894 __curr_symbol_.push_back(space_char);
5895 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005896 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005897 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005898 pat.field[1] = space;
5899 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005900 if (symbol_contains_sep) {
5901 // Remove the separator from the symbol, since it
5902 // has already appeared after the sign.
5903 __curr_symbol_.pop_back();
5904 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005905 return;
5906 default:
5907 break;
5908 }
5909 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005910 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005911 pat.field[0] = symbol;
5912 pat.field[3] = sign;
5913 switch (sep_by_space)
5914 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005915 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005916 pat.field[1] = none;
5917 pat.field[2] = value;
5918 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005919 case 1: // Space between currency-and-sign or currency and value.
5920 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005921 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005922 if (!symbol_contains_sep) {
5923 // We insert the space into the symbol instead of
5924 // setting pat.field[1]=space so that when
5925 // showbase is not set, the space goes away too.
5926 __curr_symbol_.push_back(space_char);
5927 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005928 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005930 pat.field[1] = value;
5931 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005932 if (symbol_contains_sep) {
5933 // Remove the separator from the symbol, since it
5934 // will appear before the sign.
5935 __curr_symbol_.pop_back();
5936 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005937 return;
5938 default:
5939 break;
5940 }
5941 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005942 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005943 pat.field[0] = sign;
5944 pat.field[3] = value;
5945 switch (sep_by_space)
5946 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005947 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005948 pat.field[1] = symbol;
5949 pat.field[2] = none;
5950 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005951 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005952 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005953 pat.field[2] = none;
5954 if (!symbol_contains_sep) {
5955 // We insert the space into the symbol instead of
5956 // setting pat.field[2]=space so that when
5957 // showbase is not set, the space goes away too.
5958 __curr_symbol_.push_back(space_char);
5959 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005960 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005961 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005962 pat.field[1] = space;
5963 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005964 if (symbol_contains_sep) {
5965 // Remove the separator from the symbol, since it
5966 // has already appeared after the sign.
5967 __curr_symbol_.pop_back();
5968 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 return;
5970 default:
5971 break;
5972 }
5973 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005974 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005975 pat.field[0] = symbol;
5976 pat.field[3] = value;
5977 switch (sep_by_space)
5978 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005979 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005980 pat.field[1] = sign;
5981 pat.field[2] = none;
5982 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005983 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005984 pat.field[1] = sign;
5985 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005986 if (symbol_contains_sep) {
5987 // Remove the separator from the symbol, since it
5988 // should not disappear when showbase is absent.
5989 __curr_symbol_.pop_back();
5990 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005991 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005992 case 2: // Space between sign and currency or value.
5993 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005994 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005995 if (!symbol_contains_sep) {
5996 // We insert the space into the symbol instead of
5997 // setting pat.field[1]=space so that when
5998 // showbase is not set, the space goes away too.
5999 __curr_symbol_.push_back(space_char);
6000 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006001 return;
6002 default:
6003 break;
6004 }
6005 break;
6006 default:
6007 break;
6008 }
6009 break;
6010 default:
6011 break;
6012 }
6013 pat.field[0] = symbol;
6014 pat.field[1] = sign;
6015 pat.field[2] = none;
6016 pat.field[3] = value;
6017}
6018
6019template<>
6020void
6021moneypunct_byname<char, false>::init(const char* nm)
6022{
6023 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006024 __libcpp_unique_locale loc(nm);
6025 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006026 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006027 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006028
Ben Craig3756b922016-03-09 15:39:39 +00006029 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006030 if (!checked_string_to_char_convert(__decimal_point_,
6031 lc->mon_decimal_point,
6032 loc.get()))
6033 __decimal_point_ = base::do_decimal_point();
6034 if (!checked_string_to_char_convert(__thousands_sep_,
6035 lc->mon_thousands_sep,
6036 loc.get()))
6037 __thousands_sep_ = base::do_thousands_sep();
6038
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039 __grouping_ = lc->mon_grouping;
6040 __curr_symbol_ = lc->currency_symbol;
6041 if (lc->frac_digits != CHAR_MAX)
6042 __frac_digits_ = lc->frac_digits;
6043 else
6044 __frac_digits_ = base::do_frac_digits();
6045 if (lc->p_sign_posn == 0)
6046 __positive_sign_ = "()";
6047 else
6048 __positive_sign_ = lc->positive_sign;
6049 if (lc->n_sign_posn == 0)
6050 __negative_sign_ = "()";
6051 else
6052 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006053 // Assume the positive and negative formats will want spaces in
6054 // the same places in curr_symbol since there's no way to
6055 // represent anything else.
6056 string_type __dummy_curr_symbol = __curr_symbol_;
6057 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6058 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6059 __init_pat(__neg_format_, __curr_symbol_, false,
6060 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006061}
6062
6063template<>
6064void
6065moneypunct_byname<char, true>::init(const char* nm)
6066{
6067 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006068 __libcpp_unique_locale loc(nm);
6069 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006070 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006071 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006072
Ben Craig3756b922016-03-09 15:39:39 +00006073 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006074 if (!checked_string_to_char_convert(__decimal_point_,
6075 lc->mon_decimal_point,
6076 loc.get()))
6077 __decimal_point_ = base::do_decimal_point();
6078 if (!checked_string_to_char_convert(__thousands_sep_,
6079 lc->mon_thousands_sep,
6080 loc.get()))
6081 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006082 __grouping_ = lc->mon_grouping;
6083 __curr_symbol_ = lc->int_curr_symbol;
6084 if (lc->int_frac_digits != CHAR_MAX)
6085 __frac_digits_ = lc->int_frac_digits;
6086 else
6087 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006088#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006089 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006090#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006091 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006092#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006093 __positive_sign_ = "()";
6094 else
6095 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006096#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006097 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006098#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006099 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006100#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006101 __negative_sign_ = "()";
6102 else
6103 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006104 // Assume the positive and negative formats will want spaces in
6105 // the same places in curr_symbol since there's no way to
6106 // represent anything else.
6107 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006108#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006109 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6110 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6111 __init_pat(__neg_format_, __curr_symbol_, true,
6112 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006113#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006114 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6115 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6116 lc->int_p_sign_posn, ' ');
6117 __init_pat(__neg_format_, __curr_symbol_, true,
6118 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6119 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006120#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006121}
6122
6123template<>
6124void
6125moneypunct_byname<wchar_t, false>::init(const char* nm)
6126{
6127 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006128 __libcpp_unique_locale loc(nm);
6129 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006130 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006131 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006132 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006133 if (!checked_string_to_wchar_convert(__decimal_point_,
6134 lc->mon_decimal_point,
6135 loc.get()))
6136 __decimal_point_ = base::do_decimal_point();
6137 if (!checked_string_to_wchar_convert(__thousands_sep_,
6138 lc->mon_thousands_sep,
6139 loc.get()))
6140 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141 __grouping_ = lc->mon_grouping;
6142 wchar_t wbuf[100];
6143 mbstate_t mb = {0};
6144 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006145 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006146 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006147 __throw_runtime_error("locale not supported");
6148 wchar_t* wbe = wbuf + j;
6149 __curr_symbol_.assign(wbuf, wbe);
6150 if (lc->frac_digits != CHAR_MAX)
6151 __frac_digits_ = lc->frac_digits;
6152 else
6153 __frac_digits_ = base::do_frac_digits();
6154 if (lc->p_sign_posn == 0)
6155 __positive_sign_ = L"()";
6156 else
6157 {
6158 mb = mbstate_t();
6159 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006160 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006161 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006162 __throw_runtime_error("locale not supported");
6163 wbe = wbuf + j;
6164 __positive_sign_.assign(wbuf, wbe);
6165 }
6166 if (lc->n_sign_posn == 0)
6167 __negative_sign_ = L"()";
6168 else
6169 {
6170 mb = mbstate_t();
6171 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006172 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006173 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006174 __throw_runtime_error("locale not supported");
6175 wbe = wbuf + j;
6176 __negative_sign_.assign(wbuf, wbe);
6177 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006178 // Assume the positive and negative formats will want spaces in
6179 // the same places in curr_symbol since there's no way to
6180 // represent anything else.
6181 string_type __dummy_curr_symbol = __curr_symbol_;
6182 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6183 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6184 __init_pat(__neg_format_, __curr_symbol_, false,
6185 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006186}
6187
6188template<>
6189void
6190moneypunct_byname<wchar_t, true>::init(const char* nm)
6191{
6192 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006193 __libcpp_unique_locale loc(nm);
6194 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006195 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006196 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006197
Ben Craig3756b922016-03-09 15:39:39 +00006198 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006199 if (!checked_string_to_wchar_convert(__decimal_point_,
6200 lc->mon_decimal_point,
6201 loc.get()))
6202 __decimal_point_ = base::do_decimal_point();
6203 if (!checked_string_to_wchar_convert(__thousands_sep_,
6204 lc->mon_thousands_sep,
6205 loc.get()))
6206 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006207 __grouping_ = lc->mon_grouping;
6208 wchar_t wbuf[100];
6209 mbstate_t mb = {0};
6210 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006211 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006212 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006213 __throw_runtime_error("locale not supported");
6214 wchar_t* wbe = wbuf + j;
6215 __curr_symbol_.assign(wbuf, wbe);
6216 if (lc->int_frac_digits != CHAR_MAX)
6217 __frac_digits_ = lc->int_frac_digits;
6218 else
6219 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006220#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006221 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006222#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006223 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006224#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006225 __positive_sign_ = L"()";
6226 else
6227 {
6228 mb = mbstate_t();
6229 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006230 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006231 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006232 __throw_runtime_error("locale not supported");
6233 wbe = wbuf + j;
6234 __positive_sign_.assign(wbuf, wbe);
6235 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006236#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006237 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006238#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006239 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006240#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006241 __negative_sign_ = L"()";
6242 else
6243 {
6244 mb = mbstate_t();
6245 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006246 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006247 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006248 __throw_runtime_error("locale not supported");
6249 wbe = wbuf + j;
6250 __negative_sign_.assign(wbuf, wbe);
6251 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006252 // Assume the positive and negative formats will want spaces in
6253 // the same places in curr_symbol since there's no way to
6254 // represent anything else.
6255 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006256#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006257 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6258 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6259 __init_pat(__neg_format_, __curr_symbol_, true,
6260 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006261#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006262 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6263 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6264 lc->int_p_sign_posn, L' ');
6265 __init_pat(__neg_format_, __curr_symbol_, true,
6266 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6267 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006268#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006269}
6270
6271void __do_nothing(void*) {}
6272
6273void __throw_runtime_error(const char* msg)
6274{
Howard Hinnant72f73582010-08-11 17:04:31 +00006275#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006276 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006277#else
6278 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006279 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006280#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006281}
6282
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006283template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6284template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006285
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006286template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6287template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006288
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006289template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6290template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006291
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006292template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6293template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006294
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006295template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6296template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006297
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006298template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6299template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006300
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006301template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6302template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006303
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006304template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6305template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006306
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006307template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6308template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006309
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006310template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6311template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6312template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6313template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006314
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006315template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6316template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6317template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6318template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006319
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006320template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6321template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006322
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006323template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6324template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006325
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006326template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6327template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006328
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006329template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6330template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006331
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006332template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6333template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006334
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006335template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6336template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006337
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006338template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6339template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
Reid Klecknerbc2a2ce2021-01-15 08:56:34 -08006340template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6341template 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 -04006342#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006343template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6344template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6345#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006346
Howard Hinnantc51e1022010-05-11 19:42:16 +00006347_LIBCPP_END_NAMESPACE_STD