blob: 8aa67f7b38a8bc89e96e024a4a02c8d2a17c0cab [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantc51e1022010-05-11 19:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
David Chisnall8074c342012-02-29 13:05:08 +00009// On Solaris, we need to define something to make the C99 parts of localeconv
10// visible.
11#ifdef __sun__
12#define _LCONV_C99
13#endif
14
Howard Hinnantc51e1022010-05-11 19:42:16 +000015#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000016#include "clocale"
Louis Dionneafc98402021-09-09 13:52:38 -040017#include "codecvt"
18#include "cstdio"
19#include "cstdlib"
Howard Hinnantc51e1022010-05-11 19:42:16 +000020#include "cstring"
21#include "cwctype"
Louis Dionneafc98402021-09-09 13:52:38 -040022#include "locale"
23#include "string"
24#include "type_traits"
25#include "typeinfo"
26#include "vector"
27
28#if defined(_LIBCPP_MSVCRT)
29# define _CTYPE_DISABLE_MACROS
Marshall Clow3477ec92014-07-10 15:20:28 +000030#endif
Louis Dionneafc98402021-09-09 13:52:38 -040031
32#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
33# include "__support/win32/locale_win32.h"
34#elif !defined(__BIONIC__) && !defined(__NuttX__)
35# include <langinfo.h>
36#endif
37
Weiming Zhaob613db72017-09-19 23:18:03 +000038#include "include/atomic_support.h"
Arthur O'Dwyerf5c4bb02021-04-26 09:56:50 -040039#include "include/sso_allocator.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000040#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000041
Marshall Clowab9c1772013-02-07 17:20:56 +000042// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070043// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000044#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000045#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000046#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000047
Howard Hinnantc51e1022010-05-11 19:42:16 +000048_LIBCPP_BEGIN_NAMESPACE_STD
49
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000050struct __libcpp_unique_locale {
51 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
52
53 ~__libcpp_unique_locale() {
54 if (__loc_)
55 freelocale(__loc_);
56 }
57
58 explicit operator bool() const { return __loc_; }
59
60 locale_t& get() { return __loc_; }
61
62 locale_t __loc_;
63private:
64 __libcpp_unique_locale(__libcpp_unique_locale const&);
65 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
66};
67
Howard Hinnantf312e3e2011-09-28 23:39:33 +000068#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000069locale_t __cloc() {
70 // In theory this could create a race condition. In practice
71 // the race condition is non-fatal since it will just create
72 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000073 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
74 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000075}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000076#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000077
Howard Hinnantc51e1022010-05-11 19:42:16 +000078namespace {
79
80struct release
81{
82 void operator()(locale::facet* p) {p->__release_shared();}
83};
84
Louis Dionne6e41a152021-08-09 13:26:04 -040085template <class T, class ...Args>
86T& make(Args ...args)
Howard Hinnantc51e1022010-05-11 19:42:16 +000087{
88 static typename aligned_storage<sizeof(T)>::type buf;
Louis Dionne6e41a152021-08-09 13:26:04 -040089 auto *obj = ::new (&buf) T(args...);
Eric Fiselier4db80032017-05-05 20:32:26 +000090 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000091}
92
Howard Hinnant3d2417c2012-12-27 21:17:53 +000093template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +000094inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +000095_LIBCPP_CONSTEXPR
96size_t
97countof(const T (&)[N])
98{
99 return N;
100}
101
102template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000103inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000104_LIBCPP_CONSTEXPR
105size_t
106countof(const T * const begin, const T * const end)
107{
108 return static_cast<size_t>(end - begin);
109}
110
Marshall Clow8fea1612016-08-25 15:09:01 +0000111_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
112{
113#ifndef _LIBCPP_NO_EXCEPTIONS
114 throw runtime_error(msg);
115#else
116 (void)msg;
117 _VSTD::abort();
118#endif
119}
120
Howard Hinnantc51e1022010-05-11 19:42:16 +0000121}
122
Howard Hinnantdd099492013-08-29 23:37:50 +0000123#if defined(_AIX)
124// Set priority to INT_MIN + 256 + 150
125# pragma priority ( -2147483242 )
126#endif
127
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000128const locale::category locale::none;
129const locale::category locale::collate;
130const locale::category locale::ctype;
131const locale::category locale::monetary;
132const locale::category locale::numeric;
133const locale::category locale::time;
134const locale::category locale::messages;
135const locale::category locale::all;
136
Howard Hinnantc51e1022010-05-11 19:42:16 +0000137class _LIBCPP_HIDDEN locale::__imp
138 : public facet
139{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100140 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000141#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000142// FIXME: MSVC doesn't support aligned parameters by value.
143// I can't get the __sso_allocator to work here
144// for MSVC I think for this reason.
145 vector<facet*> facets_;
146#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000147 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000148#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000149 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000150public:
151 explicit __imp(size_t refs = 0);
152 explicit __imp(const string& name, size_t refs = 0);
153 __imp(const __imp&);
154 __imp(const __imp&, const string&, locale::category c);
155 __imp(const __imp& other, const __imp& one, locale::category c);
156 __imp(const __imp&, facet* f, long id);
157 ~__imp();
158
159 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000160 bool has_facet(long id) const
161 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000162 const locale::facet* use_facet(long id) const;
163
164 static const locale& make_classic();
165 static locale& make_global();
166private:
167 void install(facet* f, long id);
168 template <class F> void install(F* f) {install(f, f->id.__get());}
169 template <class F> void install_from(const __imp& other);
170};
171
172locale::__imp::__imp(size_t refs)
173 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000174 facets_(N),
175 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000176{
177 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000178 install(&make<_VSTD::collate<char> >(1u));
179 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000180 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000181 install(&make<_VSTD::ctype<wchar_t> >(1u));
182 install(&make<codecvt<char, char, mbstate_t> >(1u));
183 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100184_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000185 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
186 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100187_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400188#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100189 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
190 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
191#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000192 install(&make<numpunct<char> >(1u));
193 install(&make<numpunct<wchar_t> >(1u));
194 install(&make<num_get<char> >(1u));
195 install(&make<num_get<wchar_t> >(1u));
196 install(&make<num_put<char> >(1u));
197 install(&make<num_put<wchar_t> >(1u));
198 install(&make<moneypunct<char, false> >(1u));
199 install(&make<moneypunct<char, true> >(1u));
200 install(&make<moneypunct<wchar_t, false> >(1u));
201 install(&make<moneypunct<wchar_t, true> >(1u));
202 install(&make<money_get<char> >(1u));
203 install(&make<money_get<wchar_t> >(1u));
204 install(&make<money_put<char> >(1u));
205 install(&make<money_put<wchar_t> >(1u));
206 install(&make<time_get<char> >(1u));
207 install(&make<time_get<wchar_t> >(1u));
208 install(&make<time_put<char> >(1u));
209 install(&make<time_put<wchar_t> >(1u));
210 install(&make<_VSTD::messages<char> >(1u));
211 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000212}
213
214locale::__imp::__imp(const string& name, size_t refs)
215 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000216 facets_(N),
217 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000218{
Howard Hinnant72f73582010-08-11 17:04:31 +0000219#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000220 try
221 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400222#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000223 facets_ = locale::classic().__locale_->facets_;
224 for (unsigned i = 0; i < facets_.size(); ++i)
225 if (facets_[i])
226 facets_[i]->__add_shared();
227 install(new collate_byname<char>(name_));
228 install(new collate_byname<wchar_t>(name_));
229 install(new ctype_byname<char>(name_));
230 install(new ctype_byname<wchar_t>(name_));
231 install(new codecvt_byname<char, char, mbstate_t>(name_));
232 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100233_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000234 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
235 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100236_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400237#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100238 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
239 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
240#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000241 install(new numpunct_byname<char>(name_));
242 install(new numpunct_byname<wchar_t>(name_));
243 install(new moneypunct_byname<char, false>(name_));
244 install(new moneypunct_byname<char, true>(name_));
245 install(new moneypunct_byname<wchar_t, false>(name_));
246 install(new moneypunct_byname<wchar_t, true>(name_));
247 install(new time_get_byname<char>(name_));
248 install(new time_get_byname<wchar_t>(name_));
249 install(new time_put_byname<char>(name_));
250 install(new time_put_byname<wchar_t>(name_));
251 install(new messages_byname<char>(name_));
252 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000253#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000254 }
255 catch (...)
256 {
257 for (unsigned i = 0; i < facets_.size(); ++i)
258 if (facets_[i])
259 facets_[i]->__release_shared();
260 throw;
261 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400262#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000263}
264
265locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000266 : facets_(max<size_t>(N, other.facets_.size())),
267 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000268{
269 facets_ = other.facets_;
270 for (unsigned i = 0; i < facets_.size(); ++i)
271 if (facets_[i])
272 facets_[i]->__add_shared();
273}
274
275locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000276 : facets_(N),
277 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000278{
279 facets_ = other.facets_;
280 for (unsigned i = 0; i < facets_.size(); ++i)
281 if (facets_[i])
282 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000283#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284 try
285 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400286#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000287 if (c & locale::collate)
288 {
289 install(new collate_byname<char>(name));
290 install(new collate_byname<wchar_t>(name));
291 }
292 if (c & locale::ctype)
293 {
294 install(new ctype_byname<char>(name));
295 install(new ctype_byname<wchar_t>(name));
296 install(new codecvt_byname<char, char, mbstate_t>(name));
297 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100298_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000299 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
300 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100301_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400302#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100303 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
304 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
305#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000306 }
307 if (c & locale::monetary)
308 {
309 install(new moneypunct_byname<char, false>(name));
310 install(new moneypunct_byname<char, true>(name));
311 install(new moneypunct_byname<wchar_t, false>(name));
312 install(new moneypunct_byname<wchar_t, true>(name));
313 }
314 if (c & locale::numeric)
315 {
316 install(new numpunct_byname<char>(name));
317 install(new numpunct_byname<wchar_t>(name));
318 }
319 if (c & locale::time)
320 {
321 install(new time_get_byname<char>(name));
322 install(new time_get_byname<wchar_t>(name));
323 install(new time_put_byname<char>(name));
324 install(new time_put_byname<wchar_t>(name));
325 }
326 if (c & locale::messages)
327 {
328 install(new messages_byname<char>(name));
329 install(new messages_byname<wchar_t>(name));
330 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000331#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000332 }
333 catch (...)
334 {
335 for (unsigned i = 0; i < facets_.size(); ++i)
336 if (facets_[i])
337 facets_[i]->__release_shared();
338 throw;
339 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400340#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000341}
342
343template<class F>
344inline
345void
346locale::__imp::install_from(const locale::__imp& one)
347{
348 long id = F::id.__get();
349 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
350}
351
352locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000353 : facets_(N),
354 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000355{
356 facets_ = other.facets_;
357 for (unsigned i = 0; i < facets_.size(); ++i)
358 if (facets_[i])
359 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000360#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000361 try
362 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400363#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000364 if (c & locale::collate)
365 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000366 install_from<_VSTD::collate<char> >(one);
367 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000368 }
369 if (c & locale::ctype)
370 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000371 install_from<_VSTD::ctype<char> >(one);
372 install_from<_VSTD::ctype<wchar_t> >(one);
373 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100374_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000375 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
376 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100377_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400378#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100379 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
380 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
381#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000382 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000383 }
384 if (c & locale::monetary)
385 {
386 install_from<moneypunct<char, false> >(one);
387 install_from<moneypunct<char, true> >(one);
388 install_from<moneypunct<wchar_t, false> >(one);
389 install_from<moneypunct<wchar_t, true> >(one);
390 install_from<money_get<char> >(one);
391 install_from<money_get<wchar_t> >(one);
392 install_from<money_put<char> >(one);
393 install_from<money_put<wchar_t> >(one);
394 }
395 if (c & locale::numeric)
396 {
397 install_from<numpunct<char> >(one);
398 install_from<numpunct<wchar_t> >(one);
399 install_from<num_get<char> >(one);
400 install_from<num_get<wchar_t> >(one);
401 install_from<num_put<char> >(one);
402 install_from<num_put<wchar_t> >(one);
403 }
404 if (c & locale::time)
405 {
406 install_from<time_get<char> >(one);
407 install_from<time_get<wchar_t> >(one);
408 install_from<time_put<char> >(one);
409 install_from<time_put<wchar_t> >(one);
410 }
411 if (c & locale::messages)
412 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000413 install_from<_VSTD::messages<char> >(one);
414 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000415 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000416#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000417 }
418 catch (...)
419 {
420 for (unsigned i = 0; i < facets_.size(); ++i)
421 if (facets_[i])
422 facets_[i]->__release_shared();
423 throw;
424 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400425#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000426}
427
428locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000429 : facets_(max<size_t>(N, other.facets_.size()+1)),
430 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000431{
432 f->__add_shared();
433 unique_ptr<facet, release> hold(f);
434 facets_ = other.facets_;
435 for (unsigned i = 0; i < other.facets_.size(); ++i)
436 if (facets_[i])
437 facets_[i]->__add_shared();
438 install(hold.get(), id);
439}
440
441locale::__imp::~__imp()
442{
443 for (unsigned i = 0; i < facets_.size(); ++i)
444 if (facets_[i])
445 facets_[i]->__release_shared();
446}
447
448void
449locale::__imp::install(facet* f, long id)
450{
451 f->__add_shared();
452 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000453 if (static_cast<size_t>(id) >= facets_.size())
454 facets_.resize(static_cast<size_t>(id+1));
455 if (facets_[static_cast<size_t>(id)])
456 facets_[static_cast<size_t>(id)]->__release_shared();
457 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000458}
459
460const locale::facet*
461locale::__imp::use_facet(long id) const
462{
463 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000464 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000465 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000466}
467
468// locale
469
470const locale&
471locale::__imp::make_classic()
472{
473 // only one thread can get in here and it only gets in once
474 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000475 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000476 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000477 return *c;
478}
479
480const locale&
481locale::classic()
482{
483 static const locale& c = __imp::make_classic();
484 return c;
485}
486
487locale&
488locale::__imp::make_global()
489{
490 // only one thread can get in here and it only gets in once
491 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000492 auto *obj = ::new (&buf) locale(locale::classic());
493 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000494}
495
496locale&
497locale::__global()
498{
499 static locale& g = __imp::make_global();
500 return g;
501}
502
Louis Dionne65358e12021-03-01 12:09:45 -0500503locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000504 : __locale_(__global().__locale_)
505{
506 __locale_->__add_shared();
507}
508
Louis Dionne65358e12021-03-01 12:09:45 -0500509locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000510 : __locale_(l.__locale_)
511{
512 __locale_->__add_shared();
513}
514
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000515locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000516{
517 __locale_->__release_shared();
518}
519
520const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500521locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000522{
523 other.__locale_->__add_shared();
524 __locale_->__release_shared();
525 __locale_ = other.__locale_;
526 return *this;
527}
528
529locale::locale(const char* name)
530 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100531 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000532{
533 __locale_->__add_shared();
534}
535
536locale::locale(const string& name)
537 : __locale_(new __imp(name))
538{
539 __locale_->__add_shared();
540}
541
542locale::locale(const locale& other, const char* name, category c)
543 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100544 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000545{
546 __locale_->__add_shared();
547}
548
549locale::locale(const locale& other, const string& name, category c)
550 : __locale_(new __imp(*other.__locale_, name, c))
551{
552 __locale_->__add_shared();
553}
554
555locale::locale(const locale& other, const locale& one, category c)
556 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
557{
558 __locale_->__add_shared();
559}
560
561string
562locale::name() const
563{
564 return __locale_->name();
565}
566
567void
568locale::__install_ctor(const locale& other, facet* f, long id)
569{
570 if (f)
571 __locale_ = new __imp(*other.__locale_, f, id);
572 else
573 __locale_ = other.__locale_;
574 __locale_->__add_shared();
575}
576
577locale
578locale::global(const locale& loc)
579{
580 locale& g = __global();
581 locale r = g;
582 g = loc;
583 if (g.name() != "*")
584 setlocale(LC_ALL, g.name().c_str());
585 return r;
586}
587
588bool
589locale::has_facet(id& x) const
590{
591 return __locale_->has_facet(x.__get());
592}
593
594const locale::facet*
595locale::use_facet(id& x) const
596{
597 return __locale_->use_facet(x.__get());
598}
599
600bool
601locale::operator==(const locale& y) const
602{
603 return (__locale_ == y.__locale_)
604 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
605}
606
607// locale::facet
608
609locale::facet::~facet()
610{
611}
612
613void
Louis Dionne65358e12021-03-01 12:09:45 -0500614locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000615{
616 delete this;
617}
618
619// locale::id
620
621int32_t locale::id::__next_id = 0;
622
623namespace
624{
625
626class __fake_bind
627{
628 locale::id* id_;
629 void (locale::id::* pmf_)();
630public:
631 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
632 : id_(id), pmf_(pmf) {}
633
634 void operator()() const
635 {
636 (id_->*pmf_)();
637 }
638};
639
640}
641
642long
643locale::id::__get()
644{
645 call_once(__flag_, __fake_bind(&locale::id::__init, this));
646 return __id_ - 1;
647}
648
649void
650locale::id::__init()
651{
Weiming Zhaob613db72017-09-19 23:18:03 +0000652 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000653}
654
655// template <> class collate_byname<char>
656
657collate_byname<char>::collate_byname(const char* n, size_t refs)
658 : collate<char>(refs),
659 __l(newlocale(LC_ALL_MASK, n, 0))
660{
661 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000662 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000663 " failed to construct for " + string(n));
664}
665
666collate_byname<char>::collate_byname(const string& name, size_t refs)
667 : collate<char>(refs),
668 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
669{
670 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000671 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000672 " failed to construct for " + name);
673}
674
675collate_byname<char>::~collate_byname()
676{
677 freelocale(__l);
678}
679
680int
681collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
682 const char_type* __lo2, const char_type* __hi2) const
683{
684 string_type lhs(__lo1, __hi1);
685 string_type rhs(__lo2, __hi2);
686 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
687 if (r < 0)
688 return -1;
689 if (r > 0)
690 return 1;
691 return r;
692}
693
694collate_byname<char>::string_type
695collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
696{
697 const string_type in(lo, hi);
698 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
699 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
700 return out;
701}
702
703// template <> class collate_byname<wchar_t>
704
705collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
706 : collate<wchar_t>(refs),
707 __l(newlocale(LC_ALL_MASK, n, 0))
708{
709 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000710 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000711 " failed to construct for " + string(n));
712}
713
714collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
715 : collate<wchar_t>(refs),
716 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
717{
718 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000719 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000720 " failed to construct for " + name);
721}
722
723collate_byname<wchar_t>::~collate_byname()
724{
725 freelocale(__l);
726}
727
728int
729collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
730 const char_type* __lo2, const char_type* __hi2) const
731{
732 string_type lhs(__lo1, __hi1);
733 string_type rhs(__lo2, __hi2);
734 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
735 if (r < 0)
736 return -1;
737 if (r > 0)
738 return 1;
739 return r;
740}
741
742collate_byname<wchar_t>::string_type
743collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
744{
745 const string_type in(lo, hi);
746 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
747 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
748 return out;
749}
750
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000751const ctype_base::mask ctype_base::space;
752const ctype_base::mask ctype_base::print;
753const ctype_base::mask ctype_base::cntrl;
754const ctype_base::mask ctype_base::upper;
755const ctype_base::mask ctype_base::lower;
756const ctype_base::mask ctype_base::alpha;
757const ctype_base::mask ctype_base::digit;
758const ctype_base::mask ctype_base::punct;
759const ctype_base::mask ctype_base::xdigit;
760const ctype_base::mask ctype_base::blank;
761const ctype_base::mask ctype_base::alnum;
762const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700763
Louis Dionne945f8682021-09-09 13:29:24 -0400764// template <> class ctype<wchar_t>;
765
Howard Hinnantc51e1022010-05-11 19:42:16 +0000766locale::id ctype<wchar_t>::id;
767
768ctype<wchar_t>::~ctype()
769{
770}
771
772bool
773ctype<wchar_t>::do_is(mask m, char_type c) const
774{
Marshall Clowd920eea2013-10-21 15:07:28 +0000775 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000776}
777
778const wchar_t*
779ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
780{
781 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000782 *vec = static_cast<mask>(isascii(*low) ?
783 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000784 return low;
785}
786
787const wchar_t*
788ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
789{
790 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000791 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000792 break;
793 return low;
794}
795
796const wchar_t*
797ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
798{
799 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000800 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000801 break;
802 return low;
803}
804
805wchar_t
806ctype<wchar_t>::do_toupper(char_type c) const
807{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000808#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
809 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000810#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000811 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000812 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000813#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000814 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000815#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000816}
817
818const wchar_t*
819ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
820{
821 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000822#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
823 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000824#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000825 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000826 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
827 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000828#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000829 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000830#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000831 return low;
832}
833
834wchar_t
835ctype<wchar_t>::do_tolower(char_type c) const
836{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000837#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
838 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000839#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000840 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000841 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000842#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000843 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000844#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000845}
846
847const wchar_t*
848ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
849{
850 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000851#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
852 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000853#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000854 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000855 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
856 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000857#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000858 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000859#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000860 return low;
861}
862
863wchar_t
864ctype<wchar_t>::do_widen(char c) const
865{
866 return c;
867}
868
869const char*
870ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
871{
872 for (; low != high; ++low, ++dest)
873 *dest = *low;
874 return low;
875}
876
877char
878ctype<wchar_t>::do_narrow(char_type c, char dfault) const
879{
880 if (isascii(c))
881 return static_cast<char>(c);
882 return dfault;
883}
884
885const wchar_t*
886ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
887{
888 for (; low != high; ++low, ++dest)
889 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000890 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000891 else
892 *dest = dfault;
893 return low;
894}
895
896// template <> class ctype<char>;
897
898locale::id ctype<char>::id;
899
900ctype<char>::ctype(const mask* tab, bool del, size_t refs)
901 : locale::facet(refs),
902 __tab_(tab),
903 __del_(del)
904{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000905 if (__tab_ == 0)
906 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000907}
908
909ctype<char>::~ctype()
910{
911 if (__tab_ && __del_)
912 delete [] __tab_;
913}
914
915char
916ctype<char>::do_toupper(char_type c) const
917{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000918#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000919 return isascii(c) ?
920 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000921#elif defined(__NetBSD__)
922 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000923#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000924 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000925 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000926#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000927 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000928#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000929}
930
931const char*
932ctype<char>::do_toupper(char_type* low, const char_type* high) const
933{
934 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000935#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000936 *low = isascii(*low) ?
937 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000938#elif defined(__NetBSD__)
939 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000940#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000941 *low = isascii(*low) ?
942 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000943#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000944 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000945#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000946 return low;
947}
948
949char
950ctype<char>::do_tolower(char_type c) const
951{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000952#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000953 return isascii(c) ?
954 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000955#elif defined(__NetBSD__)
956 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000957#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000958 return isascii(c) ?
959 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000960#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000961 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000962#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000963}
964
965const char*
966ctype<char>::do_tolower(char_type* low, const char_type* high) const
967{
968 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000969#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000970 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000971#elif defined(__NetBSD__)
972 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000973#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000974 *low = isascii(*low) ? static_cast<char>(__classic_lower_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) && isupper_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_widen(char c) const
983{
984 return c;
985}
986
987const char*
988ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
989{
990 for (; low != high; ++low, ++dest)
991 *dest = *low;
992 return low;
993}
994
995char
996ctype<char>::do_narrow(char_type c, char dfault) const
997{
998 if (isascii(c))
999 return static_cast<char>(c);
1000 return dfault;
1001}
1002
1003const char*
1004ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1005{
1006 for (; low != high; ++low, ++dest)
1007 if (isascii(*low))
1008 *dest = *low;
1009 else
1010 *dest = dfault;
1011 return low;
1012}
1013
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001014#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001015extern "C" const unsigned short ** __ctype_b_loc();
1016extern "C" const int ** __ctype_tolower_loc();
1017extern "C" const int ** __ctype_toupper_loc();
1018#endif
1019
Marshall Clow8f870232015-03-04 16:50:02 +00001020#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001021const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001022ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001023{
1024 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1025 cntrl, cntrl,
1026 cntrl, cntrl,
1027 cntrl, cntrl,
1028 cntrl, cntrl,
1029 cntrl, cntrl | space | blank,
1030 cntrl | space, cntrl | space,
1031 cntrl | space, cntrl | space,
1032 cntrl, cntrl,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl,
1040 cntrl, cntrl,
1041 space | blank | print, punct | print,
1042 punct | print, punct | print,
1043 punct | print, punct | print,
1044 punct | print, punct | print,
1045 punct | print, punct | print,
1046 punct | print, punct | print,
1047 punct | print, punct | print,
1048 punct | print, punct | print,
1049 digit | print | xdigit, digit | print | xdigit,
1050 digit | print | xdigit, digit | print | xdigit,
1051 digit | print | xdigit, digit | print | xdigit,
1052 digit | print | xdigit, digit | print | xdigit,
1053 digit | print | xdigit, digit | print | xdigit,
1054 punct | print, punct | print,
1055 punct | print, punct | print,
1056 punct | print, punct | print,
1057 punct | print, upper | xdigit | print | alpha,
1058 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1059 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1060 upper | xdigit | print | alpha, upper | print | alpha,
1061 upper | print | alpha, upper | print | alpha,
1062 upper | print | alpha, upper | print | alpha,
1063 upper | print | alpha, upper | print | alpha,
1064 upper | print | alpha, upper | print | alpha,
1065 upper | print | alpha, upper | print | alpha,
1066 upper | print | alpha, upper | print | alpha,
1067 upper | print | alpha, upper | print | alpha,
1068 upper | print | alpha, upper | print | alpha,
1069 upper | print | alpha, upper | print | alpha,
1070 upper | print | alpha, punct | print,
1071 punct | print, punct | print,
1072 punct | print, punct | print,
1073 punct | print, lower | xdigit | print | alpha,
1074 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1075 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1076 lower | xdigit | print | alpha, lower | print | alpha,
1077 lower | print | alpha, lower | print | alpha,
1078 lower | print | alpha, lower | print | alpha,
1079 lower | print | alpha, lower | print | alpha,
1080 lower | print | alpha, lower | print | alpha,
1081 lower | print | alpha, lower | print | alpha,
1082 lower | print | alpha, lower | print | alpha,
1083 lower | print | alpha, lower | print | alpha,
1084 lower | print | alpha, lower | print | alpha,
1085 lower | print | alpha, lower | print | alpha,
1086 lower | print | alpha, punct | print,
1087 punct | print, punct | print,
1088 punct | print, cntrl,
1089 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1090 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1091 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1092 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1094 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1095 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1096 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1097 };
1098 return builtin_table;
1099}
1100#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001101const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001102ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001103{
David Chisnall1d581062011-09-21 08:39:44 +00001104#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001105 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001106#elif defined(__NetBSD__)
1107 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001108#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001109 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001110#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001111 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001112#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001113 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001114#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001115 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001116#elif defined(_NEWLIB_VERSION)
1117 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1118 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001119#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001120 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001121#else
David Chisnall8074c342012-02-29 13:05:08 +00001122 // Platform not supported: abort so the person doing the port knows what to
1123 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001124# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001125 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001126 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001127 return NULL;
1128#endif
1129}
Marshall Clowb3f62842015-03-04 16:10:14 +00001130#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001131
Howard Hinnantd7a78632011-09-29 13:33:15 +00001132#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001133const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001134ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001135{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001136 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001137}
1138
1139const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001140ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001141{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001142 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001143}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001144#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001145const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001146ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001147{
1148 return _C_tolower_tab_ + 1;
1149}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001150
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001151const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001152ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001153{
1154 return _C_toupper_tab_ + 1;
1155}
1156
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001157#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001158const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001159ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001160{
1161 return *__ctype_tolower_loc();
1162}
1163
1164const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001165ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001166{
1167 return *__ctype_toupper_loc();
1168}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001169#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001170
Howard Hinnantc51e1022010-05-11 19:42:16 +00001171// template <> class ctype_byname<char>
1172
1173ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1174 : ctype<char>(0, false, refs),
1175 __l(newlocale(LC_ALL_MASK, name, 0))
1176{
1177 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001178 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001179 " failed to construct for " + string(name));
1180}
1181
1182ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1183 : ctype<char>(0, false, refs),
1184 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1185{
1186 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001187 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001188 " failed to construct for " + name);
1189}
1190
1191ctype_byname<char>::~ctype_byname()
1192{
1193 freelocale(__l);
1194}
1195
1196char
1197ctype_byname<char>::do_toupper(char_type c) const
1198{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001199 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001200}
1201
1202const char*
1203ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1204{
1205 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001206 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207 return low;
1208}
1209
1210char
1211ctype_byname<char>::do_tolower(char_type c) const
1212{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001213 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001214}
1215
1216const char*
1217ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1218{
1219 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001220 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001221 return low;
1222}
1223
1224// template <> class ctype_byname<wchar_t>
1225
1226ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1227 : ctype<wchar_t>(refs),
1228 __l(newlocale(LC_ALL_MASK, name, 0))
1229{
1230 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001231 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001232 " failed to construct for " + string(name));
1233}
1234
1235ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1236 : ctype<wchar_t>(refs),
1237 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1238{
1239 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001240 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001241 " failed to construct for " + name);
1242}
1243
1244ctype_byname<wchar_t>::~ctype_byname()
1245{
1246 freelocale(__l);
1247}
1248
1249bool
1250ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1251{
Alexis Huntc2017f12011-07-09 03:40:04 +00001252#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001253 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001254#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001255 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001256 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001257 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1258 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1259 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1260 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1261 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1262 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1263 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1264 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1265 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1266 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001267 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001268#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001269}
1270
1271const wchar_t*
1272ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1273{
1274 for (; low != high; ++low, ++vec)
1275 {
1276 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001277 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001278 else
1279 {
1280 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001281 wint_t ch = static_cast<wint_t>(*low);
1282 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001283 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001284#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001285 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001286 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001287#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001288 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001289 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001290 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001291 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001292 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001293 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001294#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001295 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001297#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001298 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001299 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001300 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001302#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001303 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001304 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001305#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001306#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001307 if (iswblank_l(ch, __l))
1308 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001309#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001310 }
1311 }
1312 return low;
1313}
1314
1315const wchar_t*
1316ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1317{
1318 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001319 {
1320#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321 if (iswctype_l(*low, m, __l))
1322 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001323#else
Marshall Clowada0f732013-02-07 14:22:51 +00001324 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001325 if ((m & space) == space && iswspace_l(ch, __l)) break;
1326 if ((m & print) == print && iswprint_l(ch, __l)) break;
1327 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1328 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1329 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1330 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1331 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1332 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1333 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1334 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001335#endif
1336 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001337 return low;
1338}
1339
1340const wchar_t*
1341ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1342{
1343 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001344 {
1345#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001346 if (!iswctype_l(*low, m, __l))
1347 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001348#else
Marshall Clowada0f732013-02-07 14:22:51 +00001349 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001350 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1351 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1352 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1353 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1354 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1355 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1356 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1357 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1358 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1359 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001360 break;
1361#endif
1362 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001363 return low;
1364}
1365
1366wchar_t
1367ctype_byname<wchar_t>::do_toupper(char_type c) const
1368{
1369 return towupper_l(c, __l);
1370}
1371
1372const wchar_t*
1373ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1374{
1375 for (; low != high; ++low)
1376 *low = towupper_l(*low, __l);
1377 return low;
1378}
1379
1380wchar_t
1381ctype_byname<wchar_t>::do_tolower(char_type c) const
1382{
1383 return towlower_l(c, __l);
1384}
1385
1386const wchar_t*
1387ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1388{
1389 for (; low != high; ++low)
1390 *low = towlower_l(*low, __l);
1391 return low;
1392}
1393
1394wchar_t
1395ctype_byname<wchar_t>::do_widen(char c) const
1396{
Ben Craig3756b922016-03-09 15:39:39 +00001397 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001398}
1399
1400const char*
1401ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1402{
1403 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001404 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001405 return low;
1406}
1407
1408char
1409ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1410{
Ben Craig3756b922016-03-09 15:39:39 +00001411 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001412 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001413}
1414
1415const wchar_t*
1416ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1417{
1418 for (; low != high; ++low, ++dest)
1419 {
Ben Craig3756b922016-03-09 15:39:39 +00001420 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001421 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001422 }
1423 return low;
1424}
1425
1426// template <> class codecvt<char, char, mbstate_t>
1427
Howard Hinnantffb308e2010-08-22 00:03:27 +00001428locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001429
1430codecvt<char, char, mbstate_t>::~codecvt()
1431{
1432}
1433
1434codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001435codecvt<char, char, mbstate_t>::do_out(state_type&,
1436 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001437 extern_type* to, extern_type*, extern_type*& to_nxt) const
1438{
1439 frm_nxt = frm;
1440 to_nxt = to;
1441 return noconv;
1442}
1443
1444codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001445codecvt<char, char, mbstate_t>::do_in(state_type&,
1446 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001447 intern_type* to, intern_type*, intern_type*& to_nxt) const
1448{
1449 frm_nxt = frm;
1450 to_nxt = to;
1451 return noconv;
1452}
1453
1454codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001455codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001456 extern_type* to, extern_type*, extern_type*& to_nxt) const
1457{
1458 to_nxt = to;
1459 return noconv;
1460}
1461
1462int
Louis Dionne65358e12021-03-01 12:09:45 -05001463codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001464{
1465 return 1;
1466}
1467
1468bool
Louis Dionne65358e12021-03-01 12:09:45 -05001469codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001470{
1471 return true;
1472}
1473
1474int
1475codecvt<char, char, mbstate_t>::do_length(state_type&,
1476 const extern_type* frm, const extern_type* end, size_t mx) const
1477{
Howard Hinnant28b24882011-12-01 20:21:04 +00001478 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001479}
1480
1481int
Louis Dionne65358e12021-03-01 12:09:45 -05001482codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001483{
1484 return 1;
1485}
1486
1487// template <> class codecvt<wchar_t, char, mbstate_t>
1488
Howard Hinnantffb308e2010-08-22 00:03:27 +00001489locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001490
1491codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1492 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001493 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001494{
1495}
1496
1497codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1498 : locale::facet(refs),
1499 __l(newlocale(LC_ALL_MASK, nm, 0))
1500{
1501 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001502 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001503 " failed to construct for " + string(nm));
1504}
1505
1506codecvt<wchar_t, char, mbstate_t>::~codecvt()
1507{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001508 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001509 freelocale(__l);
1510}
1511
1512codecvt<wchar_t, char, mbstate_t>::result
1513codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001514 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001515 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1516{
1517 // look for first internal null in frm
1518 const intern_type* fend = frm;
1519 for (; fend != frm_end; ++fend)
1520 if (*fend == 0)
1521 break;
1522 // loop over all null-terminated sequences in frm
1523 to_nxt = to;
1524 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1525 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001526 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001527 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001528 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1529 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001530 if (n == size_t(-1))
1531 {
1532 // need to recover to_nxt
1533 for (to_nxt = to; frm != frm_nxt; ++frm)
1534 {
Ben Craig3756b922016-03-09 15:39:39 +00001535 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001536 if (n == size_t(-1))
1537 break;
1538 to_nxt += n;
1539 }
1540 frm_nxt = frm;
1541 return error;
1542 }
1543 if (n == 0)
1544 return partial;
1545 to_nxt += n;
1546 if (to_nxt == to_end)
1547 break;
1548 if (fend != frm_end) // set up next null terminated sequence
1549 {
1550 // Try to write the terminating null
1551 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001552 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001553 if (n == size_t(-1)) // on error
1554 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001555 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001556 return partial;
1557 for (extern_type* p = tmp; n; --n) // write it
1558 *to_nxt++ = *p++;
1559 ++frm_nxt;
1560 // look for next null in frm
1561 for (fend = frm_nxt; fend != frm_end; ++fend)
1562 if (*fend == 0)
1563 break;
1564 }
1565 }
1566 return frm_nxt == frm_end ? ok : partial;
1567}
1568
1569codecvt<wchar_t, char, mbstate_t>::result
1570codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001571 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001572 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1573{
1574 // look for first internal null in frm
1575 const extern_type* fend = frm;
1576 for (; fend != frm_end; ++fend)
1577 if (*fend == 0)
1578 break;
1579 // loop over all null-terminated sequences in frm
1580 to_nxt = to;
1581 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1582 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001583 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001584 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001585 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1586 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001587 if (n == size_t(-1))
1588 {
1589 // need to recover to_nxt
1590 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1591 {
Ben Craig3756b922016-03-09 15:39:39 +00001592 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1593 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001594 switch (n)
1595 {
1596 case 0:
1597 ++frm;
1598 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001599 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001600 frm_nxt = frm;
1601 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001602 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001603 frm_nxt = frm;
1604 return partial;
1605 default:
1606 frm += n;
1607 break;
1608 }
1609 }
1610 frm_nxt = frm;
1611 return frm_nxt == frm_end ? ok : partial;
1612 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001613 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001614 return error;
1615 to_nxt += n;
1616 if (to_nxt == to_end)
1617 break;
1618 if (fend != frm_end) // set up next null terminated sequence
1619 {
1620 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001621 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 if (n != 0) // on error
1623 return error;
1624 ++to_nxt;
1625 ++frm_nxt;
1626 // look for next null in frm
1627 for (fend = frm_nxt; fend != frm_end; ++fend)
1628 if (*fend == 0)
1629 break;
1630 }
1631 }
1632 return frm_nxt == frm_end ? ok : partial;
1633}
1634
1635codecvt<wchar_t, char, mbstate_t>::result
1636codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1637 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1638{
1639 to_nxt = to;
1640 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001641 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001642 if (n == size_t(-1) || n == 0) // on error
1643 return error;
1644 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001645 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001646 return partial;
1647 for (extern_type* p = tmp; n; --n) // write it
1648 *to_nxt++ = *p++;
1649 return ok;
1650}
1651
1652int
Louis Dionne65358e12021-03-01 12:09:45 -05001653codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001654{
Ben Craig3756b922016-03-09 15:39:39 +00001655 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001656 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001657
1658 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001659 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001660 return 1; // which take more than 1 char to form a wchar_t
1661 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001662}
1663
1664bool
Louis Dionne65358e12021-03-01 12:09:45 -05001665codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001666{
1667 return false;
1668}
1669
1670int
1671codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1672 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1673{
1674 int nbytes = 0;
1675 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1676 {
Ben Craig3756b922016-03-09 15:39:39 +00001677 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001678 switch (n)
1679 {
1680 case 0:
1681 ++nbytes;
1682 ++frm;
1683 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001684 case size_t(-1):
1685 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001686 return nbytes;
1687 default:
1688 nbytes += n;
1689 frm += n;
1690 break;
1691 }
1692 }
1693 return nbytes;
1694}
1695
1696int
Louis Dionne65358e12021-03-01 12:09:45 -05001697codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001698{
Ben Craig3756b922016-03-09 15:39:39 +00001699 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001700}
1701
1702// Valid UTF ranges
1703// UTF-32 UTF-16 UTF-8 # of code points
1704// first second first second third fourth
1705// 000000 - 00007F 0000 - 007F 00 - 7F 127
1706// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1707// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1708// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1709// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1710// 00D800 - 00DFFF invalid
1711// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1712// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1713// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1714// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1715
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001716static
1717codecvt_base::result
1718utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1719 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1720 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1721{
1722 frm_nxt = frm;
1723 to_nxt = to;
1724 if (mode & generate_header)
1725 {
1726 if (to_end-to_nxt < 3)
1727 return codecvt_base::partial;
1728 *to_nxt++ = static_cast<uint8_t>(0xEF);
1729 *to_nxt++ = static_cast<uint8_t>(0xBB);
1730 *to_nxt++ = static_cast<uint8_t>(0xBF);
1731 }
1732 for (; frm_nxt < frm_end; ++frm_nxt)
1733 {
1734 uint16_t wc1 = *frm_nxt;
1735 if (wc1 > Maxcode)
1736 return codecvt_base::error;
1737 if (wc1 < 0x0080)
1738 {
1739 if (to_end-to_nxt < 1)
1740 return codecvt_base::partial;
1741 *to_nxt++ = static_cast<uint8_t>(wc1);
1742 }
1743 else if (wc1 < 0x0800)
1744 {
1745 if (to_end-to_nxt < 2)
1746 return codecvt_base::partial;
1747 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1748 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1749 }
1750 else if (wc1 < 0xD800)
1751 {
1752 if (to_end-to_nxt < 3)
1753 return codecvt_base::partial;
1754 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1756 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1757 }
1758 else if (wc1 < 0xDC00)
1759 {
1760 if (frm_end-frm_nxt < 2)
1761 return codecvt_base::partial;
1762 uint16_t wc2 = frm_nxt[1];
1763 if ((wc2 & 0xFC00) != 0xDC00)
1764 return codecvt_base::error;
1765 if (to_end-to_nxt < 4)
1766 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001767 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1768 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001769 return codecvt_base::error;
1770 ++frm_nxt;
1771 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1772 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1773 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1774 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1775 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1776 }
1777 else if (wc1 < 0xE000)
1778 {
1779 return codecvt_base::error;
1780 }
1781 else
1782 {
1783 if (to_end-to_nxt < 3)
1784 return codecvt_base::partial;
1785 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1786 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1787 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1788 }
1789 }
1790 return codecvt_base::ok;
1791}
1792
1793static
1794codecvt_base::result
1795utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1796 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1797 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1798{
1799 frm_nxt = frm;
1800 to_nxt = to;
1801 if (mode & generate_header)
1802 {
1803 if (to_end-to_nxt < 3)
1804 return codecvt_base::partial;
1805 *to_nxt++ = static_cast<uint8_t>(0xEF);
1806 *to_nxt++ = static_cast<uint8_t>(0xBB);
1807 *to_nxt++ = static_cast<uint8_t>(0xBF);
1808 }
1809 for (; frm_nxt < frm_end; ++frm_nxt)
1810 {
1811 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1812 if (wc1 > Maxcode)
1813 return codecvt_base::error;
1814 if (wc1 < 0x0080)
1815 {
1816 if (to_end-to_nxt < 1)
1817 return codecvt_base::partial;
1818 *to_nxt++ = static_cast<uint8_t>(wc1);
1819 }
1820 else if (wc1 < 0x0800)
1821 {
1822 if (to_end-to_nxt < 2)
1823 return codecvt_base::partial;
1824 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1825 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1826 }
1827 else if (wc1 < 0xD800)
1828 {
1829 if (to_end-to_nxt < 3)
1830 return codecvt_base::partial;
1831 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1832 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1833 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1834 }
1835 else if (wc1 < 0xDC00)
1836 {
1837 if (frm_end-frm_nxt < 2)
1838 return codecvt_base::partial;
1839 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1840 if ((wc2 & 0xFC00) != 0xDC00)
1841 return codecvt_base::error;
1842 if (to_end-to_nxt < 4)
1843 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001844 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1845 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001846 return codecvt_base::error;
1847 ++frm_nxt;
1848 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1849 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1852 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1853 }
1854 else if (wc1 < 0xE000)
1855 {
1856 return codecvt_base::error;
1857 }
1858 else
1859 {
1860 if (to_end-to_nxt < 3)
1861 return codecvt_base::partial;
1862 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1863 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1864 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1865 }
1866 }
1867 return codecvt_base::ok;
1868}
1869
1870static
1871codecvt_base::result
1872utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1873 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1874 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1875{
1876 frm_nxt = frm;
1877 to_nxt = to;
1878 if (mode & consume_header)
1879 {
1880 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1881 frm_nxt[2] == 0xBF)
1882 frm_nxt += 3;
1883 }
1884 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1885 {
1886 uint8_t c1 = *frm_nxt;
1887 if (c1 > Maxcode)
1888 return codecvt_base::error;
1889 if (c1 < 0x80)
1890 {
1891 *to_nxt = static_cast<uint16_t>(c1);
1892 ++frm_nxt;
1893 }
1894 else if (c1 < 0xC2)
1895 {
1896 return codecvt_base::error;
1897 }
1898 else if (c1 < 0xE0)
1899 {
1900 if (frm_end-frm_nxt < 2)
1901 return codecvt_base::partial;
1902 uint8_t c2 = frm_nxt[1];
1903 if ((c2 & 0xC0) != 0x80)
1904 return codecvt_base::error;
1905 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1906 if (t > Maxcode)
1907 return codecvt_base::error;
1908 *to_nxt = t;
1909 frm_nxt += 2;
1910 }
1911 else if (c1 < 0xF0)
1912 {
1913 if (frm_end-frm_nxt < 3)
1914 return codecvt_base::partial;
1915 uint8_t c2 = frm_nxt[1];
1916 uint8_t c3 = frm_nxt[2];
1917 switch (c1)
1918 {
1919 case 0xE0:
1920 if ((c2 & 0xE0) != 0xA0)
1921 return codecvt_base::error;
1922 break;
1923 case 0xED:
1924 if ((c2 & 0xE0) != 0x80)
1925 return codecvt_base::error;
1926 break;
1927 default:
1928 if ((c2 & 0xC0) != 0x80)
1929 return codecvt_base::error;
1930 break;
1931 }
1932 if ((c3 & 0xC0) != 0x80)
1933 return codecvt_base::error;
1934 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1935 | ((c2 & 0x3F) << 6)
1936 | (c3 & 0x3F));
1937 if (t > Maxcode)
1938 return codecvt_base::error;
1939 *to_nxt = t;
1940 frm_nxt += 3;
1941 }
1942 else if (c1 < 0xF5)
1943 {
1944 if (frm_end-frm_nxt < 4)
1945 return codecvt_base::partial;
1946 uint8_t c2 = frm_nxt[1];
1947 uint8_t c3 = frm_nxt[2];
1948 uint8_t c4 = frm_nxt[3];
1949 switch (c1)
1950 {
1951 case 0xF0:
1952 if (!(0x90 <= c2 && c2 <= 0xBF))
1953 return codecvt_base::error;
1954 break;
1955 case 0xF4:
1956 if ((c2 & 0xF0) != 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 || (c4 & 0xC0) != 0x80)
1965 return codecvt_base::error;
1966 if (to_end-to_nxt < 2)
1967 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001968 if ((((c1 & 7UL) << 18) +
1969 ((c2 & 0x3FUL) << 12) +
1970 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001971 return codecvt_base::error;
1972 *to_nxt = static_cast<uint16_t>(
1973 0xD800
1974 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1975 | ((c2 & 0x0F) << 2)
1976 | ((c3 & 0x30) >> 4));
1977 *++to_nxt = static_cast<uint16_t>(
1978 0xDC00
1979 | ((c3 & 0x0F) << 6)
1980 | (c4 & 0x3F));
1981 frm_nxt += 4;
1982 }
1983 else
1984 {
1985 return codecvt_base::error;
1986 }
1987 }
1988 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1989}
1990
1991static
1992codecvt_base::result
1993utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1994 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1995 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1996{
1997 frm_nxt = frm;
1998 to_nxt = to;
1999 if (mode & consume_header)
2000 {
2001 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2002 frm_nxt[2] == 0xBF)
2003 frm_nxt += 3;
2004 }
2005 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2006 {
2007 uint8_t c1 = *frm_nxt;
2008 if (c1 > Maxcode)
2009 return codecvt_base::error;
2010 if (c1 < 0x80)
2011 {
2012 *to_nxt = static_cast<uint32_t>(c1);
2013 ++frm_nxt;
2014 }
2015 else if (c1 < 0xC2)
2016 {
2017 return codecvt_base::error;
2018 }
2019 else if (c1 < 0xE0)
2020 {
2021 if (frm_end-frm_nxt < 2)
2022 return codecvt_base::partial;
2023 uint8_t c2 = frm_nxt[1];
2024 if ((c2 & 0xC0) != 0x80)
2025 return codecvt_base::error;
2026 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2027 if (t > Maxcode)
2028 return codecvt_base::error;
2029 *to_nxt = static_cast<uint32_t>(t);
2030 frm_nxt += 2;
2031 }
2032 else if (c1 < 0xF0)
2033 {
2034 if (frm_end-frm_nxt < 3)
2035 return codecvt_base::partial;
2036 uint8_t c2 = frm_nxt[1];
2037 uint8_t c3 = frm_nxt[2];
2038 switch (c1)
2039 {
2040 case 0xE0:
2041 if ((c2 & 0xE0) != 0xA0)
2042 return codecvt_base::error;
2043 break;
2044 case 0xED:
2045 if ((c2 & 0xE0) != 0x80)
2046 return codecvt_base::error;
2047 break;
2048 default:
2049 if ((c2 & 0xC0) != 0x80)
2050 return codecvt_base::error;
2051 break;
2052 }
2053 if ((c3 & 0xC0) != 0x80)
2054 return codecvt_base::error;
2055 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2056 | ((c2 & 0x3F) << 6)
2057 | (c3 & 0x3F));
2058 if (t > Maxcode)
2059 return codecvt_base::error;
2060 *to_nxt = static_cast<uint32_t>(t);
2061 frm_nxt += 3;
2062 }
2063 else if (c1 < 0xF5)
2064 {
2065 if (frm_end-frm_nxt < 4)
2066 return codecvt_base::partial;
2067 uint8_t c2 = frm_nxt[1];
2068 uint8_t c3 = frm_nxt[2];
2069 uint8_t c4 = frm_nxt[3];
2070 switch (c1)
2071 {
2072 case 0xF0:
2073 if (!(0x90 <= c2 && c2 <= 0xBF))
2074 return codecvt_base::error;
2075 break;
2076 case 0xF4:
2077 if ((c2 & 0xF0) != 0x80)
2078 return codecvt_base::error;
2079 break;
2080 default:
2081 if ((c2 & 0xC0) != 0x80)
2082 return codecvt_base::error;
2083 break;
2084 }
2085 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2086 return codecvt_base::error;
2087 if (to_end-to_nxt < 2)
2088 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002089 if ((((c1 & 7UL) << 18) +
2090 ((c2 & 0x3FUL) << 12) +
2091 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002092 return codecvt_base::error;
2093 *to_nxt = static_cast<uint32_t>(
2094 0xD800
2095 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2096 | ((c2 & 0x0F) << 2)
2097 | ((c3 & 0x30) >> 4));
2098 *++to_nxt = static_cast<uint32_t>(
2099 0xDC00
2100 | ((c3 & 0x0F) << 6)
2101 | (c4 & 0x3F));
2102 frm_nxt += 4;
2103 }
2104 else
2105 {
2106 return codecvt_base::error;
2107 }
2108 }
2109 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2110}
2111
2112static
2113int
2114utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2115 size_t mx, unsigned long Maxcode = 0x10FFFF,
2116 codecvt_mode mode = codecvt_mode(0))
2117{
2118 const uint8_t* frm_nxt = frm;
2119 if (mode & consume_header)
2120 {
2121 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2122 frm_nxt[2] == 0xBF)
2123 frm_nxt += 3;
2124 }
2125 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2126 {
2127 uint8_t c1 = *frm_nxt;
2128 if (c1 > Maxcode)
2129 break;
2130 if (c1 < 0x80)
2131 {
2132 ++frm_nxt;
2133 }
2134 else if (c1 < 0xC2)
2135 {
2136 break;
2137 }
2138 else if (c1 < 0xE0)
2139 {
2140 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2141 break;
2142 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2143 if (t > Maxcode)
2144 break;
2145 frm_nxt += 2;
2146 }
2147 else if (c1 < 0xF0)
2148 {
2149 if (frm_end-frm_nxt < 3)
2150 break;
2151 uint8_t c2 = frm_nxt[1];
2152 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002153 switch (c1)
2154 {
2155 case 0xE0:
2156 if ((c2 & 0xE0) != 0xA0)
2157 return static_cast<int>(frm_nxt - frm);
2158 break;
2159 case 0xED:
2160 if ((c2 & 0xE0) != 0x80)
2161 return static_cast<int>(frm_nxt - frm);
2162 break;
2163 default:
2164 if ((c2 & 0xC0) != 0x80)
2165 return static_cast<int>(frm_nxt - frm);
2166 break;
2167 }
2168 if ((c3 & 0xC0) != 0x80)
2169 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002170 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002171 break;
2172 frm_nxt += 3;
2173 }
2174 else if (c1 < 0xF5)
2175 {
2176 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2177 break;
2178 uint8_t c2 = frm_nxt[1];
2179 uint8_t c3 = frm_nxt[2];
2180 uint8_t c4 = frm_nxt[3];
2181 switch (c1)
2182 {
2183 case 0xF0:
2184 if (!(0x90 <= c2 && c2 <= 0xBF))
2185 return static_cast<int>(frm_nxt - frm);
2186 break;
2187 case 0xF4:
2188 if ((c2 & 0xF0) != 0x80)
2189 return static_cast<int>(frm_nxt - frm);
2190 break;
2191 default:
2192 if ((c2 & 0xC0) != 0x80)
2193 return static_cast<int>(frm_nxt - frm);
2194 break;
2195 }
2196 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2197 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002198 if ((((c1 & 7UL) << 18) +
2199 ((c2 & 0x3FUL) << 12) +
2200 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002201 break;
2202 ++nchar16_t;
2203 frm_nxt += 4;
2204 }
2205 else
2206 {
2207 break;
2208 }
2209 }
2210 return static_cast<int>(frm_nxt - frm);
2211}
2212
2213static
2214codecvt_base::result
2215ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2216 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2217 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2218{
2219 frm_nxt = frm;
2220 to_nxt = to;
2221 if (mode & generate_header)
2222 {
2223 if (to_end-to_nxt < 3)
2224 return codecvt_base::partial;
2225 *to_nxt++ = static_cast<uint8_t>(0xEF);
2226 *to_nxt++ = static_cast<uint8_t>(0xBB);
2227 *to_nxt++ = static_cast<uint8_t>(0xBF);
2228 }
2229 for (; frm_nxt < frm_end; ++frm_nxt)
2230 {
2231 uint32_t wc = *frm_nxt;
2232 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2233 return codecvt_base::error;
2234 if (wc < 0x000080)
2235 {
2236 if (to_end-to_nxt < 1)
2237 return codecvt_base::partial;
2238 *to_nxt++ = static_cast<uint8_t>(wc);
2239 }
2240 else if (wc < 0x000800)
2241 {
2242 if (to_end-to_nxt < 2)
2243 return codecvt_base::partial;
2244 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2245 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2246 }
2247 else if (wc < 0x010000)
2248 {
2249 if (to_end-to_nxt < 3)
2250 return codecvt_base::partial;
2251 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2252 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2253 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2254 }
2255 else // if (wc < 0x110000)
2256 {
2257 if (to_end-to_nxt < 4)
2258 return codecvt_base::partial;
2259 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2260 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2261 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2262 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2263 }
2264 }
2265 return codecvt_base::ok;
2266}
2267
2268static
2269codecvt_base::result
2270utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2271 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2272 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2273{
2274 frm_nxt = frm;
2275 to_nxt = to;
2276 if (mode & consume_header)
2277 {
2278 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2279 frm_nxt[2] == 0xBF)
2280 frm_nxt += 3;
2281 }
2282 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2283 {
2284 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2285 if (c1 < 0x80)
2286 {
2287 if (c1 > Maxcode)
2288 return codecvt_base::error;
2289 *to_nxt = static_cast<uint32_t>(c1);
2290 ++frm_nxt;
2291 }
2292 else if (c1 < 0xC2)
2293 {
2294 return codecvt_base::error;
2295 }
2296 else if (c1 < 0xE0)
2297 {
2298 if (frm_end-frm_nxt < 2)
2299 return codecvt_base::partial;
2300 uint8_t c2 = frm_nxt[1];
2301 if ((c2 & 0xC0) != 0x80)
2302 return codecvt_base::error;
2303 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2304 | (c2 & 0x3F));
2305 if (t > Maxcode)
2306 return codecvt_base::error;
2307 *to_nxt = t;
2308 frm_nxt += 2;
2309 }
2310 else if (c1 < 0xF0)
2311 {
2312 if (frm_end-frm_nxt < 3)
2313 return codecvt_base::partial;
2314 uint8_t c2 = frm_nxt[1];
2315 uint8_t c3 = frm_nxt[2];
2316 switch (c1)
2317 {
2318 case 0xE0:
2319 if ((c2 & 0xE0) != 0xA0)
2320 return codecvt_base::error;
2321 break;
2322 case 0xED:
2323 if ((c2 & 0xE0) != 0x80)
2324 return codecvt_base::error;
2325 break;
2326 default:
2327 if ((c2 & 0xC0) != 0x80)
2328 return codecvt_base::error;
2329 break;
2330 }
2331 if ((c3 & 0xC0) != 0x80)
2332 return codecvt_base::error;
2333 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2334 | ((c2 & 0x3F) << 6)
2335 | (c3 & 0x3F));
2336 if (t > Maxcode)
2337 return codecvt_base::error;
2338 *to_nxt = t;
2339 frm_nxt += 3;
2340 }
2341 else if (c1 < 0xF5)
2342 {
2343 if (frm_end-frm_nxt < 4)
2344 return codecvt_base::partial;
2345 uint8_t c2 = frm_nxt[1];
2346 uint8_t c3 = frm_nxt[2];
2347 uint8_t c4 = frm_nxt[3];
2348 switch (c1)
2349 {
2350 case 0xF0:
2351 if (!(0x90 <= c2 && c2 <= 0xBF))
2352 return codecvt_base::error;
2353 break;
2354 case 0xF4:
2355 if ((c2 & 0xF0) != 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 || (c4 & 0xC0) != 0x80)
2364 return codecvt_base::error;
2365 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2366 | ((c2 & 0x3F) << 12)
2367 | ((c3 & 0x3F) << 6)
2368 | (c4 & 0x3F));
2369 if (t > Maxcode)
2370 return codecvt_base::error;
2371 *to_nxt = t;
2372 frm_nxt += 4;
2373 }
2374 else
2375 {
2376 return codecvt_base::error;
2377 }
2378 }
2379 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2380}
2381
2382static
2383int
2384utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2385 size_t mx, unsigned long Maxcode = 0x10FFFF,
2386 codecvt_mode mode = codecvt_mode(0))
2387{
2388 const uint8_t* frm_nxt = frm;
2389 if (mode & consume_header)
2390 {
2391 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2392 frm_nxt[2] == 0xBF)
2393 frm_nxt += 3;
2394 }
2395 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2396 {
2397 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2398 if (c1 < 0x80)
2399 {
2400 if (c1 > Maxcode)
2401 break;
2402 ++frm_nxt;
2403 }
2404 else if (c1 < 0xC2)
2405 {
2406 break;
2407 }
2408 else if (c1 < 0xE0)
2409 {
2410 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2411 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002412 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002413 break;
2414 frm_nxt += 2;
2415 }
2416 else if (c1 < 0xF0)
2417 {
2418 if (frm_end-frm_nxt < 3)
2419 break;
2420 uint8_t c2 = frm_nxt[1];
2421 uint8_t c3 = frm_nxt[2];
2422 switch (c1)
2423 {
2424 case 0xE0:
2425 if ((c2 & 0xE0) != 0xA0)
2426 return static_cast<int>(frm_nxt - frm);
2427 break;
2428 case 0xED:
2429 if ((c2 & 0xE0) != 0x80)
2430 return static_cast<int>(frm_nxt - frm);
2431 break;
2432 default:
2433 if ((c2 & 0xC0) != 0x80)
2434 return static_cast<int>(frm_nxt - frm);
2435 break;
2436 }
2437 if ((c3 & 0xC0) != 0x80)
2438 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002439 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002440 break;
2441 frm_nxt += 3;
2442 }
2443 else if (c1 < 0xF5)
2444 {
2445 if (frm_end-frm_nxt < 4)
2446 break;
2447 uint8_t c2 = frm_nxt[1];
2448 uint8_t c3 = frm_nxt[2];
2449 uint8_t c4 = frm_nxt[3];
2450 switch (c1)
2451 {
2452 case 0xF0:
2453 if (!(0x90 <= c2 && c2 <= 0xBF))
2454 return static_cast<int>(frm_nxt - frm);
2455 break;
2456 case 0xF4:
2457 if ((c2 & 0xF0) != 0x80)
2458 return static_cast<int>(frm_nxt - frm);
2459 break;
2460 default:
2461 if ((c2 & 0xC0) != 0x80)
2462 return static_cast<int>(frm_nxt - frm);
2463 break;
2464 }
2465 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2466 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002467 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2468 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002469 break;
2470 frm_nxt += 4;
2471 }
2472 else
2473 {
2474 break;
2475 }
2476 }
2477 return static_cast<int>(frm_nxt - frm);
2478}
2479
2480static
2481codecvt_base::result
2482ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2483 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2484 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2485{
2486 frm_nxt = frm;
2487 to_nxt = to;
2488 if (mode & generate_header)
2489 {
2490 if (to_end-to_nxt < 3)
2491 return codecvt_base::partial;
2492 *to_nxt++ = static_cast<uint8_t>(0xEF);
2493 *to_nxt++ = static_cast<uint8_t>(0xBB);
2494 *to_nxt++ = static_cast<uint8_t>(0xBF);
2495 }
2496 for (; frm_nxt < frm_end; ++frm_nxt)
2497 {
2498 uint16_t wc = *frm_nxt;
2499 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2500 return codecvt_base::error;
2501 if (wc < 0x0080)
2502 {
2503 if (to_end-to_nxt < 1)
2504 return codecvt_base::partial;
2505 *to_nxt++ = static_cast<uint8_t>(wc);
2506 }
2507 else if (wc < 0x0800)
2508 {
2509 if (to_end-to_nxt < 2)
2510 return codecvt_base::partial;
2511 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2512 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2513 }
2514 else // if (wc <= 0xFFFF)
2515 {
2516 if (to_end-to_nxt < 3)
2517 return codecvt_base::partial;
2518 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2519 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2520 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2521 }
2522 }
2523 return codecvt_base::ok;
2524}
2525
2526static
2527codecvt_base::result
2528utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2529 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2530 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2531{
2532 frm_nxt = frm;
2533 to_nxt = to;
2534 if (mode & consume_header)
2535 {
2536 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2537 frm_nxt[2] == 0xBF)
2538 frm_nxt += 3;
2539 }
2540 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2541 {
2542 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2543 if (c1 < 0x80)
2544 {
2545 if (c1 > Maxcode)
2546 return codecvt_base::error;
2547 *to_nxt = static_cast<uint16_t>(c1);
2548 ++frm_nxt;
2549 }
2550 else if (c1 < 0xC2)
2551 {
2552 return codecvt_base::error;
2553 }
2554 else if (c1 < 0xE0)
2555 {
2556 if (frm_end-frm_nxt < 2)
2557 return codecvt_base::partial;
2558 uint8_t c2 = frm_nxt[1];
2559 if ((c2 & 0xC0) != 0x80)
2560 return codecvt_base::error;
2561 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2562 | (c2 & 0x3F));
2563 if (t > Maxcode)
2564 return codecvt_base::error;
2565 *to_nxt = t;
2566 frm_nxt += 2;
2567 }
2568 else if (c1 < 0xF0)
2569 {
2570 if (frm_end-frm_nxt < 3)
2571 return codecvt_base::partial;
2572 uint8_t c2 = frm_nxt[1];
2573 uint8_t c3 = frm_nxt[2];
2574 switch (c1)
2575 {
2576 case 0xE0:
2577 if ((c2 & 0xE0) != 0xA0)
2578 return codecvt_base::error;
2579 break;
2580 case 0xED:
2581 if ((c2 & 0xE0) != 0x80)
2582 return codecvt_base::error;
2583 break;
2584 default:
2585 if ((c2 & 0xC0) != 0x80)
2586 return codecvt_base::error;
2587 break;
2588 }
2589 if ((c3 & 0xC0) != 0x80)
2590 return codecvt_base::error;
2591 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2592 | ((c2 & 0x3F) << 6)
2593 | (c3 & 0x3F));
2594 if (t > Maxcode)
2595 return codecvt_base::error;
2596 *to_nxt = t;
2597 frm_nxt += 3;
2598 }
2599 else
2600 {
2601 return codecvt_base::error;
2602 }
2603 }
2604 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2605}
2606
2607static
2608int
2609utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2610 size_t mx, unsigned long Maxcode = 0x10FFFF,
2611 codecvt_mode mode = codecvt_mode(0))
2612{
2613 const uint8_t* frm_nxt = frm;
2614 if (mode & consume_header)
2615 {
2616 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2617 frm_nxt[2] == 0xBF)
2618 frm_nxt += 3;
2619 }
2620 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2621 {
2622 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2623 if (c1 < 0x80)
2624 {
2625 if (c1 > Maxcode)
2626 break;
2627 ++frm_nxt;
2628 }
2629 else if (c1 < 0xC2)
2630 {
2631 break;
2632 }
2633 else if (c1 < 0xE0)
2634 {
2635 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2636 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002637 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002638 break;
2639 frm_nxt += 2;
2640 }
2641 else if (c1 < 0xF0)
2642 {
2643 if (frm_end-frm_nxt < 3)
2644 break;
2645 uint8_t c2 = frm_nxt[1];
2646 uint8_t c3 = frm_nxt[2];
2647 switch (c1)
2648 {
2649 case 0xE0:
2650 if ((c2 & 0xE0) != 0xA0)
2651 return static_cast<int>(frm_nxt - frm);
2652 break;
2653 case 0xED:
2654 if ((c2 & 0xE0) != 0x80)
2655 return static_cast<int>(frm_nxt - frm);
2656 break;
2657 default:
2658 if ((c2 & 0xC0) != 0x80)
2659 return static_cast<int>(frm_nxt - frm);
2660 break;
2661 }
2662 if ((c3 & 0xC0) != 0x80)
2663 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002664 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002665 break;
2666 frm_nxt += 3;
2667 }
2668 else
2669 {
2670 break;
2671 }
2672 }
2673 return static_cast<int>(frm_nxt - frm);
2674}
2675
2676static
2677codecvt_base::result
2678ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2679 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2680 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2681{
2682 frm_nxt = frm;
2683 to_nxt = to;
2684 if (mode & generate_header)
2685 {
2686 if (to_end-to_nxt < 2)
2687 return codecvt_base::partial;
2688 *to_nxt++ = static_cast<uint8_t>(0xFE);
2689 *to_nxt++ = static_cast<uint8_t>(0xFF);
2690 }
2691 for (; frm_nxt < frm_end; ++frm_nxt)
2692 {
2693 uint32_t wc = *frm_nxt;
2694 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2695 return codecvt_base::error;
2696 if (wc < 0x010000)
2697 {
2698 if (to_end-to_nxt < 2)
2699 return codecvt_base::partial;
2700 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2701 *to_nxt++ = static_cast<uint8_t>(wc);
2702 }
2703 else
2704 {
2705 if (to_end-to_nxt < 4)
2706 return codecvt_base::partial;
2707 uint16_t t = static_cast<uint16_t>(
2708 0xD800
2709 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2710 | ((wc & 0x00FC00) >> 10));
2711 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2712 *to_nxt++ = static_cast<uint8_t>(t);
2713 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2714 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2715 *to_nxt++ = static_cast<uint8_t>(t);
2716 }
2717 }
2718 return codecvt_base::ok;
2719}
2720
2721static
2722codecvt_base::result
2723utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2724 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2725 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2726{
2727 frm_nxt = frm;
2728 to_nxt = to;
2729 if (mode & consume_header)
2730 {
2731 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2732 frm_nxt += 2;
2733 }
2734 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2735 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002736 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002737 if ((c1 & 0xFC00) == 0xDC00)
2738 return codecvt_base::error;
2739 if ((c1 & 0xFC00) != 0xD800)
2740 {
2741 if (c1 > Maxcode)
2742 return codecvt_base::error;
2743 *to_nxt = static_cast<uint32_t>(c1);
2744 frm_nxt += 2;
2745 }
2746 else
2747 {
2748 if (frm_end-frm_nxt < 4)
2749 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002750 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002751 if ((c2 & 0xFC00) != 0xDC00)
2752 return codecvt_base::error;
2753 uint32_t t = static_cast<uint32_t>(
2754 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2755 | ((c1 & 0x003F) << 10)
2756 | (c2 & 0x03FF));
2757 if (t > Maxcode)
2758 return codecvt_base::error;
2759 *to_nxt = t;
2760 frm_nxt += 4;
2761 }
2762 }
2763 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2764}
2765
2766static
2767int
2768utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2769 size_t mx, unsigned long Maxcode = 0x10FFFF,
2770 codecvt_mode mode = codecvt_mode(0))
2771{
2772 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002773 if (mode & consume_header)
2774 {
2775 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2776 frm_nxt += 2;
2777 }
2778 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2779 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002780 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002781 if ((c1 & 0xFC00) == 0xDC00)
2782 break;
2783 if ((c1 & 0xFC00) != 0xD800)
2784 {
2785 if (c1 > Maxcode)
2786 break;
2787 frm_nxt += 2;
2788 }
2789 else
2790 {
2791 if (frm_end-frm_nxt < 4)
2792 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002793 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002794 if ((c2 & 0xFC00) != 0xDC00)
2795 break;
2796 uint32_t t = static_cast<uint32_t>(
2797 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2798 | ((c1 & 0x003F) << 10)
2799 | (c2 & 0x03FF));
2800 if (t > Maxcode)
2801 break;
2802 frm_nxt += 4;
2803 }
2804 }
2805 return static_cast<int>(frm_nxt - frm);
2806}
2807
2808static
2809codecvt_base::result
2810ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2811 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2812 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2813{
2814 frm_nxt = frm;
2815 to_nxt = to;
2816 if (mode & generate_header)
2817 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002818 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002819 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002820 *to_nxt++ = static_cast<uint8_t>(0xFF);
2821 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002822 }
2823 for (; frm_nxt < frm_end; ++frm_nxt)
2824 {
2825 uint32_t wc = *frm_nxt;
2826 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2827 return codecvt_base::error;
2828 if (wc < 0x010000)
2829 {
2830 if (to_end-to_nxt < 2)
2831 return codecvt_base::partial;
2832 *to_nxt++ = static_cast<uint8_t>(wc);
2833 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2834 }
2835 else
2836 {
2837 if (to_end-to_nxt < 4)
2838 return codecvt_base::partial;
2839 uint16_t t = static_cast<uint16_t>(
2840 0xD800
2841 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2842 | ((wc & 0x00FC00) >> 10));
2843 *to_nxt++ = static_cast<uint8_t>(t);
2844 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2845 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2846 *to_nxt++ = static_cast<uint8_t>(t);
2847 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2848 }
2849 }
2850 return codecvt_base::ok;
2851}
2852
2853static
2854codecvt_base::result
2855utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2856 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2857 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2858{
2859 frm_nxt = frm;
2860 to_nxt = to;
2861 if (mode & consume_header)
2862 {
2863 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2864 frm_nxt += 2;
2865 }
2866 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2867 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002868 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002869 if ((c1 & 0xFC00) == 0xDC00)
2870 return codecvt_base::error;
2871 if ((c1 & 0xFC00) != 0xD800)
2872 {
2873 if (c1 > Maxcode)
2874 return codecvt_base::error;
2875 *to_nxt = static_cast<uint32_t>(c1);
2876 frm_nxt += 2;
2877 }
2878 else
2879 {
2880 if (frm_end-frm_nxt < 4)
2881 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002882 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002883 if ((c2 & 0xFC00) != 0xDC00)
2884 return codecvt_base::error;
2885 uint32_t t = static_cast<uint32_t>(
2886 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2887 | ((c1 & 0x003F) << 10)
2888 | (c2 & 0x03FF));
2889 if (t > Maxcode)
2890 return codecvt_base::error;
2891 *to_nxt = t;
2892 frm_nxt += 4;
2893 }
2894 }
2895 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2896}
2897
2898static
2899int
2900utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2901 size_t mx, unsigned long Maxcode = 0x10FFFF,
2902 codecvt_mode mode = codecvt_mode(0))
2903{
2904 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002905 if (mode & consume_header)
2906 {
2907 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2908 frm_nxt += 2;
2909 }
2910 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2911 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002912 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002913 if ((c1 & 0xFC00) == 0xDC00)
2914 break;
2915 if ((c1 & 0xFC00) != 0xD800)
2916 {
2917 if (c1 > Maxcode)
2918 break;
2919 frm_nxt += 2;
2920 }
2921 else
2922 {
2923 if (frm_end-frm_nxt < 4)
2924 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002925 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002926 if ((c2 & 0xFC00) != 0xDC00)
2927 break;
2928 uint32_t t = static_cast<uint32_t>(
2929 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2930 | ((c1 & 0x003F) << 10)
2931 | (c2 & 0x03FF));
2932 if (t > Maxcode)
2933 break;
2934 frm_nxt += 4;
2935 }
2936 }
2937 return static_cast<int>(frm_nxt - frm);
2938}
2939
2940static
2941codecvt_base::result
2942ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2943 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2944 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2945{
2946 frm_nxt = frm;
2947 to_nxt = to;
2948 if (mode & generate_header)
2949 {
2950 if (to_end-to_nxt < 2)
2951 return codecvt_base::partial;
2952 *to_nxt++ = static_cast<uint8_t>(0xFE);
2953 *to_nxt++ = static_cast<uint8_t>(0xFF);
2954 }
2955 for (; frm_nxt < frm_end; ++frm_nxt)
2956 {
2957 uint16_t wc = *frm_nxt;
2958 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2959 return codecvt_base::error;
2960 if (to_end-to_nxt < 2)
2961 return codecvt_base::partial;
2962 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2963 *to_nxt++ = static_cast<uint8_t>(wc);
2964 }
2965 return codecvt_base::ok;
2966}
2967
2968static
2969codecvt_base::result
2970utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2971 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2972 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2973{
2974 frm_nxt = frm;
2975 to_nxt = to;
2976 if (mode & consume_header)
2977 {
2978 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2979 frm_nxt += 2;
2980 }
2981 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2982 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002983 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002984 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2985 return codecvt_base::error;
2986 *to_nxt = c1;
2987 frm_nxt += 2;
2988 }
2989 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2990}
2991
2992static
2993int
2994utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2995 size_t mx, unsigned long Maxcode = 0x10FFFF,
2996 codecvt_mode mode = codecvt_mode(0))
2997{
2998 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002999 if (mode & consume_header)
3000 {
3001 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3002 frm_nxt += 2;
3003 }
3004 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3005 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003006 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003007 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3008 break;
3009 frm_nxt += 2;
3010 }
3011 return static_cast<int>(frm_nxt - frm);
3012}
3013
3014static
3015codecvt_base::result
3016ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3017 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3018 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3019{
3020 frm_nxt = frm;
3021 to_nxt = to;
3022 if (mode & generate_header)
3023 {
3024 if (to_end-to_nxt < 2)
3025 return codecvt_base::partial;
3026 *to_nxt++ = static_cast<uint8_t>(0xFF);
3027 *to_nxt++ = static_cast<uint8_t>(0xFE);
3028 }
3029 for (; frm_nxt < frm_end; ++frm_nxt)
3030 {
3031 uint16_t wc = *frm_nxt;
3032 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3033 return codecvt_base::error;
3034 if (to_end-to_nxt < 2)
3035 return codecvt_base::partial;
3036 *to_nxt++ = static_cast<uint8_t>(wc);
3037 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3038 }
3039 return codecvt_base::ok;
3040}
3041
3042static
3043codecvt_base::result
3044utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3045 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3046 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3047{
3048 frm_nxt = frm;
3049 to_nxt = to;
3050 if (mode & consume_header)
3051 {
3052 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3053 frm_nxt += 2;
3054 }
3055 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3056 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003057 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003058 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3059 return codecvt_base::error;
3060 *to_nxt = c1;
3061 frm_nxt += 2;
3062 }
3063 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3064}
3065
3066static
3067int
3068utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3069 size_t mx, unsigned long Maxcode = 0x10FFFF,
3070 codecvt_mode mode = codecvt_mode(0))
3071{
3072 const uint8_t* frm_nxt = frm;
3073 frm_nxt = frm;
3074 if (mode & consume_header)
3075 {
3076 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3077 frm_nxt += 2;
3078 }
3079 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3080 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003081 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003082 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3083 break;
3084 frm_nxt += 2;
3085 }
3086 return static_cast<int>(frm_nxt - frm);
3087}
3088
Howard Hinnantc51e1022010-05-11 19:42:16 +00003089// template <> class codecvt<char16_t, char, mbstate_t>
3090
Howard Hinnantffb308e2010-08-22 00:03:27 +00003091locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003092
3093codecvt<char16_t, char, mbstate_t>::~codecvt()
3094{
3095}
3096
3097codecvt<char16_t, char, mbstate_t>::result
3098codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003099 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003100 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3101{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003102 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3103 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3104 const uint16_t* _frm_nxt = _frm;
3105 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3106 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3107 uint8_t* _to_nxt = _to;
3108 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3109 frm_nxt = frm + (_frm_nxt - _frm);
3110 to_nxt = to + (_to_nxt - _to);
3111 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003112}
3113
3114codecvt<char16_t, char, mbstate_t>::result
3115codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003116 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003117 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3118{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003119 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3120 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3121 const uint8_t* _frm_nxt = _frm;
3122 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3123 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3124 uint16_t* _to_nxt = _to;
3125 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3126 frm_nxt = frm + (_frm_nxt - _frm);
3127 to_nxt = to + (_to_nxt - _to);
3128 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003129}
3130
3131codecvt<char16_t, char, mbstate_t>::result
3132codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3133 extern_type* to, extern_type*, extern_type*& to_nxt) const
3134{
3135 to_nxt = to;
3136 return noconv;
3137}
3138
3139int
Louis Dionne65358e12021-03-01 12:09:45 -05003140codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003141{
3142 return 0;
3143}
3144
3145bool
Louis Dionne65358e12021-03-01 12:09:45 -05003146codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003147{
3148 return false;
3149}
3150
3151int
3152codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3153 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3154{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003155 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3156 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3157 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003158}
3159
3160int
Louis Dionne65358e12021-03-01 12:09:45 -05003161codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003162{
3163 return 4;
3164}
3165
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003166#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003167
3168// template <> class codecvt<char16_t, char8_t, mbstate_t>
3169
3170locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3171
3172codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3173{
3174}
3175
3176codecvt<char16_t, char8_t, mbstate_t>::result
3177codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3178 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3179 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3180{
3181 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3182 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3183 const uint16_t* _frm_nxt = _frm;
3184 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3185 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3186 uint8_t* _to_nxt = _to;
3187 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3188 frm_nxt = frm + (_frm_nxt - _frm);
3189 to_nxt = to + (_to_nxt - _to);
3190 return r;
3191}
3192
3193codecvt<char16_t, char8_t, mbstate_t>::result
3194codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3195 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3196 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3197{
3198 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3199 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3200 const uint8_t* _frm_nxt = _frm;
3201 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3202 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3203 uint16_t* _to_nxt = _to;
3204 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3205 frm_nxt = frm + (_frm_nxt - _frm);
3206 to_nxt = to + (_to_nxt - _to);
3207 return r;
3208}
3209
3210codecvt<char16_t, char8_t, mbstate_t>::result
3211codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3212 extern_type* to, extern_type*, extern_type*& to_nxt) const
3213{
3214 to_nxt = to;
3215 return noconv;
3216}
3217
3218int
Louis Dionne65358e12021-03-01 12:09:45 -05003219codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003220{
3221 return 0;
3222}
3223
3224bool
Louis Dionne65358e12021-03-01 12:09:45 -05003225codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003226{
3227 return false;
3228}
3229
3230int
3231codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3232 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3233{
3234 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3235 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3236 return utf8_to_utf16_length(_frm, _frm_end, mx);
3237}
3238
3239int
Louis Dionne65358e12021-03-01 12:09:45 -05003240codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003241{
3242 return 4;
3243}
3244
3245#endif
3246
Howard Hinnantc51e1022010-05-11 19:42:16 +00003247// template <> class codecvt<char32_t, char, mbstate_t>
3248
Howard Hinnantffb308e2010-08-22 00:03:27 +00003249locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003250
3251codecvt<char32_t, char, mbstate_t>::~codecvt()
3252{
3253}
3254
3255codecvt<char32_t, char, mbstate_t>::result
3256codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003257 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003258 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3259{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003260 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3261 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3262 const uint32_t* _frm_nxt = _frm;
3263 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3264 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3265 uint8_t* _to_nxt = _to;
3266 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3267 frm_nxt = frm + (_frm_nxt - _frm);
3268 to_nxt = to + (_to_nxt - _to);
3269 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003270}
3271
3272codecvt<char32_t, char, mbstate_t>::result
3273codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003274 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003275 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3276{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003277 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3278 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3279 const uint8_t* _frm_nxt = _frm;
3280 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3281 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3282 uint32_t* _to_nxt = _to;
3283 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3284 frm_nxt = frm + (_frm_nxt - _frm);
3285 to_nxt = to + (_to_nxt - _to);
3286 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003287}
3288
3289codecvt<char32_t, char, mbstate_t>::result
3290codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3291 extern_type* to, extern_type*, extern_type*& to_nxt) const
3292{
3293 to_nxt = to;
3294 return noconv;
3295}
3296
3297int
Louis Dionne65358e12021-03-01 12:09:45 -05003298codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003299{
3300 return 0;
3301}
3302
3303bool
Louis Dionne65358e12021-03-01 12:09:45 -05003304codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003305{
3306 return false;
3307}
3308
3309int
3310codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3311 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3312{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003313 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3314 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3315 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003316}
3317
3318int
Louis Dionne65358e12021-03-01 12:09:45 -05003319codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003320{
3321 return 4;
3322}
3323
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003324#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003325
3326// template <> class codecvt<char32_t, char8_t, mbstate_t>
3327
3328locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3329
3330codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3331{
3332}
3333
3334codecvt<char32_t, char8_t, mbstate_t>::result
3335codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3336 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3337 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3338{
3339 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3340 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3341 const uint32_t* _frm_nxt = _frm;
3342 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3343 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3344 uint8_t* _to_nxt = _to;
3345 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3346 frm_nxt = frm + (_frm_nxt - _frm);
3347 to_nxt = to + (_to_nxt - _to);
3348 return r;
3349}
3350
3351codecvt<char32_t, char8_t, mbstate_t>::result
3352codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3353 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3354 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3355{
3356 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3357 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3358 const uint8_t* _frm_nxt = _frm;
3359 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3360 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3361 uint32_t* _to_nxt = _to;
3362 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3363 frm_nxt = frm + (_frm_nxt - _frm);
3364 to_nxt = to + (_to_nxt - _to);
3365 return r;
3366}
3367
3368codecvt<char32_t, char8_t, mbstate_t>::result
3369codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3370 extern_type* to, extern_type*, extern_type*& to_nxt) const
3371{
3372 to_nxt = to;
3373 return noconv;
3374}
3375
3376int
Louis Dionne65358e12021-03-01 12:09:45 -05003377codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003378{
3379 return 0;
3380}
3381
3382bool
Louis Dionne65358e12021-03-01 12:09:45 -05003383codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003384{
3385 return false;
3386}
3387
3388int
3389codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3390 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3391{
3392 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3393 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3394 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3395}
3396
3397int
Louis Dionne65358e12021-03-01 12:09:45 -05003398codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003399{
3400 return 4;
3401}
3402
3403#endif
3404
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003405// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003406
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003407__codecvt_utf8<wchar_t>::result
3408__codecvt_utf8<wchar_t>::do_out(state_type&,
3409 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003410 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3411{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003412#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003413 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3414 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3415 const uint16_t* _frm_nxt = _frm;
3416#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003417 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3418 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3419 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003420#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003421 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3422 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3423 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003424#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003425 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3426 _Maxcode_, _Mode_);
3427#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003428 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3429 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003430#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003431 frm_nxt = frm + (_frm_nxt - _frm);
3432 to_nxt = to + (_to_nxt - _to);
3433 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003434}
3435
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003436__codecvt_utf8<wchar_t>::result
3437__codecvt_utf8<wchar_t>::do_in(state_type&,
3438 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003439 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3440{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003441 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3442 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3443 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003444#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003445 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3446 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3447 uint16_t* _to_nxt = _to;
3448 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3449 _Maxcode_, _Mode_);
3450#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003451 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3452 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3453 uint32_t* _to_nxt = _to;
3454 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3455 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003456#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003457 frm_nxt = frm + (_frm_nxt - _frm);
3458 to_nxt = to + (_to_nxt - _to);
3459 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003460}
3461
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003462__codecvt_utf8<wchar_t>::result
3463__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003464 extern_type* to, extern_type*, extern_type*& to_nxt) const
3465{
3466 to_nxt = to;
3467 return noconv;
3468}
3469
3470int
Louis Dionne65358e12021-03-01 12:09:45 -05003471__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003472{
3473 return 0;
3474}
3475
3476bool
Louis Dionne65358e12021-03-01 12:09:45 -05003477__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003478{
3479 return false;
3480}
3481
3482int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003483__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003484 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3485{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003486 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3487 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003488#if defined(_LIBCPP_SHORT_WCHAR)
3489 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3490#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003491 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003492#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003493}
3494
3495int
Louis Dionne65358e12021-03-01 12:09:45 -05003496__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003497{
Xing Xue50b0eb42021-09-09 16:20:36 -04003498#if defined(_LIBCPP_SHORT_WCHAR)
3499 if (_Mode_ & consume_header)
3500 return 6;
3501 return 3;
3502#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003503 if (_Mode_ & consume_header)
3504 return 7;
3505 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003506#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003507}
3508
3509// __codecvt_utf8<char16_t>
3510
3511__codecvt_utf8<char16_t>::result
3512__codecvt_utf8<char16_t>::do_out(state_type&,
3513 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3514 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3515{
3516 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3517 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3518 const uint16_t* _frm_nxt = _frm;
3519 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3520 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3521 uint8_t* _to_nxt = _to;
3522 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3523 _Maxcode_, _Mode_);
3524 frm_nxt = frm + (_frm_nxt - _frm);
3525 to_nxt = to + (_to_nxt - _to);
3526 return r;
3527}
3528
3529__codecvt_utf8<char16_t>::result
3530__codecvt_utf8<char16_t>::do_in(state_type&,
3531 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3532 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3533{
3534 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3535 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3536 const uint8_t* _frm_nxt = _frm;
3537 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3538 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3539 uint16_t* _to_nxt = _to;
3540 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3541 _Maxcode_, _Mode_);
3542 frm_nxt = frm + (_frm_nxt - _frm);
3543 to_nxt = to + (_to_nxt - _to);
3544 return r;
3545}
3546
3547__codecvt_utf8<char16_t>::result
3548__codecvt_utf8<char16_t>::do_unshift(state_type&,
3549 extern_type* to, extern_type*, extern_type*& to_nxt) const
3550{
3551 to_nxt = to;
3552 return noconv;
3553}
3554
3555int
Louis Dionne65358e12021-03-01 12:09:45 -05003556__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003557{
3558 return 0;
3559}
3560
3561bool
Louis Dionne65358e12021-03-01 12:09:45 -05003562__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003563{
3564 return false;
3565}
3566
3567int
3568__codecvt_utf8<char16_t>::do_length(state_type&,
3569 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3570{
3571 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3572 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3573 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3574}
3575
3576int
Louis Dionne65358e12021-03-01 12:09:45 -05003577__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003578{
3579 if (_Mode_ & consume_header)
3580 return 6;
3581 return 3;
3582}
3583
3584// __codecvt_utf8<char32_t>
3585
3586__codecvt_utf8<char32_t>::result
3587__codecvt_utf8<char32_t>::do_out(state_type&,
3588 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3589 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3590{
3591 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3592 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3593 const uint32_t* _frm_nxt = _frm;
3594 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3595 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3596 uint8_t* _to_nxt = _to;
3597 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3598 _Maxcode_, _Mode_);
3599 frm_nxt = frm + (_frm_nxt - _frm);
3600 to_nxt = to + (_to_nxt - _to);
3601 return r;
3602}
3603
3604__codecvt_utf8<char32_t>::result
3605__codecvt_utf8<char32_t>::do_in(state_type&,
3606 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3607 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3608{
3609 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3610 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3611 const uint8_t* _frm_nxt = _frm;
3612 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3613 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3614 uint32_t* _to_nxt = _to;
3615 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3616 _Maxcode_, _Mode_);
3617 frm_nxt = frm + (_frm_nxt - _frm);
3618 to_nxt = to + (_to_nxt - _to);
3619 return r;
3620}
3621
3622__codecvt_utf8<char32_t>::result
3623__codecvt_utf8<char32_t>::do_unshift(state_type&,
3624 extern_type* to, extern_type*, extern_type*& to_nxt) const
3625{
3626 to_nxt = to;
3627 return noconv;
3628}
3629
3630int
Louis Dionne65358e12021-03-01 12:09:45 -05003631__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003632{
3633 return 0;
3634}
3635
3636bool
Louis Dionne65358e12021-03-01 12:09:45 -05003637__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003638{
3639 return false;
3640}
3641
3642int
3643__codecvt_utf8<char32_t>::do_length(state_type&,
3644 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3645{
3646 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3647 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3648 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3649}
3650
3651int
Louis Dionne65358e12021-03-01 12:09:45 -05003652__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003653{
3654 if (_Mode_ & consume_header)
3655 return 7;
3656 return 4;
3657}
3658
3659// __codecvt_utf16<wchar_t, false>
3660
3661__codecvt_utf16<wchar_t, false>::result
3662__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3663 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3664 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3665{
Xing Xue50b0eb42021-09-09 16:20:36 -04003666#if defined(_LIBCPP_SHORT_WCHAR)
3667 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3668 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3669 const uint16_t* _frm_nxt = _frm;
3670#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003671 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3672 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3673 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003674#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003675 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3676 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3677 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003678#if defined(_LIBCPP_SHORT_WCHAR)
3679 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3680 _Maxcode_, _Mode_);
3681#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003682 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3683 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003684#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003685 frm_nxt = frm + (_frm_nxt - _frm);
3686 to_nxt = to + (_to_nxt - _to);
3687 return r;
3688}
3689
3690__codecvt_utf16<wchar_t, false>::result
3691__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3692 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3693 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3694{
3695 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3696 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3697 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003698#if defined(_LIBCPP_SHORT_WCHAR)
3699 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3700 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3701 uint16_t* _to_nxt = _to;
3702 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3703 _Maxcode_, _Mode_);
3704#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003705 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3706 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3707 uint32_t* _to_nxt = _to;
3708 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3709 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003710#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003711 frm_nxt = frm + (_frm_nxt - _frm);
3712 to_nxt = to + (_to_nxt - _to);
3713 return r;
3714}
3715
3716__codecvt_utf16<wchar_t, false>::result
3717__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3718 extern_type* to, extern_type*, extern_type*& to_nxt) const
3719{
3720 to_nxt = to;
3721 return noconv;
3722}
3723
3724int
Louis Dionne65358e12021-03-01 12:09:45 -05003725__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003726{
3727 return 0;
3728}
3729
3730bool
Louis Dionne65358e12021-03-01 12:09:45 -05003731__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003732{
3733 return false;
3734}
3735
3736int
3737__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3738 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3739{
3740 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3741 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003742#if defined(_LIBCPP_SHORT_WCHAR)
3743 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3744#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003745 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003746#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003747}
3748
3749int
Louis Dionne65358e12021-03-01 12:09:45 -05003750__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003751{
Xing Xue50b0eb42021-09-09 16:20:36 -04003752#if defined(_LIBCPP_SHORT_WCHAR)
3753 if (_Mode_ & consume_header)
3754 return 4;
3755 return 2;
3756#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003757 if (_Mode_ & consume_header)
3758 return 6;
3759 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003760#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003761}
3762
3763// __codecvt_utf16<wchar_t, true>
3764
3765__codecvt_utf16<wchar_t, true>::result
3766__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3767 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3768 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3769{
Xing Xue50b0eb42021-09-09 16:20:36 -04003770#if defined(_LIBCPP_SHORT_WCHAR)
3771 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3772 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3773 const uint16_t* _frm_nxt = _frm;
3774#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003775 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3776 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3777 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003778#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003779 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3780 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3781 uint8_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04003782#if defined(_LIBCPP_SHORT_WCHAR)
3783 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3784 _Maxcode_, _Mode_);
3785#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003786 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3787 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003788#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003789 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_in(state_type&,
3796 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3797 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3798{
3799 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3800 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3801 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04003802#if defined(_LIBCPP_SHORT_WCHAR)
3803 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3804 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3805 uint16_t* _to_nxt = _to;
3806 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3807 _Maxcode_, _Mode_);
3808#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003809 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3810 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3811 uint32_t* _to_nxt = _to;
3812 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3813 _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003814#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003815 frm_nxt = frm + (_frm_nxt - _frm);
3816 to_nxt = to + (_to_nxt - _to);
3817 return r;
3818}
3819
3820__codecvt_utf16<wchar_t, true>::result
3821__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3822 extern_type* to, extern_type*, extern_type*& to_nxt) const
3823{
3824 to_nxt = to;
3825 return noconv;
3826}
3827
3828int
Louis Dionne65358e12021-03-01 12:09:45 -05003829__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003830{
3831 return 0;
3832}
3833
3834bool
Louis Dionne65358e12021-03-01 12:09:45 -05003835__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003836{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003837 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003838}
3839
3840int
3841__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3842 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3843{
3844 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3845 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
Xing Xue50b0eb42021-09-09 16:20:36 -04003846#if defined(_LIBCPP_SHORT_WCHAR)
3847 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3848#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003849 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Xing Xue50b0eb42021-09-09 16:20:36 -04003850#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003851}
3852
3853int
Louis Dionne65358e12021-03-01 12:09:45 -05003854__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003855{
Xing Xue50b0eb42021-09-09 16:20:36 -04003856#if defined(_LIBCPP_SHORT_WCHAR)
3857 if (_Mode_ & consume_header)
3858 return 4;
3859 return 2;
3860#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003861 if (_Mode_ & consume_header)
3862 return 6;
3863 return 4;
Xing Xue50b0eb42021-09-09 16:20:36 -04003864#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003865}
3866
3867// __codecvt_utf16<char16_t, false>
3868
3869__codecvt_utf16<char16_t, false>::result
3870__codecvt_utf16<char16_t, false>::do_out(state_type&,
3871 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3872 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3873{
3874 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3875 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3876 const uint16_t* _frm_nxt = _frm;
3877 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3878 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3879 uint8_t* _to_nxt = _to;
3880 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3881 _Maxcode_, _Mode_);
3882 frm_nxt = frm + (_frm_nxt - _frm);
3883 to_nxt = to + (_to_nxt - _to);
3884 return r;
3885}
3886
3887__codecvt_utf16<char16_t, false>::result
3888__codecvt_utf16<char16_t, false>::do_in(state_type&,
3889 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3890 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3891{
3892 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3893 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3894 const uint8_t* _frm_nxt = _frm;
3895 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3896 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3897 uint16_t* _to_nxt = _to;
3898 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3899 _Maxcode_, _Mode_);
3900 frm_nxt = frm + (_frm_nxt - _frm);
3901 to_nxt = to + (_to_nxt - _to);
3902 return r;
3903}
3904
3905__codecvt_utf16<char16_t, false>::result
3906__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3907 extern_type* to, extern_type*, extern_type*& to_nxt) const
3908{
3909 to_nxt = to;
3910 return noconv;
3911}
3912
3913int
Louis Dionne65358e12021-03-01 12:09:45 -05003914__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003915{
3916 return 0;
3917}
3918
3919bool
Louis Dionne65358e12021-03-01 12:09:45 -05003920__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003921{
3922 return false;
3923}
3924
3925int
3926__codecvt_utf16<char16_t, false>::do_length(state_type&,
3927 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3928{
3929 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3930 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3931 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3932}
3933
3934int
Louis Dionne65358e12021-03-01 12:09:45 -05003935__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003936{
3937 if (_Mode_ & consume_header)
3938 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003939 return 2;
3940}
3941
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003942// __codecvt_utf16<char16_t, true>
3943
3944__codecvt_utf16<char16_t, true>::result
3945__codecvt_utf16<char16_t, true>::do_out(state_type&,
3946 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3947 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3948{
3949 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3950 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3951 const uint16_t* _frm_nxt = _frm;
3952 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3953 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3954 uint8_t* _to_nxt = _to;
3955 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3956 _Maxcode_, _Mode_);
3957 frm_nxt = frm + (_frm_nxt - _frm);
3958 to_nxt = to + (_to_nxt - _to);
3959 return r;
3960}
3961
3962__codecvt_utf16<char16_t, true>::result
3963__codecvt_utf16<char16_t, true>::do_in(state_type&,
3964 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3965 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3966{
3967 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3968 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3969 const uint8_t* _frm_nxt = _frm;
3970 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3971 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3972 uint16_t* _to_nxt = _to;
3973 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3974 _Maxcode_, _Mode_);
3975 frm_nxt = frm + (_frm_nxt - _frm);
3976 to_nxt = to + (_to_nxt - _to);
3977 return r;
3978}
3979
3980__codecvt_utf16<char16_t, true>::result
3981__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3982 extern_type* to, extern_type*, extern_type*& to_nxt) const
3983{
3984 to_nxt = to;
3985 return noconv;
3986}
3987
3988int
Louis Dionne65358e12021-03-01 12:09:45 -05003989__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003990{
3991 return 0;
3992}
3993
3994bool
Louis Dionne65358e12021-03-01 12:09:45 -05003995__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003996{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003997 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003998}
3999
4000int
4001__codecvt_utf16<char16_t, true>::do_length(state_type&,
4002 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4003{
4004 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4005 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4006 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4007}
4008
4009int
Louis Dionne65358e12021-03-01 12:09:45 -05004010__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004011{
4012 if (_Mode_ & consume_header)
4013 return 4;
4014 return 2;
4015}
4016
4017// __codecvt_utf16<char32_t, false>
4018
4019__codecvt_utf16<char32_t, false>::result
4020__codecvt_utf16<char32_t, false>::do_out(state_type&,
4021 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4022 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4023{
4024 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4025 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4026 const uint32_t* _frm_nxt = _frm;
4027 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4028 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4029 uint8_t* _to_nxt = _to;
4030 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4031 _Maxcode_, _Mode_);
4032 frm_nxt = frm + (_frm_nxt - _frm);
4033 to_nxt = to + (_to_nxt - _to);
4034 return r;
4035}
4036
4037__codecvt_utf16<char32_t, false>::result
4038__codecvt_utf16<char32_t, false>::do_in(state_type&,
4039 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4040 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4041{
4042 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4043 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4044 const uint8_t* _frm_nxt = _frm;
4045 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4046 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4047 uint32_t* _to_nxt = _to;
4048 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4049 _Maxcode_, _Mode_);
4050 frm_nxt = frm + (_frm_nxt - _frm);
4051 to_nxt = to + (_to_nxt - _to);
4052 return r;
4053}
4054
4055__codecvt_utf16<char32_t, false>::result
4056__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
4057 extern_type* to, extern_type*, extern_type*& to_nxt) const
4058{
4059 to_nxt = to;
4060 return noconv;
4061}
4062
4063int
Louis Dionne65358e12021-03-01 12:09:45 -05004064__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004065{
4066 return 0;
4067}
4068
4069bool
Louis Dionne65358e12021-03-01 12:09:45 -05004070__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004071{
4072 return false;
4073}
4074
4075int
4076__codecvt_utf16<char32_t, false>::do_length(state_type&,
4077 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4078{
4079 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4080 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4081 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4082}
4083
4084int
Louis Dionne65358e12021-03-01 12:09:45 -05004085__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004086{
4087 if (_Mode_ & consume_header)
4088 return 6;
4089 return 4;
4090}
4091
4092// __codecvt_utf16<char32_t, true>
4093
4094__codecvt_utf16<char32_t, true>::result
4095__codecvt_utf16<char32_t, true>::do_out(state_type&,
4096 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4097 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4098{
4099 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4100 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4101 const uint32_t* _frm_nxt = _frm;
4102 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4103 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4104 uint8_t* _to_nxt = _to;
4105 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4106 _Maxcode_, _Mode_);
4107 frm_nxt = frm + (_frm_nxt - _frm);
4108 to_nxt = to + (_to_nxt - _to);
4109 return r;
4110}
4111
4112__codecvt_utf16<char32_t, true>::result
4113__codecvt_utf16<char32_t, true>::do_in(state_type&,
4114 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4115 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4116{
4117 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4118 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4119 const uint8_t* _frm_nxt = _frm;
4120 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4121 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4122 uint32_t* _to_nxt = _to;
4123 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4124 _Maxcode_, _Mode_);
4125 frm_nxt = frm + (_frm_nxt - _frm);
4126 to_nxt = to + (_to_nxt - _to);
4127 return r;
4128}
4129
4130__codecvt_utf16<char32_t, true>::result
4131__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4132 extern_type* to, extern_type*, extern_type*& to_nxt) const
4133{
4134 to_nxt = to;
4135 return noconv;
4136}
4137
4138int
Louis Dionne65358e12021-03-01 12:09:45 -05004139__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004140{
4141 return 0;
4142}
4143
4144bool
Louis Dionne65358e12021-03-01 12:09:45 -05004145__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004146{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004147 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004148}
4149
4150int
4151__codecvt_utf16<char32_t, true>::do_length(state_type&,
4152 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4153{
4154 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4155 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4156 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4157}
4158
4159int
Louis Dionne65358e12021-03-01 12:09:45 -05004160__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004161{
4162 if (_Mode_ & consume_header)
4163 return 6;
4164 return 4;
4165}
4166
4167// __codecvt_utf8_utf16<wchar_t>
4168
4169__codecvt_utf8_utf16<wchar_t>::result
4170__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4171 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4172 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4173{
Xing Xue50b0eb42021-09-09 16:20:36 -04004174#if defined(_LIBCPP_SHORT_WCHAR)
4175 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4176 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4177 const uint16_t* _frm_nxt = _frm;
4178#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004179 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4180 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4181 const uint32_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004182#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004183 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4184 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4185 uint8_t* _to_nxt = _to;
4186 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4187 _Maxcode_, _Mode_);
4188 frm_nxt = frm + (_frm_nxt - _frm);
4189 to_nxt = to + (_to_nxt - _to);
4190 return r;
4191}
4192
4193__codecvt_utf8_utf16<wchar_t>::result
4194__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4195 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4196 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4197{
4198 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4199 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4200 const uint8_t* _frm_nxt = _frm;
Xing Xue50b0eb42021-09-09 16:20:36 -04004201#if defined(_LIBCPP_SHORT_WCHAR)
4202 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4203 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4204 uint16_t* _to_nxt = _to;
4205#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004206 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4207 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4208 uint32_t* _to_nxt = _to;
Xing Xue50b0eb42021-09-09 16:20:36 -04004209#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004210 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4211 _Maxcode_, _Mode_);
4212 frm_nxt = frm + (_frm_nxt - _frm);
4213 to_nxt = to + (_to_nxt - _to);
4214 return r;
4215}
4216
4217__codecvt_utf8_utf16<wchar_t>::result
4218__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4219 extern_type* to, extern_type*, extern_type*& to_nxt) const
4220{
4221 to_nxt = to;
4222 return noconv;
4223}
4224
4225int
Louis Dionne65358e12021-03-01 12:09:45 -05004226__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004227{
4228 return 0;
4229}
4230
4231bool
Louis Dionne65358e12021-03-01 12:09:45 -05004232__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004233{
4234 return false;
4235}
4236
4237int
4238__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4239 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4240{
4241 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4242 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4243 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4244}
4245
4246int
Louis Dionne65358e12021-03-01 12:09:45 -05004247__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004248{
4249 if (_Mode_ & consume_header)
4250 return 7;
4251 return 4;
4252}
4253
4254// __codecvt_utf8_utf16<char16_t>
4255
4256__codecvt_utf8_utf16<char16_t>::result
4257__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4258 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4259 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4260{
4261 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4262 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4263 const uint16_t* _frm_nxt = _frm;
4264 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4265 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4266 uint8_t* _to_nxt = _to;
4267 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4268 _Maxcode_, _Mode_);
4269 frm_nxt = frm + (_frm_nxt - _frm);
4270 to_nxt = to + (_to_nxt - _to);
4271 return r;
4272}
4273
4274__codecvt_utf8_utf16<char16_t>::result
4275__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4276 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4277 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4278{
4279 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4280 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4281 const uint8_t* _frm_nxt = _frm;
4282 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4283 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4284 uint16_t* _to_nxt = _to;
4285 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4286 _Maxcode_, _Mode_);
4287 frm_nxt = frm + (_frm_nxt - _frm);
4288 to_nxt = to + (_to_nxt - _to);
4289 return r;
4290}
4291
4292__codecvt_utf8_utf16<char16_t>::result
4293__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4294 extern_type* to, extern_type*, extern_type*& to_nxt) const
4295{
4296 to_nxt = to;
4297 return noconv;
4298}
4299
4300int
Louis Dionne65358e12021-03-01 12:09:45 -05004301__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004302{
4303 return 0;
4304}
4305
4306bool
Louis Dionne65358e12021-03-01 12:09:45 -05004307__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004308{
4309 return false;
4310}
4311
4312int
4313__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4314 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4315{
4316 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4317 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4318 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4319}
4320
4321int
Louis Dionne65358e12021-03-01 12:09:45 -05004322__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004323{
4324 if (_Mode_ & consume_header)
4325 return 7;
4326 return 4;
4327}
4328
4329// __codecvt_utf8_utf16<char32_t>
4330
4331__codecvt_utf8_utf16<char32_t>::result
4332__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4333 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4334 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4335{
4336 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4337 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4338 const uint32_t* _frm_nxt = _frm;
4339 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4340 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4341 uint8_t* _to_nxt = _to;
4342 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4343 _Maxcode_, _Mode_);
4344 frm_nxt = frm + (_frm_nxt - _frm);
4345 to_nxt = to + (_to_nxt - _to);
4346 return r;
4347}
4348
4349__codecvt_utf8_utf16<char32_t>::result
4350__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4351 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4352 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4353{
4354 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4355 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4356 const uint8_t* _frm_nxt = _frm;
4357 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4358 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4359 uint32_t* _to_nxt = _to;
4360 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4361 _Maxcode_, _Mode_);
4362 frm_nxt = frm + (_frm_nxt - _frm);
4363 to_nxt = to + (_to_nxt - _to);
4364 return r;
4365}
4366
4367__codecvt_utf8_utf16<char32_t>::result
4368__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4369 extern_type* to, extern_type*, extern_type*& to_nxt) const
4370{
4371 to_nxt = to;
4372 return noconv;
4373}
4374
4375int
Louis Dionne65358e12021-03-01 12:09:45 -05004376__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004377{
4378 return 0;
4379}
4380
4381bool
Louis Dionne65358e12021-03-01 12:09:45 -05004382__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004383{
4384 return false;
4385}
4386
4387int
4388__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4389 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4390{
4391 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4392 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4393 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4394}
4395
4396int
Louis Dionne65358e12021-03-01 12:09:45 -05004397__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004398{
4399 if (_Mode_ & consume_header)
4400 return 7;
4401 return 4;
4402}
4403
Howard Hinnantc51e1022010-05-11 19:42:16 +00004404// __narrow_to_utf8<16>
4405
4406__narrow_to_utf8<16>::~__narrow_to_utf8()
4407{
4408}
4409
4410// __narrow_to_utf8<32>
4411
4412__narrow_to_utf8<32>::~__narrow_to_utf8()
4413{
4414}
4415
4416// __widen_from_utf8<16>
4417
4418__widen_from_utf8<16>::~__widen_from_utf8()
4419{
4420}
4421
4422// __widen_from_utf8<32>
4423
4424__widen_from_utf8<32>::~__widen_from_utf8()
4425{
4426}
4427
Eric Fiselierbf945a22016-12-11 00:20:59 +00004428
4429static bool checked_string_to_wchar_convert(wchar_t& dest,
4430 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004431 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004432 if (*ptr == '\0')
4433 return false;
4434 mbstate_t mb = {};
4435 wchar_t out;
4436 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4437 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4438 return false;
4439 }
4440 dest = out;
4441 return true;
4442}
4443
4444static bool checked_string_to_char_convert(char& dest,
4445 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004446 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004447 if (*ptr == '\0')
4448 return false;
4449 if (!ptr[1]) {
4450 dest = *ptr;
4451 return true;
4452 }
4453 // First convert the MBS into a wide char then attempt to narrow it using
4454 // wctob_l.
4455 wchar_t wout;
4456 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4457 return false;
4458 int res;
4459 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4460 dest = res;
4461 return true;
4462 }
Louis Dionnefc6bd362021-09-09 14:00:22 -04004463 // FIXME: Work around specific multibyte sequences that we can reasonably
Eric Fiselierbf945a22016-12-11 00:20:59 +00004464 // translate into a different single byte.
4465 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004466 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004467 case L'\u00A0': // non-breaking space
4468 dest = ' ';
4469 return true;
4470 default:
4471 return false;
4472 }
4473 _LIBCPP_UNREACHABLE();
4474}
4475
4476
Howard Hinnantc51e1022010-05-11 19:42:16 +00004477// numpunct<char> && numpunct<wchar_t>
4478
4479locale::id numpunct< char >::id;
4480locale::id numpunct<wchar_t>::id;
4481
4482numpunct<char>::numpunct(size_t refs)
4483 : locale::facet(refs),
4484 __decimal_point_('.'),
4485 __thousands_sep_(',')
4486{
4487}
4488
4489numpunct<wchar_t>::numpunct(size_t refs)
4490 : locale::facet(refs),
4491 __decimal_point_(L'.'),
4492 __thousands_sep_(L',')
4493{
4494}
4495
4496numpunct<char>::~numpunct()
4497{
4498}
4499
4500numpunct<wchar_t>::~numpunct()
4501{
4502}
4503
4504 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4505wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4506
4507 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4508wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4509
4510string numpunct< char >::do_grouping() const {return __grouping_;}
4511string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4512
4513 string numpunct< char >::do_truename() const {return "true";}
4514wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4515
4516 string numpunct< char >::do_falsename() const {return "false";}
4517wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4518
4519// numpunct_byname<char>
4520
4521numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4522 : numpunct<char>(refs)
4523{
4524 __init(nm);
4525}
4526
4527numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4528 : numpunct<char>(refs)
4529{
4530 __init(nm.c_str());
4531}
4532
4533numpunct_byname<char>::~numpunct_byname()
4534{
4535}
4536
4537void
4538numpunct_byname<char>::__init(const char* nm)
4539{
4540 if (strcmp(nm, "C") != 0)
4541 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004542 __libcpp_unique_locale loc(nm);
4543 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004544 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004545 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004546
Ben Craig3756b922016-03-09 15:39:39 +00004547 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004548 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4549 loc.get());
4550 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4551 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004552 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004553 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004554 }
4555}
4556
4557// numpunct_byname<wchar_t>
4558
4559numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4560 : numpunct<wchar_t>(refs)
4561{
4562 __init(nm);
4563}
4564
4565numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4566 : numpunct<wchar_t>(refs)
4567{
4568 __init(nm.c_str());
4569}
4570
4571numpunct_byname<wchar_t>::~numpunct_byname()
4572{
4573}
4574
4575void
4576numpunct_byname<wchar_t>::__init(const char* nm)
4577{
4578 if (strcmp(nm, "C") != 0)
4579 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004580 __libcpp_unique_locale loc(nm);
4581 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004582 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004583 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004584
Ben Craig3756b922016-03-09 15:39:39 +00004585 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004586 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4587 loc.get());
4588 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4589 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004590 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004591 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004592 }
4593}
4594
4595// num_get helpers
4596
4597int
4598__num_get_base::__get_base(ios_base& iob)
4599{
4600 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4601 if (__basefield == ios_base::oct)
4602 return 8;
4603 else if (__basefield == ios_base::hex)
4604 return 16;
4605 else if (__basefield == 0)
4606 return 0;
4607 return 10;
4608}
4609
4610const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4611
4612void
4613__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4614 ios_base::iostate& __err)
4615{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004616// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4617// 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 +00004618 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004619 {
4620 reverse(__g, __g_end);
4621 const char* __ig = __grouping.data();
4622 const char* __eg = __ig + __grouping.size();
4623 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4624 {
4625 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4626 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004627 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004628 {
4629 __err = ios_base::failbit;
4630 return;
4631 }
4632 }
4633 if (__eg - __ig > 1)
4634 ++__ig;
4635 }
4636 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4637 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004638 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004639 __err = ios_base::failbit;
4640 }
4641 }
4642}
4643
4644void
4645__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4646 ios_base::fmtflags __flags)
4647{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004648 if ((__flags & ios_base::showpos) &&
4649 (__flags & ios_base::basefield) != ios_base::oct &&
4650 (__flags & ios_base::basefield) != ios_base::hex &&
4651 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004652 *__fmtp++ = '+';
4653 if (__flags & ios_base::showbase)
4654 *__fmtp++ = '#';
4655 while(*__len)
4656 *__fmtp++ = *__len++;
4657 if ((__flags & ios_base::basefield) == ios_base::oct)
4658 *__fmtp = 'o';
4659 else if ((__flags & ios_base::basefield) == ios_base::hex)
4660 {
4661 if (__flags & ios_base::uppercase)
4662 *__fmtp = 'X';
4663 else
4664 *__fmtp = 'x';
4665 }
4666 else if (__signd)
4667 *__fmtp = 'd';
4668 else
4669 *__fmtp = 'u';
4670}
4671
4672bool
4673__num_put_base::__format_float(char* __fmtp, const char* __len,
4674 ios_base::fmtflags __flags)
4675{
4676 bool specify_precision = true;
4677 if (__flags & ios_base::showpos)
4678 *__fmtp++ = '+';
4679 if (__flags & ios_base::showpoint)
4680 *__fmtp++ = '#';
4681 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004682 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004683 if (floatfield == (ios_base::fixed | ios_base::scientific))
4684 specify_precision = false;
4685 else
4686 {
4687 *__fmtp++ = '.';
4688 *__fmtp++ = '*';
4689 }
4690 while(*__len)
4691 *__fmtp++ = *__len++;
4692 if (floatfield == ios_base::fixed)
4693 {
4694 if (uppercase)
4695 *__fmtp = 'F';
4696 else
4697 *__fmtp = 'f';
4698 }
4699 else if (floatfield == ios_base::scientific)
4700 {
4701 if (uppercase)
4702 *__fmtp = 'E';
4703 else
4704 *__fmtp = 'e';
4705 }
4706 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4707 {
4708 if (uppercase)
4709 *__fmtp = 'A';
4710 else
4711 *__fmtp = 'a';
4712 }
4713 else
4714 {
4715 if (uppercase)
4716 *__fmtp = 'G';
4717 else
4718 *__fmtp = 'g';
4719 }
4720 return specify_precision;
4721}
4722
4723char*
4724__num_put_base::__identify_padding(char* __nb, char* __ne,
4725 const ios_base& __iob)
4726{
4727 switch (__iob.flags() & ios_base::adjustfield)
4728 {
4729 case ios_base::internal:
4730 if (__nb[0] == '-' || __nb[0] == '+')
4731 return __nb+1;
4732 if (__ne - __nb >= 2 && __nb[0] == '0'
4733 && (__nb[1] == 'x' || __nb[1] == 'X'))
4734 return __nb+2;
4735 break;
4736 case ios_base::left:
4737 return __ne;
4738 case ios_base::right:
4739 default:
4740 break;
4741 }
4742 return __nb;
4743}
4744
4745// time_get
4746
4747static
4748string*
4749init_weeks()
4750{
4751 static string weeks[14];
4752 weeks[0] = "Sunday";
4753 weeks[1] = "Monday";
4754 weeks[2] = "Tuesday";
4755 weeks[3] = "Wednesday";
4756 weeks[4] = "Thursday";
4757 weeks[5] = "Friday";
4758 weeks[6] = "Saturday";
4759 weeks[7] = "Sun";
4760 weeks[8] = "Mon";
4761 weeks[9] = "Tue";
4762 weeks[10] = "Wed";
4763 weeks[11] = "Thu";
4764 weeks[12] = "Fri";
4765 weeks[13] = "Sat";
4766 return weeks;
4767}
4768
4769static
4770wstring*
4771init_wweeks()
4772{
4773 static wstring weeks[14];
4774 weeks[0] = L"Sunday";
4775 weeks[1] = L"Monday";
4776 weeks[2] = L"Tuesday";
4777 weeks[3] = L"Wednesday";
4778 weeks[4] = L"Thursday";
4779 weeks[5] = L"Friday";
4780 weeks[6] = L"Saturday";
4781 weeks[7] = L"Sun";
4782 weeks[8] = L"Mon";
4783 weeks[9] = L"Tue";
4784 weeks[10] = L"Wed";
4785 weeks[11] = L"Thu";
4786 weeks[12] = L"Fri";
4787 weeks[13] = L"Sat";
4788 return weeks;
4789}
4790
4791template <>
4792const string*
4793__time_get_c_storage<char>::__weeks() const
4794{
4795 static const string* weeks = init_weeks();
4796 return weeks;
4797}
4798
4799template <>
4800const wstring*
4801__time_get_c_storage<wchar_t>::__weeks() const
4802{
4803 static const wstring* weeks = init_wweeks();
4804 return weeks;
4805}
4806
4807static
4808string*
4809init_months()
4810{
4811 static string months[24];
4812 months[0] = "January";
4813 months[1] = "February";
4814 months[2] = "March";
4815 months[3] = "April";
4816 months[4] = "May";
4817 months[5] = "June";
4818 months[6] = "July";
4819 months[7] = "August";
4820 months[8] = "September";
4821 months[9] = "October";
4822 months[10] = "November";
4823 months[11] = "December";
4824 months[12] = "Jan";
4825 months[13] = "Feb";
4826 months[14] = "Mar";
4827 months[15] = "Apr";
4828 months[16] = "May";
4829 months[17] = "Jun";
4830 months[18] = "Jul";
4831 months[19] = "Aug";
4832 months[20] = "Sep";
4833 months[21] = "Oct";
4834 months[22] = "Nov";
4835 months[23] = "Dec";
4836 return months;
4837}
4838
4839static
4840wstring*
4841init_wmonths()
4842{
4843 static wstring months[24];
4844 months[0] = L"January";
4845 months[1] = L"February";
4846 months[2] = L"March";
4847 months[3] = L"April";
4848 months[4] = L"May";
4849 months[5] = L"June";
4850 months[6] = L"July";
4851 months[7] = L"August";
4852 months[8] = L"September";
4853 months[9] = L"October";
4854 months[10] = L"November";
4855 months[11] = L"December";
4856 months[12] = L"Jan";
4857 months[13] = L"Feb";
4858 months[14] = L"Mar";
4859 months[15] = L"Apr";
4860 months[16] = L"May";
4861 months[17] = L"Jun";
4862 months[18] = L"Jul";
4863 months[19] = L"Aug";
4864 months[20] = L"Sep";
4865 months[21] = L"Oct";
4866 months[22] = L"Nov";
4867 months[23] = L"Dec";
4868 return months;
4869}
4870
4871template <>
4872const string*
4873__time_get_c_storage<char>::__months() const
4874{
4875 static const string* months = init_months();
4876 return months;
4877}
4878
4879template <>
4880const wstring*
4881__time_get_c_storage<wchar_t>::__months() const
4882{
4883 static const wstring* months = init_wmonths();
4884 return months;
4885}
4886
4887static
4888string*
4889init_am_pm()
4890{
Marshall Clow5cc04922018-01-11 17:16:52 +00004891 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004892 am_pm[0] = "AM";
4893 am_pm[1] = "PM";
4894 return am_pm;
4895}
4896
4897static
4898wstring*
4899init_wam_pm()
4900{
Marshall Clow5cc04922018-01-11 17:16:52 +00004901 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004902 am_pm[0] = L"AM";
4903 am_pm[1] = L"PM";
4904 return am_pm;
4905}
4906
4907template <>
4908const string*
4909__time_get_c_storage<char>::__am_pm() const
4910{
4911 static const string* am_pm = init_am_pm();
4912 return am_pm;
4913}
4914
4915template <>
4916const wstring*
4917__time_get_c_storage<wchar_t>::__am_pm() const
4918{
4919 static const wstring* am_pm = init_wam_pm();
4920 return am_pm;
4921}
4922
4923template <>
4924const string&
4925__time_get_c_storage<char>::__x() const
4926{
4927 static string s("%m/%d/%y");
4928 return s;
4929}
4930
4931template <>
4932const wstring&
4933__time_get_c_storage<wchar_t>::__x() const
4934{
4935 static wstring s(L"%m/%d/%y");
4936 return s;
4937}
4938
4939template <>
4940const string&
4941__time_get_c_storage<char>::__X() const
4942{
4943 static string s("%H:%M:%S");
4944 return s;
4945}
4946
4947template <>
4948const wstring&
4949__time_get_c_storage<wchar_t>::__X() const
4950{
4951 static wstring s(L"%H:%M:%S");
4952 return s;
4953}
4954
4955template <>
4956const string&
4957__time_get_c_storage<char>::__c() const
4958{
4959 static string s("%a %b %d %H:%M:%S %Y");
4960 return s;
4961}
4962
4963template <>
4964const wstring&
4965__time_get_c_storage<wchar_t>::__c() const
4966{
4967 static wstring s(L"%a %b %d %H:%M:%S %Y");
4968 return s;
4969}
4970
4971template <>
4972const string&
4973__time_get_c_storage<char>::__r() const
4974{
4975 static string s("%I:%M:%S %p");
4976 return s;
4977}
4978
4979template <>
4980const wstring&
4981__time_get_c_storage<wchar_t>::__r() const
4982{
4983 static wstring s(L"%I:%M:%S %p");
4984 return s;
4985}
4986
4987// time_get_byname
4988
4989__time_get::__time_get(const char* nm)
4990 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4991{
4992 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004993 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004994 " failed to construct for " + string(nm));
4995}
4996
4997__time_get::__time_get(const string& nm)
4998 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4999{
5000 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005001 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005002 " failed to construct for " + nm);
5003}
5004
5005__time_get::~__time_get()
5006{
5007 freelocale(__loc_);
5008}
Marshall Clowd920eea2013-10-21 15:07:28 +00005009#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005010#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005011#endif
5012#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00005013#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00005014#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00005015
Howard Hinnantc51e1022010-05-11 19:42:16 +00005016template <>
5017string
5018__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
5019{
Howard Hinnant990207c2012-02-19 14:55:32 +00005020 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005021 t.tm_sec = 59;
5022 t.tm_min = 55;
5023 t.tm_hour = 23;
5024 t.tm_mday = 31;
5025 t.tm_mon = 11;
5026 t.tm_year = 161;
5027 t.tm_wday = 6;
5028 t.tm_yday = 364;
5029 t.tm_isdst = -1;
5030 char buf[100];
5031 char f[3] = {0};
5032 f[0] = '%';
5033 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005034 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005035 char* bb = buf;
5036 char* be = buf + n;
5037 string result;
5038 while (bb != be)
5039 {
5040 if (ct.is(ctype_base::space, *bb))
5041 {
5042 result.push_back(' ');
5043 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
5044 ;
5045 continue;
5046 }
5047 char* w = bb;
5048 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005049 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005050 ct, err, false)
5051 - this->__weeks_;
5052 if (i < 14)
5053 {
5054 result.push_back('%');
5055 if (i < 7)
5056 result.push_back('A');
5057 else
5058 result.push_back('a');
5059 bb = w;
5060 continue;
5061 }
5062 w = bb;
5063 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
5064 ct, err, false)
5065 - this->__months_;
5066 if (i < 24)
5067 {
5068 result.push_back('%');
5069 if (i < 12)
5070 result.push_back('B');
5071 else
5072 result.push_back('b');
5073 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5074 result.back() = 'm';
5075 bb = w;
5076 continue;
5077 }
5078 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5079 {
5080 w = bb;
5081 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5082 ct, err, false) - this->__am_pm_;
5083 if (i < 2)
5084 {
5085 result.push_back('%');
5086 result.push_back('p');
5087 bb = w;
5088 continue;
5089 }
5090 }
5091 w = bb;
5092 if (ct.is(ctype_base::digit, *bb))
5093 {
5094 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5095 {
5096 case 6:
5097 result.push_back('%');
5098 result.push_back('w');
5099 break;
5100 case 7:
5101 result.push_back('%');
5102 result.push_back('u');
5103 break;
5104 case 11:
5105 result.push_back('%');
5106 result.push_back('I');
5107 break;
5108 case 12:
5109 result.push_back('%');
5110 result.push_back('m');
5111 break;
5112 case 23:
5113 result.push_back('%');
5114 result.push_back('H');
5115 break;
5116 case 31:
5117 result.push_back('%');
5118 result.push_back('d');
5119 break;
5120 case 55:
5121 result.push_back('%');
5122 result.push_back('M');
5123 break;
5124 case 59:
5125 result.push_back('%');
5126 result.push_back('S');
5127 break;
5128 case 61:
5129 result.push_back('%');
5130 result.push_back('y');
5131 break;
5132 case 364:
5133 result.push_back('%');
5134 result.push_back('j');
5135 break;
5136 case 2061:
5137 result.push_back('%');
5138 result.push_back('Y');
5139 break;
5140 default:
5141 for (; w != bb; ++w)
5142 result.push_back(*w);
5143 break;
5144 }
5145 continue;
5146 }
5147 if (*bb == '%')
5148 {
5149 result.push_back('%');
5150 result.push_back('%');
5151 ++bb;
5152 continue;
5153 }
5154 result.push_back(*bb);
5155 ++bb;
5156 }
5157 return result;
5158}
5159
Marshall Clowd920eea2013-10-21 15:07:28 +00005160#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005161#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005162#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005163
Howard Hinnantc51e1022010-05-11 19:42:16 +00005164template <>
5165wstring
5166__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5167{
Howard Hinnant990207c2012-02-19 14:55:32 +00005168 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005169 t.tm_sec = 59;
5170 t.tm_min = 55;
5171 t.tm_hour = 23;
5172 t.tm_mday = 31;
5173 t.tm_mon = 11;
5174 t.tm_year = 161;
5175 t.tm_wday = 6;
5176 t.tm_yday = 364;
5177 t.tm_isdst = -1;
5178 char buf[100];
5179 char f[3] = {0};
5180 f[0] = '%';
5181 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005182 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005183 wchar_t wbuf[100];
5184 wchar_t* wbb = wbuf;
5185 mbstate_t mb = {0};
5186 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005187 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005188 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005189 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005190 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005191 wstring result;
5192 while (wbb != wbe)
5193 {
5194 if (ct.is(ctype_base::space, *wbb))
5195 {
5196 result.push_back(L' ');
5197 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5198 ;
5199 continue;
5200 }
5201 wchar_t* w = wbb;
5202 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005203 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005204 ct, err, false)
5205 - this->__weeks_;
5206 if (i < 14)
5207 {
5208 result.push_back(L'%');
5209 if (i < 7)
5210 result.push_back(L'A');
5211 else
5212 result.push_back(L'a');
5213 wbb = w;
5214 continue;
5215 }
5216 w = wbb;
5217 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5218 ct, err, false)
5219 - this->__months_;
5220 if (i < 24)
5221 {
5222 result.push_back(L'%');
5223 if (i < 12)
5224 result.push_back(L'B');
5225 else
5226 result.push_back(L'b');
5227 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5228 result.back() = L'm';
5229 wbb = w;
5230 continue;
5231 }
5232 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5233 {
5234 w = wbb;
5235 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5236 ct, err, false) - this->__am_pm_;
5237 if (i < 2)
5238 {
5239 result.push_back(L'%');
5240 result.push_back(L'p');
5241 wbb = w;
5242 continue;
5243 }
5244 }
5245 w = wbb;
5246 if (ct.is(ctype_base::digit, *wbb))
5247 {
5248 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5249 {
5250 case 6:
5251 result.push_back(L'%');
5252 result.push_back(L'w');
5253 break;
5254 case 7:
5255 result.push_back(L'%');
5256 result.push_back(L'u');
5257 break;
5258 case 11:
5259 result.push_back(L'%');
5260 result.push_back(L'I');
5261 break;
5262 case 12:
5263 result.push_back(L'%');
5264 result.push_back(L'm');
5265 break;
5266 case 23:
5267 result.push_back(L'%');
5268 result.push_back(L'H');
5269 break;
5270 case 31:
5271 result.push_back(L'%');
5272 result.push_back(L'd');
5273 break;
5274 case 55:
5275 result.push_back(L'%');
5276 result.push_back(L'M');
5277 break;
5278 case 59:
5279 result.push_back(L'%');
5280 result.push_back(L'S');
5281 break;
5282 case 61:
5283 result.push_back(L'%');
5284 result.push_back(L'y');
5285 break;
5286 case 364:
5287 result.push_back(L'%');
5288 result.push_back(L'j');
5289 break;
5290 case 2061:
5291 result.push_back(L'%');
5292 result.push_back(L'Y');
5293 break;
5294 default:
5295 for (; w != wbb; ++w)
5296 result.push_back(*w);
5297 break;
5298 }
5299 continue;
5300 }
5301 if (ct.narrow(*wbb, 0) == '%')
5302 {
5303 result.push_back(L'%');
5304 result.push_back(L'%');
5305 ++wbb;
5306 continue;
5307 }
5308 result.push_back(*wbb);
5309 ++wbb;
5310 }
5311 return result;
5312}
5313
5314template <>
5315void
5316__time_get_storage<char>::init(const ctype<char>& ct)
5317{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005318 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005319 char buf[100];
5320 // __weeks_
5321 for (int i = 0; i < 7; ++i)
5322 {
5323 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005324 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005325 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005326 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005327 __weeks_[i+7] = buf;
5328 }
5329 // __months_
5330 for (int i = 0; i < 12; ++i)
5331 {
5332 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005333 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005334 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005335 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005336 __months_[i+12] = buf;
5337 }
5338 // __am_pm_
5339 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005340 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005341 __am_pm_[0] = buf;
5342 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005343 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005344 __am_pm_[1] = buf;
5345 __c_ = __analyze('c', ct);
5346 __r_ = __analyze('r', ct);
5347 __x_ = __analyze('x', ct);
5348 __X_ = __analyze('X', ct);
5349}
5350
5351template <>
5352void
5353__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5354{
5355 tm t = {0};
5356 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005357 wchar_t wbuf[100];
5358 wchar_t* wbe;
5359 mbstate_t mb = {0};
5360 // __weeks_
5361 for (int i = 0; i < 7; ++i)
5362 {
5363 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005364 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005365 mb = mbstate_t();
5366 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005367 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005368 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005369 __throw_runtime_error("locale not supported");
5370 wbe = wbuf + j;
5371 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005372 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005373 mb = mbstate_t();
5374 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005375 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005376 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005377 __throw_runtime_error("locale not supported");
5378 wbe = wbuf + j;
5379 __weeks_[i+7].assign(wbuf, wbe);
5380 }
5381 // __months_
5382 for (int i = 0; i < 12; ++i)
5383 {
5384 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005385 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005386 mb = mbstate_t();
5387 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005388 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005389 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005390 __throw_runtime_error("locale not supported");
5391 wbe = wbuf + j;
5392 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005393 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005394 mb = mbstate_t();
5395 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005396 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005397 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005398 __throw_runtime_error("locale not supported");
5399 wbe = wbuf + j;
5400 __months_[i+12].assign(wbuf, wbe);
5401 }
5402 // __am_pm_
5403 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005404 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005405 mb = mbstate_t();
5406 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005407 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005408 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005409 __throw_runtime_error("locale not supported");
5410 wbe = wbuf + j;
5411 __am_pm_[0].assign(wbuf, wbe);
5412 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005413 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005414 mb = mbstate_t();
5415 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005416 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005417 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005418 __throw_runtime_error("locale not supported");
5419 wbe = wbuf + j;
5420 __am_pm_[1].assign(wbuf, wbe);
5421 __c_ = __analyze('c', ct);
5422 __r_ = __analyze('r', ct);
5423 __x_ = __analyze('x', ct);
5424 __X_ = __analyze('X', ct);
5425}
5426
5427template <class CharT>
5428struct _LIBCPP_HIDDEN __time_get_temp
5429 : public ctype_byname<CharT>
5430{
5431 explicit __time_get_temp(const char* nm)
5432 : ctype_byname<CharT>(nm, 1) {}
5433 explicit __time_get_temp(const string& nm)
5434 : ctype_byname<CharT>(nm, 1) {}
5435};
5436
5437template <>
5438__time_get_storage<char>::__time_get_storage(const char* __nm)
5439 : __time_get(__nm)
5440{
5441 const __time_get_temp<char> ct(__nm);
5442 init(ct);
5443}
5444
5445template <>
5446__time_get_storage<char>::__time_get_storage(const string& __nm)
5447 : __time_get(__nm)
5448{
5449 const __time_get_temp<char> ct(__nm);
5450 init(ct);
5451}
5452
5453template <>
5454__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5455 : __time_get(__nm)
5456{
5457 const __time_get_temp<wchar_t> ct(__nm);
5458 init(ct);
5459}
5460
5461template <>
5462__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5463 : __time_get(__nm)
5464{
5465 const __time_get_temp<wchar_t> ct(__nm);
5466 init(ct);
5467}
5468
5469template <>
5470time_base::dateorder
5471__time_get_storage<char>::__do_date_order() const
5472{
5473 unsigned i;
5474 for (i = 0; i < __x_.size(); ++i)
5475 if (__x_[i] == '%')
5476 break;
5477 ++i;
5478 switch (__x_[i])
5479 {
5480 case 'y':
5481 case 'Y':
5482 for (++i; i < __x_.size(); ++i)
5483 if (__x_[i] == '%')
5484 break;
5485 if (i == __x_.size())
5486 break;
5487 ++i;
5488 switch (__x_[i])
5489 {
5490 case 'm':
5491 for (++i; i < __x_.size(); ++i)
5492 if (__x_[i] == '%')
5493 break;
5494 if (i == __x_.size())
5495 break;
5496 ++i;
5497 if (__x_[i] == 'd')
5498 return time_base::ymd;
5499 break;
5500 case 'd':
5501 for (++i; i < __x_.size(); ++i)
5502 if (__x_[i] == '%')
5503 break;
5504 if (i == __x_.size())
5505 break;
5506 ++i;
5507 if (__x_[i] == 'm')
5508 return time_base::ydm;
5509 break;
5510 }
5511 break;
5512 case 'm':
5513 for (++i; i < __x_.size(); ++i)
5514 if (__x_[i] == '%')
5515 break;
5516 if (i == __x_.size())
5517 break;
5518 ++i;
5519 if (__x_[i] == 'd')
5520 {
5521 for (++i; i < __x_.size(); ++i)
5522 if (__x_[i] == '%')
5523 break;
5524 if (i == __x_.size())
5525 break;
5526 ++i;
5527 if (__x_[i] == 'y' || __x_[i] == 'Y')
5528 return time_base::mdy;
5529 break;
5530 }
5531 break;
5532 case 'd':
5533 for (++i; i < __x_.size(); ++i)
5534 if (__x_[i] == '%')
5535 break;
5536 if (i == __x_.size())
5537 break;
5538 ++i;
5539 if (__x_[i] == 'm')
5540 {
5541 for (++i; i < __x_.size(); ++i)
5542 if (__x_[i] == '%')
5543 break;
5544 if (i == __x_.size())
5545 break;
5546 ++i;
5547 if (__x_[i] == 'y' || __x_[i] == 'Y')
5548 return time_base::dmy;
5549 break;
5550 }
5551 break;
5552 }
5553 return time_base::no_order;
5554}
5555
5556template <>
5557time_base::dateorder
5558__time_get_storage<wchar_t>::__do_date_order() const
5559{
5560 unsigned i;
5561 for (i = 0; i < __x_.size(); ++i)
5562 if (__x_[i] == L'%')
5563 break;
5564 ++i;
5565 switch (__x_[i])
5566 {
5567 case L'y':
5568 case L'Y':
5569 for (++i; i < __x_.size(); ++i)
5570 if (__x_[i] == L'%')
5571 break;
5572 if (i == __x_.size())
5573 break;
5574 ++i;
5575 switch (__x_[i])
5576 {
5577 case L'm':
5578 for (++i; i < __x_.size(); ++i)
5579 if (__x_[i] == L'%')
5580 break;
5581 if (i == __x_.size())
5582 break;
5583 ++i;
5584 if (__x_[i] == L'd')
5585 return time_base::ymd;
5586 break;
5587 case L'd':
5588 for (++i; i < __x_.size(); ++i)
5589 if (__x_[i] == L'%')
5590 break;
5591 if (i == __x_.size())
5592 break;
5593 ++i;
5594 if (__x_[i] == L'm')
5595 return time_base::ydm;
5596 break;
5597 }
5598 break;
5599 case L'm':
5600 for (++i; i < __x_.size(); ++i)
5601 if (__x_[i] == L'%')
5602 break;
5603 if (i == __x_.size())
5604 break;
5605 ++i;
5606 if (__x_[i] == L'd')
5607 {
5608 for (++i; i < __x_.size(); ++i)
5609 if (__x_[i] == L'%')
5610 break;
5611 if (i == __x_.size())
5612 break;
5613 ++i;
5614 if (__x_[i] == L'y' || __x_[i] == L'Y')
5615 return time_base::mdy;
5616 break;
5617 }
5618 break;
5619 case L'd':
5620 for (++i; i < __x_.size(); ++i)
5621 if (__x_[i] == L'%')
5622 break;
5623 if (i == __x_.size())
5624 break;
5625 ++i;
5626 if (__x_[i] == L'm')
5627 {
5628 for (++i; i < __x_.size(); ++i)
5629 if (__x_[i] == L'%')
5630 break;
5631 if (i == __x_.size())
5632 break;
5633 ++i;
5634 if (__x_[i] == L'y' || __x_[i] == L'Y')
5635 return time_base::dmy;
5636 break;
5637 }
5638 break;
5639 }
5640 return time_base::no_order;
5641}
5642
5643// time_put
5644
5645__time_put::__time_put(const char* nm)
5646 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5647{
5648 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005649 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005650 " failed to construct for " + string(nm));
5651}
5652
5653__time_put::__time_put(const string& nm)
5654 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5655{
5656 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005657 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005658 " failed to construct for " + nm);
5659}
5660
5661__time_put::~__time_put()
5662{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005663 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005664 freelocale(__loc_);
5665}
5666
5667void
5668__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5669 char __fmt, char __mod) const
5670{
5671 char fmt[] = {'%', __fmt, __mod, 0};
5672 if (__mod != 0)
5673 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005674 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005675 __ne = __nb + n;
5676}
5677
5678void
5679__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5680 char __fmt, char __mod) const
5681{
5682 char __nar[100];
5683 char* __ne = __nar + 100;
5684 __do_put(__nar, __ne, __tm, __fmt, __mod);
5685 mbstate_t mb = {0};
5686 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005687 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005688 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005689 __throw_runtime_error("locale not supported");
5690 __we = __wb + j;
5691}
5692
5693// moneypunct_byname
5694
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005695template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005696static
5697void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005698__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5699 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5700 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005701{
5702 const char sign = static_cast<char>(money_base::sign);
5703 const char space = static_cast<char>(money_base::space);
5704 const char none = static_cast<char>(money_base::none);
5705 const char symbol = static_cast<char>(money_base::symbol);
5706 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005707 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5708
5709 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5710 // function'. "Space between sign and symbol or value" means that
5711 // if the sign is adjacent to the symbol, there's a space between
5712 // them, and otherwise there's a space between the sign and value.
5713 //
5714 // C11's localeconv specifies that the fourth character of an
5715 // international curr_symbol is used to separate the sign and
5716 // value when sep_by_space says to do so. C++ can't represent
5717 // that, so we just use a space. When sep_by_space says to
5718 // separate the symbol and value-or-sign with a space, we rearrange the
5719 // curr_symbol to put its spacing character on the correct side of
5720 // the symbol.
5721 //
5722 // We also need to avoid adding an extra space between the sign
5723 // and value when the currency symbol is suppressed (by not
5724 // setting showbase). We match glibc's strfmon by interpreting
5725 // sep_by_space==1 as "omit the space when the currency symbol is
5726 // absent".
5727 //
5728 // Users who want to get this right should use ICU instead.
5729
Howard Hinnantc51e1022010-05-11 19:42:16 +00005730 switch (cs_precedes)
5731 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005732 case 0: // value before curr_symbol
5733 if (symbol_contains_sep) {
5734 // Move the separator to before the symbol, to place it
5735 // between the value and symbol.
5736 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5737 __curr_symbol_.end());
5738 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005739 switch (sign_posn)
5740 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005741 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005742 pat.field[0] = sign;
5743 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005744 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 pat.field[3] = symbol;
5746 switch (sep_by_space)
5747 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005748 case 0: // No space separates the currency symbol and value.
5749 // This case may have changed between C99 and C11;
5750 // assume the currency symbol matches the intention.
5751 case 2: // Space between sign and currency or value.
5752 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005753 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005754 case 1: // Space between currency-and-sign or currency and value.
5755 if (!symbol_contains_sep) {
5756 // We insert the space into the symbol instead of
5757 // setting pat.field[2]=space so that when
5758 // showbase is not set, the space goes away too.
5759 __curr_symbol_.insert(0, 1, space_char);
5760 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005761 return;
5762 default:
5763 break;
5764 }
5765 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005766 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005767 pat.field[0] = sign;
5768 pat.field[3] = symbol;
5769 switch (sep_by_space)
5770 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005771 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005772 pat.field[1] = value;
5773 pat.field[2] = none;
5774 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005775 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005776 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005777 pat.field[2] = none;
5778 if (!symbol_contains_sep) {
5779 // We insert the space into the symbol instead of
5780 // setting pat.field[2]=space so that when
5781 // showbase is not set, the space goes away too.
5782 __curr_symbol_.insert(0, 1, space_char);
5783 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005784 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005785 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005786 pat.field[1] = space;
5787 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005788 if (symbol_contains_sep) {
5789 // Remove the separator from the symbol, since it
5790 // has already appeared after the sign.
5791 __curr_symbol_.erase(__curr_symbol_.begin());
5792 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005793 return;
5794 default:
5795 break;
5796 }
5797 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005798 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005799 pat.field[0] = value;
5800 pat.field[3] = sign;
5801 switch (sep_by_space)
5802 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005803 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005804 pat.field[1] = none;
5805 pat.field[2] = symbol;
5806 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005807 case 1: // Space between currency-and-sign or currency and value.
5808 if (!symbol_contains_sep) {
5809 // We insert the space into the symbol instead of
5810 // setting pat.field[1]=space so that when
5811 // showbase is not set, the space goes away too.
5812 __curr_symbol_.insert(0, 1, space_char);
5813 }
5814 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005815 pat.field[2] = symbol;
5816 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005817 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005818 pat.field[1] = symbol;
5819 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005820 if (symbol_contains_sep) {
5821 // Remove the separator from the symbol, since it
5822 // should not be removed if showbase is absent.
5823 __curr_symbol_.erase(__curr_symbol_.begin());
5824 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005825 return;
5826 default:
5827 break;
5828 }
5829 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005830 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005831 pat.field[0] = value;
5832 pat.field[3] = symbol;
5833 switch (sep_by_space)
5834 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005835 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005836 pat.field[1] = none;
5837 pat.field[2] = sign;
5838 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005839 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005840 pat.field[1] = space;
5841 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005842 if (symbol_contains_sep) {
5843 // Remove the separator from the symbol, since it
5844 // has already appeared before the sign.
5845 __curr_symbol_.erase(__curr_symbol_.begin());
5846 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005847 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005848 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005849 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005850 pat.field[2] = none;
5851 if (!symbol_contains_sep) {
5852 // We insert the space into the symbol instead of
5853 // setting pat.field[2]=space so that when
5854 // showbase is not set, the space goes away too.
5855 __curr_symbol_.insert(0, 1, space_char);
5856 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005857 return;
5858 default:
5859 break;
5860 }
5861 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005862 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005863 pat.field[0] = value;
5864 pat.field[3] = sign;
5865 switch (sep_by_space)
5866 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005867 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005868 pat.field[1] = none;
5869 pat.field[2] = symbol;
5870 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005871 case 1: // Space between currency-and-sign or currency and value.
5872 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005873 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005874 if (!symbol_contains_sep) {
5875 // We insert the space into the symbol instead of
5876 // setting pat.field[1]=space so that when
5877 // showbase is not set, the space goes away too.
5878 __curr_symbol_.insert(0, 1, space_char);
5879 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005880 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005881 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005882 pat.field[1] = symbol;
5883 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005884 if (symbol_contains_sep) {
5885 // Remove the separator from the symbol, since it
5886 // should not disappear when showbase is absent.
5887 __curr_symbol_.erase(__curr_symbol_.begin());
5888 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005889 return;
5890 default:
5891 break;
5892 }
5893 break;
5894 default:
5895 break;
5896 }
5897 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005898 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005899 switch (sign_posn)
5900 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005901 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005902 pat.field[0] = sign;
5903 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005904 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005905 pat.field[3] = value;
5906 switch (sep_by_space)
5907 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005908 case 0: // No space separates the currency symbol and value.
5909 // This case may have changed between C99 and C11;
5910 // assume the currency symbol matches the intention.
5911 case 2: // Space between sign and currency or value.
5912 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005913 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005914 case 1: // Space between currency-and-sign or currency and value.
5915 if (!symbol_contains_sep) {
5916 // We insert the space into the symbol instead of
5917 // setting pat.field[2]=space so that when
5918 // showbase is not set, the space goes away too.
5919 __curr_symbol_.insert(0, 1, space_char);
5920 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005921 return;
5922 default:
5923 break;
5924 }
5925 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005926 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005927 pat.field[0] = sign;
5928 pat.field[3] = value;
5929 switch (sep_by_space)
5930 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005931 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005932 pat.field[1] = symbol;
5933 pat.field[2] = none;
5934 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005935 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005936 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005937 pat.field[2] = none;
5938 if (!symbol_contains_sep) {
5939 // We insert the space into the symbol instead of
5940 // setting pat.field[2]=space so that when
5941 // showbase is not set, the space goes away too.
5942 __curr_symbol_.push_back(space_char);
5943 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005944 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005945 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005946 pat.field[1] = space;
5947 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005948 if (symbol_contains_sep) {
5949 // Remove the separator from the symbol, since it
5950 // has already appeared after the sign.
5951 __curr_symbol_.pop_back();
5952 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005953 return;
5954 default:
5955 break;
5956 }
5957 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005958 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005959 pat.field[0] = symbol;
5960 pat.field[3] = sign;
5961 switch (sep_by_space)
5962 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005963 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005964 pat.field[1] = none;
5965 pat.field[2] = value;
5966 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005967 case 1: // Space between currency-and-sign or currency and value.
5968 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005970 if (!symbol_contains_sep) {
5971 // We insert the space into the symbol instead of
5972 // setting pat.field[1]=space so that when
5973 // showbase is not set, the space goes away too.
5974 __curr_symbol_.push_back(space_char);
5975 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005976 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005977 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005978 pat.field[1] = value;
5979 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005980 if (symbol_contains_sep) {
5981 // Remove the separator from the symbol, since it
5982 // will appear before the sign.
5983 __curr_symbol_.pop_back();
5984 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005985 return;
5986 default:
5987 break;
5988 }
5989 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005990 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005991 pat.field[0] = sign;
5992 pat.field[3] = value;
5993 switch (sep_by_space)
5994 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005995 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005996 pat.field[1] = symbol;
5997 pat.field[2] = none;
5998 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005999 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006000 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006001 pat.field[2] = none;
6002 if (!symbol_contains_sep) {
6003 // We insert the space into the symbol instead of
6004 // setting pat.field[2]=space so that when
6005 // showbase is not set, the space goes away too.
6006 __curr_symbol_.push_back(space_char);
6007 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006008 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006009 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006010 pat.field[1] = space;
6011 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006012 if (symbol_contains_sep) {
6013 // Remove the separator from the symbol, since it
6014 // has already appeared after the sign.
6015 __curr_symbol_.pop_back();
6016 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006017 return;
6018 default:
6019 break;
6020 }
6021 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006022 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006023 pat.field[0] = symbol;
6024 pat.field[3] = value;
6025 switch (sep_by_space)
6026 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006027 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006028 pat.field[1] = sign;
6029 pat.field[2] = none;
6030 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006031 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00006032 pat.field[1] = sign;
6033 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006034 if (symbol_contains_sep) {
6035 // Remove the separator from the symbol, since it
6036 // should not disappear when showbase is absent.
6037 __curr_symbol_.pop_back();
6038 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006040 case 2: // Space between sign and currency or value.
6041 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006042 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006043 if (!symbol_contains_sep) {
6044 // We insert the space into the symbol instead of
6045 // setting pat.field[1]=space so that when
6046 // showbase is not set, the space goes away too.
6047 __curr_symbol_.push_back(space_char);
6048 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00006049 return;
6050 default:
6051 break;
6052 }
6053 break;
6054 default:
6055 break;
6056 }
6057 break;
6058 default:
6059 break;
6060 }
6061 pat.field[0] = symbol;
6062 pat.field[1] = sign;
6063 pat.field[2] = none;
6064 pat.field[3] = value;
6065}
6066
6067template<>
6068void
6069moneypunct_byname<char, false>::init(const char* nm)
6070{
6071 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006072 __libcpp_unique_locale loc(nm);
6073 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006074 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006075 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006076
Ben Craig3756b922016-03-09 15:39:39 +00006077 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006078 if (!checked_string_to_char_convert(__decimal_point_,
6079 lc->mon_decimal_point,
6080 loc.get()))
6081 __decimal_point_ = base::do_decimal_point();
6082 if (!checked_string_to_char_convert(__thousands_sep_,
6083 lc->mon_thousands_sep,
6084 loc.get()))
6085 __thousands_sep_ = base::do_thousands_sep();
6086
Howard Hinnantc51e1022010-05-11 19:42:16 +00006087 __grouping_ = lc->mon_grouping;
6088 __curr_symbol_ = lc->currency_symbol;
6089 if (lc->frac_digits != CHAR_MAX)
6090 __frac_digits_ = lc->frac_digits;
6091 else
6092 __frac_digits_ = base::do_frac_digits();
6093 if (lc->p_sign_posn == 0)
6094 __positive_sign_ = "()";
6095 else
6096 __positive_sign_ = lc->positive_sign;
6097 if (lc->n_sign_posn == 0)
6098 __negative_sign_ = "()";
6099 else
6100 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006101 // Assume the positive and negative formats will want spaces in
6102 // the same places in curr_symbol since there's no way to
6103 // represent anything else.
6104 string_type __dummy_curr_symbol = __curr_symbol_;
6105 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6106 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6107 __init_pat(__neg_format_, __curr_symbol_, false,
6108 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006109}
6110
6111template<>
6112void
6113moneypunct_byname<char, true>::init(const char* nm)
6114{
6115 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006116 __libcpp_unique_locale loc(nm);
6117 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006118 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006119 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006120
Ben Craig3756b922016-03-09 15:39:39 +00006121 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006122 if (!checked_string_to_char_convert(__decimal_point_,
6123 lc->mon_decimal_point,
6124 loc.get()))
6125 __decimal_point_ = base::do_decimal_point();
6126 if (!checked_string_to_char_convert(__thousands_sep_,
6127 lc->mon_thousands_sep,
6128 loc.get()))
6129 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006130 __grouping_ = lc->mon_grouping;
6131 __curr_symbol_ = lc->int_curr_symbol;
6132 if (lc->int_frac_digits != CHAR_MAX)
6133 __frac_digits_ = lc->int_frac_digits;
6134 else
6135 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006136#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006137 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006138#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006139 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006140#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141 __positive_sign_ = "()";
6142 else
6143 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006144#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006145 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006146#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006147 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006148#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006149 __negative_sign_ = "()";
6150 else
6151 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006152 // Assume the positive and negative formats will want spaces in
6153 // the same places in curr_symbol since there's no way to
6154 // represent anything else.
6155 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006156#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006157 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6158 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6159 __init_pat(__neg_format_, __curr_symbol_, true,
6160 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006161#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006162 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6163 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6164 lc->int_p_sign_posn, ' ');
6165 __init_pat(__neg_format_, __curr_symbol_, true,
6166 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6167 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006168#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006169}
6170
6171template<>
6172void
6173moneypunct_byname<wchar_t, false>::init(const char* nm)
6174{
6175 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006176 __libcpp_unique_locale loc(nm);
6177 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006178 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006179 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006180 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006181 if (!checked_string_to_wchar_convert(__decimal_point_,
6182 lc->mon_decimal_point,
6183 loc.get()))
6184 __decimal_point_ = base::do_decimal_point();
6185 if (!checked_string_to_wchar_convert(__thousands_sep_,
6186 lc->mon_thousands_sep,
6187 loc.get()))
6188 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006189 __grouping_ = lc->mon_grouping;
6190 wchar_t wbuf[100];
6191 mbstate_t mb = {0};
6192 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006193 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006194 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006195 __throw_runtime_error("locale not supported");
6196 wchar_t* wbe = wbuf + j;
6197 __curr_symbol_.assign(wbuf, wbe);
6198 if (lc->frac_digits != CHAR_MAX)
6199 __frac_digits_ = lc->frac_digits;
6200 else
6201 __frac_digits_ = base::do_frac_digits();
6202 if (lc->p_sign_posn == 0)
6203 __positive_sign_ = L"()";
6204 else
6205 {
6206 mb = mbstate_t();
6207 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006208 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006209 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006210 __throw_runtime_error("locale not supported");
6211 wbe = wbuf + j;
6212 __positive_sign_.assign(wbuf, wbe);
6213 }
6214 if (lc->n_sign_posn == 0)
6215 __negative_sign_ = L"()";
6216 else
6217 {
6218 mb = mbstate_t();
6219 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006220 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006221 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006222 __throw_runtime_error("locale not supported");
6223 wbe = wbuf + j;
6224 __negative_sign_.assign(wbuf, wbe);
6225 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006226 // Assume the positive and negative formats will want spaces in
6227 // the same places in curr_symbol since there's no way to
6228 // represent anything else.
6229 string_type __dummy_curr_symbol = __curr_symbol_;
6230 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6231 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6232 __init_pat(__neg_format_, __curr_symbol_, false,
6233 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006234}
6235
6236template<>
6237void
6238moneypunct_byname<wchar_t, true>::init(const char* nm)
6239{
6240 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006241 __libcpp_unique_locale loc(nm);
6242 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006243 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006244 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006245
Ben Craig3756b922016-03-09 15:39:39 +00006246 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006247 if (!checked_string_to_wchar_convert(__decimal_point_,
6248 lc->mon_decimal_point,
6249 loc.get()))
6250 __decimal_point_ = base::do_decimal_point();
6251 if (!checked_string_to_wchar_convert(__thousands_sep_,
6252 lc->mon_thousands_sep,
6253 loc.get()))
6254 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006255 __grouping_ = lc->mon_grouping;
6256 wchar_t wbuf[100];
6257 mbstate_t mb = {0};
6258 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006259 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006260 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006261 __throw_runtime_error("locale not supported");
6262 wchar_t* wbe = wbuf + j;
6263 __curr_symbol_.assign(wbuf, wbe);
6264 if (lc->int_frac_digits != CHAR_MAX)
6265 __frac_digits_ = lc->int_frac_digits;
6266 else
6267 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006268#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006269 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006270#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006271 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006272#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006273 __positive_sign_ = L"()";
6274 else
6275 {
6276 mb = mbstate_t();
6277 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006278 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006279 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006280 __throw_runtime_error("locale not supported");
6281 wbe = wbuf + j;
6282 __positive_sign_.assign(wbuf, wbe);
6283 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006284#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006285 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006286#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006287 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006288#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006289 __negative_sign_ = L"()";
6290 else
6291 {
6292 mb = mbstate_t();
6293 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006294 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006295 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006296 __throw_runtime_error("locale not supported");
6297 wbe = wbuf + j;
6298 __negative_sign_.assign(wbuf, wbe);
6299 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006300 // Assume the positive and negative formats will want spaces in
6301 // the same places in curr_symbol since there's no way to
6302 // represent anything else.
6303 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006304#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006305 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6306 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6307 __init_pat(__neg_format_, __curr_symbol_, true,
6308 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006309#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006310 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6311 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6312 lc->int_p_sign_posn, L' ');
6313 __init_pat(__neg_format_, __curr_symbol_, true,
6314 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6315 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006316#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006317}
6318
6319void __do_nothing(void*) {}
6320
6321void __throw_runtime_error(const char* msg)
6322{
Howard Hinnant72f73582010-08-11 17:04:31 +00006323#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006324 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006325#else
6326 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006327 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006328#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006329}
6330
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006331template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6332template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006333
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006334template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6335template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006336
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006337template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6338template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006339
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006340template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6341template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006342
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006343template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6344template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006345
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006346template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6347template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006348
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006349template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6350template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006351
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006352template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6353template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006354
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006355template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6356template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006357
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006358template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6359template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6360template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6361template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006362
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006363template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6364template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6365template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6366template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006367
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006368template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6369template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006370
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006371template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6372template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006373
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006374template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6375template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006376
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006377template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6378template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006379
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006380template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6381template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006382
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006383template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6384template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006385
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006386template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6387template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
Reid Klecknerbc2a2ce2021-01-15 08:56:34 -08006388template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6389template 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 -04006390#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006391template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6392template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6393#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006394
Howard Hinnantc51e1022010-05-11 19:42:16 +00006395_LIBCPP_END_NAMESPACE_STD