blob: f1978e046a2313bbd8f5a6824ed44bcc69a58f6a [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);
3488 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003489}
3490
3491int
Louis Dionne65358e12021-03-01 12:09:45 -05003492__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003493{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003494 if (_Mode_ & consume_header)
3495 return 7;
3496 return 4;
3497}
3498
3499// __codecvt_utf8<char16_t>
3500
3501__codecvt_utf8<char16_t>::result
3502__codecvt_utf8<char16_t>::do_out(state_type&,
3503 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3504 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3505{
3506 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3507 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3508 const uint16_t* _frm_nxt = _frm;
3509 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3510 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3511 uint8_t* _to_nxt = _to;
3512 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3513 _Maxcode_, _Mode_);
3514 frm_nxt = frm + (_frm_nxt - _frm);
3515 to_nxt = to + (_to_nxt - _to);
3516 return r;
3517}
3518
3519__codecvt_utf8<char16_t>::result
3520__codecvt_utf8<char16_t>::do_in(state_type&,
3521 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3522 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3523{
3524 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3525 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3526 const uint8_t* _frm_nxt = _frm;
3527 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3528 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3529 uint16_t* _to_nxt = _to;
3530 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3531 _Maxcode_, _Mode_);
3532 frm_nxt = frm + (_frm_nxt - _frm);
3533 to_nxt = to + (_to_nxt - _to);
3534 return r;
3535}
3536
3537__codecvt_utf8<char16_t>::result
3538__codecvt_utf8<char16_t>::do_unshift(state_type&,
3539 extern_type* to, extern_type*, extern_type*& to_nxt) const
3540{
3541 to_nxt = to;
3542 return noconv;
3543}
3544
3545int
Louis Dionne65358e12021-03-01 12:09:45 -05003546__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003547{
3548 return 0;
3549}
3550
3551bool
Louis Dionne65358e12021-03-01 12:09:45 -05003552__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003553{
3554 return false;
3555}
3556
3557int
3558__codecvt_utf8<char16_t>::do_length(state_type&,
3559 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3560{
3561 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3562 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3563 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3564}
3565
3566int
Louis Dionne65358e12021-03-01 12:09:45 -05003567__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003568{
3569 if (_Mode_ & consume_header)
3570 return 6;
3571 return 3;
3572}
3573
3574// __codecvt_utf8<char32_t>
3575
3576__codecvt_utf8<char32_t>::result
3577__codecvt_utf8<char32_t>::do_out(state_type&,
3578 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3579 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3580{
3581 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3582 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3583 const uint32_t* _frm_nxt = _frm;
3584 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3585 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3586 uint8_t* _to_nxt = _to;
3587 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3588 _Maxcode_, _Mode_);
3589 frm_nxt = frm + (_frm_nxt - _frm);
3590 to_nxt = to + (_to_nxt - _to);
3591 return r;
3592}
3593
3594__codecvt_utf8<char32_t>::result
3595__codecvt_utf8<char32_t>::do_in(state_type&,
3596 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3597 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3598{
3599 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3600 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3601 const uint8_t* _frm_nxt = _frm;
3602 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3603 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3604 uint32_t* _to_nxt = _to;
3605 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3606 _Maxcode_, _Mode_);
3607 frm_nxt = frm + (_frm_nxt - _frm);
3608 to_nxt = to + (_to_nxt - _to);
3609 return r;
3610}
3611
3612__codecvt_utf8<char32_t>::result
3613__codecvt_utf8<char32_t>::do_unshift(state_type&,
3614 extern_type* to, extern_type*, extern_type*& to_nxt) const
3615{
3616 to_nxt = to;
3617 return noconv;
3618}
3619
3620int
Louis Dionne65358e12021-03-01 12:09:45 -05003621__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003622{
3623 return 0;
3624}
3625
3626bool
Louis Dionne65358e12021-03-01 12:09:45 -05003627__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003628{
3629 return false;
3630}
3631
3632int
3633__codecvt_utf8<char32_t>::do_length(state_type&,
3634 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3635{
3636 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3637 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3638 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3639}
3640
3641int
Louis Dionne65358e12021-03-01 12:09:45 -05003642__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003643{
3644 if (_Mode_ & consume_header)
3645 return 7;
3646 return 4;
3647}
3648
3649// __codecvt_utf16<wchar_t, false>
3650
3651__codecvt_utf16<wchar_t, false>::result
3652__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3653 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3654 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3655{
3656 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3657 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3658 const uint32_t* _frm_nxt = _frm;
3659 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3660 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3661 uint8_t* _to_nxt = _to;
3662 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3663 _Maxcode_, _Mode_);
3664 frm_nxt = frm + (_frm_nxt - _frm);
3665 to_nxt = to + (_to_nxt - _to);
3666 return r;
3667}
3668
3669__codecvt_utf16<wchar_t, false>::result
3670__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3671 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3672 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3673{
3674 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3675 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3676 const uint8_t* _frm_nxt = _frm;
3677 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3678 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3679 uint32_t* _to_nxt = _to;
3680 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3681 _Maxcode_, _Mode_);
3682 frm_nxt = frm + (_frm_nxt - _frm);
3683 to_nxt = to + (_to_nxt - _to);
3684 return r;
3685}
3686
3687__codecvt_utf16<wchar_t, false>::result
3688__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3689 extern_type* to, extern_type*, extern_type*& to_nxt) const
3690{
3691 to_nxt = to;
3692 return noconv;
3693}
3694
3695int
Louis Dionne65358e12021-03-01 12:09:45 -05003696__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003697{
3698 return 0;
3699}
3700
3701bool
Louis Dionne65358e12021-03-01 12:09:45 -05003702__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003703{
3704 return false;
3705}
3706
3707int
3708__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3709 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3710{
3711 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3712 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3713 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3714}
3715
3716int
Louis Dionne65358e12021-03-01 12:09:45 -05003717__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003718{
3719 if (_Mode_ & consume_header)
3720 return 6;
3721 return 4;
3722}
3723
3724// __codecvt_utf16<wchar_t, true>
3725
3726__codecvt_utf16<wchar_t, true>::result
3727__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3728 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3729 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3730{
3731 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3732 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3733 const uint32_t* _frm_nxt = _frm;
3734 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3735 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3736 uint8_t* _to_nxt = _to;
3737 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3738 _Maxcode_, _Mode_);
3739 frm_nxt = frm + (_frm_nxt - _frm);
3740 to_nxt = to + (_to_nxt - _to);
3741 return r;
3742}
3743
3744__codecvt_utf16<wchar_t, true>::result
3745__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3746 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3747 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3748{
3749 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3750 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3751 const uint8_t* _frm_nxt = _frm;
3752 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3753 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3754 uint32_t* _to_nxt = _to;
3755 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3756 _Maxcode_, _Mode_);
3757 frm_nxt = frm + (_frm_nxt - _frm);
3758 to_nxt = to + (_to_nxt - _to);
3759 return r;
3760}
3761
3762__codecvt_utf16<wchar_t, true>::result
3763__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3764 extern_type* to, extern_type*, extern_type*& to_nxt) const
3765{
3766 to_nxt = to;
3767 return noconv;
3768}
3769
3770int
Louis Dionne65358e12021-03-01 12:09:45 -05003771__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003772{
3773 return 0;
3774}
3775
3776bool
Louis Dionne65358e12021-03-01 12:09:45 -05003777__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003778{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003779 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003780}
3781
3782int
3783__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3784 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3785{
3786 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3787 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3788 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3789}
3790
3791int
Louis Dionne65358e12021-03-01 12:09:45 -05003792__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003793{
3794 if (_Mode_ & consume_header)
3795 return 6;
3796 return 4;
3797}
3798
3799// __codecvt_utf16<char16_t, false>
3800
3801__codecvt_utf16<char16_t, false>::result
3802__codecvt_utf16<char16_t, false>::do_out(state_type&,
3803 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3804 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3805{
3806 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3807 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3808 const uint16_t* _frm_nxt = _frm;
3809 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3810 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3811 uint8_t* _to_nxt = _to;
3812 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3813 _Maxcode_, _Mode_);
3814 frm_nxt = frm + (_frm_nxt - _frm);
3815 to_nxt = to + (_to_nxt - _to);
3816 return r;
3817}
3818
3819__codecvt_utf16<char16_t, false>::result
3820__codecvt_utf16<char16_t, false>::do_in(state_type&,
3821 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3822 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3823{
3824 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3825 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3826 const uint8_t* _frm_nxt = _frm;
3827 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3828 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3829 uint16_t* _to_nxt = _to;
3830 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3831 _Maxcode_, _Mode_);
3832 frm_nxt = frm + (_frm_nxt - _frm);
3833 to_nxt = to + (_to_nxt - _to);
3834 return r;
3835}
3836
3837__codecvt_utf16<char16_t, false>::result
3838__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3839 extern_type* to, extern_type*, extern_type*& to_nxt) const
3840{
3841 to_nxt = to;
3842 return noconv;
3843}
3844
3845int
Louis Dionne65358e12021-03-01 12:09:45 -05003846__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003847{
3848 return 0;
3849}
3850
3851bool
Louis Dionne65358e12021-03-01 12:09:45 -05003852__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003853{
3854 return false;
3855}
3856
3857int
3858__codecvt_utf16<char16_t, false>::do_length(state_type&,
3859 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3860{
3861 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3862 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3863 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3864}
3865
3866int
Louis Dionne65358e12021-03-01 12:09:45 -05003867__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003868{
3869 if (_Mode_ & consume_header)
3870 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003871 return 2;
3872}
3873
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003874// __codecvt_utf16<char16_t, true>
3875
3876__codecvt_utf16<char16_t, true>::result
3877__codecvt_utf16<char16_t, true>::do_out(state_type&,
3878 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3879 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3880{
3881 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3882 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3883 const uint16_t* _frm_nxt = _frm;
3884 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3885 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3886 uint8_t* _to_nxt = _to;
3887 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3888 _Maxcode_, _Mode_);
3889 frm_nxt = frm + (_frm_nxt - _frm);
3890 to_nxt = to + (_to_nxt - _to);
3891 return r;
3892}
3893
3894__codecvt_utf16<char16_t, true>::result
3895__codecvt_utf16<char16_t, true>::do_in(state_type&,
3896 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3897 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3898{
3899 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3900 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3901 const uint8_t* _frm_nxt = _frm;
3902 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3903 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3904 uint16_t* _to_nxt = _to;
3905 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3906 _Maxcode_, _Mode_);
3907 frm_nxt = frm + (_frm_nxt - _frm);
3908 to_nxt = to + (_to_nxt - _to);
3909 return r;
3910}
3911
3912__codecvt_utf16<char16_t, true>::result
3913__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3914 extern_type* to, extern_type*, extern_type*& to_nxt) const
3915{
3916 to_nxt = to;
3917 return noconv;
3918}
3919
3920int
Louis Dionne65358e12021-03-01 12:09:45 -05003921__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003922{
3923 return 0;
3924}
3925
3926bool
Louis Dionne65358e12021-03-01 12:09:45 -05003927__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003928{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003929 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003930}
3931
3932int
3933__codecvt_utf16<char16_t, true>::do_length(state_type&,
3934 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3935{
3936 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3937 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3938 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3939}
3940
3941int
Louis Dionne65358e12021-03-01 12:09:45 -05003942__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003943{
3944 if (_Mode_ & consume_header)
3945 return 4;
3946 return 2;
3947}
3948
3949// __codecvt_utf16<char32_t, false>
3950
3951__codecvt_utf16<char32_t, false>::result
3952__codecvt_utf16<char32_t, false>::do_out(state_type&,
3953 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3954 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3955{
3956 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3957 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3958 const uint32_t* _frm_nxt = _frm;
3959 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3960 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3961 uint8_t* _to_nxt = _to;
3962 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3963 _Maxcode_, _Mode_);
3964 frm_nxt = frm + (_frm_nxt - _frm);
3965 to_nxt = to + (_to_nxt - _to);
3966 return r;
3967}
3968
3969__codecvt_utf16<char32_t, false>::result
3970__codecvt_utf16<char32_t, false>::do_in(state_type&,
3971 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3972 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3973{
3974 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3975 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3976 const uint8_t* _frm_nxt = _frm;
3977 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3978 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3979 uint32_t* _to_nxt = _to;
3980 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3981 _Maxcode_, _Mode_);
3982 frm_nxt = frm + (_frm_nxt - _frm);
3983 to_nxt = to + (_to_nxt - _to);
3984 return r;
3985}
3986
3987__codecvt_utf16<char32_t, false>::result
3988__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3989 extern_type* to, extern_type*, extern_type*& to_nxt) const
3990{
3991 to_nxt = to;
3992 return noconv;
3993}
3994
3995int
Louis Dionne65358e12021-03-01 12:09:45 -05003996__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003997{
3998 return 0;
3999}
4000
4001bool
Louis Dionne65358e12021-03-01 12:09:45 -05004002__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004003{
4004 return false;
4005}
4006
4007int
4008__codecvt_utf16<char32_t, false>::do_length(state_type&,
4009 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4010{
4011 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4012 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4013 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4014}
4015
4016int
Louis Dionne65358e12021-03-01 12:09:45 -05004017__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004018{
4019 if (_Mode_ & consume_header)
4020 return 6;
4021 return 4;
4022}
4023
4024// __codecvt_utf16<char32_t, true>
4025
4026__codecvt_utf16<char32_t, true>::result
4027__codecvt_utf16<char32_t, true>::do_out(state_type&,
4028 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4029 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4030{
4031 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4032 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4033 const uint32_t* _frm_nxt = _frm;
4034 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4035 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4036 uint8_t* _to_nxt = _to;
4037 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4038 _Maxcode_, _Mode_);
4039 frm_nxt = frm + (_frm_nxt - _frm);
4040 to_nxt = to + (_to_nxt - _to);
4041 return r;
4042}
4043
4044__codecvt_utf16<char32_t, true>::result
4045__codecvt_utf16<char32_t, true>::do_in(state_type&,
4046 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4047 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4048{
4049 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4050 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4051 const uint8_t* _frm_nxt = _frm;
4052 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4053 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4054 uint32_t* _to_nxt = _to;
4055 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4056 _Maxcode_, _Mode_);
4057 frm_nxt = frm + (_frm_nxt - _frm);
4058 to_nxt = to + (_to_nxt - _to);
4059 return r;
4060}
4061
4062__codecvt_utf16<char32_t, true>::result
4063__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4064 extern_type* to, extern_type*, extern_type*& to_nxt) const
4065{
4066 to_nxt = to;
4067 return noconv;
4068}
4069
4070int
Louis Dionne65358e12021-03-01 12:09:45 -05004071__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004072{
4073 return 0;
4074}
4075
4076bool
Louis Dionne65358e12021-03-01 12:09:45 -05004077__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004078{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004079 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004080}
4081
4082int
4083__codecvt_utf16<char32_t, true>::do_length(state_type&,
4084 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4085{
4086 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4087 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4088 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4089}
4090
4091int
Louis Dionne65358e12021-03-01 12:09:45 -05004092__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004093{
4094 if (_Mode_ & consume_header)
4095 return 6;
4096 return 4;
4097}
4098
4099// __codecvt_utf8_utf16<wchar_t>
4100
4101__codecvt_utf8_utf16<wchar_t>::result
4102__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4103 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4104 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4105{
4106 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4107 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4108 const uint32_t* _frm_nxt = _frm;
4109 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4110 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4111 uint8_t* _to_nxt = _to;
4112 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4113 _Maxcode_, _Mode_);
4114 frm_nxt = frm + (_frm_nxt - _frm);
4115 to_nxt = to + (_to_nxt - _to);
4116 return r;
4117}
4118
4119__codecvt_utf8_utf16<wchar_t>::result
4120__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4121 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4122 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4123{
4124 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4125 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4126 const uint8_t* _frm_nxt = _frm;
4127 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4128 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4129 uint32_t* _to_nxt = _to;
4130 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4131 _Maxcode_, _Mode_);
4132 frm_nxt = frm + (_frm_nxt - _frm);
4133 to_nxt = to + (_to_nxt - _to);
4134 return r;
4135}
4136
4137__codecvt_utf8_utf16<wchar_t>::result
4138__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4139 extern_type* to, extern_type*, extern_type*& to_nxt) const
4140{
4141 to_nxt = to;
4142 return noconv;
4143}
4144
4145int
Louis Dionne65358e12021-03-01 12:09:45 -05004146__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004147{
4148 return 0;
4149}
4150
4151bool
Louis Dionne65358e12021-03-01 12:09:45 -05004152__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004153{
4154 return false;
4155}
4156
4157int
4158__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4159 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4160{
4161 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4162 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4163 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4164}
4165
4166int
Louis Dionne65358e12021-03-01 12:09:45 -05004167__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004168{
4169 if (_Mode_ & consume_header)
4170 return 7;
4171 return 4;
4172}
4173
4174// __codecvt_utf8_utf16<char16_t>
4175
4176__codecvt_utf8_utf16<char16_t>::result
4177__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4178 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4179 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4180{
4181 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4182 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4183 const uint16_t* _frm_nxt = _frm;
4184 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4185 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4186 uint8_t* _to_nxt = _to;
4187 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4188 _Maxcode_, _Mode_);
4189 frm_nxt = frm + (_frm_nxt - _frm);
4190 to_nxt = to + (_to_nxt - _to);
4191 return r;
4192}
4193
4194__codecvt_utf8_utf16<char16_t>::result
4195__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4196 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4197 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4198{
4199 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4200 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4201 const uint8_t* _frm_nxt = _frm;
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 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4206 _Maxcode_, _Mode_);
4207 frm_nxt = frm + (_frm_nxt - _frm);
4208 to_nxt = to + (_to_nxt - _to);
4209 return r;
4210}
4211
4212__codecvt_utf8_utf16<char16_t>::result
4213__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4214 extern_type* to, extern_type*, extern_type*& to_nxt) const
4215{
4216 to_nxt = to;
4217 return noconv;
4218}
4219
4220int
Louis Dionne65358e12021-03-01 12:09:45 -05004221__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004222{
4223 return 0;
4224}
4225
4226bool
Louis Dionne65358e12021-03-01 12:09:45 -05004227__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004228{
4229 return false;
4230}
4231
4232int
4233__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4234 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4235{
4236 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4237 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4238 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4239}
4240
4241int
Louis Dionne65358e12021-03-01 12:09:45 -05004242__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004243{
4244 if (_Mode_ & consume_header)
4245 return 7;
4246 return 4;
4247}
4248
4249// __codecvt_utf8_utf16<char32_t>
4250
4251__codecvt_utf8_utf16<char32_t>::result
4252__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4253 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4254 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4255{
4256 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4257 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4258 const uint32_t* _frm_nxt = _frm;
4259 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4260 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4261 uint8_t* _to_nxt = _to;
4262 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4263 _Maxcode_, _Mode_);
4264 frm_nxt = frm + (_frm_nxt - _frm);
4265 to_nxt = to + (_to_nxt - _to);
4266 return r;
4267}
4268
4269__codecvt_utf8_utf16<char32_t>::result
4270__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4271 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4272 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4273{
4274 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4275 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4276 const uint8_t* _frm_nxt = _frm;
4277 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4278 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4279 uint32_t* _to_nxt = _to;
4280 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4281 _Maxcode_, _Mode_);
4282 frm_nxt = frm + (_frm_nxt - _frm);
4283 to_nxt = to + (_to_nxt - _to);
4284 return r;
4285}
4286
4287__codecvt_utf8_utf16<char32_t>::result
4288__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4289 extern_type* to, extern_type*, extern_type*& to_nxt) const
4290{
4291 to_nxt = to;
4292 return noconv;
4293}
4294
4295int
Louis Dionne65358e12021-03-01 12:09:45 -05004296__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004297{
4298 return 0;
4299}
4300
4301bool
Louis Dionne65358e12021-03-01 12:09:45 -05004302__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004303{
4304 return false;
4305}
4306
4307int
4308__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4309 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4310{
4311 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4312 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4313 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4314}
4315
4316int
Louis Dionne65358e12021-03-01 12:09:45 -05004317__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004318{
4319 if (_Mode_ & consume_header)
4320 return 7;
4321 return 4;
4322}
4323
Howard Hinnantc51e1022010-05-11 19:42:16 +00004324// __narrow_to_utf8<16>
4325
4326__narrow_to_utf8<16>::~__narrow_to_utf8()
4327{
4328}
4329
4330// __narrow_to_utf8<32>
4331
4332__narrow_to_utf8<32>::~__narrow_to_utf8()
4333{
4334}
4335
4336// __widen_from_utf8<16>
4337
4338__widen_from_utf8<16>::~__widen_from_utf8()
4339{
4340}
4341
4342// __widen_from_utf8<32>
4343
4344__widen_from_utf8<32>::~__widen_from_utf8()
4345{
4346}
4347
Eric Fiselierbf945a22016-12-11 00:20:59 +00004348
4349static bool checked_string_to_wchar_convert(wchar_t& dest,
4350 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004351 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004352 if (*ptr == '\0')
4353 return false;
4354 mbstate_t mb = {};
4355 wchar_t out;
4356 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4357 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4358 return false;
4359 }
4360 dest = out;
4361 return true;
4362}
4363
4364static bool checked_string_to_char_convert(char& dest,
4365 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004366 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004367 if (*ptr == '\0')
4368 return false;
4369 if (!ptr[1]) {
4370 dest = *ptr;
4371 return true;
4372 }
4373 // First convert the MBS into a wide char then attempt to narrow it using
4374 // wctob_l.
4375 wchar_t wout;
4376 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4377 return false;
4378 int res;
4379 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4380 dest = res;
4381 return true;
4382 }
4383 // FIXME: Work around specific multibyte sequences that we can reasonable
4384 // translate into a different single byte.
4385 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004386 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004387 case L'\u00A0': // non-breaking space
4388 dest = ' ';
4389 return true;
4390 default:
4391 return false;
4392 }
4393 _LIBCPP_UNREACHABLE();
4394}
4395
4396
Howard Hinnantc51e1022010-05-11 19:42:16 +00004397// numpunct<char> && numpunct<wchar_t>
4398
4399locale::id numpunct< char >::id;
4400locale::id numpunct<wchar_t>::id;
4401
4402numpunct<char>::numpunct(size_t refs)
4403 : locale::facet(refs),
4404 __decimal_point_('.'),
4405 __thousands_sep_(',')
4406{
4407}
4408
4409numpunct<wchar_t>::numpunct(size_t refs)
4410 : locale::facet(refs),
4411 __decimal_point_(L'.'),
4412 __thousands_sep_(L',')
4413{
4414}
4415
4416numpunct<char>::~numpunct()
4417{
4418}
4419
4420numpunct<wchar_t>::~numpunct()
4421{
4422}
4423
4424 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4425wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4426
4427 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4428wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4429
4430string numpunct< char >::do_grouping() const {return __grouping_;}
4431string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4432
4433 string numpunct< char >::do_truename() const {return "true";}
4434wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4435
4436 string numpunct< char >::do_falsename() const {return "false";}
4437wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4438
4439// numpunct_byname<char>
4440
4441numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4442 : numpunct<char>(refs)
4443{
4444 __init(nm);
4445}
4446
4447numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4448 : numpunct<char>(refs)
4449{
4450 __init(nm.c_str());
4451}
4452
4453numpunct_byname<char>::~numpunct_byname()
4454{
4455}
4456
4457void
4458numpunct_byname<char>::__init(const char* nm)
4459{
4460 if (strcmp(nm, "C") != 0)
4461 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004462 __libcpp_unique_locale loc(nm);
4463 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004464 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004465 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004466
Ben Craig3756b922016-03-09 15:39:39 +00004467 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004468 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4469 loc.get());
4470 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4471 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004472 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004473 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004474 }
4475}
4476
4477// numpunct_byname<wchar_t>
4478
4479numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4480 : numpunct<wchar_t>(refs)
4481{
4482 __init(nm);
4483}
4484
4485numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4486 : numpunct<wchar_t>(refs)
4487{
4488 __init(nm.c_str());
4489}
4490
4491numpunct_byname<wchar_t>::~numpunct_byname()
4492{
4493}
4494
4495void
4496numpunct_byname<wchar_t>::__init(const char* nm)
4497{
4498 if (strcmp(nm, "C") != 0)
4499 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004500 __libcpp_unique_locale loc(nm);
4501 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004502 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004503 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004504
Ben Craig3756b922016-03-09 15:39:39 +00004505 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004506 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4507 loc.get());
4508 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4509 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004510 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004511 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004512 }
4513}
4514
4515// num_get helpers
4516
4517int
4518__num_get_base::__get_base(ios_base& iob)
4519{
4520 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4521 if (__basefield == ios_base::oct)
4522 return 8;
4523 else if (__basefield == ios_base::hex)
4524 return 16;
4525 else if (__basefield == 0)
4526 return 0;
4527 return 10;
4528}
4529
4530const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4531
4532void
4533__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4534 ios_base::iostate& __err)
4535{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004536// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4537// 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 +00004538 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004539 {
4540 reverse(__g, __g_end);
4541 const char* __ig = __grouping.data();
4542 const char* __eg = __ig + __grouping.size();
4543 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4544 {
4545 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4546 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004547 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004548 {
4549 __err = ios_base::failbit;
4550 return;
4551 }
4552 }
4553 if (__eg - __ig > 1)
4554 ++__ig;
4555 }
4556 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4557 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004558 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004559 __err = ios_base::failbit;
4560 }
4561 }
4562}
4563
4564void
4565__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4566 ios_base::fmtflags __flags)
4567{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004568 if ((__flags & ios_base::showpos) &&
4569 (__flags & ios_base::basefield) != ios_base::oct &&
4570 (__flags & ios_base::basefield) != ios_base::hex &&
4571 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004572 *__fmtp++ = '+';
4573 if (__flags & ios_base::showbase)
4574 *__fmtp++ = '#';
4575 while(*__len)
4576 *__fmtp++ = *__len++;
4577 if ((__flags & ios_base::basefield) == ios_base::oct)
4578 *__fmtp = 'o';
4579 else if ((__flags & ios_base::basefield) == ios_base::hex)
4580 {
4581 if (__flags & ios_base::uppercase)
4582 *__fmtp = 'X';
4583 else
4584 *__fmtp = 'x';
4585 }
4586 else if (__signd)
4587 *__fmtp = 'd';
4588 else
4589 *__fmtp = 'u';
4590}
4591
4592bool
4593__num_put_base::__format_float(char* __fmtp, const char* __len,
4594 ios_base::fmtflags __flags)
4595{
4596 bool specify_precision = true;
4597 if (__flags & ios_base::showpos)
4598 *__fmtp++ = '+';
4599 if (__flags & ios_base::showpoint)
4600 *__fmtp++ = '#';
4601 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004602 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004603 if (floatfield == (ios_base::fixed | ios_base::scientific))
4604 specify_precision = false;
4605 else
4606 {
4607 *__fmtp++ = '.';
4608 *__fmtp++ = '*';
4609 }
4610 while(*__len)
4611 *__fmtp++ = *__len++;
4612 if (floatfield == ios_base::fixed)
4613 {
4614 if (uppercase)
4615 *__fmtp = 'F';
4616 else
4617 *__fmtp = 'f';
4618 }
4619 else if (floatfield == ios_base::scientific)
4620 {
4621 if (uppercase)
4622 *__fmtp = 'E';
4623 else
4624 *__fmtp = 'e';
4625 }
4626 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4627 {
4628 if (uppercase)
4629 *__fmtp = 'A';
4630 else
4631 *__fmtp = 'a';
4632 }
4633 else
4634 {
4635 if (uppercase)
4636 *__fmtp = 'G';
4637 else
4638 *__fmtp = 'g';
4639 }
4640 return specify_precision;
4641}
4642
4643char*
4644__num_put_base::__identify_padding(char* __nb, char* __ne,
4645 const ios_base& __iob)
4646{
4647 switch (__iob.flags() & ios_base::adjustfield)
4648 {
4649 case ios_base::internal:
4650 if (__nb[0] == '-' || __nb[0] == '+')
4651 return __nb+1;
4652 if (__ne - __nb >= 2 && __nb[0] == '0'
4653 && (__nb[1] == 'x' || __nb[1] == 'X'))
4654 return __nb+2;
4655 break;
4656 case ios_base::left:
4657 return __ne;
4658 case ios_base::right:
4659 default:
4660 break;
4661 }
4662 return __nb;
4663}
4664
4665// time_get
4666
4667static
4668string*
4669init_weeks()
4670{
4671 static string weeks[14];
4672 weeks[0] = "Sunday";
4673 weeks[1] = "Monday";
4674 weeks[2] = "Tuesday";
4675 weeks[3] = "Wednesday";
4676 weeks[4] = "Thursday";
4677 weeks[5] = "Friday";
4678 weeks[6] = "Saturday";
4679 weeks[7] = "Sun";
4680 weeks[8] = "Mon";
4681 weeks[9] = "Tue";
4682 weeks[10] = "Wed";
4683 weeks[11] = "Thu";
4684 weeks[12] = "Fri";
4685 weeks[13] = "Sat";
4686 return weeks;
4687}
4688
4689static
4690wstring*
4691init_wweeks()
4692{
4693 static wstring weeks[14];
4694 weeks[0] = L"Sunday";
4695 weeks[1] = L"Monday";
4696 weeks[2] = L"Tuesday";
4697 weeks[3] = L"Wednesday";
4698 weeks[4] = L"Thursday";
4699 weeks[5] = L"Friday";
4700 weeks[6] = L"Saturday";
4701 weeks[7] = L"Sun";
4702 weeks[8] = L"Mon";
4703 weeks[9] = L"Tue";
4704 weeks[10] = L"Wed";
4705 weeks[11] = L"Thu";
4706 weeks[12] = L"Fri";
4707 weeks[13] = L"Sat";
4708 return weeks;
4709}
4710
4711template <>
4712const string*
4713__time_get_c_storage<char>::__weeks() const
4714{
4715 static const string* weeks = init_weeks();
4716 return weeks;
4717}
4718
4719template <>
4720const wstring*
4721__time_get_c_storage<wchar_t>::__weeks() const
4722{
4723 static const wstring* weeks = init_wweeks();
4724 return weeks;
4725}
4726
4727static
4728string*
4729init_months()
4730{
4731 static string months[24];
4732 months[0] = "January";
4733 months[1] = "February";
4734 months[2] = "March";
4735 months[3] = "April";
4736 months[4] = "May";
4737 months[5] = "June";
4738 months[6] = "July";
4739 months[7] = "August";
4740 months[8] = "September";
4741 months[9] = "October";
4742 months[10] = "November";
4743 months[11] = "December";
4744 months[12] = "Jan";
4745 months[13] = "Feb";
4746 months[14] = "Mar";
4747 months[15] = "Apr";
4748 months[16] = "May";
4749 months[17] = "Jun";
4750 months[18] = "Jul";
4751 months[19] = "Aug";
4752 months[20] = "Sep";
4753 months[21] = "Oct";
4754 months[22] = "Nov";
4755 months[23] = "Dec";
4756 return months;
4757}
4758
4759static
4760wstring*
4761init_wmonths()
4762{
4763 static wstring months[24];
4764 months[0] = L"January";
4765 months[1] = L"February";
4766 months[2] = L"March";
4767 months[3] = L"April";
4768 months[4] = L"May";
4769 months[5] = L"June";
4770 months[6] = L"July";
4771 months[7] = L"August";
4772 months[8] = L"September";
4773 months[9] = L"October";
4774 months[10] = L"November";
4775 months[11] = L"December";
4776 months[12] = L"Jan";
4777 months[13] = L"Feb";
4778 months[14] = L"Mar";
4779 months[15] = L"Apr";
4780 months[16] = L"May";
4781 months[17] = L"Jun";
4782 months[18] = L"Jul";
4783 months[19] = L"Aug";
4784 months[20] = L"Sep";
4785 months[21] = L"Oct";
4786 months[22] = L"Nov";
4787 months[23] = L"Dec";
4788 return months;
4789}
4790
4791template <>
4792const string*
4793__time_get_c_storage<char>::__months() const
4794{
4795 static const string* months = init_months();
4796 return months;
4797}
4798
4799template <>
4800const wstring*
4801__time_get_c_storage<wchar_t>::__months() const
4802{
4803 static const wstring* months = init_wmonths();
4804 return months;
4805}
4806
4807static
4808string*
4809init_am_pm()
4810{
Marshall Clow5cc04922018-01-11 17:16:52 +00004811 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004812 am_pm[0] = "AM";
4813 am_pm[1] = "PM";
4814 return am_pm;
4815}
4816
4817static
4818wstring*
4819init_wam_pm()
4820{
Marshall Clow5cc04922018-01-11 17:16:52 +00004821 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004822 am_pm[0] = L"AM";
4823 am_pm[1] = L"PM";
4824 return am_pm;
4825}
4826
4827template <>
4828const string*
4829__time_get_c_storage<char>::__am_pm() const
4830{
4831 static const string* am_pm = init_am_pm();
4832 return am_pm;
4833}
4834
4835template <>
4836const wstring*
4837__time_get_c_storage<wchar_t>::__am_pm() const
4838{
4839 static const wstring* am_pm = init_wam_pm();
4840 return am_pm;
4841}
4842
4843template <>
4844const string&
4845__time_get_c_storage<char>::__x() const
4846{
4847 static string s("%m/%d/%y");
4848 return s;
4849}
4850
4851template <>
4852const wstring&
4853__time_get_c_storage<wchar_t>::__x() const
4854{
4855 static wstring s(L"%m/%d/%y");
4856 return s;
4857}
4858
4859template <>
4860const string&
4861__time_get_c_storage<char>::__X() const
4862{
4863 static string s("%H:%M:%S");
4864 return s;
4865}
4866
4867template <>
4868const wstring&
4869__time_get_c_storage<wchar_t>::__X() const
4870{
4871 static wstring s(L"%H:%M:%S");
4872 return s;
4873}
4874
4875template <>
4876const string&
4877__time_get_c_storage<char>::__c() const
4878{
4879 static string s("%a %b %d %H:%M:%S %Y");
4880 return s;
4881}
4882
4883template <>
4884const wstring&
4885__time_get_c_storage<wchar_t>::__c() const
4886{
4887 static wstring s(L"%a %b %d %H:%M:%S %Y");
4888 return s;
4889}
4890
4891template <>
4892const string&
4893__time_get_c_storage<char>::__r() const
4894{
4895 static string s("%I:%M:%S %p");
4896 return s;
4897}
4898
4899template <>
4900const wstring&
4901__time_get_c_storage<wchar_t>::__r() const
4902{
4903 static wstring s(L"%I:%M:%S %p");
4904 return s;
4905}
4906
4907// time_get_byname
4908
4909__time_get::__time_get(const char* nm)
4910 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4911{
4912 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004913 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004914 " failed to construct for " + string(nm));
4915}
4916
4917__time_get::__time_get(const string& nm)
4918 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4919{
4920 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004921 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004922 " failed to construct for " + nm);
4923}
4924
4925__time_get::~__time_get()
4926{
4927 freelocale(__loc_);
4928}
Marshall Clowd920eea2013-10-21 15:07:28 +00004929#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004930#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004931#endif
4932#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004933#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004934#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004935
Howard Hinnantc51e1022010-05-11 19:42:16 +00004936template <>
4937string
4938__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4939{
Howard Hinnant990207c2012-02-19 14:55:32 +00004940 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004941 t.tm_sec = 59;
4942 t.tm_min = 55;
4943 t.tm_hour = 23;
4944 t.tm_mday = 31;
4945 t.tm_mon = 11;
4946 t.tm_year = 161;
4947 t.tm_wday = 6;
4948 t.tm_yday = 364;
4949 t.tm_isdst = -1;
4950 char buf[100];
4951 char f[3] = {0};
4952 f[0] = '%';
4953 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004954 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004955 char* bb = buf;
4956 char* be = buf + n;
4957 string result;
4958 while (bb != be)
4959 {
4960 if (ct.is(ctype_base::space, *bb))
4961 {
4962 result.push_back(' ');
4963 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4964 ;
4965 continue;
4966 }
4967 char* w = bb;
4968 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004969 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004970 ct, err, false)
4971 - this->__weeks_;
4972 if (i < 14)
4973 {
4974 result.push_back('%');
4975 if (i < 7)
4976 result.push_back('A');
4977 else
4978 result.push_back('a');
4979 bb = w;
4980 continue;
4981 }
4982 w = bb;
4983 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4984 ct, err, false)
4985 - this->__months_;
4986 if (i < 24)
4987 {
4988 result.push_back('%');
4989 if (i < 12)
4990 result.push_back('B');
4991 else
4992 result.push_back('b');
4993 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4994 result.back() = 'm';
4995 bb = w;
4996 continue;
4997 }
4998 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4999 {
5000 w = bb;
5001 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5002 ct, err, false) - this->__am_pm_;
5003 if (i < 2)
5004 {
5005 result.push_back('%');
5006 result.push_back('p');
5007 bb = w;
5008 continue;
5009 }
5010 }
5011 w = bb;
5012 if (ct.is(ctype_base::digit, *bb))
5013 {
5014 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5015 {
5016 case 6:
5017 result.push_back('%');
5018 result.push_back('w');
5019 break;
5020 case 7:
5021 result.push_back('%');
5022 result.push_back('u');
5023 break;
5024 case 11:
5025 result.push_back('%');
5026 result.push_back('I');
5027 break;
5028 case 12:
5029 result.push_back('%');
5030 result.push_back('m');
5031 break;
5032 case 23:
5033 result.push_back('%');
5034 result.push_back('H');
5035 break;
5036 case 31:
5037 result.push_back('%');
5038 result.push_back('d');
5039 break;
5040 case 55:
5041 result.push_back('%');
5042 result.push_back('M');
5043 break;
5044 case 59:
5045 result.push_back('%');
5046 result.push_back('S');
5047 break;
5048 case 61:
5049 result.push_back('%');
5050 result.push_back('y');
5051 break;
5052 case 364:
5053 result.push_back('%');
5054 result.push_back('j');
5055 break;
5056 case 2061:
5057 result.push_back('%');
5058 result.push_back('Y');
5059 break;
5060 default:
5061 for (; w != bb; ++w)
5062 result.push_back(*w);
5063 break;
5064 }
5065 continue;
5066 }
5067 if (*bb == '%')
5068 {
5069 result.push_back('%');
5070 result.push_back('%');
5071 ++bb;
5072 continue;
5073 }
5074 result.push_back(*bb);
5075 ++bb;
5076 }
5077 return result;
5078}
5079
Marshall Clowd920eea2013-10-21 15:07:28 +00005080#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005081#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005082#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005083
Howard Hinnantc51e1022010-05-11 19:42:16 +00005084template <>
5085wstring
5086__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5087{
Howard Hinnant990207c2012-02-19 14:55:32 +00005088 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005089 t.tm_sec = 59;
5090 t.tm_min = 55;
5091 t.tm_hour = 23;
5092 t.tm_mday = 31;
5093 t.tm_mon = 11;
5094 t.tm_year = 161;
5095 t.tm_wday = 6;
5096 t.tm_yday = 364;
5097 t.tm_isdst = -1;
5098 char buf[100];
5099 char f[3] = {0};
5100 f[0] = '%';
5101 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005102 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005103 wchar_t wbuf[100];
5104 wchar_t* wbb = wbuf;
5105 mbstate_t mb = {0};
5106 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005107 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005108 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005109 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005110 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005111 wstring result;
5112 while (wbb != wbe)
5113 {
5114 if (ct.is(ctype_base::space, *wbb))
5115 {
5116 result.push_back(L' ');
5117 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5118 ;
5119 continue;
5120 }
5121 wchar_t* w = wbb;
5122 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005123 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005124 ct, err, false)
5125 - this->__weeks_;
5126 if (i < 14)
5127 {
5128 result.push_back(L'%');
5129 if (i < 7)
5130 result.push_back(L'A');
5131 else
5132 result.push_back(L'a');
5133 wbb = w;
5134 continue;
5135 }
5136 w = wbb;
5137 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5138 ct, err, false)
5139 - this->__months_;
5140 if (i < 24)
5141 {
5142 result.push_back(L'%');
5143 if (i < 12)
5144 result.push_back(L'B');
5145 else
5146 result.push_back(L'b');
5147 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5148 result.back() = L'm';
5149 wbb = w;
5150 continue;
5151 }
5152 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5153 {
5154 w = wbb;
5155 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5156 ct, err, false) - this->__am_pm_;
5157 if (i < 2)
5158 {
5159 result.push_back(L'%');
5160 result.push_back(L'p');
5161 wbb = w;
5162 continue;
5163 }
5164 }
5165 w = wbb;
5166 if (ct.is(ctype_base::digit, *wbb))
5167 {
5168 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5169 {
5170 case 6:
5171 result.push_back(L'%');
5172 result.push_back(L'w');
5173 break;
5174 case 7:
5175 result.push_back(L'%');
5176 result.push_back(L'u');
5177 break;
5178 case 11:
5179 result.push_back(L'%');
5180 result.push_back(L'I');
5181 break;
5182 case 12:
5183 result.push_back(L'%');
5184 result.push_back(L'm');
5185 break;
5186 case 23:
5187 result.push_back(L'%');
5188 result.push_back(L'H');
5189 break;
5190 case 31:
5191 result.push_back(L'%');
5192 result.push_back(L'd');
5193 break;
5194 case 55:
5195 result.push_back(L'%');
5196 result.push_back(L'M');
5197 break;
5198 case 59:
5199 result.push_back(L'%');
5200 result.push_back(L'S');
5201 break;
5202 case 61:
5203 result.push_back(L'%');
5204 result.push_back(L'y');
5205 break;
5206 case 364:
5207 result.push_back(L'%');
5208 result.push_back(L'j');
5209 break;
5210 case 2061:
5211 result.push_back(L'%');
5212 result.push_back(L'Y');
5213 break;
5214 default:
5215 for (; w != wbb; ++w)
5216 result.push_back(*w);
5217 break;
5218 }
5219 continue;
5220 }
5221 if (ct.narrow(*wbb, 0) == '%')
5222 {
5223 result.push_back(L'%');
5224 result.push_back(L'%');
5225 ++wbb;
5226 continue;
5227 }
5228 result.push_back(*wbb);
5229 ++wbb;
5230 }
5231 return result;
5232}
5233
5234template <>
5235void
5236__time_get_storage<char>::init(const ctype<char>& ct)
5237{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005238 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005239 char buf[100];
5240 // __weeks_
5241 for (int i = 0; i < 7; ++i)
5242 {
5243 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005244 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005245 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005246 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005247 __weeks_[i+7] = buf;
5248 }
5249 // __months_
5250 for (int i = 0; i < 12; ++i)
5251 {
5252 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005253 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005254 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005255 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005256 __months_[i+12] = buf;
5257 }
5258 // __am_pm_
5259 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005260 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005261 __am_pm_[0] = buf;
5262 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005263 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005264 __am_pm_[1] = buf;
5265 __c_ = __analyze('c', ct);
5266 __r_ = __analyze('r', ct);
5267 __x_ = __analyze('x', ct);
5268 __X_ = __analyze('X', ct);
5269}
5270
5271template <>
5272void
5273__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5274{
5275 tm t = {0};
5276 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005277 wchar_t wbuf[100];
5278 wchar_t* wbe;
5279 mbstate_t mb = {0};
5280 // __weeks_
5281 for (int i = 0; i < 7; ++i)
5282 {
5283 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005284 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005285 mb = mbstate_t();
5286 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005287 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005288 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005289 __throw_runtime_error("locale not supported");
5290 wbe = wbuf + j;
5291 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005292 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005293 mb = mbstate_t();
5294 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005295 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005296 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005297 __throw_runtime_error("locale not supported");
5298 wbe = wbuf + j;
5299 __weeks_[i+7].assign(wbuf, wbe);
5300 }
5301 // __months_
5302 for (int i = 0; i < 12; ++i)
5303 {
5304 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005305 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005306 mb = mbstate_t();
5307 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005308 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005309 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005310 __throw_runtime_error("locale not supported");
5311 wbe = wbuf + j;
5312 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005313 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005314 mb = mbstate_t();
5315 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005316 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005317 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005318 __throw_runtime_error("locale not supported");
5319 wbe = wbuf + j;
5320 __months_[i+12].assign(wbuf, wbe);
5321 }
5322 // __am_pm_
5323 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005324 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005325 mb = mbstate_t();
5326 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005327 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005328 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005329 __throw_runtime_error("locale not supported");
5330 wbe = wbuf + j;
5331 __am_pm_[0].assign(wbuf, wbe);
5332 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005333 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005334 mb = mbstate_t();
5335 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005336 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005337 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005338 __throw_runtime_error("locale not supported");
5339 wbe = wbuf + j;
5340 __am_pm_[1].assign(wbuf, wbe);
5341 __c_ = __analyze('c', ct);
5342 __r_ = __analyze('r', ct);
5343 __x_ = __analyze('x', ct);
5344 __X_ = __analyze('X', ct);
5345}
5346
5347template <class CharT>
5348struct _LIBCPP_HIDDEN __time_get_temp
5349 : public ctype_byname<CharT>
5350{
5351 explicit __time_get_temp(const char* nm)
5352 : ctype_byname<CharT>(nm, 1) {}
5353 explicit __time_get_temp(const string& nm)
5354 : ctype_byname<CharT>(nm, 1) {}
5355};
5356
5357template <>
5358__time_get_storage<char>::__time_get_storage(const char* __nm)
5359 : __time_get(__nm)
5360{
5361 const __time_get_temp<char> ct(__nm);
5362 init(ct);
5363}
5364
5365template <>
5366__time_get_storage<char>::__time_get_storage(const string& __nm)
5367 : __time_get(__nm)
5368{
5369 const __time_get_temp<char> ct(__nm);
5370 init(ct);
5371}
5372
5373template <>
5374__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5375 : __time_get(__nm)
5376{
5377 const __time_get_temp<wchar_t> ct(__nm);
5378 init(ct);
5379}
5380
5381template <>
5382__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5383 : __time_get(__nm)
5384{
5385 const __time_get_temp<wchar_t> ct(__nm);
5386 init(ct);
5387}
5388
5389template <>
5390time_base::dateorder
5391__time_get_storage<char>::__do_date_order() const
5392{
5393 unsigned i;
5394 for (i = 0; i < __x_.size(); ++i)
5395 if (__x_[i] == '%')
5396 break;
5397 ++i;
5398 switch (__x_[i])
5399 {
5400 case 'y':
5401 case 'Y':
5402 for (++i; i < __x_.size(); ++i)
5403 if (__x_[i] == '%')
5404 break;
5405 if (i == __x_.size())
5406 break;
5407 ++i;
5408 switch (__x_[i])
5409 {
5410 case 'm':
5411 for (++i; i < __x_.size(); ++i)
5412 if (__x_[i] == '%')
5413 break;
5414 if (i == __x_.size())
5415 break;
5416 ++i;
5417 if (__x_[i] == 'd')
5418 return time_base::ymd;
5419 break;
5420 case 'd':
5421 for (++i; i < __x_.size(); ++i)
5422 if (__x_[i] == '%')
5423 break;
5424 if (i == __x_.size())
5425 break;
5426 ++i;
5427 if (__x_[i] == 'm')
5428 return time_base::ydm;
5429 break;
5430 }
5431 break;
5432 case 'm':
5433 for (++i; i < __x_.size(); ++i)
5434 if (__x_[i] == '%')
5435 break;
5436 if (i == __x_.size())
5437 break;
5438 ++i;
5439 if (__x_[i] == 'd')
5440 {
5441 for (++i; i < __x_.size(); ++i)
5442 if (__x_[i] == '%')
5443 break;
5444 if (i == __x_.size())
5445 break;
5446 ++i;
5447 if (__x_[i] == 'y' || __x_[i] == 'Y')
5448 return time_base::mdy;
5449 break;
5450 }
5451 break;
5452 case 'd':
5453 for (++i; i < __x_.size(); ++i)
5454 if (__x_[i] == '%')
5455 break;
5456 if (i == __x_.size())
5457 break;
5458 ++i;
5459 if (__x_[i] == 'm')
5460 {
5461 for (++i; i < __x_.size(); ++i)
5462 if (__x_[i] == '%')
5463 break;
5464 if (i == __x_.size())
5465 break;
5466 ++i;
5467 if (__x_[i] == 'y' || __x_[i] == 'Y')
5468 return time_base::dmy;
5469 break;
5470 }
5471 break;
5472 }
5473 return time_base::no_order;
5474}
5475
5476template <>
5477time_base::dateorder
5478__time_get_storage<wchar_t>::__do_date_order() const
5479{
5480 unsigned i;
5481 for (i = 0; i < __x_.size(); ++i)
5482 if (__x_[i] == L'%')
5483 break;
5484 ++i;
5485 switch (__x_[i])
5486 {
5487 case L'y':
5488 case L'Y':
5489 for (++i; i < __x_.size(); ++i)
5490 if (__x_[i] == L'%')
5491 break;
5492 if (i == __x_.size())
5493 break;
5494 ++i;
5495 switch (__x_[i])
5496 {
5497 case L'm':
5498 for (++i; i < __x_.size(); ++i)
5499 if (__x_[i] == L'%')
5500 break;
5501 if (i == __x_.size())
5502 break;
5503 ++i;
5504 if (__x_[i] == L'd')
5505 return time_base::ymd;
5506 break;
5507 case L'd':
5508 for (++i; i < __x_.size(); ++i)
5509 if (__x_[i] == L'%')
5510 break;
5511 if (i == __x_.size())
5512 break;
5513 ++i;
5514 if (__x_[i] == L'm')
5515 return time_base::ydm;
5516 break;
5517 }
5518 break;
5519 case L'm':
5520 for (++i; i < __x_.size(); ++i)
5521 if (__x_[i] == L'%')
5522 break;
5523 if (i == __x_.size())
5524 break;
5525 ++i;
5526 if (__x_[i] == L'd')
5527 {
5528 for (++i; i < __x_.size(); ++i)
5529 if (__x_[i] == L'%')
5530 break;
5531 if (i == __x_.size())
5532 break;
5533 ++i;
5534 if (__x_[i] == L'y' || __x_[i] == L'Y')
5535 return time_base::mdy;
5536 break;
5537 }
5538 break;
5539 case L'd':
5540 for (++i; i < __x_.size(); ++i)
5541 if (__x_[i] == L'%')
5542 break;
5543 if (i == __x_.size())
5544 break;
5545 ++i;
5546 if (__x_[i] == L'm')
5547 {
5548 for (++i; i < __x_.size(); ++i)
5549 if (__x_[i] == L'%')
5550 break;
5551 if (i == __x_.size())
5552 break;
5553 ++i;
5554 if (__x_[i] == L'y' || __x_[i] == L'Y')
5555 return time_base::dmy;
5556 break;
5557 }
5558 break;
5559 }
5560 return time_base::no_order;
5561}
5562
5563// time_put
5564
5565__time_put::__time_put(const char* nm)
5566 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5567{
5568 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005569 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005570 " failed to construct for " + string(nm));
5571}
5572
5573__time_put::__time_put(const string& nm)
5574 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5575{
5576 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005577 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005578 " failed to construct for " + nm);
5579}
5580
5581__time_put::~__time_put()
5582{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005583 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005584 freelocale(__loc_);
5585}
5586
5587void
5588__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5589 char __fmt, char __mod) const
5590{
5591 char fmt[] = {'%', __fmt, __mod, 0};
5592 if (__mod != 0)
5593 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005594 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005595 __ne = __nb + n;
5596}
5597
5598void
5599__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5600 char __fmt, char __mod) const
5601{
5602 char __nar[100];
5603 char* __ne = __nar + 100;
5604 __do_put(__nar, __ne, __tm, __fmt, __mod);
5605 mbstate_t mb = {0};
5606 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005607 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005608 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005609 __throw_runtime_error("locale not supported");
5610 __we = __wb + j;
5611}
5612
5613// moneypunct_byname
5614
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005615template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005616static
5617void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005618__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5619 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5620 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005621{
5622 const char sign = static_cast<char>(money_base::sign);
5623 const char space = static_cast<char>(money_base::space);
5624 const char none = static_cast<char>(money_base::none);
5625 const char symbol = static_cast<char>(money_base::symbol);
5626 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005627 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5628
5629 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5630 // function'. "Space between sign and symbol or value" means that
5631 // if the sign is adjacent to the symbol, there's a space between
5632 // them, and otherwise there's a space between the sign and value.
5633 //
5634 // C11's localeconv specifies that the fourth character of an
5635 // international curr_symbol is used to separate the sign and
5636 // value when sep_by_space says to do so. C++ can't represent
5637 // that, so we just use a space. When sep_by_space says to
5638 // separate the symbol and value-or-sign with a space, we rearrange the
5639 // curr_symbol to put its spacing character on the correct side of
5640 // the symbol.
5641 //
5642 // We also need to avoid adding an extra space between the sign
5643 // and value when the currency symbol is suppressed (by not
5644 // setting showbase). We match glibc's strfmon by interpreting
5645 // sep_by_space==1 as "omit the space when the currency symbol is
5646 // absent".
5647 //
5648 // Users who want to get this right should use ICU instead.
5649
Howard Hinnantc51e1022010-05-11 19:42:16 +00005650 switch (cs_precedes)
5651 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005652 case 0: // value before curr_symbol
5653 if (symbol_contains_sep) {
5654 // Move the separator to before the symbol, to place it
5655 // between the value and symbol.
5656 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5657 __curr_symbol_.end());
5658 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005659 switch (sign_posn)
5660 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005661 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005662 pat.field[0] = sign;
5663 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005664 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005665 pat.field[3] = symbol;
5666 switch (sep_by_space)
5667 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005668 case 0: // No space separates the currency symbol and value.
5669 // This case may have changed between C99 and C11;
5670 // assume the currency symbol matches the intention.
5671 case 2: // Space between sign and currency or value.
5672 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005673 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005674 case 1: // Space between currency-and-sign or currency and value.
5675 if (!symbol_contains_sep) {
5676 // We insert the space into the symbol instead of
5677 // setting pat.field[2]=space so that when
5678 // showbase is not set, the space goes away too.
5679 __curr_symbol_.insert(0, 1, space_char);
5680 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005681 return;
5682 default:
5683 break;
5684 }
5685 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005686 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005687 pat.field[0] = sign;
5688 pat.field[3] = symbol;
5689 switch (sep_by_space)
5690 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005691 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005692 pat.field[1] = value;
5693 pat.field[2] = none;
5694 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005695 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005696 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005697 pat.field[2] = none;
5698 if (!symbol_contains_sep) {
5699 // We insert the space into the symbol instead of
5700 // setting pat.field[2]=space so that when
5701 // showbase is not set, the space goes away too.
5702 __curr_symbol_.insert(0, 1, space_char);
5703 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005704 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005705 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005706 pat.field[1] = space;
5707 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005708 if (symbol_contains_sep) {
5709 // Remove the separator from the symbol, since it
5710 // has already appeared after the sign.
5711 __curr_symbol_.erase(__curr_symbol_.begin());
5712 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005713 return;
5714 default:
5715 break;
5716 }
5717 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005718 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005719 pat.field[0] = value;
5720 pat.field[3] = sign;
5721 switch (sep_by_space)
5722 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005723 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005724 pat.field[1] = none;
5725 pat.field[2] = symbol;
5726 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005727 case 1: // Space between currency-and-sign or currency and value.
5728 if (!symbol_contains_sep) {
5729 // We insert the space into the symbol instead of
5730 // setting pat.field[1]=space so that when
5731 // showbase is not set, the space goes away too.
5732 __curr_symbol_.insert(0, 1, space_char);
5733 }
5734 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005735 pat.field[2] = symbol;
5736 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005737 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005738 pat.field[1] = symbol;
5739 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005740 if (symbol_contains_sep) {
5741 // Remove the separator from the symbol, since it
5742 // should not be removed if showbase is absent.
5743 __curr_symbol_.erase(__curr_symbol_.begin());
5744 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 return;
5746 default:
5747 break;
5748 }
5749 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005750 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005751 pat.field[0] = value;
5752 pat.field[3] = symbol;
5753 switch (sep_by_space)
5754 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005755 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005756 pat.field[1] = none;
5757 pat.field[2] = sign;
5758 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005759 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005760 pat.field[1] = space;
5761 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005762 if (symbol_contains_sep) {
5763 // Remove the separator from the symbol, since it
5764 // has already appeared before the sign.
5765 __curr_symbol_.erase(__curr_symbol_.begin());
5766 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005767 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005768 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005769 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005770 pat.field[2] = none;
5771 if (!symbol_contains_sep) {
5772 // We insert the space into the symbol instead of
5773 // setting pat.field[2]=space so that when
5774 // showbase is not set, the space goes away too.
5775 __curr_symbol_.insert(0, 1, space_char);
5776 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005777 return;
5778 default:
5779 break;
5780 }
5781 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005782 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005783 pat.field[0] = value;
5784 pat.field[3] = sign;
5785 switch (sep_by_space)
5786 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005787 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005788 pat.field[1] = none;
5789 pat.field[2] = symbol;
5790 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005791 case 1: // Space between currency-and-sign or currency and value.
5792 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005793 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005794 if (!symbol_contains_sep) {
5795 // We insert the space into the symbol instead of
5796 // setting pat.field[1]=space so that when
5797 // showbase is not set, the space goes away too.
5798 __curr_symbol_.insert(0, 1, space_char);
5799 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005800 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005801 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005802 pat.field[1] = symbol;
5803 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005804 if (symbol_contains_sep) {
5805 // Remove the separator from the symbol, since it
5806 // should not disappear when showbase is absent.
5807 __curr_symbol_.erase(__curr_symbol_.begin());
5808 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005809 return;
5810 default:
5811 break;
5812 }
5813 break;
5814 default:
5815 break;
5816 }
5817 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005818 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005819 switch (sign_posn)
5820 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005821 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005822 pat.field[0] = sign;
5823 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005824 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005825 pat.field[3] = value;
5826 switch (sep_by_space)
5827 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005828 case 0: // No space separates the currency symbol and value.
5829 // This case may have changed between C99 and C11;
5830 // assume the currency symbol matches the intention.
5831 case 2: // Space between sign and currency or value.
5832 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005833 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005834 case 1: // Space between currency-and-sign or currency and value.
5835 if (!symbol_contains_sep) {
5836 // We insert the space into the symbol instead of
5837 // setting pat.field[2]=space so that when
5838 // showbase is not set, the space goes away too.
5839 __curr_symbol_.insert(0, 1, space_char);
5840 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005841 return;
5842 default:
5843 break;
5844 }
5845 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005846 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005847 pat.field[0] = sign;
5848 pat.field[3] = value;
5849 switch (sep_by_space)
5850 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005851 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005852 pat.field[1] = symbol;
5853 pat.field[2] = none;
5854 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005855 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005856 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005857 pat.field[2] = none;
5858 if (!symbol_contains_sep) {
5859 // We insert the space into the symbol instead of
5860 // setting pat.field[2]=space so that when
5861 // showbase is not set, the space goes away too.
5862 __curr_symbol_.push_back(space_char);
5863 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005864 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005865 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005866 pat.field[1] = space;
5867 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005868 if (symbol_contains_sep) {
5869 // Remove the separator from the symbol, since it
5870 // has already appeared after the sign.
5871 __curr_symbol_.pop_back();
5872 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005873 return;
5874 default:
5875 break;
5876 }
5877 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005878 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005879 pat.field[0] = symbol;
5880 pat.field[3] = sign;
5881 switch (sep_by_space)
5882 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005883 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005884 pat.field[1] = none;
5885 pat.field[2] = value;
5886 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005887 case 1: // Space between currency-and-sign or currency and value.
5888 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005889 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005890 if (!symbol_contains_sep) {
5891 // We insert the space into the symbol instead of
5892 // setting pat.field[1]=space so that when
5893 // showbase is not set, the space goes away too.
5894 __curr_symbol_.push_back(space_char);
5895 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005896 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005897 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005898 pat.field[1] = value;
5899 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005900 if (symbol_contains_sep) {
5901 // Remove the separator from the symbol, since it
5902 // will appear before the sign.
5903 __curr_symbol_.pop_back();
5904 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005905 return;
5906 default:
5907 break;
5908 }
5909 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005910 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005911 pat.field[0] = sign;
5912 pat.field[3] = value;
5913 switch (sep_by_space)
5914 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005915 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005916 pat.field[1] = symbol;
5917 pat.field[2] = none;
5918 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005919 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005920 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005921 pat.field[2] = none;
5922 if (!symbol_contains_sep) {
5923 // We insert the space into the symbol instead of
5924 // setting pat.field[2]=space so that when
5925 // showbase is not set, the space goes away too.
5926 __curr_symbol_.push_back(space_char);
5927 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005928 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005930 pat.field[1] = space;
5931 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005932 if (symbol_contains_sep) {
5933 // Remove the separator from the symbol, since it
5934 // has already appeared after the sign.
5935 __curr_symbol_.pop_back();
5936 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005937 return;
5938 default:
5939 break;
5940 }
5941 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005942 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005943 pat.field[0] = symbol;
5944 pat.field[3] = value;
5945 switch (sep_by_space)
5946 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005947 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005948 pat.field[1] = sign;
5949 pat.field[2] = none;
5950 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005951 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005952 pat.field[1] = sign;
5953 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005954 if (symbol_contains_sep) {
5955 // Remove the separator from the symbol, since it
5956 // should not disappear when showbase is absent.
5957 __curr_symbol_.pop_back();
5958 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005959 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005960 case 2: // Space between sign and currency or value.
5961 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005962 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005963 if (!symbol_contains_sep) {
5964 // We insert the space into the symbol instead of
5965 // setting pat.field[1]=space so that when
5966 // showbase is not set, the space goes away too.
5967 __curr_symbol_.push_back(space_char);
5968 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 return;
5970 default:
5971 break;
5972 }
5973 break;
5974 default:
5975 break;
5976 }
5977 break;
5978 default:
5979 break;
5980 }
5981 pat.field[0] = symbol;
5982 pat.field[1] = sign;
5983 pat.field[2] = none;
5984 pat.field[3] = value;
5985}
5986
5987template<>
5988void
5989moneypunct_byname<char, false>::init(const char* nm)
5990{
5991 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005992 __libcpp_unique_locale loc(nm);
5993 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005994 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005995 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005996
Ben Craig3756b922016-03-09 15:39:39 +00005997 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005998 if (!checked_string_to_char_convert(__decimal_point_,
5999 lc->mon_decimal_point,
6000 loc.get()))
6001 __decimal_point_ = base::do_decimal_point();
6002 if (!checked_string_to_char_convert(__thousands_sep_,
6003 lc->mon_thousands_sep,
6004 loc.get()))
6005 __thousands_sep_ = base::do_thousands_sep();
6006
Howard Hinnantc51e1022010-05-11 19:42:16 +00006007 __grouping_ = lc->mon_grouping;
6008 __curr_symbol_ = lc->currency_symbol;
6009 if (lc->frac_digits != CHAR_MAX)
6010 __frac_digits_ = lc->frac_digits;
6011 else
6012 __frac_digits_ = base::do_frac_digits();
6013 if (lc->p_sign_posn == 0)
6014 __positive_sign_ = "()";
6015 else
6016 __positive_sign_ = lc->positive_sign;
6017 if (lc->n_sign_posn == 0)
6018 __negative_sign_ = "()";
6019 else
6020 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006021 // Assume the positive and negative formats will want spaces in
6022 // the same places in curr_symbol since there's no way to
6023 // represent anything else.
6024 string_type __dummy_curr_symbol = __curr_symbol_;
6025 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6026 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6027 __init_pat(__neg_format_, __curr_symbol_, false,
6028 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006029}
6030
6031template<>
6032void
6033moneypunct_byname<char, true>::init(const char* nm)
6034{
6035 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006036 __libcpp_unique_locale loc(nm);
6037 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006038 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006040
Ben Craig3756b922016-03-09 15:39:39 +00006041 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006042 if (!checked_string_to_char_convert(__decimal_point_,
6043 lc->mon_decimal_point,
6044 loc.get()))
6045 __decimal_point_ = base::do_decimal_point();
6046 if (!checked_string_to_char_convert(__thousands_sep_,
6047 lc->mon_thousands_sep,
6048 loc.get()))
6049 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006050 __grouping_ = lc->mon_grouping;
6051 __curr_symbol_ = lc->int_curr_symbol;
6052 if (lc->int_frac_digits != CHAR_MAX)
6053 __frac_digits_ = lc->int_frac_digits;
6054 else
6055 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006056#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006057 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006058#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006059 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006060#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006061 __positive_sign_ = "()";
6062 else
6063 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006064#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006065 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006066#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006067 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006068#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006069 __negative_sign_ = "()";
6070 else
6071 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006072 // Assume the positive and negative formats will want spaces in
6073 // the same places in curr_symbol since there's no way to
6074 // represent anything else.
6075 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006076#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006077 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6078 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6079 __init_pat(__neg_format_, __curr_symbol_, true,
6080 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006081#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006082 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6083 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6084 lc->int_p_sign_posn, ' ');
6085 __init_pat(__neg_format_, __curr_symbol_, true,
6086 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6087 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006088#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006089}
6090
6091template<>
6092void
6093moneypunct_byname<wchar_t, false>::init(const char* nm)
6094{
6095 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006096 __libcpp_unique_locale loc(nm);
6097 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006098 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006099 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006100 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006101 if (!checked_string_to_wchar_convert(__decimal_point_,
6102 lc->mon_decimal_point,
6103 loc.get()))
6104 __decimal_point_ = base::do_decimal_point();
6105 if (!checked_string_to_wchar_convert(__thousands_sep_,
6106 lc->mon_thousands_sep,
6107 loc.get()))
6108 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006109 __grouping_ = lc->mon_grouping;
6110 wchar_t wbuf[100];
6111 mbstate_t mb = {0};
6112 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006113 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006114 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006115 __throw_runtime_error("locale not supported");
6116 wchar_t* wbe = wbuf + j;
6117 __curr_symbol_.assign(wbuf, wbe);
6118 if (lc->frac_digits != CHAR_MAX)
6119 __frac_digits_ = lc->frac_digits;
6120 else
6121 __frac_digits_ = base::do_frac_digits();
6122 if (lc->p_sign_posn == 0)
6123 __positive_sign_ = L"()";
6124 else
6125 {
6126 mb = mbstate_t();
6127 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006128 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006129 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006130 __throw_runtime_error("locale not supported");
6131 wbe = wbuf + j;
6132 __positive_sign_.assign(wbuf, wbe);
6133 }
6134 if (lc->n_sign_posn == 0)
6135 __negative_sign_ = L"()";
6136 else
6137 {
6138 mb = mbstate_t();
6139 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006140 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006141 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006142 __throw_runtime_error("locale not supported");
6143 wbe = wbuf + j;
6144 __negative_sign_.assign(wbuf, wbe);
6145 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006146 // Assume the positive and negative formats will want spaces in
6147 // the same places in curr_symbol since there's no way to
6148 // represent anything else.
6149 string_type __dummy_curr_symbol = __curr_symbol_;
6150 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6151 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6152 __init_pat(__neg_format_, __curr_symbol_, false,
6153 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006154}
6155
6156template<>
6157void
6158moneypunct_byname<wchar_t, true>::init(const char* nm)
6159{
6160 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006161 __libcpp_unique_locale loc(nm);
6162 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006163 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006164 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006165
Ben Craig3756b922016-03-09 15:39:39 +00006166 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006167 if (!checked_string_to_wchar_convert(__decimal_point_,
6168 lc->mon_decimal_point,
6169 loc.get()))
6170 __decimal_point_ = base::do_decimal_point();
6171 if (!checked_string_to_wchar_convert(__thousands_sep_,
6172 lc->mon_thousands_sep,
6173 loc.get()))
6174 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006175 __grouping_ = lc->mon_grouping;
6176 wchar_t wbuf[100];
6177 mbstate_t mb = {0};
6178 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006179 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006180 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006181 __throw_runtime_error("locale not supported");
6182 wchar_t* wbe = wbuf + j;
6183 __curr_symbol_.assign(wbuf, wbe);
6184 if (lc->int_frac_digits != CHAR_MAX)
6185 __frac_digits_ = lc->int_frac_digits;
6186 else
6187 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006188#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006189 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006190#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006191 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006192#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006193 __positive_sign_ = L"()";
6194 else
6195 {
6196 mb = mbstate_t();
6197 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006198 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006199 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006200 __throw_runtime_error("locale not supported");
6201 wbe = wbuf + j;
6202 __positive_sign_.assign(wbuf, wbe);
6203 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006204#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006205 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006206#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006207 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006208#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006209 __negative_sign_ = L"()";
6210 else
6211 {
6212 mb = mbstate_t();
6213 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006214 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006215 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006216 __throw_runtime_error("locale not supported");
6217 wbe = wbuf + j;
6218 __negative_sign_.assign(wbuf, wbe);
6219 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006220 // Assume the positive and negative formats will want spaces in
6221 // the same places in curr_symbol since there's no way to
6222 // represent anything else.
6223 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006224#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006225 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6226 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6227 __init_pat(__neg_format_, __curr_symbol_, true,
6228 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006229#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006230 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6231 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6232 lc->int_p_sign_posn, L' ');
6233 __init_pat(__neg_format_, __curr_symbol_, true,
6234 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6235 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006236#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006237}
6238
6239void __do_nothing(void*) {}
6240
6241void __throw_runtime_error(const char* msg)
6242{
Howard Hinnant72f73582010-08-11 17:04:31 +00006243#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006244 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006245#else
6246 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006247 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006248#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006249}
6250
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006251template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6252template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006253
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006254template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6255template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006256
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006257template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6258template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006259
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006260template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6261template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006262
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006263template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6264template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006265
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006266template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6267template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006268
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006269template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6270template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006271
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006272template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6273template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006274
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006275template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6276template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006277
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006278template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6279template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6280template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6281template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006282
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006283template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6284template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6285template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6286template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006287
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006288template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6289template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006290
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006291template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6292template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006293
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006294template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6295template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006296
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006297template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6298template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006299
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006300template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6301template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006302
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006303template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6304template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006305
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006306template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6307template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
Reid Klecknerbc2a2ce2021-01-15 08:56:34 -08006308template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6309template 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 -04006310#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006311template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6312template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6313#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006314
Howard Hinnantc51e1022010-05-11 19:42:16 +00006315_LIBCPP_END_NAMESPACE_STD