blob: 79650963d57473513570b30aed03385c716f05b4 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Chandler Carruthd2012102019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantc51e1022010-05-11 19:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
David Chisnall8074c342012-02-29 13:05:08 +00009// On Solaris, we need to define something to make the C99 parts of localeconv
10// visible.
11#ifdef __sun__
12#define _LCONV_C99
13#endif
14
Howard Hinnantc51e1022010-05-11 19:42:16 +000015#include "string"
16#include "locale"
Howard Hinnant7282c5a2010-05-30 21:39:41 +000017#include "codecvt"
Howard Hinnantc51e1022010-05-11 19:42:16 +000018#include "vector"
19#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000020#include "typeinfo"
Howard Hinnant718dae32013-07-28 18:20:00 +000021#ifndef _LIBCPP_NO_EXCEPTIONS
22# include "type_traits"
23#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000024#include "clocale"
25#include "cstring"
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +000026#if defined(_LIBCPP_MSVCRT)
27#define _CTYPE_DISABLE_MACROS
28#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000029#include "cwctype"
Howard Hinnant8ad70912013-09-17 01:34:47 +000030#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Louis Dionne90a04492021-02-02 16:58:38 -050031#include "__support/win32/locale_win32.h"
Xiang Xiao85529232020-11-18 16:16:18 -050032#elif !defined(__BIONIC__) && !defined(__NuttX__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000033#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000034#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000035#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000036#include <stdio.h>
Weiming Zhaob613db72017-09-19 23:18:03 +000037#include "include/atomic_support.h"
Arthur O'Dwyerf5c4bb02021-04-26 09:56:50 -040038#include "include/sso_allocator.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000039#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000040
Marshall Clowab9c1772013-02-07 17:20:56 +000041// On Linux, wint_t and wchar_t have different signed-ness, and this causes
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -070042// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000043#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000044#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000045#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000046
Howard Hinnantc51e1022010-05-11 19:42:16 +000047_LIBCPP_BEGIN_NAMESPACE_STD
48
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000049struct __libcpp_unique_locale {
50 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
51
52 ~__libcpp_unique_locale() {
53 if (__loc_)
54 freelocale(__loc_);
55 }
56
57 explicit operator bool() const { return __loc_; }
58
59 locale_t& get() { return __loc_; }
60
61 locale_t __loc_;
62private:
63 __libcpp_unique_locale(__libcpp_unique_locale const&);
64 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
65};
66
Howard Hinnantf312e3e2011-09-28 23:39:33 +000067#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000068locale_t __cloc() {
69 // In theory this could create a race condition. In practice
70 // the race condition is non-fatal since it will just create
71 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000072 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
73 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000074}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000075#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000076
Howard Hinnantc51e1022010-05-11 19:42:16 +000077namespace {
78
79struct release
80{
81 void operator()(locale::facet* p) {p->__release_shared();}
82};
83
Louis Dionne6e41a152021-08-09 13:26:04 -040084template <class T, class ...Args>
85T& make(Args ...args)
Howard Hinnantc51e1022010-05-11 19:42:16 +000086{
87 static typename aligned_storage<sizeof(T)>::type buf;
Louis Dionne6e41a152021-08-09 13:26:04 -040088 auto *obj = ::new (&buf) T(args...);
Eric Fiselier4db80032017-05-05 20:32:26 +000089 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000090}
91
Howard Hinnant3d2417c2012-12-27 21:17:53 +000092template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +000093inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +000094_LIBCPP_CONSTEXPR
95size_t
96countof(const T (&)[N])
97{
98 return N;
99}
100
101template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000102inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000103_LIBCPP_CONSTEXPR
104size_t
105countof(const T * const begin, const T * const end)
106{
107 return static_cast<size_t>(end - begin);
108}
109
Marshall Clow8fea1612016-08-25 15:09:01 +0000110_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
111{
112#ifndef _LIBCPP_NO_EXCEPTIONS
113 throw runtime_error(msg);
114#else
115 (void)msg;
116 _VSTD::abort();
117#endif
118}
119
Howard Hinnantc51e1022010-05-11 19:42:16 +0000120}
121
Howard Hinnantdd099492013-08-29 23:37:50 +0000122#if defined(_AIX)
123// Set priority to INT_MIN + 256 + 150
124# pragma priority ( -2147483242 )
125#endif
126
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000127const locale::category locale::none;
128const locale::category locale::collate;
129const locale::category locale::ctype;
130const locale::category locale::monetary;
131const locale::category locale::numeric;
132const locale::category locale::time;
133const locale::category locale::messages;
134const locale::category locale::all;
135
Howard Hinnantc51e1022010-05-11 19:42:16 +0000136class _LIBCPP_HIDDEN locale::__imp
137 : public facet
138{
Marek Kurdej718b62c2020-12-02 08:57:02 +0100139 enum {N = 30};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000140#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000141// FIXME: MSVC doesn't support aligned parameters by value.
142// I can't get the __sso_allocator to work here
143// for MSVC I think for this reason.
144 vector<facet*> facets_;
145#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000146 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000147#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000148 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000149public:
150 explicit __imp(size_t refs = 0);
151 explicit __imp(const string& name, size_t refs = 0);
152 __imp(const __imp&);
153 __imp(const __imp&, const string&, locale::category c);
154 __imp(const __imp& other, const __imp& one, locale::category c);
155 __imp(const __imp&, facet* f, long id);
156 ~__imp();
157
158 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000159 bool has_facet(long id) const
160 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000161 const locale::facet* use_facet(long id) const;
162
163 static const locale& make_classic();
164 static locale& make_global();
165private:
166 void install(facet* f, long id);
167 template <class F> void install(F* f) {install(f, f->id.__get());}
168 template <class F> void install_from(const __imp& other);
169};
170
171locale::__imp::__imp(size_t refs)
172 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000173 facets_(N),
174 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000175{
176 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000177 install(&make<_VSTD::collate<char> >(1u));
178 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000179 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000180 install(&make<_VSTD::ctype<wchar_t> >(1u));
181 install(&make<codecvt<char, char, mbstate_t> >(1u));
182 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100183_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnant28b24882011-12-01 20:21:04 +0000184 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
185 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100186_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400187#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100188 install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u));
189 install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u));
190#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000191 install(&make<numpunct<char> >(1u));
192 install(&make<numpunct<wchar_t> >(1u));
193 install(&make<num_get<char> >(1u));
194 install(&make<num_get<wchar_t> >(1u));
195 install(&make<num_put<char> >(1u));
196 install(&make<num_put<wchar_t> >(1u));
197 install(&make<moneypunct<char, false> >(1u));
198 install(&make<moneypunct<char, true> >(1u));
199 install(&make<moneypunct<wchar_t, false> >(1u));
200 install(&make<moneypunct<wchar_t, true> >(1u));
201 install(&make<money_get<char> >(1u));
202 install(&make<money_get<wchar_t> >(1u));
203 install(&make<money_put<char> >(1u));
204 install(&make<money_put<wchar_t> >(1u));
205 install(&make<time_get<char> >(1u));
206 install(&make<time_get<wchar_t> >(1u));
207 install(&make<time_put<char> >(1u));
208 install(&make<time_put<wchar_t> >(1u));
209 install(&make<_VSTD::messages<char> >(1u));
210 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000211}
212
213locale::__imp::__imp(const string& name, size_t refs)
214 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000215 facets_(N),
216 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000217{
Howard Hinnant72f73582010-08-11 17:04:31 +0000218#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000219 try
220 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400221#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000222 facets_ = locale::classic().__locale_->facets_;
223 for (unsigned i = 0; i < facets_.size(); ++i)
224 if (facets_[i])
225 facets_[i]->__add_shared();
226 install(new collate_byname<char>(name_));
227 install(new collate_byname<wchar_t>(name_));
228 install(new ctype_byname<char>(name_));
229 install(new ctype_byname<wchar_t>(name_));
230 install(new codecvt_byname<char, char, mbstate_t>(name_));
231 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100232_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
234 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100235_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400236#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100237 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_));
238 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_));
239#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000240 install(new numpunct_byname<char>(name_));
241 install(new numpunct_byname<wchar_t>(name_));
242 install(new moneypunct_byname<char, false>(name_));
243 install(new moneypunct_byname<char, true>(name_));
244 install(new moneypunct_byname<wchar_t, false>(name_));
245 install(new moneypunct_byname<wchar_t, true>(name_));
246 install(new time_get_byname<char>(name_));
247 install(new time_get_byname<wchar_t>(name_));
248 install(new time_put_byname<char>(name_));
249 install(new time_put_byname<wchar_t>(name_));
250 install(new messages_byname<char>(name_));
251 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000252#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000253 }
254 catch (...)
255 {
256 for (unsigned i = 0; i < facets_.size(); ++i)
257 if (facets_[i])
258 facets_[i]->__release_shared();
259 throw;
260 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400261#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262}
263
264locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000265 : facets_(max<size_t>(N, other.facets_.size())),
266 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000267{
268 facets_ = other.facets_;
269 for (unsigned i = 0; i < facets_.size(); ++i)
270 if (facets_[i])
271 facets_[i]->__add_shared();
272}
273
274locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000275 : facets_(N),
276 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000277{
278 facets_ = other.facets_;
279 for (unsigned i = 0; i < facets_.size(); ++i)
280 if (facets_[i])
281 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000282#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000283 try
284 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400285#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000286 if (c & locale::collate)
287 {
288 install(new collate_byname<char>(name));
289 install(new collate_byname<wchar_t>(name));
290 }
291 if (c & locale::ctype)
292 {
293 install(new ctype_byname<char>(name));
294 install(new ctype_byname<wchar_t>(name));
295 install(new codecvt_byname<char, char, mbstate_t>(name));
296 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100297_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000298 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
299 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100300_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400301#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100302 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
303 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
304#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000305 }
306 if (c & locale::monetary)
307 {
308 install(new moneypunct_byname<char, false>(name));
309 install(new moneypunct_byname<char, true>(name));
310 install(new moneypunct_byname<wchar_t, false>(name));
311 install(new moneypunct_byname<wchar_t, true>(name));
312 }
313 if (c & locale::numeric)
314 {
315 install(new numpunct_byname<char>(name));
316 install(new numpunct_byname<wchar_t>(name));
317 }
318 if (c & locale::time)
319 {
320 install(new time_get_byname<char>(name));
321 install(new time_get_byname<wchar_t>(name));
322 install(new time_put_byname<char>(name));
323 install(new time_put_byname<wchar_t>(name));
324 }
325 if (c & locale::messages)
326 {
327 install(new messages_byname<char>(name));
328 install(new messages_byname<wchar_t>(name));
329 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000330#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000331 }
332 catch (...)
333 {
334 for (unsigned i = 0; i < facets_.size(); ++i)
335 if (facets_[i])
336 facets_[i]->__release_shared();
337 throw;
338 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400339#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000340}
341
342template<class F>
343inline
344void
345locale::__imp::install_from(const locale::__imp& one)
346{
347 long id = F::id.__get();
348 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
349}
350
351locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000352 : facets_(N),
353 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000354{
355 facets_ = other.facets_;
356 for (unsigned i = 0; i < facets_.size(); ++i)
357 if (facets_[i])
358 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000359#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000360 try
361 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400362#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000363 if (c & locale::collate)
364 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000365 install_from<_VSTD::collate<char> >(one);
366 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000367 }
368 if (c & locale::ctype)
369 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000370 install_from<_VSTD::ctype<char> >(one);
371 install_from<_VSTD::ctype<wchar_t> >(one);
372 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100373_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000374 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
375 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100376_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400377#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100378 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
379 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
380#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000381 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000382 }
383 if (c & locale::monetary)
384 {
385 install_from<moneypunct<char, false> >(one);
386 install_from<moneypunct<char, true> >(one);
387 install_from<moneypunct<wchar_t, false> >(one);
388 install_from<moneypunct<wchar_t, true> >(one);
389 install_from<money_get<char> >(one);
390 install_from<money_get<wchar_t> >(one);
391 install_from<money_put<char> >(one);
392 install_from<money_put<wchar_t> >(one);
393 }
394 if (c & locale::numeric)
395 {
396 install_from<numpunct<char> >(one);
397 install_from<numpunct<wchar_t> >(one);
398 install_from<num_get<char> >(one);
399 install_from<num_get<wchar_t> >(one);
400 install_from<num_put<char> >(one);
401 install_from<num_put<wchar_t> >(one);
402 }
403 if (c & locale::time)
404 {
405 install_from<time_get<char> >(one);
406 install_from<time_get<wchar_t> >(one);
407 install_from<time_put<char> >(one);
408 install_from<time_put<wchar_t> >(one);
409 }
410 if (c & locale::messages)
411 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000412 install_from<_VSTD::messages<char> >(one);
413 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000414 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000415#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000416 }
417 catch (...)
418 {
419 for (unsigned i = 0; i < facets_.size(); ++i)
420 if (facets_[i])
421 facets_[i]->__release_shared();
422 throw;
423 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400424#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000425}
426
427locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000428 : facets_(max<size_t>(N, other.facets_.size()+1)),
429 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000430{
431 f->__add_shared();
432 unique_ptr<facet, release> hold(f);
433 facets_ = other.facets_;
434 for (unsigned i = 0; i < other.facets_.size(); ++i)
435 if (facets_[i])
436 facets_[i]->__add_shared();
437 install(hold.get(), id);
438}
439
440locale::__imp::~__imp()
441{
442 for (unsigned i = 0; i < facets_.size(); ++i)
443 if (facets_[i])
444 facets_[i]->__release_shared();
445}
446
447void
448locale::__imp::install(facet* f, long id)
449{
450 f->__add_shared();
451 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000452 if (static_cast<size_t>(id) >= facets_.size())
453 facets_.resize(static_cast<size_t>(id+1));
454 if (facets_[static_cast<size_t>(id)])
455 facets_[static_cast<size_t>(id)]->__release_shared();
456 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000457}
458
459const locale::facet*
460locale::__imp::use_facet(long id) const
461{
462 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000463 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000464 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000465}
466
467// locale
468
469const locale&
470locale::__imp::make_classic()
471{
472 // only one thread can get in here and it only gets in once
473 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000474 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000475 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000476 return *c;
477}
478
479const locale&
480locale::classic()
481{
482 static const locale& c = __imp::make_classic();
483 return c;
484}
485
486locale&
487locale::__imp::make_global()
488{
489 // only one thread can get in here and it only gets in once
490 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000491 auto *obj = ::new (&buf) locale(locale::classic());
492 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000493}
494
495locale&
496locale::__global()
497{
498 static locale& g = __imp::make_global();
499 return g;
500}
501
Louis Dionne65358e12021-03-01 12:09:45 -0500502locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000503 : __locale_(__global().__locale_)
504{
505 __locale_->__add_shared();
506}
507
Louis Dionne65358e12021-03-01 12:09:45 -0500508locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509 : __locale_(l.__locale_)
510{
511 __locale_->__add_shared();
512}
513
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000514locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000515{
516 __locale_->__release_shared();
517}
518
519const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500520locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000521{
522 other.__locale_->__add_shared();
523 __locale_->__release_shared();
524 __locale_ = other.__locale_;
525 return *this;
526}
527
528locale::locale(const char* name)
529 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100530 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000531{
532 __locale_->__add_shared();
533}
534
535locale::locale(const string& name)
536 : __locale_(new __imp(name))
537{
538 __locale_->__add_shared();
539}
540
541locale::locale(const locale& other, const char* name, category c)
542 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100543 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000544{
545 __locale_->__add_shared();
546}
547
548locale::locale(const locale& other, const string& name, category c)
549 : __locale_(new __imp(*other.__locale_, name, c))
550{
551 __locale_->__add_shared();
552}
553
554locale::locale(const locale& other, const locale& one, category c)
555 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
556{
557 __locale_->__add_shared();
558}
559
560string
561locale::name() const
562{
563 return __locale_->name();
564}
565
566void
567locale::__install_ctor(const locale& other, facet* f, long id)
568{
569 if (f)
570 __locale_ = new __imp(*other.__locale_, f, id);
571 else
572 __locale_ = other.__locale_;
573 __locale_->__add_shared();
574}
575
576locale
577locale::global(const locale& loc)
578{
579 locale& g = __global();
580 locale r = g;
581 g = loc;
582 if (g.name() != "*")
583 setlocale(LC_ALL, g.name().c_str());
584 return r;
585}
586
587bool
588locale::has_facet(id& x) const
589{
590 return __locale_->has_facet(x.__get());
591}
592
593const locale::facet*
594locale::use_facet(id& x) const
595{
596 return __locale_->use_facet(x.__get());
597}
598
599bool
600locale::operator==(const locale& y) const
601{
602 return (__locale_ == y.__locale_)
603 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
604}
605
606// locale::facet
607
608locale::facet::~facet()
609{
610}
611
612void
Louis Dionne65358e12021-03-01 12:09:45 -0500613locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000614{
615 delete this;
616}
617
618// locale::id
619
620int32_t locale::id::__next_id = 0;
621
622namespace
623{
624
625class __fake_bind
626{
627 locale::id* id_;
628 void (locale::id::* pmf_)();
629public:
630 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
631 : id_(id), pmf_(pmf) {}
632
633 void operator()() const
634 {
635 (id_->*pmf_)();
636 }
637};
638
639}
640
641long
642locale::id::__get()
643{
644 call_once(__flag_, __fake_bind(&locale::id::__init, this));
645 return __id_ - 1;
646}
647
648void
649locale::id::__init()
650{
Weiming Zhaob613db72017-09-19 23:18:03 +0000651 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000652}
653
654// template <> class collate_byname<char>
655
656collate_byname<char>::collate_byname(const char* n, size_t refs)
657 : collate<char>(refs),
658 __l(newlocale(LC_ALL_MASK, n, 0))
659{
660 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000661 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000662 " failed to construct for " + string(n));
663}
664
665collate_byname<char>::collate_byname(const string& name, size_t refs)
666 : collate<char>(refs),
667 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
668{
669 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000670 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000671 " failed to construct for " + name);
672}
673
674collate_byname<char>::~collate_byname()
675{
676 freelocale(__l);
677}
678
679int
680collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
681 const char_type* __lo2, const char_type* __hi2) const
682{
683 string_type lhs(__lo1, __hi1);
684 string_type rhs(__lo2, __hi2);
685 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
686 if (r < 0)
687 return -1;
688 if (r > 0)
689 return 1;
690 return r;
691}
692
693collate_byname<char>::string_type
694collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
695{
696 const string_type in(lo, hi);
697 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
698 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
699 return out;
700}
701
702// template <> class collate_byname<wchar_t>
703
704collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
705 : collate<wchar_t>(refs),
706 __l(newlocale(LC_ALL_MASK, n, 0))
707{
708 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000709 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000710 " failed to construct for " + string(n));
711}
712
713collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
714 : collate<wchar_t>(refs),
715 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
716{
717 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000718 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000719 " failed to construct for " + name);
720}
721
722collate_byname<wchar_t>::~collate_byname()
723{
724 freelocale(__l);
725}
726
727int
728collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
729 const char_type* __lo2, const char_type* __hi2) const
730{
731 string_type lhs(__lo1, __hi1);
732 string_type rhs(__lo2, __hi2);
733 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
734 if (r < 0)
735 return -1;
736 if (r > 0)
737 return 1;
738 return r;
739}
740
741collate_byname<wchar_t>::string_type
742collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
743{
744 const string_type in(lo, hi);
745 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
746 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
747 return out;
748}
749
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000750const ctype_base::mask ctype_base::space;
751const ctype_base::mask ctype_base::print;
752const ctype_base::mask ctype_base::cntrl;
753const ctype_base::mask ctype_base::upper;
754const ctype_base::mask ctype_base::lower;
755const ctype_base::mask ctype_base::alpha;
756const ctype_base::mask ctype_base::digit;
757const ctype_base::mask ctype_base::punct;
758const ctype_base::mask ctype_base::xdigit;
759const ctype_base::mask ctype_base::blank;
760const ctype_base::mask ctype_base::alnum;
761const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700762
Louis Dionne945f8682021-09-09 13:29:24 -0400763// template <> class ctype<wchar_t>;
764
Howard Hinnantc51e1022010-05-11 19:42:16 +0000765locale::id ctype<wchar_t>::id;
766
767ctype<wchar_t>::~ctype()
768{
769}
770
771bool
772ctype<wchar_t>::do_is(mask m, char_type c) const
773{
Marshall Clowd920eea2013-10-21 15:07:28 +0000774 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000775}
776
777const wchar_t*
778ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
779{
780 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000781 *vec = static_cast<mask>(isascii(*low) ?
782 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000783 return low;
784}
785
786const wchar_t*
787ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
788{
789 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000790 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000791 break;
792 return low;
793}
794
795const wchar_t*
796ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
797{
798 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000799 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000800 break;
801 return low;
802}
803
804wchar_t
805ctype<wchar_t>::do_toupper(char_type c) const
806{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000807#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
808 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000809#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000810 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000811 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000812#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000813 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000814#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000815}
816
817const wchar_t*
818ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
819{
820 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000821#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
822 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000823#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000824 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000825 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
826 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000827#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000828 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000829#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000830 return low;
831}
832
833wchar_t
834ctype<wchar_t>::do_tolower(char_type c) const
835{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000836#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
837 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000838#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000839 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000840 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000841#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000842 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000843#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000844}
845
846const wchar_t*
847ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
848{
849 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000850#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
851 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000852#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000853 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000854 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
855 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000856#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000857 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000858#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000859 return low;
860}
861
862wchar_t
863ctype<wchar_t>::do_widen(char c) const
864{
865 return c;
866}
867
868const char*
869ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
870{
871 for (; low != high; ++low, ++dest)
872 *dest = *low;
873 return low;
874}
875
876char
877ctype<wchar_t>::do_narrow(char_type c, char dfault) const
878{
879 if (isascii(c))
880 return static_cast<char>(c);
881 return dfault;
882}
883
884const wchar_t*
885ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
886{
887 for (; low != high; ++low, ++dest)
888 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000889 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890 else
891 *dest = dfault;
892 return low;
893}
894
895// template <> class ctype<char>;
896
897locale::id ctype<char>::id;
898
899ctype<char>::ctype(const mask* tab, bool del, size_t refs)
900 : locale::facet(refs),
901 __tab_(tab),
902 __del_(del)
903{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000904 if (__tab_ == 0)
905 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000906}
907
908ctype<char>::~ctype()
909{
910 if (__tab_ && __del_)
911 delete [] __tab_;
912}
913
914char
915ctype<char>::do_toupper(char_type c) const
916{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000917#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000918 return isascii(c) ?
919 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000920#elif defined(__NetBSD__)
921 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000922#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000923 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000924 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000925#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000926 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000927#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000928}
929
930const char*
931ctype<char>::do_toupper(char_type* low, const char_type* high) const
932{
933 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000934#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000935 *low = isascii(*low) ?
936 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000937#elif defined(__NetBSD__)
938 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000939#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000940 *low = isascii(*low) ?
941 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000942#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000943 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000944#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000945 return low;
946}
947
948char
949ctype<char>::do_tolower(char_type c) const
950{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000951#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000952 return isascii(c) ?
953 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000954#elif defined(__NetBSD__)
955 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000956#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000957 return isascii(c) ?
958 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000959#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000960 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000961#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000962}
963
964const char*
965ctype<char>::do_tolower(char_type* low, const char_type* high) const
966{
967 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000968#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000969 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000970#elif defined(__NetBSD__)
971 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000972#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000973 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000974#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000975 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000976#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000977 return low;
978}
979
980char
981ctype<char>::do_widen(char c) const
982{
983 return c;
984}
985
986const char*
987ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
988{
989 for (; low != high; ++low, ++dest)
990 *dest = *low;
991 return low;
992}
993
994char
995ctype<char>::do_narrow(char_type c, char dfault) const
996{
997 if (isascii(c))
998 return static_cast<char>(c);
999 return dfault;
1000}
1001
1002const char*
1003ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1004{
1005 for (; low != high; ++low, ++dest)
1006 if (isascii(*low))
1007 *dest = *low;
1008 else
1009 *dest = dfault;
1010 return low;
1011}
1012
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001013#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001014extern "C" const unsigned short ** __ctype_b_loc();
1015extern "C" const int ** __ctype_tolower_loc();
1016extern "C" const int ** __ctype_toupper_loc();
1017#endif
1018
Marshall Clow8f870232015-03-04 16:50:02 +00001019#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001020const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001021ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001022{
1023 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1024 cntrl, cntrl,
1025 cntrl, cntrl,
1026 cntrl, cntrl,
1027 cntrl, cntrl,
1028 cntrl, cntrl | space | blank,
1029 cntrl | space, cntrl | space,
1030 cntrl | space, cntrl | space,
1031 cntrl, cntrl,
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 space | blank | print, punct | print,
1041 punct | 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 digit | print | xdigit, digit | print | xdigit,
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 punct | print, punct | print,
1054 punct | print, punct | print,
1055 punct | print, punct | print,
1056 punct | print, upper | xdigit | print | alpha,
1057 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1058 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1059 upper | xdigit | print | alpha, upper | print | alpha,
1060 upper | 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, punct | print,
1070 punct | print, punct | print,
1071 punct | print, punct | print,
1072 punct | print, lower | xdigit | print | alpha,
1073 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1074 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1075 lower | xdigit | print | alpha, lower | print | alpha,
1076 lower | 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, punct | print,
1086 punct | print, punct | print,
1087 punct | print, cntrl,
1088 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 };
1097 return builtin_table;
1098}
1099#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001100const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001101ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001102{
David Chisnall1d581062011-09-21 08:39:44 +00001103#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001104 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001105#elif defined(__NetBSD__)
1106 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001107#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001108 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001109#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001110 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001111#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001112 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001113#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001114 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001115#elif defined(_NEWLIB_VERSION)
1116 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1117 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001118#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001119 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001120#else
David Chisnall8074c342012-02-29 13:05:08 +00001121 // Platform not supported: abort so the person doing the port knows what to
1122 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001123# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001124 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001125 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001126 return NULL;
1127#endif
1128}
Marshall Clowb3f62842015-03-04 16:10:14 +00001129#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001130
Howard Hinnantd7a78632011-09-29 13:33:15 +00001131#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001132const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001133ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001134{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001135 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001136}
1137
1138const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001139ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001140{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001141 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001142}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001143#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001144const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001145ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001146{
1147 return _C_tolower_tab_ + 1;
1148}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001149
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001150const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001151ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001152{
1153 return _C_toupper_tab_ + 1;
1154}
1155
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001156#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001157const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001158ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001159{
1160 return *__ctype_tolower_loc();
1161}
1162
1163const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001164ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001165{
1166 return *__ctype_toupper_loc();
1167}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001168#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001169
Howard Hinnantc51e1022010-05-11 19:42:16 +00001170// template <> class ctype_byname<char>
1171
1172ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1173 : ctype<char>(0, false, refs),
1174 __l(newlocale(LC_ALL_MASK, name, 0))
1175{
1176 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001177 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001178 " failed to construct for " + string(name));
1179}
1180
1181ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1182 : ctype<char>(0, false, refs),
1183 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1184{
1185 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001186 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001187 " failed to construct for " + name);
1188}
1189
1190ctype_byname<char>::~ctype_byname()
1191{
1192 freelocale(__l);
1193}
1194
1195char
1196ctype_byname<char>::do_toupper(char_type c) const
1197{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001198 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001199}
1200
1201const char*
1202ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1203{
1204 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001205 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001206 return low;
1207}
1208
1209char
1210ctype_byname<char>::do_tolower(char_type c) const
1211{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001212 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001213}
1214
1215const char*
1216ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1217{
1218 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001219 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001220 return low;
1221}
1222
1223// template <> class ctype_byname<wchar_t>
1224
1225ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1226 : ctype<wchar_t>(refs),
1227 __l(newlocale(LC_ALL_MASK, name, 0))
1228{
1229 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001230 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001231 " failed to construct for " + string(name));
1232}
1233
1234ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1235 : ctype<wchar_t>(refs),
1236 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1237{
1238 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001239 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001240 " failed to construct for " + name);
1241}
1242
1243ctype_byname<wchar_t>::~ctype_byname()
1244{
1245 freelocale(__l);
1246}
1247
1248bool
1249ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1250{
Alexis Huntc2017f12011-07-09 03:40:04 +00001251#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001252 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001253#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001254 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001255 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001256 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1257 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1258 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1259 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1260 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1261 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1262 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1263 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1264 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1265 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001266 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001267#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001268}
1269
1270const wchar_t*
1271ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1272{
1273 for (; low != high; ++low, ++vec)
1274 {
1275 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001276 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001277 else
1278 {
1279 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001280 wint_t ch = static_cast<wint_t>(*low);
1281 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001282 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001283#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001284 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001285 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001286#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001287 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001288 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001289 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001290 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001291 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001292 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001293#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001294 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001295 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001296#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001297 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001298 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001299 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001301#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001302 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001303 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001304#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001305#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001306 if (iswblank_l(ch, __l))
1307 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001308#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001309 }
1310 }
1311 return low;
1312}
1313
1314const wchar_t*
1315ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1316{
1317 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001318 {
1319#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001320 if (iswctype_l(*low, m, __l))
1321 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001322#else
Marshall Clowada0f732013-02-07 14:22:51 +00001323 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001324 if ((m & space) == space && iswspace_l(ch, __l)) break;
1325 if ((m & print) == print && iswprint_l(ch, __l)) break;
1326 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1327 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1328 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1329 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1330 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1331 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1332 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1333 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001334#endif
1335 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001336 return low;
1337}
1338
1339const wchar_t*
1340ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1341{
1342 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001343 {
1344#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345 if (!iswctype_l(*low, m, __l))
1346 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001347#else
Marshall Clowada0f732013-02-07 14:22:51 +00001348 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001349 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1350 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1351 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1352 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1353 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1354 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1355 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1356 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1357 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1358 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001359 break;
1360#endif
1361 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001362 return low;
1363}
1364
1365wchar_t
1366ctype_byname<wchar_t>::do_toupper(char_type c) const
1367{
1368 return towupper_l(c, __l);
1369}
1370
1371const wchar_t*
1372ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1373{
1374 for (; low != high; ++low)
1375 *low = towupper_l(*low, __l);
1376 return low;
1377}
1378
1379wchar_t
1380ctype_byname<wchar_t>::do_tolower(char_type c) const
1381{
1382 return towlower_l(c, __l);
1383}
1384
1385const wchar_t*
1386ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1387{
1388 for (; low != high; ++low)
1389 *low = towlower_l(*low, __l);
1390 return low;
1391}
1392
1393wchar_t
1394ctype_byname<wchar_t>::do_widen(char c) const
1395{
Ben Craig3756b922016-03-09 15:39:39 +00001396 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001397}
1398
1399const char*
1400ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1401{
1402 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001403 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404 return low;
1405}
1406
1407char
1408ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1409{
Ben Craig3756b922016-03-09 15:39:39 +00001410 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001411 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001412}
1413
1414const wchar_t*
1415ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1416{
1417 for (; low != high; ++low, ++dest)
1418 {
Ben Craig3756b922016-03-09 15:39:39 +00001419 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001420 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001421 }
1422 return low;
1423}
1424
1425// template <> class codecvt<char, char, mbstate_t>
1426
Howard Hinnantffb308e2010-08-22 00:03:27 +00001427locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001428
1429codecvt<char, char, mbstate_t>::~codecvt()
1430{
1431}
1432
1433codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001434codecvt<char, char, mbstate_t>::do_out(state_type&,
1435 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001436 extern_type* to, extern_type*, extern_type*& to_nxt) const
1437{
1438 frm_nxt = frm;
1439 to_nxt = to;
1440 return noconv;
1441}
1442
1443codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001444codecvt<char, char, mbstate_t>::do_in(state_type&,
1445 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001446 intern_type* to, intern_type*, intern_type*& to_nxt) const
1447{
1448 frm_nxt = frm;
1449 to_nxt = to;
1450 return noconv;
1451}
1452
1453codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001454codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001455 extern_type* to, extern_type*, extern_type*& to_nxt) const
1456{
1457 to_nxt = to;
1458 return noconv;
1459}
1460
1461int
Louis Dionne65358e12021-03-01 12:09:45 -05001462codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001463{
1464 return 1;
1465}
1466
1467bool
Louis Dionne65358e12021-03-01 12:09:45 -05001468codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001469{
1470 return true;
1471}
1472
1473int
1474codecvt<char, char, mbstate_t>::do_length(state_type&,
1475 const extern_type* frm, const extern_type* end, size_t mx) const
1476{
Howard Hinnant28b24882011-12-01 20:21:04 +00001477 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001478}
1479
1480int
Louis Dionne65358e12021-03-01 12:09:45 -05001481codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001482{
1483 return 1;
1484}
1485
1486// template <> class codecvt<wchar_t, char, mbstate_t>
1487
Howard Hinnantffb308e2010-08-22 00:03:27 +00001488locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001489
1490codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1491 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001492 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001493{
1494}
1495
1496codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1497 : locale::facet(refs),
1498 __l(newlocale(LC_ALL_MASK, nm, 0))
1499{
1500 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001501 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001502 " failed to construct for " + string(nm));
1503}
1504
1505codecvt<wchar_t, char, mbstate_t>::~codecvt()
1506{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001507 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001508 freelocale(__l);
1509}
1510
1511codecvt<wchar_t, char, mbstate_t>::result
1512codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001513 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001514 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1515{
1516 // look for first internal null in frm
1517 const intern_type* fend = frm;
1518 for (; fend != frm_end; ++fend)
1519 if (*fend == 0)
1520 break;
1521 // loop over all null-terminated sequences in frm
1522 to_nxt = to;
1523 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1524 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001525 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001527 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1528 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001529 if (n == size_t(-1))
1530 {
1531 // need to recover to_nxt
1532 for (to_nxt = to; frm != frm_nxt; ++frm)
1533 {
Ben Craig3756b922016-03-09 15:39:39 +00001534 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001535 if (n == size_t(-1))
1536 break;
1537 to_nxt += n;
1538 }
1539 frm_nxt = frm;
1540 return error;
1541 }
1542 if (n == 0)
1543 return partial;
1544 to_nxt += n;
1545 if (to_nxt == to_end)
1546 break;
1547 if (fend != frm_end) // set up next null terminated sequence
1548 {
1549 // Try to write the terminating null
1550 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001551 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001552 if (n == size_t(-1)) // on error
1553 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001554 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001555 return partial;
1556 for (extern_type* p = tmp; n; --n) // write it
1557 *to_nxt++ = *p++;
1558 ++frm_nxt;
1559 // look for next null in frm
1560 for (fend = frm_nxt; fend != frm_end; ++fend)
1561 if (*fend == 0)
1562 break;
1563 }
1564 }
1565 return frm_nxt == frm_end ? ok : partial;
1566}
1567
1568codecvt<wchar_t, char, mbstate_t>::result
1569codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001570 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001571 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1572{
1573 // look for first internal null in frm
1574 const extern_type* fend = frm;
1575 for (; fend != frm_end; ++fend)
1576 if (*fend == 0)
1577 break;
1578 // loop over all null-terminated sequences in frm
1579 to_nxt = to;
1580 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1581 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001582 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001583 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001584 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1585 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001586 if (n == size_t(-1))
1587 {
1588 // need to recover to_nxt
1589 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1590 {
Ben Craig3756b922016-03-09 15:39:39 +00001591 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1592 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001593 switch (n)
1594 {
1595 case 0:
1596 ++frm;
1597 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001598 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001599 frm_nxt = frm;
1600 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001601 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001602 frm_nxt = frm;
1603 return partial;
1604 default:
1605 frm += n;
1606 break;
1607 }
1608 }
1609 frm_nxt = frm;
1610 return frm_nxt == frm_end ? ok : partial;
1611 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001612 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001613 return error;
1614 to_nxt += n;
1615 if (to_nxt == to_end)
1616 break;
1617 if (fend != frm_end) // set up next null terminated sequence
1618 {
1619 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001620 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001621 if (n != 0) // on error
1622 return error;
1623 ++to_nxt;
1624 ++frm_nxt;
1625 // look for next null in frm
1626 for (fend = frm_nxt; fend != frm_end; ++fend)
1627 if (*fend == 0)
1628 break;
1629 }
1630 }
1631 return frm_nxt == frm_end ? ok : partial;
1632}
1633
1634codecvt<wchar_t, char, mbstate_t>::result
1635codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1636 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1637{
1638 to_nxt = to;
1639 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001640 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001641 if (n == size_t(-1) || n == 0) // on error
1642 return error;
1643 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001644 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001645 return partial;
1646 for (extern_type* p = tmp; n; --n) // write it
1647 *to_nxt++ = *p++;
1648 return ok;
1649}
1650
1651int
Louis Dionne65358e12021-03-01 12:09:45 -05001652codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001653{
Ben Craig3756b922016-03-09 15:39:39 +00001654 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001655 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001656
1657 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001658 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001659 return 1; // which take more than 1 char to form a wchar_t
1660 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001661}
1662
1663bool
Louis Dionne65358e12021-03-01 12:09:45 -05001664codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001665{
1666 return false;
1667}
1668
1669int
1670codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1671 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1672{
1673 int nbytes = 0;
1674 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1675 {
Ben Craig3756b922016-03-09 15:39:39 +00001676 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001677 switch (n)
1678 {
1679 case 0:
1680 ++nbytes;
1681 ++frm;
1682 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001683 case size_t(-1):
1684 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001685 return nbytes;
1686 default:
1687 nbytes += n;
1688 frm += n;
1689 break;
1690 }
1691 }
1692 return nbytes;
1693}
1694
1695int
Louis Dionne65358e12021-03-01 12:09:45 -05001696codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001697{
Ben Craig3756b922016-03-09 15:39:39 +00001698 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001699}
1700
1701// Valid UTF ranges
1702// UTF-32 UTF-16 UTF-8 # of code points
1703// first second first second third fourth
1704// 000000 - 00007F 0000 - 007F 00 - 7F 127
1705// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1706// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1707// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1708// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1709// 00D800 - 00DFFF invalid
1710// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1711// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1712// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1713// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1714
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001715static
1716codecvt_base::result
1717utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1718 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1719 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1720{
1721 frm_nxt = frm;
1722 to_nxt = to;
1723 if (mode & generate_header)
1724 {
1725 if (to_end-to_nxt < 3)
1726 return codecvt_base::partial;
1727 *to_nxt++ = static_cast<uint8_t>(0xEF);
1728 *to_nxt++ = static_cast<uint8_t>(0xBB);
1729 *to_nxt++ = static_cast<uint8_t>(0xBF);
1730 }
1731 for (; frm_nxt < frm_end; ++frm_nxt)
1732 {
1733 uint16_t wc1 = *frm_nxt;
1734 if (wc1 > Maxcode)
1735 return codecvt_base::error;
1736 if (wc1 < 0x0080)
1737 {
1738 if (to_end-to_nxt < 1)
1739 return codecvt_base::partial;
1740 *to_nxt++ = static_cast<uint8_t>(wc1);
1741 }
1742 else if (wc1 < 0x0800)
1743 {
1744 if (to_end-to_nxt < 2)
1745 return codecvt_base::partial;
1746 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1747 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1748 }
1749 else if (wc1 < 0xD800)
1750 {
1751 if (to_end-to_nxt < 3)
1752 return codecvt_base::partial;
1753 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1754 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1756 }
1757 else if (wc1 < 0xDC00)
1758 {
1759 if (frm_end-frm_nxt < 2)
1760 return codecvt_base::partial;
1761 uint16_t wc2 = frm_nxt[1];
1762 if ((wc2 & 0xFC00) != 0xDC00)
1763 return codecvt_base::error;
1764 if (to_end-to_nxt < 4)
1765 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001766 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1767 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001768 return codecvt_base::error;
1769 ++frm_nxt;
1770 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1771 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1772 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1773 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1774 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1775 }
1776 else if (wc1 < 0xE000)
1777 {
1778 return codecvt_base::error;
1779 }
1780 else
1781 {
1782 if (to_end-to_nxt < 3)
1783 return codecvt_base::partial;
1784 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1785 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1786 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1787 }
1788 }
1789 return codecvt_base::ok;
1790}
1791
1792static
1793codecvt_base::result
1794utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1795 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1796 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1797{
1798 frm_nxt = frm;
1799 to_nxt = to;
1800 if (mode & generate_header)
1801 {
1802 if (to_end-to_nxt < 3)
1803 return codecvt_base::partial;
1804 *to_nxt++ = static_cast<uint8_t>(0xEF);
1805 *to_nxt++ = static_cast<uint8_t>(0xBB);
1806 *to_nxt++ = static_cast<uint8_t>(0xBF);
1807 }
1808 for (; frm_nxt < frm_end; ++frm_nxt)
1809 {
1810 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1811 if (wc1 > Maxcode)
1812 return codecvt_base::error;
1813 if (wc1 < 0x0080)
1814 {
1815 if (to_end-to_nxt < 1)
1816 return codecvt_base::partial;
1817 *to_nxt++ = static_cast<uint8_t>(wc1);
1818 }
1819 else if (wc1 < 0x0800)
1820 {
1821 if (to_end-to_nxt < 2)
1822 return codecvt_base::partial;
1823 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1824 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1825 }
1826 else if (wc1 < 0xD800)
1827 {
1828 if (to_end-to_nxt < 3)
1829 return codecvt_base::partial;
1830 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1831 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1832 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1833 }
1834 else if (wc1 < 0xDC00)
1835 {
1836 if (frm_end-frm_nxt < 2)
1837 return codecvt_base::partial;
1838 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1839 if ((wc2 & 0xFC00) != 0xDC00)
1840 return codecvt_base::error;
1841 if (to_end-to_nxt < 4)
1842 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001843 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1844 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001845 return codecvt_base::error;
1846 ++frm_nxt;
1847 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1848 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1849 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1852 }
1853 else if (wc1 < 0xE000)
1854 {
1855 return codecvt_base::error;
1856 }
1857 else
1858 {
1859 if (to_end-to_nxt < 3)
1860 return codecvt_base::partial;
1861 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1862 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1863 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1864 }
1865 }
1866 return codecvt_base::ok;
1867}
1868
1869static
1870codecvt_base::result
1871utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1872 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1873 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1874{
1875 frm_nxt = frm;
1876 to_nxt = to;
1877 if (mode & consume_header)
1878 {
1879 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1880 frm_nxt[2] == 0xBF)
1881 frm_nxt += 3;
1882 }
1883 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1884 {
1885 uint8_t c1 = *frm_nxt;
1886 if (c1 > Maxcode)
1887 return codecvt_base::error;
1888 if (c1 < 0x80)
1889 {
1890 *to_nxt = static_cast<uint16_t>(c1);
1891 ++frm_nxt;
1892 }
1893 else if (c1 < 0xC2)
1894 {
1895 return codecvt_base::error;
1896 }
1897 else if (c1 < 0xE0)
1898 {
1899 if (frm_end-frm_nxt < 2)
1900 return codecvt_base::partial;
1901 uint8_t c2 = frm_nxt[1];
1902 if ((c2 & 0xC0) != 0x80)
1903 return codecvt_base::error;
1904 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1905 if (t > Maxcode)
1906 return codecvt_base::error;
1907 *to_nxt = t;
1908 frm_nxt += 2;
1909 }
1910 else if (c1 < 0xF0)
1911 {
1912 if (frm_end-frm_nxt < 3)
1913 return codecvt_base::partial;
1914 uint8_t c2 = frm_nxt[1];
1915 uint8_t c3 = frm_nxt[2];
1916 switch (c1)
1917 {
1918 case 0xE0:
1919 if ((c2 & 0xE0) != 0xA0)
1920 return codecvt_base::error;
1921 break;
1922 case 0xED:
1923 if ((c2 & 0xE0) != 0x80)
1924 return codecvt_base::error;
1925 break;
1926 default:
1927 if ((c2 & 0xC0) != 0x80)
1928 return codecvt_base::error;
1929 break;
1930 }
1931 if ((c3 & 0xC0) != 0x80)
1932 return codecvt_base::error;
1933 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1934 | ((c2 & 0x3F) << 6)
1935 | (c3 & 0x3F));
1936 if (t > Maxcode)
1937 return codecvt_base::error;
1938 *to_nxt = t;
1939 frm_nxt += 3;
1940 }
1941 else if (c1 < 0xF5)
1942 {
1943 if (frm_end-frm_nxt < 4)
1944 return codecvt_base::partial;
1945 uint8_t c2 = frm_nxt[1];
1946 uint8_t c3 = frm_nxt[2];
1947 uint8_t c4 = frm_nxt[3];
1948 switch (c1)
1949 {
1950 case 0xF0:
1951 if (!(0x90 <= c2 && c2 <= 0xBF))
1952 return codecvt_base::error;
1953 break;
1954 case 0xF4:
1955 if ((c2 & 0xF0) != 0x80)
1956 return codecvt_base::error;
1957 break;
1958 default:
1959 if ((c2 & 0xC0) != 0x80)
1960 return codecvt_base::error;
1961 break;
1962 }
1963 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1964 return codecvt_base::error;
1965 if (to_end-to_nxt < 2)
1966 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001967 if ((((c1 & 7UL) << 18) +
1968 ((c2 & 0x3FUL) << 12) +
1969 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001970 return codecvt_base::error;
1971 *to_nxt = static_cast<uint16_t>(
1972 0xD800
1973 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1974 | ((c2 & 0x0F) << 2)
1975 | ((c3 & 0x30) >> 4));
1976 *++to_nxt = static_cast<uint16_t>(
1977 0xDC00
1978 | ((c3 & 0x0F) << 6)
1979 | (c4 & 0x3F));
1980 frm_nxt += 4;
1981 }
1982 else
1983 {
1984 return codecvt_base::error;
1985 }
1986 }
1987 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1988}
1989
1990static
1991codecvt_base::result
1992utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1993 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1994 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1995{
1996 frm_nxt = frm;
1997 to_nxt = to;
1998 if (mode & consume_header)
1999 {
2000 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2001 frm_nxt[2] == 0xBF)
2002 frm_nxt += 3;
2003 }
2004 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2005 {
2006 uint8_t c1 = *frm_nxt;
2007 if (c1 > Maxcode)
2008 return codecvt_base::error;
2009 if (c1 < 0x80)
2010 {
2011 *to_nxt = static_cast<uint32_t>(c1);
2012 ++frm_nxt;
2013 }
2014 else if (c1 < 0xC2)
2015 {
2016 return codecvt_base::error;
2017 }
2018 else if (c1 < 0xE0)
2019 {
2020 if (frm_end-frm_nxt < 2)
2021 return codecvt_base::partial;
2022 uint8_t c2 = frm_nxt[1];
2023 if ((c2 & 0xC0) != 0x80)
2024 return codecvt_base::error;
2025 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2026 if (t > Maxcode)
2027 return codecvt_base::error;
2028 *to_nxt = static_cast<uint32_t>(t);
2029 frm_nxt += 2;
2030 }
2031 else if (c1 < 0xF0)
2032 {
2033 if (frm_end-frm_nxt < 3)
2034 return codecvt_base::partial;
2035 uint8_t c2 = frm_nxt[1];
2036 uint8_t c3 = frm_nxt[2];
2037 switch (c1)
2038 {
2039 case 0xE0:
2040 if ((c2 & 0xE0) != 0xA0)
2041 return codecvt_base::error;
2042 break;
2043 case 0xED:
2044 if ((c2 & 0xE0) != 0x80)
2045 return codecvt_base::error;
2046 break;
2047 default:
2048 if ((c2 & 0xC0) != 0x80)
2049 return codecvt_base::error;
2050 break;
2051 }
2052 if ((c3 & 0xC0) != 0x80)
2053 return codecvt_base::error;
2054 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2055 | ((c2 & 0x3F) << 6)
2056 | (c3 & 0x3F));
2057 if (t > Maxcode)
2058 return codecvt_base::error;
2059 *to_nxt = static_cast<uint32_t>(t);
2060 frm_nxt += 3;
2061 }
2062 else if (c1 < 0xF5)
2063 {
2064 if (frm_end-frm_nxt < 4)
2065 return codecvt_base::partial;
2066 uint8_t c2 = frm_nxt[1];
2067 uint8_t c3 = frm_nxt[2];
2068 uint8_t c4 = frm_nxt[3];
2069 switch (c1)
2070 {
2071 case 0xF0:
2072 if (!(0x90 <= c2 && c2 <= 0xBF))
2073 return codecvt_base::error;
2074 break;
2075 case 0xF4:
2076 if ((c2 & 0xF0) != 0x80)
2077 return codecvt_base::error;
2078 break;
2079 default:
2080 if ((c2 & 0xC0) != 0x80)
2081 return codecvt_base::error;
2082 break;
2083 }
2084 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2085 return codecvt_base::error;
2086 if (to_end-to_nxt < 2)
2087 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002088 if ((((c1 & 7UL) << 18) +
2089 ((c2 & 0x3FUL) << 12) +
2090 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002091 return codecvt_base::error;
2092 *to_nxt = static_cast<uint32_t>(
2093 0xD800
2094 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2095 | ((c2 & 0x0F) << 2)
2096 | ((c3 & 0x30) >> 4));
2097 *++to_nxt = static_cast<uint32_t>(
2098 0xDC00
2099 | ((c3 & 0x0F) << 6)
2100 | (c4 & 0x3F));
2101 frm_nxt += 4;
2102 }
2103 else
2104 {
2105 return codecvt_base::error;
2106 }
2107 }
2108 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2109}
2110
2111static
2112int
2113utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2114 size_t mx, unsigned long Maxcode = 0x10FFFF,
2115 codecvt_mode mode = codecvt_mode(0))
2116{
2117 const uint8_t* frm_nxt = frm;
2118 if (mode & consume_header)
2119 {
2120 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2121 frm_nxt[2] == 0xBF)
2122 frm_nxt += 3;
2123 }
2124 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2125 {
2126 uint8_t c1 = *frm_nxt;
2127 if (c1 > Maxcode)
2128 break;
2129 if (c1 < 0x80)
2130 {
2131 ++frm_nxt;
2132 }
2133 else if (c1 < 0xC2)
2134 {
2135 break;
2136 }
2137 else if (c1 < 0xE0)
2138 {
2139 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2140 break;
2141 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2142 if (t > Maxcode)
2143 break;
2144 frm_nxt += 2;
2145 }
2146 else if (c1 < 0xF0)
2147 {
2148 if (frm_end-frm_nxt < 3)
2149 break;
2150 uint8_t c2 = frm_nxt[1];
2151 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002152 switch (c1)
2153 {
2154 case 0xE0:
2155 if ((c2 & 0xE0) != 0xA0)
2156 return static_cast<int>(frm_nxt - frm);
2157 break;
2158 case 0xED:
2159 if ((c2 & 0xE0) != 0x80)
2160 return static_cast<int>(frm_nxt - frm);
2161 break;
2162 default:
2163 if ((c2 & 0xC0) != 0x80)
2164 return static_cast<int>(frm_nxt - frm);
2165 break;
2166 }
2167 if ((c3 & 0xC0) != 0x80)
2168 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002169 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002170 break;
2171 frm_nxt += 3;
2172 }
2173 else if (c1 < 0xF5)
2174 {
2175 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2176 break;
2177 uint8_t c2 = frm_nxt[1];
2178 uint8_t c3 = frm_nxt[2];
2179 uint8_t c4 = frm_nxt[3];
2180 switch (c1)
2181 {
2182 case 0xF0:
2183 if (!(0x90 <= c2 && c2 <= 0xBF))
2184 return static_cast<int>(frm_nxt - frm);
2185 break;
2186 case 0xF4:
2187 if ((c2 & 0xF0) != 0x80)
2188 return static_cast<int>(frm_nxt - frm);
2189 break;
2190 default:
2191 if ((c2 & 0xC0) != 0x80)
2192 return static_cast<int>(frm_nxt - frm);
2193 break;
2194 }
2195 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2196 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002197 if ((((c1 & 7UL) << 18) +
2198 ((c2 & 0x3FUL) << 12) +
2199 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002200 break;
2201 ++nchar16_t;
2202 frm_nxt += 4;
2203 }
2204 else
2205 {
2206 break;
2207 }
2208 }
2209 return static_cast<int>(frm_nxt - frm);
2210}
2211
2212static
2213codecvt_base::result
2214ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2215 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2216 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2217{
2218 frm_nxt = frm;
2219 to_nxt = to;
2220 if (mode & generate_header)
2221 {
2222 if (to_end-to_nxt < 3)
2223 return codecvt_base::partial;
2224 *to_nxt++ = static_cast<uint8_t>(0xEF);
2225 *to_nxt++ = static_cast<uint8_t>(0xBB);
2226 *to_nxt++ = static_cast<uint8_t>(0xBF);
2227 }
2228 for (; frm_nxt < frm_end; ++frm_nxt)
2229 {
2230 uint32_t wc = *frm_nxt;
2231 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2232 return codecvt_base::error;
2233 if (wc < 0x000080)
2234 {
2235 if (to_end-to_nxt < 1)
2236 return codecvt_base::partial;
2237 *to_nxt++ = static_cast<uint8_t>(wc);
2238 }
2239 else if (wc < 0x000800)
2240 {
2241 if (to_end-to_nxt < 2)
2242 return codecvt_base::partial;
2243 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2244 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2245 }
2246 else if (wc < 0x010000)
2247 {
2248 if (to_end-to_nxt < 3)
2249 return codecvt_base::partial;
2250 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2251 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2252 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2253 }
2254 else // if (wc < 0x110000)
2255 {
2256 if (to_end-to_nxt < 4)
2257 return codecvt_base::partial;
2258 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2259 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2260 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2261 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2262 }
2263 }
2264 return codecvt_base::ok;
2265}
2266
2267static
2268codecvt_base::result
2269utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2270 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2271 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2272{
2273 frm_nxt = frm;
2274 to_nxt = to;
2275 if (mode & consume_header)
2276 {
2277 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2278 frm_nxt[2] == 0xBF)
2279 frm_nxt += 3;
2280 }
2281 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2282 {
2283 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2284 if (c1 < 0x80)
2285 {
2286 if (c1 > Maxcode)
2287 return codecvt_base::error;
2288 *to_nxt = static_cast<uint32_t>(c1);
2289 ++frm_nxt;
2290 }
2291 else if (c1 < 0xC2)
2292 {
2293 return codecvt_base::error;
2294 }
2295 else if (c1 < 0xE0)
2296 {
2297 if (frm_end-frm_nxt < 2)
2298 return codecvt_base::partial;
2299 uint8_t c2 = frm_nxt[1];
2300 if ((c2 & 0xC0) != 0x80)
2301 return codecvt_base::error;
2302 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2303 | (c2 & 0x3F));
2304 if (t > Maxcode)
2305 return codecvt_base::error;
2306 *to_nxt = t;
2307 frm_nxt += 2;
2308 }
2309 else if (c1 < 0xF0)
2310 {
2311 if (frm_end-frm_nxt < 3)
2312 return codecvt_base::partial;
2313 uint8_t c2 = frm_nxt[1];
2314 uint8_t c3 = frm_nxt[2];
2315 switch (c1)
2316 {
2317 case 0xE0:
2318 if ((c2 & 0xE0) != 0xA0)
2319 return codecvt_base::error;
2320 break;
2321 case 0xED:
2322 if ((c2 & 0xE0) != 0x80)
2323 return codecvt_base::error;
2324 break;
2325 default:
2326 if ((c2 & 0xC0) != 0x80)
2327 return codecvt_base::error;
2328 break;
2329 }
2330 if ((c3 & 0xC0) != 0x80)
2331 return codecvt_base::error;
2332 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2333 | ((c2 & 0x3F) << 6)
2334 | (c3 & 0x3F));
2335 if (t > Maxcode)
2336 return codecvt_base::error;
2337 *to_nxt = t;
2338 frm_nxt += 3;
2339 }
2340 else if (c1 < 0xF5)
2341 {
2342 if (frm_end-frm_nxt < 4)
2343 return codecvt_base::partial;
2344 uint8_t c2 = frm_nxt[1];
2345 uint8_t c3 = frm_nxt[2];
2346 uint8_t c4 = frm_nxt[3];
2347 switch (c1)
2348 {
2349 case 0xF0:
2350 if (!(0x90 <= c2 && c2 <= 0xBF))
2351 return codecvt_base::error;
2352 break;
2353 case 0xF4:
2354 if ((c2 & 0xF0) != 0x80)
2355 return codecvt_base::error;
2356 break;
2357 default:
2358 if ((c2 & 0xC0) != 0x80)
2359 return codecvt_base::error;
2360 break;
2361 }
2362 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2363 return codecvt_base::error;
2364 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2365 | ((c2 & 0x3F) << 12)
2366 | ((c3 & 0x3F) << 6)
2367 | (c4 & 0x3F));
2368 if (t > Maxcode)
2369 return codecvt_base::error;
2370 *to_nxt = t;
2371 frm_nxt += 4;
2372 }
2373 else
2374 {
2375 return codecvt_base::error;
2376 }
2377 }
2378 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2379}
2380
2381static
2382int
2383utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2384 size_t mx, unsigned long Maxcode = 0x10FFFF,
2385 codecvt_mode mode = codecvt_mode(0))
2386{
2387 const uint8_t* frm_nxt = frm;
2388 if (mode & consume_header)
2389 {
2390 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2391 frm_nxt[2] == 0xBF)
2392 frm_nxt += 3;
2393 }
2394 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2395 {
2396 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2397 if (c1 < 0x80)
2398 {
2399 if (c1 > Maxcode)
2400 break;
2401 ++frm_nxt;
2402 }
2403 else if (c1 < 0xC2)
2404 {
2405 break;
2406 }
2407 else if (c1 < 0xE0)
2408 {
2409 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2410 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002411 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002412 break;
2413 frm_nxt += 2;
2414 }
2415 else if (c1 < 0xF0)
2416 {
2417 if (frm_end-frm_nxt < 3)
2418 break;
2419 uint8_t c2 = frm_nxt[1];
2420 uint8_t c3 = frm_nxt[2];
2421 switch (c1)
2422 {
2423 case 0xE0:
2424 if ((c2 & 0xE0) != 0xA0)
2425 return static_cast<int>(frm_nxt - frm);
2426 break;
2427 case 0xED:
2428 if ((c2 & 0xE0) != 0x80)
2429 return static_cast<int>(frm_nxt - frm);
2430 break;
2431 default:
2432 if ((c2 & 0xC0) != 0x80)
2433 return static_cast<int>(frm_nxt - frm);
2434 break;
2435 }
2436 if ((c3 & 0xC0) != 0x80)
2437 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002438 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002439 break;
2440 frm_nxt += 3;
2441 }
2442 else if (c1 < 0xF5)
2443 {
2444 if (frm_end-frm_nxt < 4)
2445 break;
2446 uint8_t c2 = frm_nxt[1];
2447 uint8_t c3 = frm_nxt[2];
2448 uint8_t c4 = frm_nxt[3];
2449 switch (c1)
2450 {
2451 case 0xF0:
2452 if (!(0x90 <= c2 && c2 <= 0xBF))
2453 return static_cast<int>(frm_nxt - frm);
2454 break;
2455 case 0xF4:
2456 if ((c2 & 0xF0) != 0x80)
2457 return static_cast<int>(frm_nxt - frm);
2458 break;
2459 default:
2460 if ((c2 & 0xC0) != 0x80)
2461 return static_cast<int>(frm_nxt - frm);
2462 break;
2463 }
2464 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2465 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002466 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2467 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002468 break;
2469 frm_nxt += 4;
2470 }
2471 else
2472 {
2473 break;
2474 }
2475 }
2476 return static_cast<int>(frm_nxt - frm);
2477}
2478
2479static
2480codecvt_base::result
2481ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2482 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2483 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2484{
2485 frm_nxt = frm;
2486 to_nxt = to;
2487 if (mode & generate_header)
2488 {
2489 if (to_end-to_nxt < 3)
2490 return codecvt_base::partial;
2491 *to_nxt++ = static_cast<uint8_t>(0xEF);
2492 *to_nxt++ = static_cast<uint8_t>(0xBB);
2493 *to_nxt++ = static_cast<uint8_t>(0xBF);
2494 }
2495 for (; frm_nxt < frm_end; ++frm_nxt)
2496 {
2497 uint16_t wc = *frm_nxt;
2498 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2499 return codecvt_base::error;
2500 if (wc < 0x0080)
2501 {
2502 if (to_end-to_nxt < 1)
2503 return codecvt_base::partial;
2504 *to_nxt++ = static_cast<uint8_t>(wc);
2505 }
2506 else if (wc < 0x0800)
2507 {
2508 if (to_end-to_nxt < 2)
2509 return codecvt_base::partial;
2510 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2511 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2512 }
2513 else // if (wc <= 0xFFFF)
2514 {
2515 if (to_end-to_nxt < 3)
2516 return codecvt_base::partial;
2517 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2518 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2519 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2520 }
2521 }
2522 return codecvt_base::ok;
2523}
2524
2525static
2526codecvt_base::result
2527utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2528 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2529 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2530{
2531 frm_nxt = frm;
2532 to_nxt = to;
2533 if (mode & consume_header)
2534 {
2535 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2536 frm_nxt[2] == 0xBF)
2537 frm_nxt += 3;
2538 }
2539 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2540 {
2541 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2542 if (c1 < 0x80)
2543 {
2544 if (c1 > Maxcode)
2545 return codecvt_base::error;
2546 *to_nxt = static_cast<uint16_t>(c1);
2547 ++frm_nxt;
2548 }
2549 else if (c1 < 0xC2)
2550 {
2551 return codecvt_base::error;
2552 }
2553 else if (c1 < 0xE0)
2554 {
2555 if (frm_end-frm_nxt < 2)
2556 return codecvt_base::partial;
2557 uint8_t c2 = frm_nxt[1];
2558 if ((c2 & 0xC0) != 0x80)
2559 return codecvt_base::error;
2560 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2561 | (c2 & 0x3F));
2562 if (t > Maxcode)
2563 return codecvt_base::error;
2564 *to_nxt = t;
2565 frm_nxt += 2;
2566 }
2567 else if (c1 < 0xF0)
2568 {
2569 if (frm_end-frm_nxt < 3)
2570 return codecvt_base::partial;
2571 uint8_t c2 = frm_nxt[1];
2572 uint8_t c3 = frm_nxt[2];
2573 switch (c1)
2574 {
2575 case 0xE0:
2576 if ((c2 & 0xE0) != 0xA0)
2577 return codecvt_base::error;
2578 break;
2579 case 0xED:
2580 if ((c2 & 0xE0) != 0x80)
2581 return codecvt_base::error;
2582 break;
2583 default:
2584 if ((c2 & 0xC0) != 0x80)
2585 return codecvt_base::error;
2586 break;
2587 }
2588 if ((c3 & 0xC0) != 0x80)
2589 return codecvt_base::error;
2590 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2591 | ((c2 & 0x3F) << 6)
2592 | (c3 & 0x3F));
2593 if (t > Maxcode)
2594 return codecvt_base::error;
2595 *to_nxt = t;
2596 frm_nxt += 3;
2597 }
2598 else
2599 {
2600 return codecvt_base::error;
2601 }
2602 }
2603 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2604}
2605
2606static
2607int
2608utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2609 size_t mx, unsigned long Maxcode = 0x10FFFF,
2610 codecvt_mode mode = codecvt_mode(0))
2611{
2612 const uint8_t* frm_nxt = frm;
2613 if (mode & consume_header)
2614 {
2615 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2616 frm_nxt[2] == 0xBF)
2617 frm_nxt += 3;
2618 }
2619 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2620 {
2621 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2622 if (c1 < 0x80)
2623 {
2624 if (c1 > Maxcode)
2625 break;
2626 ++frm_nxt;
2627 }
2628 else if (c1 < 0xC2)
2629 {
2630 break;
2631 }
2632 else if (c1 < 0xE0)
2633 {
2634 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2635 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002636 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002637 break;
2638 frm_nxt += 2;
2639 }
2640 else if (c1 < 0xF0)
2641 {
2642 if (frm_end-frm_nxt < 3)
2643 break;
2644 uint8_t c2 = frm_nxt[1];
2645 uint8_t c3 = frm_nxt[2];
2646 switch (c1)
2647 {
2648 case 0xE0:
2649 if ((c2 & 0xE0) != 0xA0)
2650 return static_cast<int>(frm_nxt - frm);
2651 break;
2652 case 0xED:
2653 if ((c2 & 0xE0) != 0x80)
2654 return static_cast<int>(frm_nxt - frm);
2655 break;
2656 default:
2657 if ((c2 & 0xC0) != 0x80)
2658 return static_cast<int>(frm_nxt - frm);
2659 break;
2660 }
2661 if ((c3 & 0xC0) != 0x80)
2662 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002663 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002664 break;
2665 frm_nxt += 3;
2666 }
2667 else
2668 {
2669 break;
2670 }
2671 }
2672 return static_cast<int>(frm_nxt - frm);
2673}
2674
2675static
2676codecvt_base::result
2677ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2678 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2679 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2680{
2681 frm_nxt = frm;
2682 to_nxt = to;
2683 if (mode & generate_header)
2684 {
2685 if (to_end-to_nxt < 2)
2686 return codecvt_base::partial;
2687 *to_nxt++ = static_cast<uint8_t>(0xFE);
2688 *to_nxt++ = static_cast<uint8_t>(0xFF);
2689 }
2690 for (; frm_nxt < frm_end; ++frm_nxt)
2691 {
2692 uint32_t wc = *frm_nxt;
2693 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2694 return codecvt_base::error;
2695 if (wc < 0x010000)
2696 {
2697 if (to_end-to_nxt < 2)
2698 return codecvt_base::partial;
2699 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2700 *to_nxt++ = static_cast<uint8_t>(wc);
2701 }
2702 else
2703 {
2704 if (to_end-to_nxt < 4)
2705 return codecvt_base::partial;
2706 uint16_t t = static_cast<uint16_t>(
2707 0xD800
2708 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2709 | ((wc & 0x00FC00) >> 10));
2710 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2711 *to_nxt++ = static_cast<uint8_t>(t);
2712 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2713 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2714 *to_nxt++ = static_cast<uint8_t>(t);
2715 }
2716 }
2717 return codecvt_base::ok;
2718}
2719
2720static
2721codecvt_base::result
2722utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2723 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2724 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2725{
2726 frm_nxt = frm;
2727 to_nxt = to;
2728 if (mode & consume_header)
2729 {
2730 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2731 frm_nxt += 2;
2732 }
2733 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2734 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002735 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002736 if ((c1 & 0xFC00) == 0xDC00)
2737 return codecvt_base::error;
2738 if ((c1 & 0xFC00) != 0xD800)
2739 {
2740 if (c1 > Maxcode)
2741 return codecvt_base::error;
2742 *to_nxt = static_cast<uint32_t>(c1);
2743 frm_nxt += 2;
2744 }
2745 else
2746 {
2747 if (frm_end-frm_nxt < 4)
2748 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002749 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002750 if ((c2 & 0xFC00) != 0xDC00)
2751 return codecvt_base::error;
2752 uint32_t t = static_cast<uint32_t>(
2753 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2754 | ((c1 & 0x003F) << 10)
2755 | (c2 & 0x03FF));
2756 if (t > Maxcode)
2757 return codecvt_base::error;
2758 *to_nxt = t;
2759 frm_nxt += 4;
2760 }
2761 }
2762 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2763}
2764
2765static
2766int
2767utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2768 size_t mx, unsigned long Maxcode = 0x10FFFF,
2769 codecvt_mode mode = codecvt_mode(0))
2770{
2771 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002772 if (mode & consume_header)
2773 {
2774 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2775 frm_nxt += 2;
2776 }
2777 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2778 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002779 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002780 if ((c1 & 0xFC00) == 0xDC00)
2781 break;
2782 if ((c1 & 0xFC00) != 0xD800)
2783 {
2784 if (c1 > Maxcode)
2785 break;
2786 frm_nxt += 2;
2787 }
2788 else
2789 {
2790 if (frm_end-frm_nxt < 4)
2791 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002792 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002793 if ((c2 & 0xFC00) != 0xDC00)
2794 break;
2795 uint32_t t = static_cast<uint32_t>(
2796 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2797 | ((c1 & 0x003F) << 10)
2798 | (c2 & 0x03FF));
2799 if (t > Maxcode)
2800 break;
2801 frm_nxt += 4;
2802 }
2803 }
2804 return static_cast<int>(frm_nxt - frm);
2805}
2806
2807static
2808codecvt_base::result
2809ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2810 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2811 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2812{
2813 frm_nxt = frm;
2814 to_nxt = to;
2815 if (mode & generate_header)
2816 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002817 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002818 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002819 *to_nxt++ = static_cast<uint8_t>(0xFF);
2820 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002821 }
2822 for (; frm_nxt < frm_end; ++frm_nxt)
2823 {
2824 uint32_t wc = *frm_nxt;
2825 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2826 return codecvt_base::error;
2827 if (wc < 0x010000)
2828 {
2829 if (to_end-to_nxt < 2)
2830 return codecvt_base::partial;
2831 *to_nxt++ = static_cast<uint8_t>(wc);
2832 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2833 }
2834 else
2835 {
2836 if (to_end-to_nxt < 4)
2837 return codecvt_base::partial;
2838 uint16_t t = static_cast<uint16_t>(
2839 0xD800
2840 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2841 | ((wc & 0x00FC00) >> 10));
2842 *to_nxt++ = static_cast<uint8_t>(t);
2843 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2844 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2845 *to_nxt++ = static_cast<uint8_t>(t);
2846 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2847 }
2848 }
2849 return codecvt_base::ok;
2850}
2851
2852static
2853codecvt_base::result
2854utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2855 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2856 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2857{
2858 frm_nxt = frm;
2859 to_nxt = to;
2860 if (mode & consume_header)
2861 {
2862 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2863 frm_nxt += 2;
2864 }
2865 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2866 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002867 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002868 if ((c1 & 0xFC00) == 0xDC00)
2869 return codecvt_base::error;
2870 if ((c1 & 0xFC00) != 0xD800)
2871 {
2872 if (c1 > Maxcode)
2873 return codecvt_base::error;
2874 *to_nxt = static_cast<uint32_t>(c1);
2875 frm_nxt += 2;
2876 }
2877 else
2878 {
2879 if (frm_end-frm_nxt < 4)
2880 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002881 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002882 if ((c2 & 0xFC00) != 0xDC00)
2883 return codecvt_base::error;
2884 uint32_t t = static_cast<uint32_t>(
2885 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2886 | ((c1 & 0x003F) << 10)
2887 | (c2 & 0x03FF));
2888 if (t > Maxcode)
2889 return codecvt_base::error;
2890 *to_nxt = t;
2891 frm_nxt += 4;
2892 }
2893 }
2894 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2895}
2896
2897static
2898int
2899utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2900 size_t mx, unsigned long Maxcode = 0x10FFFF,
2901 codecvt_mode mode = codecvt_mode(0))
2902{
2903 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002904 if (mode & consume_header)
2905 {
2906 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2907 frm_nxt += 2;
2908 }
2909 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2910 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002911 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002912 if ((c1 & 0xFC00) == 0xDC00)
2913 break;
2914 if ((c1 & 0xFC00) != 0xD800)
2915 {
2916 if (c1 > Maxcode)
2917 break;
2918 frm_nxt += 2;
2919 }
2920 else
2921 {
2922 if (frm_end-frm_nxt < 4)
2923 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002924 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002925 if ((c2 & 0xFC00) != 0xDC00)
2926 break;
2927 uint32_t t = static_cast<uint32_t>(
2928 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2929 | ((c1 & 0x003F) << 10)
2930 | (c2 & 0x03FF));
2931 if (t > Maxcode)
2932 break;
2933 frm_nxt += 4;
2934 }
2935 }
2936 return static_cast<int>(frm_nxt - frm);
2937}
2938
2939static
2940codecvt_base::result
2941ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2942 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2943 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2944{
2945 frm_nxt = frm;
2946 to_nxt = to;
2947 if (mode & generate_header)
2948 {
2949 if (to_end-to_nxt < 2)
2950 return codecvt_base::partial;
2951 *to_nxt++ = static_cast<uint8_t>(0xFE);
2952 *to_nxt++ = static_cast<uint8_t>(0xFF);
2953 }
2954 for (; frm_nxt < frm_end; ++frm_nxt)
2955 {
2956 uint16_t wc = *frm_nxt;
2957 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2958 return codecvt_base::error;
2959 if (to_end-to_nxt < 2)
2960 return codecvt_base::partial;
2961 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2962 *to_nxt++ = static_cast<uint8_t>(wc);
2963 }
2964 return codecvt_base::ok;
2965}
2966
2967static
2968codecvt_base::result
2969utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2970 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2971 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2972{
2973 frm_nxt = frm;
2974 to_nxt = to;
2975 if (mode & consume_header)
2976 {
2977 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2978 frm_nxt += 2;
2979 }
2980 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2981 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002982 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002983 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2984 return codecvt_base::error;
2985 *to_nxt = c1;
2986 frm_nxt += 2;
2987 }
2988 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2989}
2990
2991static
2992int
2993utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2994 size_t mx, unsigned long Maxcode = 0x10FFFF,
2995 codecvt_mode mode = codecvt_mode(0))
2996{
2997 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002998 if (mode & consume_header)
2999 {
3000 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3001 frm_nxt += 2;
3002 }
3003 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3004 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003005 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003006 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3007 break;
3008 frm_nxt += 2;
3009 }
3010 return static_cast<int>(frm_nxt - frm);
3011}
3012
3013static
3014codecvt_base::result
3015ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3016 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3017 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3018{
3019 frm_nxt = frm;
3020 to_nxt = to;
3021 if (mode & generate_header)
3022 {
3023 if (to_end-to_nxt < 2)
3024 return codecvt_base::partial;
3025 *to_nxt++ = static_cast<uint8_t>(0xFF);
3026 *to_nxt++ = static_cast<uint8_t>(0xFE);
3027 }
3028 for (; frm_nxt < frm_end; ++frm_nxt)
3029 {
3030 uint16_t wc = *frm_nxt;
3031 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3032 return codecvt_base::error;
3033 if (to_end-to_nxt < 2)
3034 return codecvt_base::partial;
3035 *to_nxt++ = static_cast<uint8_t>(wc);
3036 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3037 }
3038 return codecvt_base::ok;
3039}
3040
3041static
3042codecvt_base::result
3043utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3044 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3045 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3046{
3047 frm_nxt = frm;
3048 to_nxt = to;
3049 if (mode & consume_header)
3050 {
3051 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3052 frm_nxt += 2;
3053 }
3054 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3055 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003056 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003057 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3058 return codecvt_base::error;
3059 *to_nxt = c1;
3060 frm_nxt += 2;
3061 }
3062 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3063}
3064
3065static
3066int
3067utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3068 size_t mx, unsigned long Maxcode = 0x10FFFF,
3069 codecvt_mode mode = codecvt_mode(0))
3070{
3071 const uint8_t* frm_nxt = frm;
3072 frm_nxt = frm;
3073 if (mode & consume_header)
3074 {
3075 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3076 frm_nxt += 2;
3077 }
3078 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3079 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003080 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003081 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3082 break;
3083 frm_nxt += 2;
3084 }
3085 return static_cast<int>(frm_nxt - frm);
3086}
3087
Howard Hinnantc51e1022010-05-11 19:42:16 +00003088// template <> class codecvt<char16_t, char, mbstate_t>
3089
Howard Hinnantffb308e2010-08-22 00:03:27 +00003090locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003091
3092codecvt<char16_t, char, mbstate_t>::~codecvt()
3093{
3094}
3095
3096codecvt<char16_t, char, mbstate_t>::result
3097codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003098 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003099 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3100{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003101 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3102 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3103 const uint16_t* _frm_nxt = _frm;
3104 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3105 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3106 uint8_t* _to_nxt = _to;
3107 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3108 frm_nxt = frm + (_frm_nxt - _frm);
3109 to_nxt = to + (_to_nxt - _to);
3110 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003111}
3112
3113codecvt<char16_t, char, mbstate_t>::result
3114codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003115 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003116 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3117{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003118 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3119 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3120 const uint8_t* _frm_nxt = _frm;
3121 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3122 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3123 uint16_t* _to_nxt = _to;
3124 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3125 frm_nxt = frm + (_frm_nxt - _frm);
3126 to_nxt = to + (_to_nxt - _to);
3127 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003128}
3129
3130codecvt<char16_t, char, mbstate_t>::result
3131codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3132 extern_type* to, extern_type*, extern_type*& to_nxt) const
3133{
3134 to_nxt = to;
3135 return noconv;
3136}
3137
3138int
Louis Dionne65358e12021-03-01 12:09:45 -05003139codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003140{
3141 return 0;
3142}
3143
3144bool
Louis Dionne65358e12021-03-01 12:09:45 -05003145codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003146{
3147 return false;
3148}
3149
3150int
3151codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3152 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3153{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003154 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3155 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3156 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003157}
3158
3159int
Louis Dionne65358e12021-03-01 12:09:45 -05003160codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003161{
3162 return 4;
3163}
3164
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003165#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003166
3167// template <> class codecvt<char16_t, char8_t, mbstate_t>
3168
3169locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3170
3171codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3172{
3173}
3174
3175codecvt<char16_t, char8_t, mbstate_t>::result
3176codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3177 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3178 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3179{
3180 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3181 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3182 const uint16_t* _frm_nxt = _frm;
3183 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3184 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3185 uint8_t* _to_nxt = _to;
3186 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3187 frm_nxt = frm + (_frm_nxt - _frm);
3188 to_nxt = to + (_to_nxt - _to);
3189 return r;
3190}
3191
3192codecvt<char16_t, char8_t, mbstate_t>::result
3193codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3194 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3195 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3196{
3197 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3198 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3199 const uint8_t* _frm_nxt = _frm;
3200 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3201 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3202 uint16_t* _to_nxt = _to;
3203 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3204 frm_nxt = frm + (_frm_nxt - _frm);
3205 to_nxt = to + (_to_nxt - _to);
3206 return r;
3207}
3208
3209codecvt<char16_t, char8_t, mbstate_t>::result
3210codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3211 extern_type* to, extern_type*, extern_type*& to_nxt) const
3212{
3213 to_nxt = to;
3214 return noconv;
3215}
3216
3217int
Louis Dionne65358e12021-03-01 12:09:45 -05003218codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003219{
3220 return 0;
3221}
3222
3223bool
Louis Dionne65358e12021-03-01 12:09:45 -05003224codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003225{
3226 return false;
3227}
3228
3229int
3230codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3231 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3232{
3233 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3234 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3235 return utf8_to_utf16_length(_frm, _frm_end, mx);
3236}
3237
3238int
Louis Dionne65358e12021-03-01 12:09:45 -05003239codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003240{
3241 return 4;
3242}
3243
3244#endif
3245
Howard Hinnantc51e1022010-05-11 19:42:16 +00003246// template <> class codecvt<char32_t, char, mbstate_t>
3247
Howard Hinnantffb308e2010-08-22 00:03:27 +00003248locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003249
3250codecvt<char32_t, char, mbstate_t>::~codecvt()
3251{
3252}
3253
3254codecvt<char32_t, char, mbstate_t>::result
3255codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003256 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003257 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3258{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003259 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3260 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3261 const uint32_t* _frm_nxt = _frm;
3262 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3263 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3264 uint8_t* _to_nxt = _to;
3265 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3266 frm_nxt = frm + (_frm_nxt - _frm);
3267 to_nxt = to + (_to_nxt - _to);
3268 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003269}
3270
3271codecvt<char32_t, char, mbstate_t>::result
3272codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003273 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003274 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3275{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003276 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3277 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3278 const uint8_t* _frm_nxt = _frm;
3279 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3280 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3281 uint32_t* _to_nxt = _to;
3282 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3283 frm_nxt = frm + (_frm_nxt - _frm);
3284 to_nxt = to + (_to_nxt - _to);
3285 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003286}
3287
3288codecvt<char32_t, char, mbstate_t>::result
3289codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3290 extern_type* to, extern_type*, extern_type*& to_nxt) const
3291{
3292 to_nxt = to;
3293 return noconv;
3294}
3295
3296int
Louis Dionne65358e12021-03-01 12:09:45 -05003297codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003298{
3299 return 0;
3300}
3301
3302bool
Louis Dionne65358e12021-03-01 12:09:45 -05003303codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003304{
3305 return false;
3306}
3307
3308int
3309codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3310 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3311{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003312 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3313 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3314 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003315}
3316
3317int
Louis Dionne65358e12021-03-01 12:09:45 -05003318codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003319{
3320 return 4;
3321}
3322
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003323#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003324
3325// template <> class codecvt<char32_t, char8_t, mbstate_t>
3326
3327locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3328
3329codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3330{
3331}
3332
3333codecvt<char32_t, char8_t, mbstate_t>::result
3334codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3335 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3336 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3337{
3338 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3339 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3340 const uint32_t* _frm_nxt = _frm;
3341 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3342 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3343 uint8_t* _to_nxt = _to;
3344 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3345 frm_nxt = frm + (_frm_nxt - _frm);
3346 to_nxt = to + (_to_nxt - _to);
3347 return r;
3348}
3349
3350codecvt<char32_t, char8_t, mbstate_t>::result
3351codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3352 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3353 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3354{
3355 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3356 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3357 const uint8_t* _frm_nxt = _frm;
3358 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3359 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3360 uint32_t* _to_nxt = _to;
3361 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3362 frm_nxt = frm + (_frm_nxt - _frm);
3363 to_nxt = to + (_to_nxt - _to);
3364 return r;
3365}
3366
3367codecvt<char32_t, char8_t, mbstate_t>::result
3368codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3369 extern_type* to, extern_type*, extern_type*& to_nxt) const
3370{
3371 to_nxt = to;
3372 return noconv;
3373}
3374
3375int
Louis Dionne65358e12021-03-01 12:09:45 -05003376codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003377{
3378 return 0;
3379}
3380
3381bool
Louis Dionne65358e12021-03-01 12:09:45 -05003382codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003383{
3384 return false;
3385}
3386
3387int
3388codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3389 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3390{
3391 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3392 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3393 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3394}
3395
3396int
Louis Dionne65358e12021-03-01 12:09:45 -05003397codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003398{
3399 return 4;
3400}
3401
3402#endif
3403
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003404// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003405
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003406__codecvt_utf8<wchar_t>::result
3407__codecvt_utf8<wchar_t>::do_out(state_type&,
3408 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003409 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3410{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003411#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003412 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3413 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3414 const uint16_t* _frm_nxt = _frm;
3415#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003416 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3417 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3418 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003419#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003420 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3421 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3422 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003423#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003424 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3425 _Maxcode_, _Mode_);
3426#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003427 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3428 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003429#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003430 frm_nxt = frm + (_frm_nxt - _frm);
3431 to_nxt = to + (_to_nxt - _to);
3432 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003433}
3434
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003435__codecvt_utf8<wchar_t>::result
3436__codecvt_utf8<wchar_t>::do_in(state_type&,
3437 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003438 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3439{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003440 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3441 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3442 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003443#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003444 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3445 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3446 uint16_t* _to_nxt = _to;
3447 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3448 _Maxcode_, _Mode_);
3449#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003450 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3451 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3452 uint32_t* _to_nxt = _to;
3453 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3454 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003455#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003456 frm_nxt = frm + (_frm_nxt - _frm);
3457 to_nxt = to + (_to_nxt - _to);
3458 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003459}
3460
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003461__codecvt_utf8<wchar_t>::result
3462__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003463 extern_type* to, extern_type*, extern_type*& to_nxt) const
3464{
3465 to_nxt = to;
3466 return noconv;
3467}
3468
3469int
Louis Dionne65358e12021-03-01 12:09:45 -05003470__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003471{
3472 return 0;
3473}
3474
3475bool
Louis Dionne65358e12021-03-01 12:09:45 -05003476__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003477{
3478 return false;
3479}
3480
3481int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003482__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003483 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3484{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003485 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3486 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3487 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003488}
3489
3490int
Louis Dionne65358e12021-03-01 12:09:45 -05003491__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003492{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003493 if (_Mode_ & consume_header)
3494 return 7;
3495 return 4;
3496}
3497
3498// __codecvt_utf8<char16_t>
3499
3500__codecvt_utf8<char16_t>::result
3501__codecvt_utf8<char16_t>::do_out(state_type&,
3502 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3503 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3504{
3505 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3506 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3507 const uint16_t* _frm_nxt = _frm;
3508 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3509 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3510 uint8_t* _to_nxt = _to;
3511 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3512 _Maxcode_, _Mode_);
3513 frm_nxt = frm + (_frm_nxt - _frm);
3514 to_nxt = to + (_to_nxt - _to);
3515 return r;
3516}
3517
3518__codecvt_utf8<char16_t>::result
3519__codecvt_utf8<char16_t>::do_in(state_type&,
3520 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3521 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3522{
3523 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3524 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3525 const uint8_t* _frm_nxt = _frm;
3526 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3527 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3528 uint16_t* _to_nxt = _to;
3529 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3530 _Maxcode_, _Mode_);
3531 frm_nxt = frm + (_frm_nxt - _frm);
3532 to_nxt = to + (_to_nxt - _to);
3533 return r;
3534}
3535
3536__codecvt_utf8<char16_t>::result
3537__codecvt_utf8<char16_t>::do_unshift(state_type&,
3538 extern_type* to, extern_type*, extern_type*& to_nxt) const
3539{
3540 to_nxt = to;
3541 return noconv;
3542}
3543
3544int
Louis Dionne65358e12021-03-01 12:09:45 -05003545__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003546{
3547 return 0;
3548}
3549
3550bool
Louis Dionne65358e12021-03-01 12:09:45 -05003551__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003552{
3553 return false;
3554}
3555
3556int
3557__codecvt_utf8<char16_t>::do_length(state_type&,
3558 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3559{
3560 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3561 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3562 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3563}
3564
3565int
Louis Dionne65358e12021-03-01 12:09:45 -05003566__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003567{
3568 if (_Mode_ & consume_header)
3569 return 6;
3570 return 3;
3571}
3572
3573// __codecvt_utf8<char32_t>
3574
3575__codecvt_utf8<char32_t>::result
3576__codecvt_utf8<char32_t>::do_out(state_type&,
3577 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3578 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3579{
3580 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3581 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3582 const uint32_t* _frm_nxt = _frm;
3583 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3584 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3585 uint8_t* _to_nxt = _to;
3586 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3587 _Maxcode_, _Mode_);
3588 frm_nxt = frm + (_frm_nxt - _frm);
3589 to_nxt = to + (_to_nxt - _to);
3590 return r;
3591}
3592
3593__codecvt_utf8<char32_t>::result
3594__codecvt_utf8<char32_t>::do_in(state_type&,
3595 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3596 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3597{
3598 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3599 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3600 const uint8_t* _frm_nxt = _frm;
3601 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3602 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3603 uint32_t* _to_nxt = _to;
3604 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3605 _Maxcode_, _Mode_);
3606 frm_nxt = frm + (_frm_nxt - _frm);
3607 to_nxt = to + (_to_nxt - _to);
3608 return r;
3609}
3610
3611__codecvt_utf8<char32_t>::result
3612__codecvt_utf8<char32_t>::do_unshift(state_type&,
3613 extern_type* to, extern_type*, extern_type*& to_nxt) const
3614{
3615 to_nxt = to;
3616 return noconv;
3617}
3618
3619int
Louis Dionne65358e12021-03-01 12:09:45 -05003620__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003621{
3622 return 0;
3623}
3624
3625bool
Louis Dionne65358e12021-03-01 12:09:45 -05003626__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003627{
3628 return false;
3629}
3630
3631int
3632__codecvt_utf8<char32_t>::do_length(state_type&,
3633 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3634{
3635 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3636 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3637 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3638}
3639
3640int
Louis Dionne65358e12021-03-01 12:09:45 -05003641__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003642{
3643 if (_Mode_ & consume_header)
3644 return 7;
3645 return 4;
3646}
3647
3648// __codecvt_utf16<wchar_t, false>
3649
3650__codecvt_utf16<wchar_t, false>::result
3651__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3652 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3653 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3654{
3655 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3656 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3657 const uint32_t* _frm_nxt = _frm;
3658 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3659 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3660 uint8_t* _to_nxt = _to;
3661 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3662 _Maxcode_, _Mode_);
3663 frm_nxt = frm + (_frm_nxt - _frm);
3664 to_nxt = to + (_to_nxt - _to);
3665 return r;
3666}
3667
3668__codecvt_utf16<wchar_t, false>::result
3669__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3670 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3671 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3672{
3673 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3674 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3675 const uint8_t* _frm_nxt = _frm;
3676 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3677 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3678 uint32_t* _to_nxt = _to;
3679 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3680 _Maxcode_, _Mode_);
3681 frm_nxt = frm + (_frm_nxt - _frm);
3682 to_nxt = to + (_to_nxt - _to);
3683 return r;
3684}
3685
3686__codecvt_utf16<wchar_t, false>::result
3687__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3688 extern_type* to, extern_type*, extern_type*& to_nxt) const
3689{
3690 to_nxt = to;
3691 return noconv;
3692}
3693
3694int
Louis Dionne65358e12021-03-01 12:09:45 -05003695__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003696{
3697 return 0;
3698}
3699
3700bool
Louis Dionne65358e12021-03-01 12:09:45 -05003701__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003702{
3703 return false;
3704}
3705
3706int
3707__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3708 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3709{
3710 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3711 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3712 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3713}
3714
3715int
Louis Dionne65358e12021-03-01 12:09:45 -05003716__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003717{
3718 if (_Mode_ & consume_header)
3719 return 6;
3720 return 4;
3721}
3722
3723// __codecvt_utf16<wchar_t, true>
3724
3725__codecvt_utf16<wchar_t, true>::result
3726__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3727 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3728 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3729{
3730 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3731 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3732 const uint32_t* _frm_nxt = _frm;
3733 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3734 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3735 uint8_t* _to_nxt = _to;
3736 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3737 _Maxcode_, _Mode_);
3738 frm_nxt = frm + (_frm_nxt - _frm);
3739 to_nxt = to + (_to_nxt - _to);
3740 return r;
3741}
3742
3743__codecvt_utf16<wchar_t, true>::result
3744__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3745 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3746 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3747{
3748 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3749 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3750 const uint8_t* _frm_nxt = _frm;
3751 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3752 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3753 uint32_t* _to_nxt = _to;
3754 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3755 _Maxcode_, _Mode_);
3756 frm_nxt = frm + (_frm_nxt - _frm);
3757 to_nxt = to + (_to_nxt - _to);
3758 return r;
3759}
3760
3761__codecvt_utf16<wchar_t, true>::result
3762__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3763 extern_type* to, extern_type*, extern_type*& to_nxt) const
3764{
3765 to_nxt = to;
3766 return noconv;
3767}
3768
3769int
Louis Dionne65358e12021-03-01 12:09:45 -05003770__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003771{
3772 return 0;
3773}
3774
3775bool
Louis Dionne65358e12021-03-01 12:09:45 -05003776__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003777{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003778 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003779}
3780
3781int
3782__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3783 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3784{
3785 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3786 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3787 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3788}
3789
3790int
Louis Dionne65358e12021-03-01 12:09:45 -05003791__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003792{
3793 if (_Mode_ & consume_header)
3794 return 6;
3795 return 4;
3796}
3797
3798// __codecvt_utf16<char16_t, false>
3799
3800__codecvt_utf16<char16_t, false>::result
3801__codecvt_utf16<char16_t, false>::do_out(state_type&,
3802 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3803 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3804{
3805 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3806 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3807 const uint16_t* _frm_nxt = _frm;
3808 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3809 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3810 uint8_t* _to_nxt = _to;
3811 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3812 _Maxcode_, _Mode_);
3813 frm_nxt = frm + (_frm_nxt - _frm);
3814 to_nxt = to + (_to_nxt - _to);
3815 return r;
3816}
3817
3818__codecvt_utf16<char16_t, false>::result
3819__codecvt_utf16<char16_t, false>::do_in(state_type&,
3820 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3821 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3822{
3823 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3824 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3825 const uint8_t* _frm_nxt = _frm;
3826 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3827 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3828 uint16_t* _to_nxt = _to;
3829 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3830 _Maxcode_, _Mode_);
3831 frm_nxt = frm + (_frm_nxt - _frm);
3832 to_nxt = to + (_to_nxt - _to);
3833 return r;
3834}
3835
3836__codecvt_utf16<char16_t, false>::result
3837__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3838 extern_type* to, extern_type*, extern_type*& to_nxt) const
3839{
3840 to_nxt = to;
3841 return noconv;
3842}
3843
3844int
Louis Dionne65358e12021-03-01 12:09:45 -05003845__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003846{
3847 return 0;
3848}
3849
3850bool
Louis Dionne65358e12021-03-01 12:09:45 -05003851__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003852{
3853 return false;
3854}
3855
3856int
3857__codecvt_utf16<char16_t, false>::do_length(state_type&,
3858 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3859{
3860 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3861 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3862 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3863}
3864
3865int
Louis Dionne65358e12021-03-01 12:09:45 -05003866__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003867{
3868 if (_Mode_ & consume_header)
3869 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003870 return 2;
3871}
3872
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003873// __codecvt_utf16<char16_t, true>
3874
3875__codecvt_utf16<char16_t, true>::result
3876__codecvt_utf16<char16_t, true>::do_out(state_type&,
3877 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3878 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3879{
3880 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3881 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3882 const uint16_t* _frm_nxt = _frm;
3883 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3884 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3885 uint8_t* _to_nxt = _to;
3886 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3887 _Maxcode_, _Mode_);
3888 frm_nxt = frm + (_frm_nxt - _frm);
3889 to_nxt = to + (_to_nxt - _to);
3890 return r;
3891}
3892
3893__codecvt_utf16<char16_t, true>::result
3894__codecvt_utf16<char16_t, true>::do_in(state_type&,
3895 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3896 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3897{
3898 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3899 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3900 const uint8_t* _frm_nxt = _frm;
3901 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3902 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3903 uint16_t* _to_nxt = _to;
3904 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3905 _Maxcode_, _Mode_);
3906 frm_nxt = frm + (_frm_nxt - _frm);
3907 to_nxt = to + (_to_nxt - _to);
3908 return r;
3909}
3910
3911__codecvt_utf16<char16_t, true>::result
3912__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3913 extern_type* to, extern_type*, extern_type*& to_nxt) const
3914{
3915 to_nxt = to;
3916 return noconv;
3917}
3918
3919int
Louis Dionne65358e12021-03-01 12:09:45 -05003920__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003921{
3922 return 0;
3923}
3924
3925bool
Louis Dionne65358e12021-03-01 12:09:45 -05003926__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003927{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003928 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003929}
3930
3931int
3932__codecvt_utf16<char16_t, true>::do_length(state_type&,
3933 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3934{
3935 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3936 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3937 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3938}
3939
3940int
Louis Dionne65358e12021-03-01 12:09:45 -05003941__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003942{
3943 if (_Mode_ & consume_header)
3944 return 4;
3945 return 2;
3946}
3947
3948// __codecvt_utf16<char32_t, false>
3949
3950__codecvt_utf16<char32_t, false>::result
3951__codecvt_utf16<char32_t, false>::do_out(state_type&,
3952 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3953 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3954{
3955 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3956 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3957 const uint32_t* _frm_nxt = _frm;
3958 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3959 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3960 uint8_t* _to_nxt = _to;
3961 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3962 _Maxcode_, _Mode_);
3963 frm_nxt = frm + (_frm_nxt - _frm);
3964 to_nxt = to + (_to_nxt - _to);
3965 return r;
3966}
3967
3968__codecvt_utf16<char32_t, false>::result
3969__codecvt_utf16<char32_t, false>::do_in(state_type&,
3970 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3971 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3972{
3973 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3974 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3975 const uint8_t* _frm_nxt = _frm;
3976 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3977 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3978 uint32_t* _to_nxt = _to;
3979 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3980 _Maxcode_, _Mode_);
3981 frm_nxt = frm + (_frm_nxt - _frm);
3982 to_nxt = to + (_to_nxt - _to);
3983 return r;
3984}
3985
3986__codecvt_utf16<char32_t, false>::result
3987__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3988 extern_type* to, extern_type*, extern_type*& to_nxt) const
3989{
3990 to_nxt = to;
3991 return noconv;
3992}
3993
3994int
Louis Dionne65358e12021-03-01 12:09:45 -05003995__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003996{
3997 return 0;
3998}
3999
4000bool
Louis Dionne65358e12021-03-01 12:09:45 -05004001__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004002{
4003 return false;
4004}
4005
4006int
4007__codecvt_utf16<char32_t, false>::do_length(state_type&,
4008 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4009{
4010 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4011 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4012 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4013}
4014
4015int
Louis Dionne65358e12021-03-01 12:09:45 -05004016__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004017{
4018 if (_Mode_ & consume_header)
4019 return 6;
4020 return 4;
4021}
4022
4023// __codecvt_utf16<char32_t, true>
4024
4025__codecvt_utf16<char32_t, true>::result
4026__codecvt_utf16<char32_t, true>::do_out(state_type&,
4027 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4028 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4029{
4030 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4031 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4032 const uint32_t* _frm_nxt = _frm;
4033 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4034 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4035 uint8_t* _to_nxt = _to;
4036 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4037 _Maxcode_, _Mode_);
4038 frm_nxt = frm + (_frm_nxt - _frm);
4039 to_nxt = to + (_to_nxt - _to);
4040 return r;
4041}
4042
4043__codecvt_utf16<char32_t, true>::result
4044__codecvt_utf16<char32_t, true>::do_in(state_type&,
4045 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4046 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4047{
4048 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4049 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4050 const uint8_t* _frm_nxt = _frm;
4051 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4052 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4053 uint32_t* _to_nxt = _to;
4054 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4055 _Maxcode_, _Mode_);
4056 frm_nxt = frm + (_frm_nxt - _frm);
4057 to_nxt = to + (_to_nxt - _to);
4058 return r;
4059}
4060
4061__codecvt_utf16<char32_t, true>::result
4062__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4063 extern_type* to, extern_type*, extern_type*& to_nxt) const
4064{
4065 to_nxt = to;
4066 return noconv;
4067}
4068
4069int
Louis Dionne65358e12021-03-01 12:09:45 -05004070__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004071{
4072 return 0;
4073}
4074
4075bool
Louis Dionne65358e12021-03-01 12:09:45 -05004076__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004077{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004078 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004079}
4080
4081int
4082__codecvt_utf16<char32_t, true>::do_length(state_type&,
4083 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4084{
4085 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4086 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4087 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4088}
4089
4090int
Louis Dionne65358e12021-03-01 12:09:45 -05004091__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004092{
4093 if (_Mode_ & consume_header)
4094 return 6;
4095 return 4;
4096}
4097
4098// __codecvt_utf8_utf16<wchar_t>
4099
4100__codecvt_utf8_utf16<wchar_t>::result
4101__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4102 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4103 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4104{
4105 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4106 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4107 const uint32_t* _frm_nxt = _frm;
4108 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4109 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4110 uint8_t* _to_nxt = _to;
4111 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4112 _Maxcode_, _Mode_);
4113 frm_nxt = frm + (_frm_nxt - _frm);
4114 to_nxt = to + (_to_nxt - _to);
4115 return r;
4116}
4117
4118__codecvt_utf8_utf16<wchar_t>::result
4119__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4120 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4121 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4122{
4123 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4124 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4125 const uint8_t* _frm_nxt = _frm;
4126 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4127 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4128 uint32_t* _to_nxt = _to;
4129 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4130 _Maxcode_, _Mode_);
4131 frm_nxt = frm + (_frm_nxt - _frm);
4132 to_nxt = to + (_to_nxt - _to);
4133 return r;
4134}
4135
4136__codecvt_utf8_utf16<wchar_t>::result
4137__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4138 extern_type* to, extern_type*, extern_type*& to_nxt) const
4139{
4140 to_nxt = to;
4141 return noconv;
4142}
4143
4144int
Louis Dionne65358e12021-03-01 12:09:45 -05004145__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004146{
4147 return 0;
4148}
4149
4150bool
Louis Dionne65358e12021-03-01 12:09:45 -05004151__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004152{
4153 return false;
4154}
4155
4156int
4157__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4158 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4159{
4160 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4161 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4162 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4163}
4164
4165int
Louis Dionne65358e12021-03-01 12:09:45 -05004166__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004167{
4168 if (_Mode_ & consume_header)
4169 return 7;
4170 return 4;
4171}
4172
4173// __codecvt_utf8_utf16<char16_t>
4174
4175__codecvt_utf8_utf16<char16_t>::result
4176__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4177 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4178 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4179{
4180 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4181 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4182 const uint16_t* _frm_nxt = _frm;
4183 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4184 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4185 uint8_t* _to_nxt = _to;
4186 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4187 _Maxcode_, _Mode_);
4188 frm_nxt = frm + (_frm_nxt - _frm);
4189 to_nxt = to + (_to_nxt - _to);
4190 return r;
4191}
4192
4193__codecvt_utf8_utf16<char16_t>::result
4194__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4195 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4196 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4197{
4198 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4199 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4200 const uint8_t* _frm_nxt = _frm;
4201 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4202 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4203 uint16_t* _to_nxt = _to;
4204 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4205 _Maxcode_, _Mode_);
4206 frm_nxt = frm + (_frm_nxt - _frm);
4207 to_nxt = to + (_to_nxt - _to);
4208 return r;
4209}
4210
4211__codecvt_utf8_utf16<char16_t>::result
4212__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4213 extern_type* to, extern_type*, extern_type*& to_nxt) const
4214{
4215 to_nxt = to;
4216 return noconv;
4217}
4218
4219int
Louis Dionne65358e12021-03-01 12:09:45 -05004220__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004221{
4222 return 0;
4223}
4224
4225bool
Louis Dionne65358e12021-03-01 12:09:45 -05004226__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004227{
4228 return false;
4229}
4230
4231int
4232__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4233 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4234{
4235 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4236 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4237 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4238}
4239
4240int
Louis Dionne65358e12021-03-01 12:09:45 -05004241__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004242{
4243 if (_Mode_ & consume_header)
4244 return 7;
4245 return 4;
4246}
4247
4248// __codecvt_utf8_utf16<char32_t>
4249
4250__codecvt_utf8_utf16<char32_t>::result
4251__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4252 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4253 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4254{
4255 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4256 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4257 const uint32_t* _frm_nxt = _frm;
4258 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4259 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4260 uint8_t* _to_nxt = _to;
4261 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4262 _Maxcode_, _Mode_);
4263 frm_nxt = frm + (_frm_nxt - _frm);
4264 to_nxt = to + (_to_nxt - _to);
4265 return r;
4266}
4267
4268__codecvt_utf8_utf16<char32_t>::result
4269__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4270 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4271 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4272{
4273 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4274 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4275 const uint8_t* _frm_nxt = _frm;
4276 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4277 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4278 uint32_t* _to_nxt = _to;
4279 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4280 _Maxcode_, _Mode_);
4281 frm_nxt = frm + (_frm_nxt - _frm);
4282 to_nxt = to + (_to_nxt - _to);
4283 return r;
4284}
4285
4286__codecvt_utf8_utf16<char32_t>::result
4287__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4288 extern_type* to, extern_type*, extern_type*& to_nxt) const
4289{
4290 to_nxt = to;
4291 return noconv;
4292}
4293
4294int
Louis Dionne65358e12021-03-01 12:09:45 -05004295__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004296{
4297 return 0;
4298}
4299
4300bool
Louis Dionne65358e12021-03-01 12:09:45 -05004301__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004302{
4303 return false;
4304}
4305
4306int
4307__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4308 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4309{
4310 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4311 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4312 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4313}
4314
4315int
Louis Dionne65358e12021-03-01 12:09:45 -05004316__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004317{
4318 if (_Mode_ & consume_header)
4319 return 7;
4320 return 4;
4321}
4322
Howard Hinnantc51e1022010-05-11 19:42:16 +00004323// __narrow_to_utf8<16>
4324
4325__narrow_to_utf8<16>::~__narrow_to_utf8()
4326{
4327}
4328
4329// __narrow_to_utf8<32>
4330
4331__narrow_to_utf8<32>::~__narrow_to_utf8()
4332{
4333}
4334
4335// __widen_from_utf8<16>
4336
4337__widen_from_utf8<16>::~__widen_from_utf8()
4338{
4339}
4340
4341// __widen_from_utf8<32>
4342
4343__widen_from_utf8<32>::~__widen_from_utf8()
4344{
4345}
4346
Eric Fiselierbf945a22016-12-11 00:20:59 +00004347
4348static bool checked_string_to_wchar_convert(wchar_t& dest,
4349 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004350 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004351 if (*ptr == '\0')
4352 return false;
4353 mbstate_t mb = {};
4354 wchar_t out;
4355 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4356 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4357 return false;
4358 }
4359 dest = out;
4360 return true;
4361}
4362
4363static bool checked_string_to_char_convert(char& dest,
4364 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004365 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004366 if (*ptr == '\0')
4367 return false;
4368 if (!ptr[1]) {
4369 dest = *ptr;
4370 return true;
4371 }
4372 // First convert the MBS into a wide char then attempt to narrow it using
4373 // wctob_l.
4374 wchar_t wout;
4375 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4376 return false;
4377 int res;
4378 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4379 dest = res;
4380 return true;
4381 }
4382 // FIXME: Work around specific multibyte sequences that we can reasonable
4383 // translate into a different single byte.
4384 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004385 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004386 case L'\u00A0': // non-breaking space
4387 dest = ' ';
4388 return true;
4389 default:
4390 return false;
4391 }
4392 _LIBCPP_UNREACHABLE();
4393}
4394
4395
Howard Hinnantc51e1022010-05-11 19:42:16 +00004396// numpunct<char> && numpunct<wchar_t>
4397
4398locale::id numpunct< char >::id;
4399locale::id numpunct<wchar_t>::id;
4400
4401numpunct<char>::numpunct(size_t refs)
4402 : locale::facet(refs),
4403 __decimal_point_('.'),
4404 __thousands_sep_(',')
4405{
4406}
4407
4408numpunct<wchar_t>::numpunct(size_t refs)
4409 : locale::facet(refs),
4410 __decimal_point_(L'.'),
4411 __thousands_sep_(L',')
4412{
4413}
4414
4415numpunct<char>::~numpunct()
4416{
4417}
4418
4419numpunct<wchar_t>::~numpunct()
4420{
4421}
4422
4423 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4424wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4425
4426 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4427wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4428
4429string numpunct< char >::do_grouping() const {return __grouping_;}
4430string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4431
4432 string numpunct< char >::do_truename() const {return "true";}
4433wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4434
4435 string numpunct< char >::do_falsename() const {return "false";}
4436wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4437
4438// numpunct_byname<char>
4439
4440numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4441 : numpunct<char>(refs)
4442{
4443 __init(nm);
4444}
4445
4446numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4447 : numpunct<char>(refs)
4448{
4449 __init(nm.c_str());
4450}
4451
4452numpunct_byname<char>::~numpunct_byname()
4453{
4454}
4455
4456void
4457numpunct_byname<char>::__init(const char* nm)
4458{
4459 if (strcmp(nm, "C") != 0)
4460 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004461 __libcpp_unique_locale loc(nm);
4462 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004463 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004464 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004465
Ben Craig3756b922016-03-09 15:39:39 +00004466 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004467 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4468 loc.get());
4469 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4470 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004471 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004472 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004473 }
4474}
4475
4476// numpunct_byname<wchar_t>
4477
4478numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4479 : numpunct<wchar_t>(refs)
4480{
4481 __init(nm);
4482}
4483
4484numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4485 : numpunct<wchar_t>(refs)
4486{
4487 __init(nm.c_str());
4488}
4489
4490numpunct_byname<wchar_t>::~numpunct_byname()
4491{
4492}
4493
4494void
4495numpunct_byname<wchar_t>::__init(const char* nm)
4496{
4497 if (strcmp(nm, "C") != 0)
4498 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004499 __libcpp_unique_locale loc(nm);
4500 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004501 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004502 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004503
Ben Craig3756b922016-03-09 15:39:39 +00004504 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004505 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4506 loc.get());
4507 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4508 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004509 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004510 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004511 }
4512}
4513
4514// num_get helpers
4515
4516int
4517__num_get_base::__get_base(ios_base& iob)
4518{
4519 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4520 if (__basefield == ios_base::oct)
4521 return 8;
4522 else if (__basefield == ios_base::hex)
4523 return 16;
4524 else if (__basefield == 0)
4525 return 0;
4526 return 10;
4527}
4528
4529const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4530
4531void
4532__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4533 ios_base::iostate& __err)
4534{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004535// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4536// 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 +00004537 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004538 {
4539 reverse(__g, __g_end);
4540 const char* __ig = __grouping.data();
4541 const char* __eg = __ig + __grouping.size();
4542 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4543 {
4544 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4545 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004546 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004547 {
4548 __err = ios_base::failbit;
4549 return;
4550 }
4551 }
4552 if (__eg - __ig > 1)
4553 ++__ig;
4554 }
4555 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4556 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004557 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004558 __err = ios_base::failbit;
4559 }
4560 }
4561}
4562
4563void
4564__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4565 ios_base::fmtflags __flags)
4566{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004567 if ((__flags & ios_base::showpos) &&
4568 (__flags & ios_base::basefield) != ios_base::oct &&
4569 (__flags & ios_base::basefield) != ios_base::hex &&
4570 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004571 *__fmtp++ = '+';
4572 if (__flags & ios_base::showbase)
4573 *__fmtp++ = '#';
4574 while(*__len)
4575 *__fmtp++ = *__len++;
4576 if ((__flags & ios_base::basefield) == ios_base::oct)
4577 *__fmtp = 'o';
4578 else if ((__flags & ios_base::basefield) == ios_base::hex)
4579 {
4580 if (__flags & ios_base::uppercase)
4581 *__fmtp = 'X';
4582 else
4583 *__fmtp = 'x';
4584 }
4585 else if (__signd)
4586 *__fmtp = 'd';
4587 else
4588 *__fmtp = 'u';
4589}
4590
4591bool
4592__num_put_base::__format_float(char* __fmtp, const char* __len,
4593 ios_base::fmtflags __flags)
4594{
4595 bool specify_precision = true;
4596 if (__flags & ios_base::showpos)
4597 *__fmtp++ = '+';
4598 if (__flags & ios_base::showpoint)
4599 *__fmtp++ = '#';
4600 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004601 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004602 if (floatfield == (ios_base::fixed | ios_base::scientific))
4603 specify_precision = false;
4604 else
4605 {
4606 *__fmtp++ = '.';
4607 *__fmtp++ = '*';
4608 }
4609 while(*__len)
4610 *__fmtp++ = *__len++;
4611 if (floatfield == ios_base::fixed)
4612 {
4613 if (uppercase)
4614 *__fmtp = 'F';
4615 else
4616 *__fmtp = 'f';
4617 }
4618 else if (floatfield == ios_base::scientific)
4619 {
4620 if (uppercase)
4621 *__fmtp = 'E';
4622 else
4623 *__fmtp = 'e';
4624 }
4625 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4626 {
4627 if (uppercase)
4628 *__fmtp = 'A';
4629 else
4630 *__fmtp = 'a';
4631 }
4632 else
4633 {
4634 if (uppercase)
4635 *__fmtp = 'G';
4636 else
4637 *__fmtp = 'g';
4638 }
4639 return specify_precision;
4640}
4641
4642char*
4643__num_put_base::__identify_padding(char* __nb, char* __ne,
4644 const ios_base& __iob)
4645{
4646 switch (__iob.flags() & ios_base::adjustfield)
4647 {
4648 case ios_base::internal:
4649 if (__nb[0] == '-' || __nb[0] == '+')
4650 return __nb+1;
4651 if (__ne - __nb >= 2 && __nb[0] == '0'
4652 && (__nb[1] == 'x' || __nb[1] == 'X'))
4653 return __nb+2;
4654 break;
4655 case ios_base::left:
4656 return __ne;
4657 case ios_base::right:
4658 default:
4659 break;
4660 }
4661 return __nb;
4662}
4663
4664// time_get
4665
4666static
4667string*
4668init_weeks()
4669{
4670 static string weeks[14];
4671 weeks[0] = "Sunday";
4672 weeks[1] = "Monday";
4673 weeks[2] = "Tuesday";
4674 weeks[3] = "Wednesday";
4675 weeks[4] = "Thursday";
4676 weeks[5] = "Friday";
4677 weeks[6] = "Saturday";
4678 weeks[7] = "Sun";
4679 weeks[8] = "Mon";
4680 weeks[9] = "Tue";
4681 weeks[10] = "Wed";
4682 weeks[11] = "Thu";
4683 weeks[12] = "Fri";
4684 weeks[13] = "Sat";
4685 return weeks;
4686}
4687
4688static
4689wstring*
4690init_wweeks()
4691{
4692 static wstring weeks[14];
4693 weeks[0] = L"Sunday";
4694 weeks[1] = L"Monday";
4695 weeks[2] = L"Tuesday";
4696 weeks[3] = L"Wednesday";
4697 weeks[4] = L"Thursday";
4698 weeks[5] = L"Friday";
4699 weeks[6] = L"Saturday";
4700 weeks[7] = L"Sun";
4701 weeks[8] = L"Mon";
4702 weeks[9] = L"Tue";
4703 weeks[10] = L"Wed";
4704 weeks[11] = L"Thu";
4705 weeks[12] = L"Fri";
4706 weeks[13] = L"Sat";
4707 return weeks;
4708}
4709
4710template <>
4711const string*
4712__time_get_c_storage<char>::__weeks() const
4713{
4714 static const string* weeks = init_weeks();
4715 return weeks;
4716}
4717
4718template <>
4719const wstring*
4720__time_get_c_storage<wchar_t>::__weeks() const
4721{
4722 static const wstring* weeks = init_wweeks();
4723 return weeks;
4724}
4725
4726static
4727string*
4728init_months()
4729{
4730 static string months[24];
4731 months[0] = "January";
4732 months[1] = "February";
4733 months[2] = "March";
4734 months[3] = "April";
4735 months[4] = "May";
4736 months[5] = "June";
4737 months[6] = "July";
4738 months[7] = "August";
4739 months[8] = "September";
4740 months[9] = "October";
4741 months[10] = "November";
4742 months[11] = "December";
4743 months[12] = "Jan";
4744 months[13] = "Feb";
4745 months[14] = "Mar";
4746 months[15] = "Apr";
4747 months[16] = "May";
4748 months[17] = "Jun";
4749 months[18] = "Jul";
4750 months[19] = "Aug";
4751 months[20] = "Sep";
4752 months[21] = "Oct";
4753 months[22] = "Nov";
4754 months[23] = "Dec";
4755 return months;
4756}
4757
4758static
4759wstring*
4760init_wmonths()
4761{
4762 static wstring months[24];
4763 months[0] = L"January";
4764 months[1] = L"February";
4765 months[2] = L"March";
4766 months[3] = L"April";
4767 months[4] = L"May";
4768 months[5] = L"June";
4769 months[6] = L"July";
4770 months[7] = L"August";
4771 months[8] = L"September";
4772 months[9] = L"October";
4773 months[10] = L"November";
4774 months[11] = L"December";
4775 months[12] = L"Jan";
4776 months[13] = L"Feb";
4777 months[14] = L"Mar";
4778 months[15] = L"Apr";
4779 months[16] = L"May";
4780 months[17] = L"Jun";
4781 months[18] = L"Jul";
4782 months[19] = L"Aug";
4783 months[20] = L"Sep";
4784 months[21] = L"Oct";
4785 months[22] = L"Nov";
4786 months[23] = L"Dec";
4787 return months;
4788}
4789
4790template <>
4791const string*
4792__time_get_c_storage<char>::__months() const
4793{
4794 static const string* months = init_months();
4795 return months;
4796}
4797
4798template <>
4799const wstring*
4800__time_get_c_storage<wchar_t>::__months() const
4801{
4802 static const wstring* months = init_wmonths();
4803 return months;
4804}
4805
4806static
4807string*
4808init_am_pm()
4809{
Marshall Clow5cc04922018-01-11 17:16:52 +00004810 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004811 am_pm[0] = "AM";
4812 am_pm[1] = "PM";
4813 return am_pm;
4814}
4815
4816static
4817wstring*
4818init_wam_pm()
4819{
Marshall Clow5cc04922018-01-11 17:16:52 +00004820 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004821 am_pm[0] = L"AM";
4822 am_pm[1] = L"PM";
4823 return am_pm;
4824}
4825
4826template <>
4827const string*
4828__time_get_c_storage<char>::__am_pm() const
4829{
4830 static const string* am_pm = init_am_pm();
4831 return am_pm;
4832}
4833
4834template <>
4835const wstring*
4836__time_get_c_storage<wchar_t>::__am_pm() const
4837{
4838 static const wstring* am_pm = init_wam_pm();
4839 return am_pm;
4840}
4841
4842template <>
4843const string&
4844__time_get_c_storage<char>::__x() const
4845{
4846 static string s("%m/%d/%y");
4847 return s;
4848}
4849
4850template <>
4851const wstring&
4852__time_get_c_storage<wchar_t>::__x() const
4853{
4854 static wstring s(L"%m/%d/%y");
4855 return s;
4856}
4857
4858template <>
4859const string&
4860__time_get_c_storage<char>::__X() const
4861{
4862 static string s("%H:%M:%S");
4863 return s;
4864}
4865
4866template <>
4867const wstring&
4868__time_get_c_storage<wchar_t>::__X() const
4869{
4870 static wstring s(L"%H:%M:%S");
4871 return s;
4872}
4873
4874template <>
4875const string&
4876__time_get_c_storage<char>::__c() const
4877{
4878 static string s("%a %b %d %H:%M:%S %Y");
4879 return s;
4880}
4881
4882template <>
4883const wstring&
4884__time_get_c_storage<wchar_t>::__c() const
4885{
4886 static wstring s(L"%a %b %d %H:%M:%S %Y");
4887 return s;
4888}
4889
4890template <>
4891const string&
4892__time_get_c_storage<char>::__r() const
4893{
4894 static string s("%I:%M:%S %p");
4895 return s;
4896}
4897
4898template <>
4899const wstring&
4900__time_get_c_storage<wchar_t>::__r() const
4901{
4902 static wstring s(L"%I:%M:%S %p");
4903 return s;
4904}
4905
4906// time_get_byname
4907
4908__time_get::__time_get(const char* nm)
4909 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4910{
4911 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004912 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004913 " failed to construct for " + string(nm));
4914}
4915
4916__time_get::__time_get(const string& nm)
4917 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4918{
4919 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004920 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004921 " failed to construct for " + nm);
4922}
4923
4924__time_get::~__time_get()
4925{
4926 freelocale(__loc_);
4927}
Marshall Clowd920eea2013-10-21 15:07:28 +00004928#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004929#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004930#endif
4931#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004932#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004933#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004934
Howard Hinnantc51e1022010-05-11 19:42:16 +00004935template <>
4936string
4937__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4938{
Howard Hinnant990207c2012-02-19 14:55:32 +00004939 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004940 t.tm_sec = 59;
4941 t.tm_min = 55;
4942 t.tm_hour = 23;
4943 t.tm_mday = 31;
4944 t.tm_mon = 11;
4945 t.tm_year = 161;
4946 t.tm_wday = 6;
4947 t.tm_yday = 364;
4948 t.tm_isdst = -1;
4949 char buf[100];
4950 char f[3] = {0};
4951 f[0] = '%';
4952 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004953 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004954 char* bb = buf;
4955 char* be = buf + n;
4956 string result;
4957 while (bb != be)
4958 {
4959 if (ct.is(ctype_base::space, *bb))
4960 {
4961 result.push_back(' ');
4962 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4963 ;
4964 continue;
4965 }
4966 char* w = bb;
4967 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004968 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004969 ct, err, false)
4970 - this->__weeks_;
4971 if (i < 14)
4972 {
4973 result.push_back('%');
4974 if (i < 7)
4975 result.push_back('A');
4976 else
4977 result.push_back('a');
4978 bb = w;
4979 continue;
4980 }
4981 w = bb;
4982 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4983 ct, err, false)
4984 - this->__months_;
4985 if (i < 24)
4986 {
4987 result.push_back('%');
4988 if (i < 12)
4989 result.push_back('B');
4990 else
4991 result.push_back('b');
4992 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4993 result.back() = 'm';
4994 bb = w;
4995 continue;
4996 }
4997 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4998 {
4999 w = bb;
5000 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5001 ct, err, false) - this->__am_pm_;
5002 if (i < 2)
5003 {
5004 result.push_back('%');
5005 result.push_back('p');
5006 bb = w;
5007 continue;
5008 }
5009 }
5010 w = bb;
5011 if (ct.is(ctype_base::digit, *bb))
5012 {
5013 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5014 {
5015 case 6:
5016 result.push_back('%');
5017 result.push_back('w');
5018 break;
5019 case 7:
5020 result.push_back('%');
5021 result.push_back('u');
5022 break;
5023 case 11:
5024 result.push_back('%');
5025 result.push_back('I');
5026 break;
5027 case 12:
5028 result.push_back('%');
5029 result.push_back('m');
5030 break;
5031 case 23:
5032 result.push_back('%');
5033 result.push_back('H');
5034 break;
5035 case 31:
5036 result.push_back('%');
5037 result.push_back('d');
5038 break;
5039 case 55:
5040 result.push_back('%');
5041 result.push_back('M');
5042 break;
5043 case 59:
5044 result.push_back('%');
5045 result.push_back('S');
5046 break;
5047 case 61:
5048 result.push_back('%');
5049 result.push_back('y');
5050 break;
5051 case 364:
5052 result.push_back('%');
5053 result.push_back('j');
5054 break;
5055 case 2061:
5056 result.push_back('%');
5057 result.push_back('Y');
5058 break;
5059 default:
5060 for (; w != bb; ++w)
5061 result.push_back(*w);
5062 break;
5063 }
5064 continue;
5065 }
5066 if (*bb == '%')
5067 {
5068 result.push_back('%');
5069 result.push_back('%');
5070 ++bb;
5071 continue;
5072 }
5073 result.push_back(*bb);
5074 ++bb;
5075 }
5076 return result;
5077}
5078
Marshall Clowd920eea2013-10-21 15:07:28 +00005079#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005080#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005081#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005082
Howard Hinnantc51e1022010-05-11 19:42:16 +00005083template <>
5084wstring
5085__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5086{
Howard Hinnant990207c2012-02-19 14:55:32 +00005087 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005088 t.tm_sec = 59;
5089 t.tm_min = 55;
5090 t.tm_hour = 23;
5091 t.tm_mday = 31;
5092 t.tm_mon = 11;
5093 t.tm_year = 161;
5094 t.tm_wday = 6;
5095 t.tm_yday = 364;
5096 t.tm_isdst = -1;
5097 char buf[100];
5098 char f[3] = {0};
5099 f[0] = '%';
5100 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005101 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005102 wchar_t wbuf[100];
5103 wchar_t* wbb = wbuf;
5104 mbstate_t mb = {0};
5105 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005106 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005107 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005108 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005109 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005110 wstring result;
5111 while (wbb != wbe)
5112 {
5113 if (ct.is(ctype_base::space, *wbb))
5114 {
5115 result.push_back(L' ');
5116 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5117 ;
5118 continue;
5119 }
5120 wchar_t* w = wbb;
5121 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005122 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005123 ct, err, false)
5124 - this->__weeks_;
5125 if (i < 14)
5126 {
5127 result.push_back(L'%');
5128 if (i < 7)
5129 result.push_back(L'A');
5130 else
5131 result.push_back(L'a');
5132 wbb = w;
5133 continue;
5134 }
5135 w = wbb;
5136 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5137 ct, err, false)
5138 - this->__months_;
5139 if (i < 24)
5140 {
5141 result.push_back(L'%');
5142 if (i < 12)
5143 result.push_back(L'B');
5144 else
5145 result.push_back(L'b');
5146 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5147 result.back() = L'm';
5148 wbb = w;
5149 continue;
5150 }
5151 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5152 {
5153 w = wbb;
5154 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5155 ct, err, false) - this->__am_pm_;
5156 if (i < 2)
5157 {
5158 result.push_back(L'%');
5159 result.push_back(L'p');
5160 wbb = w;
5161 continue;
5162 }
5163 }
5164 w = wbb;
5165 if (ct.is(ctype_base::digit, *wbb))
5166 {
5167 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5168 {
5169 case 6:
5170 result.push_back(L'%');
5171 result.push_back(L'w');
5172 break;
5173 case 7:
5174 result.push_back(L'%');
5175 result.push_back(L'u');
5176 break;
5177 case 11:
5178 result.push_back(L'%');
5179 result.push_back(L'I');
5180 break;
5181 case 12:
5182 result.push_back(L'%');
5183 result.push_back(L'm');
5184 break;
5185 case 23:
5186 result.push_back(L'%');
5187 result.push_back(L'H');
5188 break;
5189 case 31:
5190 result.push_back(L'%');
5191 result.push_back(L'd');
5192 break;
5193 case 55:
5194 result.push_back(L'%');
5195 result.push_back(L'M');
5196 break;
5197 case 59:
5198 result.push_back(L'%');
5199 result.push_back(L'S');
5200 break;
5201 case 61:
5202 result.push_back(L'%');
5203 result.push_back(L'y');
5204 break;
5205 case 364:
5206 result.push_back(L'%');
5207 result.push_back(L'j');
5208 break;
5209 case 2061:
5210 result.push_back(L'%');
5211 result.push_back(L'Y');
5212 break;
5213 default:
5214 for (; w != wbb; ++w)
5215 result.push_back(*w);
5216 break;
5217 }
5218 continue;
5219 }
5220 if (ct.narrow(*wbb, 0) == '%')
5221 {
5222 result.push_back(L'%');
5223 result.push_back(L'%');
5224 ++wbb;
5225 continue;
5226 }
5227 result.push_back(*wbb);
5228 ++wbb;
5229 }
5230 return result;
5231}
5232
5233template <>
5234void
5235__time_get_storage<char>::init(const ctype<char>& ct)
5236{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005237 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005238 char buf[100];
5239 // __weeks_
5240 for (int i = 0; i < 7; ++i)
5241 {
5242 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005243 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005244 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005245 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005246 __weeks_[i+7] = buf;
5247 }
5248 // __months_
5249 for (int i = 0; i < 12; ++i)
5250 {
5251 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005252 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005253 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005254 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005255 __months_[i+12] = buf;
5256 }
5257 // __am_pm_
5258 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005259 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005260 __am_pm_[0] = buf;
5261 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005262 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005263 __am_pm_[1] = buf;
5264 __c_ = __analyze('c', ct);
5265 __r_ = __analyze('r', ct);
5266 __x_ = __analyze('x', ct);
5267 __X_ = __analyze('X', ct);
5268}
5269
5270template <>
5271void
5272__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5273{
5274 tm t = {0};
5275 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005276 wchar_t wbuf[100];
5277 wchar_t* wbe;
5278 mbstate_t mb = {0};
5279 // __weeks_
5280 for (int i = 0; i < 7; ++i)
5281 {
5282 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005283 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005284 mb = mbstate_t();
5285 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005286 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005287 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005288 __throw_runtime_error("locale not supported");
5289 wbe = wbuf + j;
5290 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005291 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005292 mb = mbstate_t();
5293 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005294 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005295 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005296 __throw_runtime_error("locale not supported");
5297 wbe = wbuf + j;
5298 __weeks_[i+7].assign(wbuf, wbe);
5299 }
5300 // __months_
5301 for (int i = 0; i < 12; ++i)
5302 {
5303 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005304 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005305 mb = mbstate_t();
5306 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005307 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005308 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005309 __throw_runtime_error("locale not supported");
5310 wbe = wbuf + j;
5311 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005312 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005313 mb = mbstate_t();
5314 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005315 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005316 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005317 __throw_runtime_error("locale not supported");
5318 wbe = wbuf + j;
5319 __months_[i+12].assign(wbuf, wbe);
5320 }
5321 // __am_pm_
5322 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005323 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005324 mb = mbstate_t();
5325 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005326 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005327 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005328 __throw_runtime_error("locale not supported");
5329 wbe = wbuf + j;
5330 __am_pm_[0].assign(wbuf, wbe);
5331 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005332 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005333 mb = mbstate_t();
5334 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005335 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005336 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005337 __throw_runtime_error("locale not supported");
5338 wbe = wbuf + j;
5339 __am_pm_[1].assign(wbuf, wbe);
5340 __c_ = __analyze('c', ct);
5341 __r_ = __analyze('r', ct);
5342 __x_ = __analyze('x', ct);
5343 __X_ = __analyze('X', ct);
5344}
5345
5346template <class CharT>
5347struct _LIBCPP_HIDDEN __time_get_temp
5348 : public ctype_byname<CharT>
5349{
5350 explicit __time_get_temp(const char* nm)
5351 : ctype_byname<CharT>(nm, 1) {}
5352 explicit __time_get_temp(const string& nm)
5353 : ctype_byname<CharT>(nm, 1) {}
5354};
5355
5356template <>
5357__time_get_storage<char>::__time_get_storage(const char* __nm)
5358 : __time_get(__nm)
5359{
5360 const __time_get_temp<char> ct(__nm);
5361 init(ct);
5362}
5363
5364template <>
5365__time_get_storage<char>::__time_get_storage(const string& __nm)
5366 : __time_get(__nm)
5367{
5368 const __time_get_temp<char> ct(__nm);
5369 init(ct);
5370}
5371
5372template <>
5373__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5374 : __time_get(__nm)
5375{
5376 const __time_get_temp<wchar_t> ct(__nm);
5377 init(ct);
5378}
5379
5380template <>
5381__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5382 : __time_get(__nm)
5383{
5384 const __time_get_temp<wchar_t> ct(__nm);
5385 init(ct);
5386}
5387
5388template <>
5389time_base::dateorder
5390__time_get_storage<char>::__do_date_order() const
5391{
5392 unsigned i;
5393 for (i = 0; i < __x_.size(); ++i)
5394 if (__x_[i] == '%')
5395 break;
5396 ++i;
5397 switch (__x_[i])
5398 {
5399 case 'y':
5400 case 'Y':
5401 for (++i; i < __x_.size(); ++i)
5402 if (__x_[i] == '%')
5403 break;
5404 if (i == __x_.size())
5405 break;
5406 ++i;
5407 switch (__x_[i])
5408 {
5409 case 'm':
5410 for (++i; i < __x_.size(); ++i)
5411 if (__x_[i] == '%')
5412 break;
5413 if (i == __x_.size())
5414 break;
5415 ++i;
5416 if (__x_[i] == 'd')
5417 return time_base::ymd;
5418 break;
5419 case 'd':
5420 for (++i; i < __x_.size(); ++i)
5421 if (__x_[i] == '%')
5422 break;
5423 if (i == __x_.size())
5424 break;
5425 ++i;
5426 if (__x_[i] == 'm')
5427 return time_base::ydm;
5428 break;
5429 }
5430 break;
5431 case 'm':
5432 for (++i; i < __x_.size(); ++i)
5433 if (__x_[i] == '%')
5434 break;
5435 if (i == __x_.size())
5436 break;
5437 ++i;
5438 if (__x_[i] == 'd')
5439 {
5440 for (++i; i < __x_.size(); ++i)
5441 if (__x_[i] == '%')
5442 break;
5443 if (i == __x_.size())
5444 break;
5445 ++i;
5446 if (__x_[i] == 'y' || __x_[i] == 'Y')
5447 return time_base::mdy;
5448 break;
5449 }
5450 break;
5451 case 'd':
5452 for (++i; i < __x_.size(); ++i)
5453 if (__x_[i] == '%')
5454 break;
5455 if (i == __x_.size())
5456 break;
5457 ++i;
5458 if (__x_[i] == 'm')
5459 {
5460 for (++i; i < __x_.size(); ++i)
5461 if (__x_[i] == '%')
5462 break;
5463 if (i == __x_.size())
5464 break;
5465 ++i;
5466 if (__x_[i] == 'y' || __x_[i] == 'Y')
5467 return time_base::dmy;
5468 break;
5469 }
5470 break;
5471 }
5472 return time_base::no_order;
5473}
5474
5475template <>
5476time_base::dateorder
5477__time_get_storage<wchar_t>::__do_date_order() const
5478{
5479 unsigned i;
5480 for (i = 0; i < __x_.size(); ++i)
5481 if (__x_[i] == L'%')
5482 break;
5483 ++i;
5484 switch (__x_[i])
5485 {
5486 case L'y':
5487 case L'Y':
5488 for (++i; i < __x_.size(); ++i)
5489 if (__x_[i] == L'%')
5490 break;
5491 if (i == __x_.size())
5492 break;
5493 ++i;
5494 switch (__x_[i])
5495 {
5496 case L'm':
5497 for (++i; i < __x_.size(); ++i)
5498 if (__x_[i] == L'%')
5499 break;
5500 if (i == __x_.size())
5501 break;
5502 ++i;
5503 if (__x_[i] == L'd')
5504 return time_base::ymd;
5505 break;
5506 case L'd':
5507 for (++i; i < __x_.size(); ++i)
5508 if (__x_[i] == L'%')
5509 break;
5510 if (i == __x_.size())
5511 break;
5512 ++i;
5513 if (__x_[i] == L'm')
5514 return time_base::ydm;
5515 break;
5516 }
5517 break;
5518 case L'm':
5519 for (++i; i < __x_.size(); ++i)
5520 if (__x_[i] == L'%')
5521 break;
5522 if (i == __x_.size())
5523 break;
5524 ++i;
5525 if (__x_[i] == L'd')
5526 {
5527 for (++i; i < __x_.size(); ++i)
5528 if (__x_[i] == L'%')
5529 break;
5530 if (i == __x_.size())
5531 break;
5532 ++i;
5533 if (__x_[i] == L'y' || __x_[i] == L'Y')
5534 return time_base::mdy;
5535 break;
5536 }
5537 break;
5538 case L'd':
5539 for (++i; i < __x_.size(); ++i)
5540 if (__x_[i] == L'%')
5541 break;
5542 if (i == __x_.size())
5543 break;
5544 ++i;
5545 if (__x_[i] == L'm')
5546 {
5547 for (++i; i < __x_.size(); ++i)
5548 if (__x_[i] == L'%')
5549 break;
5550 if (i == __x_.size())
5551 break;
5552 ++i;
5553 if (__x_[i] == L'y' || __x_[i] == L'Y')
5554 return time_base::dmy;
5555 break;
5556 }
5557 break;
5558 }
5559 return time_base::no_order;
5560}
5561
5562// time_put
5563
5564__time_put::__time_put(const char* nm)
5565 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5566{
5567 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005568 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005569 " failed to construct for " + string(nm));
5570}
5571
5572__time_put::__time_put(const string& nm)
5573 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5574{
5575 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005576 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 " failed to construct for " + nm);
5578}
5579
5580__time_put::~__time_put()
5581{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005582 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005583 freelocale(__loc_);
5584}
5585
5586void
5587__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5588 char __fmt, char __mod) const
5589{
5590 char fmt[] = {'%', __fmt, __mod, 0};
5591 if (__mod != 0)
5592 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005593 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005594 __ne = __nb + n;
5595}
5596
5597void
5598__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5599 char __fmt, char __mod) const
5600{
5601 char __nar[100];
5602 char* __ne = __nar + 100;
5603 __do_put(__nar, __ne, __tm, __fmt, __mod);
5604 mbstate_t mb = {0};
5605 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005606 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005607 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005608 __throw_runtime_error("locale not supported");
5609 __we = __wb + j;
5610}
5611
5612// moneypunct_byname
5613
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005614template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005615static
5616void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005617__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5618 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5619 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005620{
5621 const char sign = static_cast<char>(money_base::sign);
5622 const char space = static_cast<char>(money_base::space);
5623 const char none = static_cast<char>(money_base::none);
5624 const char symbol = static_cast<char>(money_base::symbol);
5625 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005626 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5627
5628 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5629 // function'. "Space between sign and symbol or value" means that
5630 // if the sign is adjacent to the symbol, there's a space between
5631 // them, and otherwise there's a space between the sign and value.
5632 //
5633 // C11's localeconv specifies that the fourth character of an
5634 // international curr_symbol is used to separate the sign and
5635 // value when sep_by_space says to do so. C++ can't represent
5636 // that, so we just use a space. When sep_by_space says to
5637 // separate the symbol and value-or-sign with a space, we rearrange the
5638 // curr_symbol to put its spacing character on the correct side of
5639 // the symbol.
5640 //
5641 // We also need to avoid adding an extra space between the sign
5642 // and value when the currency symbol is suppressed (by not
5643 // setting showbase). We match glibc's strfmon by interpreting
5644 // sep_by_space==1 as "omit the space when the currency symbol is
5645 // absent".
5646 //
5647 // Users who want to get this right should use ICU instead.
5648
Howard Hinnantc51e1022010-05-11 19:42:16 +00005649 switch (cs_precedes)
5650 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005651 case 0: // value before curr_symbol
5652 if (symbol_contains_sep) {
5653 // Move the separator to before the symbol, to place it
5654 // between the value and symbol.
5655 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5656 __curr_symbol_.end());
5657 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005658 switch (sign_posn)
5659 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005660 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005661 pat.field[0] = sign;
5662 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005663 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005664 pat.field[3] = symbol;
5665 switch (sep_by_space)
5666 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005667 case 0: // No space separates the currency symbol and value.
5668 // This case may have changed between C99 and C11;
5669 // assume the currency symbol matches the intention.
5670 case 2: // Space between sign and currency or value.
5671 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005672 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005673 case 1: // Space between currency-and-sign or currency and value.
5674 if (!symbol_contains_sep) {
5675 // We insert the space into the symbol instead of
5676 // setting pat.field[2]=space so that when
5677 // showbase is not set, the space goes away too.
5678 __curr_symbol_.insert(0, 1, space_char);
5679 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005680 return;
5681 default:
5682 break;
5683 }
5684 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005685 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005686 pat.field[0] = sign;
5687 pat.field[3] = symbol;
5688 switch (sep_by_space)
5689 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005690 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005691 pat.field[1] = value;
5692 pat.field[2] = none;
5693 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005694 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005695 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005696 pat.field[2] = none;
5697 if (!symbol_contains_sep) {
5698 // We insert the space into the symbol instead of
5699 // setting pat.field[2]=space so that when
5700 // showbase is not set, the space goes away too.
5701 __curr_symbol_.insert(0, 1, space_char);
5702 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005703 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005704 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005705 pat.field[1] = space;
5706 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005707 if (symbol_contains_sep) {
5708 // Remove the separator from the symbol, since it
5709 // has already appeared after the sign.
5710 __curr_symbol_.erase(__curr_symbol_.begin());
5711 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005712 return;
5713 default:
5714 break;
5715 }
5716 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005717 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005718 pat.field[0] = value;
5719 pat.field[3] = sign;
5720 switch (sep_by_space)
5721 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005722 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005723 pat.field[1] = none;
5724 pat.field[2] = symbol;
5725 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005726 case 1: // Space between currency-and-sign or currency and value.
5727 if (!symbol_contains_sep) {
5728 // We insert the space into the symbol instead of
5729 // setting pat.field[1]=space so that when
5730 // showbase is not set, the space goes away too.
5731 __curr_symbol_.insert(0, 1, space_char);
5732 }
5733 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005734 pat.field[2] = symbol;
5735 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005736 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005737 pat.field[1] = symbol;
5738 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005739 if (symbol_contains_sep) {
5740 // Remove the separator from the symbol, since it
5741 // should not be removed if showbase is absent.
5742 __curr_symbol_.erase(__curr_symbol_.begin());
5743 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005744 return;
5745 default:
5746 break;
5747 }
5748 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005749 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005750 pat.field[0] = value;
5751 pat.field[3] = symbol;
5752 switch (sep_by_space)
5753 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005754 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005755 pat.field[1] = none;
5756 pat.field[2] = sign;
5757 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005758 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005759 pat.field[1] = space;
5760 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005761 if (symbol_contains_sep) {
5762 // Remove the separator from the symbol, since it
5763 // has already appeared before the sign.
5764 __curr_symbol_.erase(__curr_symbol_.begin());
5765 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005766 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005767 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005768 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005769 pat.field[2] = none;
5770 if (!symbol_contains_sep) {
5771 // We insert the space into the symbol instead of
5772 // setting pat.field[2]=space so that when
5773 // showbase is not set, the space goes away too.
5774 __curr_symbol_.insert(0, 1, space_char);
5775 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005776 return;
5777 default:
5778 break;
5779 }
5780 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005781 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005782 pat.field[0] = value;
5783 pat.field[3] = sign;
5784 switch (sep_by_space)
5785 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005786 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005787 pat.field[1] = none;
5788 pat.field[2] = symbol;
5789 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005790 case 1: // Space between currency-and-sign or currency and value.
5791 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005792 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005793 if (!symbol_contains_sep) {
5794 // We insert the space into the symbol instead of
5795 // setting pat.field[1]=space so that when
5796 // showbase is not set, the space goes away too.
5797 __curr_symbol_.insert(0, 1, space_char);
5798 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005799 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005800 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005801 pat.field[1] = symbol;
5802 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005803 if (symbol_contains_sep) {
5804 // Remove the separator from the symbol, since it
5805 // should not disappear when showbase is absent.
5806 __curr_symbol_.erase(__curr_symbol_.begin());
5807 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005808 return;
5809 default:
5810 break;
5811 }
5812 break;
5813 default:
5814 break;
5815 }
5816 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005817 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005818 switch (sign_posn)
5819 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005820 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005821 pat.field[0] = sign;
5822 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005823 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005824 pat.field[3] = value;
5825 switch (sep_by_space)
5826 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005827 case 0: // No space separates the currency symbol and value.
5828 // This case may have changed between C99 and C11;
5829 // assume the currency symbol matches the intention.
5830 case 2: // Space between sign and currency or value.
5831 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005832 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005833 case 1: // Space between currency-and-sign or currency and value.
5834 if (!symbol_contains_sep) {
5835 // We insert the space into the symbol instead of
5836 // setting pat.field[2]=space so that when
5837 // showbase is not set, the space goes away too.
5838 __curr_symbol_.insert(0, 1, space_char);
5839 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005840 return;
5841 default:
5842 break;
5843 }
5844 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005845 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005846 pat.field[0] = sign;
5847 pat.field[3] = value;
5848 switch (sep_by_space)
5849 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005850 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005851 pat.field[1] = symbol;
5852 pat.field[2] = none;
5853 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005854 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005855 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005856 pat.field[2] = none;
5857 if (!symbol_contains_sep) {
5858 // We insert the space into the symbol instead of
5859 // setting pat.field[2]=space so that when
5860 // showbase is not set, the space goes away too.
5861 __curr_symbol_.push_back(space_char);
5862 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005863 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005864 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005865 pat.field[1] = space;
5866 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005867 if (symbol_contains_sep) {
5868 // Remove the separator from the symbol, since it
5869 // has already appeared after the sign.
5870 __curr_symbol_.pop_back();
5871 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005872 return;
5873 default:
5874 break;
5875 }
5876 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005877 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005878 pat.field[0] = symbol;
5879 pat.field[3] = sign;
5880 switch (sep_by_space)
5881 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005882 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005883 pat.field[1] = none;
5884 pat.field[2] = value;
5885 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005886 case 1: // Space between currency-and-sign or currency and value.
5887 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005888 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005889 if (!symbol_contains_sep) {
5890 // We insert the space into the symbol instead of
5891 // setting pat.field[1]=space so that when
5892 // showbase is not set, the space goes away too.
5893 __curr_symbol_.push_back(space_char);
5894 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005895 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005896 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005897 pat.field[1] = value;
5898 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005899 if (symbol_contains_sep) {
5900 // Remove the separator from the symbol, since it
5901 // will appear before the sign.
5902 __curr_symbol_.pop_back();
5903 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005904 return;
5905 default:
5906 break;
5907 }
5908 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005909 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005910 pat.field[0] = sign;
5911 pat.field[3] = value;
5912 switch (sep_by_space)
5913 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005914 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005915 pat.field[1] = symbol;
5916 pat.field[2] = none;
5917 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005918 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005919 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005920 pat.field[2] = none;
5921 if (!symbol_contains_sep) {
5922 // We insert the space into the symbol instead of
5923 // setting pat.field[2]=space so that when
5924 // showbase is not set, the space goes away too.
5925 __curr_symbol_.push_back(space_char);
5926 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005927 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005928 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005929 pat.field[1] = space;
5930 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005931 if (symbol_contains_sep) {
5932 // Remove the separator from the symbol, since it
5933 // has already appeared after the sign.
5934 __curr_symbol_.pop_back();
5935 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005936 return;
5937 default:
5938 break;
5939 }
5940 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005941 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005942 pat.field[0] = symbol;
5943 pat.field[3] = value;
5944 switch (sep_by_space)
5945 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005946 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 pat.field[1] = sign;
5948 pat.field[2] = none;
5949 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005950 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005951 pat.field[1] = sign;
5952 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005953 if (symbol_contains_sep) {
5954 // Remove the separator from the symbol, since it
5955 // should not disappear when showbase is absent.
5956 __curr_symbol_.pop_back();
5957 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005958 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005959 case 2: // Space between sign and currency or value.
5960 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005961 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005962 if (!symbol_contains_sep) {
5963 // We insert the space into the symbol instead of
5964 // setting pat.field[1]=space so that when
5965 // showbase is not set, the space goes away too.
5966 __curr_symbol_.push_back(space_char);
5967 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005968 return;
5969 default:
5970 break;
5971 }
5972 break;
5973 default:
5974 break;
5975 }
5976 break;
5977 default:
5978 break;
5979 }
5980 pat.field[0] = symbol;
5981 pat.field[1] = sign;
5982 pat.field[2] = none;
5983 pat.field[3] = value;
5984}
5985
5986template<>
5987void
5988moneypunct_byname<char, false>::init(const char* nm)
5989{
5990 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005991 __libcpp_unique_locale loc(nm);
5992 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005993 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005994 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005995
Ben Craig3756b922016-03-09 15:39:39 +00005996 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005997 if (!checked_string_to_char_convert(__decimal_point_,
5998 lc->mon_decimal_point,
5999 loc.get()))
6000 __decimal_point_ = base::do_decimal_point();
6001 if (!checked_string_to_char_convert(__thousands_sep_,
6002 lc->mon_thousands_sep,
6003 loc.get()))
6004 __thousands_sep_ = base::do_thousands_sep();
6005
Howard Hinnantc51e1022010-05-11 19:42:16 +00006006 __grouping_ = lc->mon_grouping;
6007 __curr_symbol_ = lc->currency_symbol;
6008 if (lc->frac_digits != CHAR_MAX)
6009 __frac_digits_ = lc->frac_digits;
6010 else
6011 __frac_digits_ = base::do_frac_digits();
6012 if (lc->p_sign_posn == 0)
6013 __positive_sign_ = "()";
6014 else
6015 __positive_sign_ = lc->positive_sign;
6016 if (lc->n_sign_posn == 0)
6017 __negative_sign_ = "()";
6018 else
6019 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006020 // Assume the positive and negative formats will want spaces in
6021 // the same places in curr_symbol since there's no way to
6022 // represent anything else.
6023 string_type __dummy_curr_symbol = __curr_symbol_;
6024 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6025 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6026 __init_pat(__neg_format_, __curr_symbol_, false,
6027 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006028}
6029
6030template<>
6031void
6032moneypunct_byname<char, true>::init(const char* nm)
6033{
6034 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006035 __libcpp_unique_locale loc(nm);
6036 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006037 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006038 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006039
Ben Craig3756b922016-03-09 15:39:39 +00006040 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006041 if (!checked_string_to_char_convert(__decimal_point_,
6042 lc->mon_decimal_point,
6043 loc.get()))
6044 __decimal_point_ = base::do_decimal_point();
6045 if (!checked_string_to_char_convert(__thousands_sep_,
6046 lc->mon_thousands_sep,
6047 loc.get()))
6048 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006049 __grouping_ = lc->mon_grouping;
6050 __curr_symbol_ = lc->int_curr_symbol;
6051 if (lc->int_frac_digits != CHAR_MAX)
6052 __frac_digits_ = lc->int_frac_digits;
6053 else
6054 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006055#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006056 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006057#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006058 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006059#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006060 __positive_sign_ = "()";
6061 else
6062 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006063#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006064 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006065#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006066 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006067#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006068 __negative_sign_ = "()";
6069 else
6070 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006071 // Assume the positive and negative formats will want spaces in
6072 // the same places in curr_symbol since there's no way to
6073 // represent anything else.
6074 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006075#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006076 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6077 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6078 __init_pat(__neg_format_, __curr_symbol_, true,
6079 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006080#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006081 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6082 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6083 lc->int_p_sign_posn, ' ');
6084 __init_pat(__neg_format_, __curr_symbol_, true,
6085 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6086 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006087#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006088}
6089
6090template<>
6091void
6092moneypunct_byname<wchar_t, false>::init(const char* nm)
6093{
6094 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006095 __libcpp_unique_locale loc(nm);
6096 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006097 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006098 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006099 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006100 if (!checked_string_to_wchar_convert(__decimal_point_,
6101 lc->mon_decimal_point,
6102 loc.get()))
6103 __decimal_point_ = base::do_decimal_point();
6104 if (!checked_string_to_wchar_convert(__thousands_sep_,
6105 lc->mon_thousands_sep,
6106 loc.get()))
6107 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006108 __grouping_ = lc->mon_grouping;
6109 wchar_t wbuf[100];
6110 mbstate_t mb = {0};
6111 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006112 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006113 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006114 __throw_runtime_error("locale not supported");
6115 wchar_t* wbe = wbuf + j;
6116 __curr_symbol_.assign(wbuf, wbe);
6117 if (lc->frac_digits != CHAR_MAX)
6118 __frac_digits_ = lc->frac_digits;
6119 else
6120 __frac_digits_ = base::do_frac_digits();
6121 if (lc->p_sign_posn == 0)
6122 __positive_sign_ = L"()";
6123 else
6124 {
6125 mb = mbstate_t();
6126 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006127 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006128 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006129 __throw_runtime_error("locale not supported");
6130 wbe = wbuf + j;
6131 __positive_sign_.assign(wbuf, wbe);
6132 }
6133 if (lc->n_sign_posn == 0)
6134 __negative_sign_ = L"()";
6135 else
6136 {
6137 mb = mbstate_t();
6138 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006139 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006140 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141 __throw_runtime_error("locale not supported");
6142 wbe = wbuf + j;
6143 __negative_sign_.assign(wbuf, wbe);
6144 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006145 // Assume the positive and negative formats will want spaces in
6146 // the same places in curr_symbol since there's no way to
6147 // represent anything else.
6148 string_type __dummy_curr_symbol = __curr_symbol_;
6149 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6150 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6151 __init_pat(__neg_format_, __curr_symbol_, false,
6152 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006153}
6154
6155template<>
6156void
6157moneypunct_byname<wchar_t, true>::init(const char* nm)
6158{
6159 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006160 __libcpp_unique_locale loc(nm);
6161 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006162 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006163 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006164
Ben Craig3756b922016-03-09 15:39:39 +00006165 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006166 if (!checked_string_to_wchar_convert(__decimal_point_,
6167 lc->mon_decimal_point,
6168 loc.get()))
6169 __decimal_point_ = base::do_decimal_point();
6170 if (!checked_string_to_wchar_convert(__thousands_sep_,
6171 lc->mon_thousands_sep,
6172 loc.get()))
6173 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006174 __grouping_ = lc->mon_grouping;
6175 wchar_t wbuf[100];
6176 mbstate_t mb = {0};
6177 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006178 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006179 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006180 __throw_runtime_error("locale not supported");
6181 wchar_t* wbe = wbuf + j;
6182 __curr_symbol_.assign(wbuf, wbe);
6183 if (lc->int_frac_digits != CHAR_MAX)
6184 __frac_digits_ = lc->int_frac_digits;
6185 else
6186 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006187#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006188 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006189#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006190 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006191#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006192 __positive_sign_ = L"()";
6193 else
6194 {
6195 mb = mbstate_t();
6196 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006197 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006198 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006199 __throw_runtime_error("locale not supported");
6200 wbe = wbuf + j;
6201 __positive_sign_.assign(wbuf, wbe);
6202 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006203#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006204 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006205#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006206 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006207#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006208 __negative_sign_ = L"()";
6209 else
6210 {
6211 mb = mbstate_t();
6212 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006213 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006214 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006215 __throw_runtime_error("locale not supported");
6216 wbe = wbuf + j;
6217 __negative_sign_.assign(wbuf, wbe);
6218 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006219 // Assume the positive and negative formats will want spaces in
6220 // the same places in curr_symbol since there's no way to
6221 // represent anything else.
6222 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006223#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006224 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6225 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6226 __init_pat(__neg_format_, __curr_symbol_, true,
6227 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006228#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006229 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6230 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6231 lc->int_p_sign_posn, L' ');
6232 __init_pat(__neg_format_, __curr_symbol_, true,
6233 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6234 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006235#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006236}
6237
6238void __do_nothing(void*) {}
6239
6240void __throw_runtime_error(const char* msg)
6241{
Howard Hinnant72f73582010-08-11 17:04:31 +00006242#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006243 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006244#else
6245 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006246 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006247#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006248}
6249
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006250template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6251template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006252
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006253template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6254template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006255
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006256template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6257template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006258
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006259template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6260template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006261
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006262template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6263template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006264
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006265template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6266template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006267
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006268template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6269template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006270
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006271template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6272template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006273
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006274template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6275template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006276
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006277template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6278template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6279template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6280template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006281
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006282template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6283template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6284template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6285template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006286
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006287template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6288template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006289
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006290template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6291template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006292
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006293template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6294template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006295
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006296template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6297template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006298
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006299template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6300template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006301
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006302template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6303template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006304
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006305template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6306template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
Reid Klecknerbc2a2ce2021-01-15 08:56:34 -08006307template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6308template 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 -04006309#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006310template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6311template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6312#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006313
Howard Hinnantc51e1022010-05-11 19:42:16 +00006314_LIBCPP_END_NAMESPACE_STD