blob: e590d5d99d3a4480c948af1d59f15dac76046f46 [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
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000264// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000265// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000266#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000267#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000268#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000269#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000270
Howard Hinnantc51e1022010-05-11 19:42:16 +0000271locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000272 : facets_(max<size_t>(N, other.facets_.size())),
273 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000274{
275 facets_ = other.facets_;
276 for (unsigned i = 0; i < facets_.size(); ++i)
277 if (facets_[i])
278 facets_[i]->__add_shared();
279}
280
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000281#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000282#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000283#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000284
Howard Hinnantc51e1022010-05-11 19:42:16 +0000285locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000286 : facets_(N),
287 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288{
289 facets_ = other.facets_;
290 for (unsigned i = 0; i < facets_.size(); ++i)
291 if (facets_[i])
292 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000293#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000294 try
295 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400296#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000297 if (c & locale::collate)
298 {
299 install(new collate_byname<char>(name));
300 install(new collate_byname<wchar_t>(name));
301 }
302 if (c & locale::ctype)
303 {
304 install(new ctype_byname<char>(name));
305 install(new ctype_byname<wchar_t>(name));
306 install(new codecvt_byname<char, char, mbstate_t>(name));
307 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100308_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantc51e1022010-05-11 19:42:16 +0000309 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
310 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
Marek Kurdej718b62c2020-12-02 08:57:02 +0100311_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400312#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100313 install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name));
314 install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name));
315#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000316 }
317 if (c & locale::monetary)
318 {
319 install(new moneypunct_byname<char, false>(name));
320 install(new moneypunct_byname<char, true>(name));
321 install(new moneypunct_byname<wchar_t, false>(name));
322 install(new moneypunct_byname<wchar_t, true>(name));
323 }
324 if (c & locale::numeric)
325 {
326 install(new numpunct_byname<char>(name));
327 install(new numpunct_byname<wchar_t>(name));
328 }
329 if (c & locale::time)
330 {
331 install(new time_get_byname<char>(name));
332 install(new time_get_byname<wchar_t>(name));
333 install(new time_put_byname<char>(name));
334 install(new time_put_byname<wchar_t>(name));
335 }
336 if (c & locale::messages)
337 {
338 install(new messages_byname<char>(name));
339 install(new messages_byname<wchar_t>(name));
340 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000341#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000342 }
343 catch (...)
344 {
345 for (unsigned i = 0; i < facets_.size(); ++i)
346 if (facets_[i])
347 facets_[i]->__release_shared();
348 throw;
349 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400350#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000351}
352
353template<class F>
354inline
355void
356locale::__imp::install_from(const locale::__imp& one)
357{
358 long id = F::id.__get();
359 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
360}
361
362locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000363 : facets_(N),
364 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000365{
366 facets_ = other.facets_;
367 for (unsigned i = 0; i < facets_.size(); ++i)
368 if (facets_[i])
369 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000370#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000371 try
372 {
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400373#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000374 if (c & locale::collate)
375 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000376 install_from<_VSTD::collate<char> >(one);
377 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000378 }
379 if (c & locale::ctype)
380 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000381 install_from<_VSTD::ctype<char> >(one);
382 install_from<_VSTD::ctype<wchar_t> >(one);
383 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100384_LIBCPP_SUPPRESS_DEPRECATED_PUSH
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000385 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
386 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
Marek Kurdej718b62c2020-12-02 08:57:02 +0100387_LIBCPP_SUPPRESS_DEPRECATED_POP
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400388#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +0100389 install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one);
390 install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one);
391#endif
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000392 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000393 }
394 if (c & locale::monetary)
395 {
396 install_from<moneypunct<char, false> >(one);
397 install_from<moneypunct<char, true> >(one);
398 install_from<moneypunct<wchar_t, false> >(one);
399 install_from<moneypunct<wchar_t, true> >(one);
400 install_from<money_get<char> >(one);
401 install_from<money_get<wchar_t> >(one);
402 install_from<money_put<char> >(one);
403 install_from<money_put<wchar_t> >(one);
404 }
405 if (c & locale::numeric)
406 {
407 install_from<numpunct<char> >(one);
408 install_from<numpunct<wchar_t> >(one);
409 install_from<num_get<char> >(one);
410 install_from<num_get<wchar_t> >(one);
411 install_from<num_put<char> >(one);
412 install_from<num_put<wchar_t> >(one);
413 }
414 if (c & locale::time)
415 {
416 install_from<time_get<char> >(one);
417 install_from<time_get<wchar_t> >(one);
418 install_from<time_put<char> >(one);
419 install_from<time_put<wchar_t> >(one);
420 }
421 if (c & locale::messages)
422 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000423 install_from<_VSTD::messages<char> >(one);
424 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000425 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000426#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000427 }
428 catch (...)
429 {
430 for (unsigned i = 0; i < facets_.size(); ++i)
431 if (facets_[i])
432 facets_[i]->__release_shared();
433 throw;
434 }
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400435#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000436}
437
438locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000439 : facets_(max<size_t>(N, other.facets_.size()+1)),
440 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000441{
442 f->__add_shared();
443 unique_ptr<facet, release> hold(f);
444 facets_ = other.facets_;
445 for (unsigned i = 0; i < other.facets_.size(); ++i)
446 if (facets_[i])
447 facets_[i]->__add_shared();
448 install(hold.get(), id);
449}
450
451locale::__imp::~__imp()
452{
453 for (unsigned i = 0; i < facets_.size(); ++i)
454 if (facets_[i])
455 facets_[i]->__release_shared();
456}
457
458void
459locale::__imp::install(facet* f, long id)
460{
461 f->__add_shared();
462 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000463 if (static_cast<size_t>(id) >= facets_.size())
464 facets_.resize(static_cast<size_t>(id+1));
465 if (facets_[static_cast<size_t>(id)])
466 facets_[static_cast<size_t>(id)]->__release_shared();
467 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000468}
469
470const locale::facet*
471locale::__imp::use_facet(long id) const
472{
473 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000474 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000475 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000476}
477
478// locale
479
480const locale&
481locale::__imp::make_classic()
482{
483 // only one thread can get in here and it only gets in once
484 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000485 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000486 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000487 return *c;
488}
489
490const locale&
491locale::classic()
492{
493 static const locale& c = __imp::make_classic();
494 return c;
495}
496
497locale&
498locale::__imp::make_global()
499{
500 // only one thread can get in here and it only gets in once
501 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000502 auto *obj = ::new (&buf) locale(locale::classic());
503 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000504}
505
506locale&
507locale::__global()
508{
509 static locale& g = __imp::make_global();
510 return g;
511}
512
Louis Dionne65358e12021-03-01 12:09:45 -0500513locale::locale() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000514 : __locale_(__global().__locale_)
515{
516 __locale_->__add_shared();
517}
518
Louis Dionne65358e12021-03-01 12:09:45 -0500519locale::locale(const locale& l) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000520 : __locale_(l.__locale_)
521{
522 __locale_->__add_shared();
523}
524
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000525locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000526{
527 __locale_->__release_shared();
528}
529
530const locale&
Louis Dionne65358e12021-03-01 12:09:45 -0500531locale::operator=(const locale& other) noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000532{
533 other.__locale_->__add_shared();
534 __locale_->__release_shared();
535 __locale_ = other.__locale_;
536 return *this;
537}
538
539locale::locale(const char* name)
540 : __locale_(name ? new __imp(name)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100541 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000542{
543 __locale_->__add_shared();
544}
545
546locale::locale(const string& name)
547 : __locale_(new __imp(name))
548{
549 __locale_->__add_shared();
550}
551
552locale::locale(const locale& other, const char* name, category c)
553 : __locale_(name ? new __imp(*other.__locale_, name, c)
Joerg Sonnenbergerc19e2fa2020-01-23 02:20:09 +0100554 : (__throw_runtime_error("locale constructed with null"), nullptr))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000555{
556 __locale_->__add_shared();
557}
558
559locale::locale(const locale& other, const string& name, category c)
560 : __locale_(new __imp(*other.__locale_, name, c))
561{
562 __locale_->__add_shared();
563}
564
565locale::locale(const locale& other, const locale& one, category c)
566 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
567{
568 __locale_->__add_shared();
569}
570
571string
572locale::name() const
573{
574 return __locale_->name();
575}
576
577void
578locale::__install_ctor(const locale& other, facet* f, long id)
579{
580 if (f)
581 __locale_ = new __imp(*other.__locale_, f, id);
582 else
583 __locale_ = other.__locale_;
584 __locale_->__add_shared();
585}
586
587locale
588locale::global(const locale& loc)
589{
590 locale& g = __global();
591 locale r = g;
592 g = loc;
593 if (g.name() != "*")
594 setlocale(LC_ALL, g.name().c_str());
595 return r;
596}
597
598bool
599locale::has_facet(id& x) const
600{
601 return __locale_->has_facet(x.__get());
602}
603
604const locale::facet*
605locale::use_facet(id& x) const
606{
607 return __locale_->use_facet(x.__get());
608}
609
610bool
611locale::operator==(const locale& y) const
612{
613 return (__locale_ == y.__locale_)
614 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
615}
616
617// locale::facet
618
619locale::facet::~facet()
620{
621}
622
623void
Louis Dionne65358e12021-03-01 12:09:45 -0500624locale::facet::__on_zero_shared() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +0000625{
626 delete this;
627}
628
629// locale::id
630
631int32_t locale::id::__next_id = 0;
632
633namespace
634{
635
636class __fake_bind
637{
638 locale::id* id_;
639 void (locale::id::* pmf_)();
640public:
641 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
642 : id_(id), pmf_(pmf) {}
643
644 void operator()() const
645 {
646 (id_->*pmf_)();
647 }
648};
649
650}
651
652long
653locale::id::__get()
654{
655 call_once(__flag_, __fake_bind(&locale::id::__init, this));
656 return __id_ - 1;
657}
658
659void
660locale::id::__init()
661{
Weiming Zhaob613db72017-09-19 23:18:03 +0000662 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000663}
664
665// template <> class collate_byname<char>
666
667collate_byname<char>::collate_byname(const char* n, size_t refs)
668 : collate<char>(refs),
669 __l(newlocale(LC_ALL_MASK, n, 0))
670{
671 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000672 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000673 " failed to construct for " + string(n));
674}
675
676collate_byname<char>::collate_byname(const string& name, size_t refs)
677 : collate<char>(refs),
678 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
679{
680 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000681 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000682 " failed to construct for " + name);
683}
684
685collate_byname<char>::~collate_byname()
686{
687 freelocale(__l);
688}
689
690int
691collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
692 const char_type* __lo2, const char_type* __hi2) const
693{
694 string_type lhs(__lo1, __hi1);
695 string_type rhs(__lo2, __hi2);
696 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
697 if (r < 0)
698 return -1;
699 if (r > 0)
700 return 1;
701 return r;
702}
703
704collate_byname<char>::string_type
705collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
706{
707 const string_type in(lo, hi);
708 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
709 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
710 return out;
711}
712
713// template <> class collate_byname<wchar_t>
714
715collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
716 : collate<wchar_t>(refs),
717 __l(newlocale(LC_ALL_MASK, n, 0))
718{
719 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000720 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000721 " failed to construct for " + string(n));
722}
723
724collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
725 : collate<wchar_t>(refs),
726 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
727{
728 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000729 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000730 " failed to construct for " + name);
731}
732
733collate_byname<wchar_t>::~collate_byname()
734{
735 freelocale(__l);
736}
737
738int
739collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
740 const char_type* __lo2, const char_type* __hi2) const
741{
742 string_type lhs(__lo1, __hi1);
743 string_type rhs(__lo2, __hi2);
744 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
745 if (r < 0)
746 return -1;
747 if (r > 0)
748 return 1;
749 return r;
750}
751
752collate_byname<wchar_t>::string_type
753collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
754{
755 const string_type in(lo, hi);
756 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
757 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
758 return out;
759}
760
761// template <> class ctype<wchar_t>;
762
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000763const ctype_base::mask ctype_base::space;
764const ctype_base::mask ctype_base::print;
765const ctype_base::mask ctype_base::cntrl;
766const ctype_base::mask ctype_base::upper;
767const ctype_base::mask ctype_base::lower;
768const ctype_base::mask ctype_base::alpha;
769const ctype_base::mask ctype_base::digit;
770const ctype_base::mask ctype_base::punct;
771const ctype_base::mask ctype_base::xdigit;
772const ctype_base::mask ctype_base::blank;
773const ctype_base::mask ctype_base::alnum;
774const ctype_base::mask ctype_base::graph;
Stephan T. Lavavejfb39ad72019-10-23 11:45:36 -0700775
Howard Hinnantc51e1022010-05-11 19:42:16 +0000776locale::id ctype<wchar_t>::id;
777
778ctype<wchar_t>::~ctype()
779{
780}
781
782bool
783ctype<wchar_t>::do_is(mask m, char_type c) const
784{
Marshall Clowd920eea2013-10-21 15:07:28 +0000785 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000786}
787
788const wchar_t*
789ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
790{
791 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000792 *vec = static_cast<mask>(isascii(*low) ?
793 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000794 return low;
795}
796
797const wchar_t*
798ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
799{
800 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000801 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000802 break;
803 return low;
804}
805
806const wchar_t*
807ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
808{
809 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000810 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000811 break;
812 return low;
813}
814
815wchar_t
816ctype<wchar_t>::do_toupper(char_type c) const
817{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000818#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
819 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000820#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000821 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000822 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000823#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000824 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000825#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000826}
827
828const wchar_t*
829ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
830{
831 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000832#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
833 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000834#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000835 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000836 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
837 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000838#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000839 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000840#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000841 return low;
842}
843
844wchar_t
845ctype<wchar_t>::do_tolower(char_type c) const
846{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000847#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
848 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000849#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000850 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000851 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000852#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000853 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000854#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000855}
856
857const wchar_t*
858ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
859{
860 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000861#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
862 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000863#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000864 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000865 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
866 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000867#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000868 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000869#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000870 return low;
871}
872
873wchar_t
874ctype<wchar_t>::do_widen(char c) const
875{
876 return c;
877}
878
879const char*
880ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
881{
882 for (; low != high; ++low, ++dest)
883 *dest = *low;
884 return low;
885}
886
887char
888ctype<wchar_t>::do_narrow(char_type c, char dfault) const
889{
890 if (isascii(c))
891 return static_cast<char>(c);
892 return dfault;
893}
894
895const wchar_t*
896ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
897{
898 for (; low != high; ++low, ++dest)
899 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000900 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000901 else
902 *dest = dfault;
903 return low;
904}
905
906// template <> class ctype<char>;
907
908locale::id ctype<char>::id;
909
910ctype<char>::ctype(const mask* tab, bool del, size_t refs)
911 : locale::facet(refs),
912 __tab_(tab),
913 __del_(del)
914{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000915 if (__tab_ == 0)
916 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000917}
918
919ctype<char>::~ctype()
920{
921 if (__tab_ && __del_)
922 delete [] __tab_;
923}
924
925char
926ctype<char>::do_toupper(char_type c) const
927{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000928#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000929 return isascii(c) ?
930 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000931#elif defined(__NetBSD__)
932 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000933#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000934 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000935 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000936#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000937 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000938#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000939}
940
941const char*
942ctype<char>::do_toupper(char_type* low, const char_type* high) const
943{
944 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000945#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000946 *low = isascii(*low) ?
947 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000948#elif defined(__NetBSD__)
949 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000950#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000951 *low = isascii(*low) ?
952 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000953#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000954 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000955#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000956 return low;
957}
958
959char
960ctype<char>::do_tolower(char_type c) const
961{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000962#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000963 return isascii(c) ?
964 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000965#elif defined(__NetBSD__)
966 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000967#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000968 return isascii(c) ?
969 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000970#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000971 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000972#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000973}
974
975const char*
976ctype<char>::do_tolower(char_type* low, const char_type* high) const
977{
978 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000979#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000980 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000981#elif defined(__NetBSD__)
982 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000983#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000984 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000985#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000986 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000987#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000988 return low;
989}
990
991char
992ctype<char>::do_widen(char c) const
993{
994 return c;
995}
996
997const char*
998ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
999{
1000 for (; low != high; ++low, ++dest)
1001 *dest = *low;
1002 return low;
1003}
1004
1005char
1006ctype<char>::do_narrow(char_type c, char dfault) const
1007{
1008 if (isascii(c))
1009 return static_cast<char>(c);
1010 return dfault;
1011}
1012
1013const char*
1014ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1015{
1016 for (; low != high; ++low, ++dest)
1017 if (isascii(*low))
1018 *dest = *low;
1019 else
1020 *dest = dfault;
1021 return low;
1022}
1023
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001024#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001025extern "C" const unsigned short ** __ctype_b_loc();
1026extern "C" const int ** __ctype_tolower_loc();
1027extern "C" const int ** __ctype_toupper_loc();
1028#endif
1029
Marshall Clow8f870232015-03-04 16:50:02 +00001030#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001031const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001032ctype<char>::classic_table() noexcept
Marshall Clowb3f62842015-03-04 16:10:14 +00001033{
1034 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl | space | blank,
1040 cntrl | space, cntrl | space,
1041 cntrl | space, cntrl | space,
1042 cntrl, cntrl,
1043 cntrl, cntrl,
1044 cntrl, cntrl,
1045 cntrl, cntrl,
1046 cntrl, cntrl,
1047 cntrl, cntrl,
1048 cntrl, cntrl,
1049 cntrl, cntrl,
1050 cntrl, cntrl,
1051 space | blank | print, punct | print,
1052 punct | print, punct | print,
1053 punct | print, punct | print,
1054 punct | print, punct | print,
1055 punct | print, punct | print,
1056 punct | print, punct | print,
1057 punct | print, punct | print,
1058 punct | print, punct | print,
1059 digit | print | xdigit, digit | print | xdigit,
1060 digit | print | xdigit, digit | print | xdigit,
1061 digit | print | xdigit, digit | print | xdigit,
1062 digit | print | xdigit, digit | print | xdigit,
1063 digit | print | xdigit, digit | print | xdigit,
1064 punct | print, punct | print,
1065 punct | print, punct | print,
1066 punct | print, punct | print,
1067 punct | print, upper | xdigit | print | alpha,
1068 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1069 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1070 upper | xdigit | print | alpha, upper | print | alpha,
1071 upper | print | alpha, upper | print | alpha,
1072 upper | print | alpha, upper | print | alpha,
1073 upper | print | alpha, upper | print | alpha,
1074 upper | print | alpha, upper | print | alpha,
1075 upper | print | alpha, upper | print | alpha,
1076 upper | print | alpha, upper | print | alpha,
1077 upper | print | alpha, upper | print | alpha,
1078 upper | print | alpha, upper | print | alpha,
1079 upper | print | alpha, upper | print | alpha,
1080 upper | print | alpha, punct | print,
1081 punct | print, punct | print,
1082 punct | print, punct | print,
1083 punct | print, lower | xdigit | print | alpha,
1084 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1085 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1086 lower | xdigit | print | alpha, lower | print | alpha,
1087 lower | print | alpha, lower | print | alpha,
1088 lower | print | alpha, lower | print | alpha,
1089 lower | print | alpha, lower | print | alpha,
1090 lower | print | alpha, lower | print | alpha,
1091 lower | print | alpha, lower | print | alpha,
1092 lower | print | alpha, lower | print | alpha,
1093 lower | print | alpha, lower | print | alpha,
1094 lower | print | alpha, lower | print | alpha,
1095 lower | print | alpha, lower | print | alpha,
1096 lower | print | alpha, punct | print,
1097 punct | print, punct | print,
1098 punct | print, cntrl,
1099 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1107 };
1108 return builtin_table;
1109}
1110#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001111const ctype<char>::mask*
Louis Dionne65358e12021-03-01 12:09:45 -05001112ctype<char>::classic_table() noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001113{
David Chisnall1d581062011-09-21 08:39:44 +00001114#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001115 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001116#elif defined(__NetBSD__)
1117 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001118#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001119 return _LIBCPP_GET_C_LOCALE->__ctype_b;
Martin Storsjö65ab7302021-05-06 10:18:41 +03001120#elif defined(__sun__)
David Chisnall8074c342012-02-29 13:05:08 +00001121 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001122#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001123 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001124#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001125 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001126#elif defined(_NEWLIB_VERSION)
1127 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1128 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001129#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001130 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001131#else
David Chisnall8074c342012-02-29 13:05:08 +00001132 // Platform not supported: abort so the person doing the port knows what to
1133 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001134# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001135 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001136 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001137 return NULL;
1138#endif
1139}
Marshall Clowb3f62842015-03-04 16:10:14 +00001140#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001141
Howard Hinnantd7a78632011-09-29 13:33:15 +00001142#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001143const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001144ctype<char>::__classic_lower_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001145{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001146 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001147}
1148
1149const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001150ctype<char>::__classic_upper_table() noexcept
Alexis Hunt92b0c812011-07-09 00:56:23 +00001151{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001152 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001153}
YAMAMOTO Takashi43f19082020-10-28 15:40:16 -04001154#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001155const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001156ctype<char>::__classic_lower_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001157{
1158 return _C_tolower_tab_ + 1;
1159}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001160
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001161const short*
Louis Dionne65358e12021-03-01 12:09:45 -05001162ctype<char>::__classic_upper_table() noexcept
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001163{
1164 return _C_toupper_tab_ + 1;
1165}
1166
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001167#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001168const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001169ctype<char>::__classic_lower_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001170{
1171 return *__ctype_tolower_loc();
1172}
1173
1174const int*
Louis Dionne65358e12021-03-01 12:09:45 -05001175ctype<char>::__classic_upper_table() noexcept
Howard Hinnant942dbd22013-03-29 18:27:28 +00001176{
1177 return *__ctype_toupper_loc();
1178}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001179#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001180
Howard Hinnantc51e1022010-05-11 19:42:16 +00001181// template <> class ctype_byname<char>
1182
1183ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1184 : ctype<char>(0, false, refs),
1185 __l(newlocale(LC_ALL_MASK, name, 0))
1186{
1187 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001188 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001189 " failed to construct for " + string(name));
1190}
1191
1192ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1193 : ctype<char>(0, false, refs),
1194 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1195{
1196 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001197 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001198 " failed to construct for " + name);
1199}
1200
1201ctype_byname<char>::~ctype_byname()
1202{
1203 freelocale(__l);
1204}
1205
1206char
1207ctype_byname<char>::do_toupper(char_type c) const
1208{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001209 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001210}
1211
1212const char*
1213ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1214{
1215 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001216 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001217 return low;
1218}
1219
1220char
1221ctype_byname<char>::do_tolower(char_type c) const
1222{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001223 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001224}
1225
1226const char*
1227ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1228{
1229 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001230 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001231 return low;
1232}
1233
1234// template <> class ctype_byname<wchar_t>
1235
1236ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1237 : ctype<wchar_t>(refs),
1238 __l(newlocale(LC_ALL_MASK, name, 0))
1239{
1240 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001241 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001242 " failed to construct for " + string(name));
1243}
1244
1245ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1246 : ctype<wchar_t>(refs),
1247 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1248{
1249 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001250 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001251 " failed to construct for " + name);
1252}
1253
1254ctype_byname<wchar_t>::~ctype_byname()
1255{
1256 freelocale(__l);
1257}
1258
1259bool
1260ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1261{
Alexis Huntc2017f12011-07-09 03:40:04 +00001262#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001263 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001264#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001265 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001266 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001267 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1268 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1269 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1270 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1271 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1272 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1273 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1274 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1275 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1276 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001277 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001278#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001279}
1280
1281const wchar_t*
1282ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1283{
1284 for (; low != high; ++low, ++vec)
1285 {
1286 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001287 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001288 else
1289 {
1290 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001291 wint_t ch = static_cast<wint_t>(*low);
1292 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001293 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001294#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001295 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001297#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001298 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001299 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001300 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001302 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001303 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001304#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001305 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001306 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001307#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001308 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001309 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001310 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001311 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001312#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001313 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001314 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001315#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001316#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001317 if (iswblank_l(ch, __l))
1318 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001319#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001320 }
1321 }
1322 return low;
1323}
1324
1325const wchar_t*
1326ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1327{
1328 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001329 {
1330#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001331 if (iswctype_l(*low, m, __l))
1332 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001333#else
Marshall Clowada0f732013-02-07 14:22:51 +00001334 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001335 if ((m & space) == space && iswspace_l(ch, __l)) break;
1336 if ((m & print) == print && iswprint_l(ch, __l)) break;
1337 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1338 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1339 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1340 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1341 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1342 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1343 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1344 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001345#endif
1346 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001347 return low;
1348}
1349
1350const wchar_t*
1351ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1352{
1353 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001354 {
1355#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001356 if (!iswctype_l(*low, m, __l))
1357 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001358#else
Marshall Clowada0f732013-02-07 14:22:51 +00001359 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001360 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1361 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1362 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1363 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1364 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1365 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1366 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1367 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1368 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1369 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001370 break;
1371#endif
1372 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001373 return low;
1374}
1375
1376wchar_t
1377ctype_byname<wchar_t>::do_toupper(char_type c) const
1378{
1379 return towupper_l(c, __l);
1380}
1381
1382const wchar_t*
1383ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1384{
1385 for (; low != high; ++low)
1386 *low = towupper_l(*low, __l);
1387 return low;
1388}
1389
1390wchar_t
1391ctype_byname<wchar_t>::do_tolower(char_type c) const
1392{
1393 return towlower_l(c, __l);
1394}
1395
1396const wchar_t*
1397ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1398{
1399 for (; low != high; ++low)
1400 *low = towlower_l(*low, __l);
1401 return low;
1402}
1403
1404wchar_t
1405ctype_byname<wchar_t>::do_widen(char c) const
1406{
Ben Craig3756b922016-03-09 15:39:39 +00001407 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001408}
1409
1410const char*
1411ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1412{
1413 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001414 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001415 return low;
1416}
1417
1418char
1419ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1420{
Ben Craig3756b922016-03-09 15:39:39 +00001421 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001422 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001423}
1424
1425const wchar_t*
1426ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1427{
1428 for (; low != high; ++low, ++dest)
1429 {
Ben Craig3756b922016-03-09 15:39:39 +00001430 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001431 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001432 }
1433 return low;
1434}
1435
1436// template <> class codecvt<char, char, mbstate_t>
1437
Howard Hinnantffb308e2010-08-22 00:03:27 +00001438locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001439
1440codecvt<char, char, mbstate_t>::~codecvt()
1441{
1442}
1443
1444codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001445codecvt<char, char, mbstate_t>::do_out(state_type&,
1446 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001447 extern_type* to, extern_type*, extern_type*& to_nxt) const
1448{
1449 frm_nxt = frm;
1450 to_nxt = to;
1451 return noconv;
1452}
1453
1454codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001455codecvt<char, char, mbstate_t>::do_in(state_type&,
1456 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001457 intern_type* to, intern_type*, intern_type*& to_nxt) const
1458{
1459 frm_nxt = frm;
1460 to_nxt = to;
1461 return noconv;
1462}
1463
1464codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001465codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001466 extern_type* to, extern_type*, extern_type*& to_nxt) const
1467{
1468 to_nxt = to;
1469 return noconv;
1470}
1471
1472int
Louis Dionne65358e12021-03-01 12:09:45 -05001473codecvt<char, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001474{
1475 return 1;
1476}
1477
1478bool
Louis Dionne65358e12021-03-01 12:09:45 -05001479codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001480{
1481 return true;
1482}
1483
1484int
1485codecvt<char, char, mbstate_t>::do_length(state_type&,
1486 const extern_type* frm, const extern_type* end, size_t mx) const
1487{
Howard Hinnant28b24882011-12-01 20:21:04 +00001488 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001489}
1490
1491int
Louis Dionne65358e12021-03-01 12:09:45 -05001492codecvt<char, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001493{
1494 return 1;
1495}
1496
1497// template <> class codecvt<wchar_t, char, mbstate_t>
1498
Howard Hinnantffb308e2010-08-22 00:03:27 +00001499locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001500
1501codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1502 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001503 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001504{
1505}
1506
1507codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1508 : locale::facet(refs),
1509 __l(newlocale(LC_ALL_MASK, nm, 0))
1510{
1511 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001512 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001513 " failed to construct for " + string(nm));
1514}
1515
1516codecvt<wchar_t, char, mbstate_t>::~codecvt()
1517{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001518 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001519 freelocale(__l);
1520}
1521
1522codecvt<wchar_t, char, mbstate_t>::result
1523codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001524 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001525 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1526{
1527 // look for first internal null in frm
1528 const intern_type* fend = frm;
1529 for (; fend != frm_end; ++fend)
1530 if (*fend == 0)
1531 break;
1532 // loop over all null-terminated sequences in frm
1533 to_nxt = to;
1534 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1535 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001536 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001537 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001538 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1539 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001540 if (n == size_t(-1))
1541 {
1542 // need to recover to_nxt
1543 for (to_nxt = to; frm != frm_nxt; ++frm)
1544 {
Ben Craig3756b922016-03-09 15:39:39 +00001545 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001546 if (n == size_t(-1))
1547 break;
1548 to_nxt += n;
1549 }
1550 frm_nxt = frm;
1551 return error;
1552 }
1553 if (n == 0)
1554 return partial;
1555 to_nxt += n;
1556 if (to_nxt == to_end)
1557 break;
1558 if (fend != frm_end) // set up next null terminated sequence
1559 {
1560 // Try to write the terminating null
1561 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001562 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001563 if (n == size_t(-1)) // on error
1564 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001565 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001566 return partial;
1567 for (extern_type* p = tmp; n; --n) // write it
1568 *to_nxt++ = *p++;
1569 ++frm_nxt;
1570 // look for next null in frm
1571 for (fend = frm_nxt; fend != frm_end; ++fend)
1572 if (*fend == 0)
1573 break;
1574 }
1575 }
1576 return frm_nxt == frm_end ? ok : partial;
1577}
1578
1579codecvt<wchar_t, char, mbstate_t>::result
1580codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001581 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001582 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1583{
1584 // look for first internal null in frm
1585 const extern_type* fend = frm;
1586 for (; fend != frm_end; ++fend)
1587 if (*fend == 0)
1588 break;
1589 // loop over all null-terminated sequences in frm
1590 to_nxt = to;
1591 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1592 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001593 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001594 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001595 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1596 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001597 if (n == size_t(-1))
1598 {
1599 // need to recover to_nxt
1600 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1601 {
Ben Craig3756b922016-03-09 15:39:39 +00001602 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1603 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001604 switch (n)
1605 {
1606 case 0:
1607 ++frm;
1608 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001609 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001610 frm_nxt = frm;
1611 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001612 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001613 frm_nxt = frm;
1614 return partial;
1615 default:
1616 frm += n;
1617 break;
1618 }
1619 }
1620 frm_nxt = frm;
1621 return frm_nxt == frm_end ? ok : partial;
1622 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001623 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001624 return error;
1625 to_nxt += n;
1626 if (to_nxt == to_end)
1627 break;
1628 if (fend != frm_end) // set up next null terminated sequence
1629 {
1630 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001631 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001632 if (n != 0) // on error
1633 return error;
1634 ++to_nxt;
1635 ++frm_nxt;
1636 // look for next null in frm
1637 for (fend = frm_nxt; fend != frm_end; ++fend)
1638 if (*fend == 0)
1639 break;
1640 }
1641 }
1642 return frm_nxt == frm_end ? ok : partial;
1643}
1644
1645codecvt<wchar_t, char, mbstate_t>::result
1646codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1647 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1648{
1649 to_nxt = to;
1650 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001651 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001652 if (n == size_t(-1) || n == 0) // on error
1653 return error;
1654 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001655 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001656 return partial;
1657 for (extern_type* p = tmp; n; --n) // write it
1658 *to_nxt++ = *p++;
1659 return ok;
1660}
1661
1662int
Louis Dionne65358e12021-03-01 12:09:45 -05001663codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001664{
Ben Craig3756b922016-03-09 15:39:39 +00001665 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001666 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001667
1668 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001669 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001670 return 1; // which take more than 1 char to form a wchar_t
1671 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001672}
1673
1674bool
Louis Dionne65358e12021-03-01 12:09:45 -05001675codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001676{
1677 return false;
1678}
1679
1680int
1681codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1682 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1683{
1684 int nbytes = 0;
1685 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1686 {
Ben Craig3756b922016-03-09 15:39:39 +00001687 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001688 switch (n)
1689 {
1690 case 0:
1691 ++nbytes;
1692 ++frm;
1693 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001694 case size_t(-1):
1695 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001696 return nbytes;
1697 default:
1698 nbytes += n;
1699 frm += n;
1700 break;
1701 }
1702 }
1703 return nbytes;
1704}
1705
1706int
Louis Dionne65358e12021-03-01 12:09:45 -05001707codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00001708{
Ben Craig3756b922016-03-09 15:39:39 +00001709 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001710}
1711
1712// Valid UTF ranges
1713// UTF-32 UTF-16 UTF-8 # of code points
1714// first second first second third fourth
1715// 000000 - 00007F 0000 - 007F 00 - 7F 127
1716// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1717// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1718// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1719// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1720// 00D800 - 00DFFF invalid
1721// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1722// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1723// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1724// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1725
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001726static
1727codecvt_base::result
1728utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1729 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1730 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1731{
1732 frm_nxt = frm;
1733 to_nxt = to;
1734 if (mode & generate_header)
1735 {
1736 if (to_end-to_nxt < 3)
1737 return codecvt_base::partial;
1738 *to_nxt++ = static_cast<uint8_t>(0xEF);
1739 *to_nxt++ = static_cast<uint8_t>(0xBB);
1740 *to_nxt++ = static_cast<uint8_t>(0xBF);
1741 }
1742 for (; frm_nxt < frm_end; ++frm_nxt)
1743 {
1744 uint16_t wc1 = *frm_nxt;
1745 if (wc1 > Maxcode)
1746 return codecvt_base::error;
1747 if (wc1 < 0x0080)
1748 {
1749 if (to_end-to_nxt < 1)
1750 return codecvt_base::partial;
1751 *to_nxt++ = static_cast<uint8_t>(wc1);
1752 }
1753 else if (wc1 < 0x0800)
1754 {
1755 if (to_end-to_nxt < 2)
1756 return codecvt_base::partial;
1757 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1758 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1759 }
1760 else if (wc1 < 0xD800)
1761 {
1762 if (to_end-to_nxt < 3)
1763 return codecvt_base::partial;
1764 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1765 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1766 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1767 }
1768 else if (wc1 < 0xDC00)
1769 {
1770 if (frm_end-frm_nxt < 2)
1771 return codecvt_base::partial;
1772 uint16_t wc2 = frm_nxt[1];
1773 if ((wc2 & 0xFC00) != 0xDC00)
1774 return codecvt_base::error;
1775 if (to_end-to_nxt < 4)
1776 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001777 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1778 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001779 return codecvt_base::error;
1780 ++frm_nxt;
1781 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1782 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1783 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1784 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1785 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1786 }
1787 else if (wc1 < 0xE000)
1788 {
1789 return codecvt_base::error;
1790 }
1791 else
1792 {
1793 if (to_end-to_nxt < 3)
1794 return codecvt_base::partial;
1795 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1796 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1797 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1798 }
1799 }
1800 return codecvt_base::ok;
1801}
1802
1803static
1804codecvt_base::result
1805utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1806 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1807 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1808{
1809 frm_nxt = frm;
1810 to_nxt = to;
1811 if (mode & generate_header)
1812 {
1813 if (to_end-to_nxt < 3)
1814 return codecvt_base::partial;
1815 *to_nxt++ = static_cast<uint8_t>(0xEF);
1816 *to_nxt++ = static_cast<uint8_t>(0xBB);
1817 *to_nxt++ = static_cast<uint8_t>(0xBF);
1818 }
1819 for (; frm_nxt < frm_end; ++frm_nxt)
1820 {
1821 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1822 if (wc1 > Maxcode)
1823 return codecvt_base::error;
1824 if (wc1 < 0x0080)
1825 {
1826 if (to_end-to_nxt < 1)
1827 return codecvt_base::partial;
1828 *to_nxt++ = static_cast<uint8_t>(wc1);
1829 }
1830 else if (wc1 < 0x0800)
1831 {
1832 if (to_end-to_nxt < 2)
1833 return codecvt_base::partial;
1834 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1835 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1836 }
1837 else if (wc1 < 0xD800)
1838 {
1839 if (to_end-to_nxt < 3)
1840 return codecvt_base::partial;
1841 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1842 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1843 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1844 }
1845 else if (wc1 < 0xDC00)
1846 {
1847 if (frm_end-frm_nxt < 2)
1848 return codecvt_base::partial;
1849 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1850 if ((wc2 & 0xFC00) != 0xDC00)
1851 return codecvt_base::error;
1852 if (to_end-to_nxt < 4)
1853 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001854 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1855 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001856 return codecvt_base::error;
1857 ++frm_nxt;
1858 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1859 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1860 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1861 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1862 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1863 }
1864 else if (wc1 < 0xE000)
1865 {
1866 return codecvt_base::error;
1867 }
1868 else
1869 {
1870 if (to_end-to_nxt < 3)
1871 return codecvt_base::partial;
1872 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1873 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1874 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1875 }
1876 }
1877 return codecvt_base::ok;
1878}
1879
1880static
1881codecvt_base::result
1882utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1883 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1884 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1885{
1886 frm_nxt = frm;
1887 to_nxt = to;
1888 if (mode & consume_header)
1889 {
1890 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1891 frm_nxt[2] == 0xBF)
1892 frm_nxt += 3;
1893 }
1894 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1895 {
1896 uint8_t c1 = *frm_nxt;
1897 if (c1 > Maxcode)
1898 return codecvt_base::error;
1899 if (c1 < 0x80)
1900 {
1901 *to_nxt = static_cast<uint16_t>(c1);
1902 ++frm_nxt;
1903 }
1904 else if (c1 < 0xC2)
1905 {
1906 return codecvt_base::error;
1907 }
1908 else if (c1 < 0xE0)
1909 {
1910 if (frm_end-frm_nxt < 2)
1911 return codecvt_base::partial;
1912 uint8_t c2 = frm_nxt[1];
1913 if ((c2 & 0xC0) != 0x80)
1914 return codecvt_base::error;
1915 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1916 if (t > Maxcode)
1917 return codecvt_base::error;
1918 *to_nxt = t;
1919 frm_nxt += 2;
1920 }
1921 else if (c1 < 0xF0)
1922 {
1923 if (frm_end-frm_nxt < 3)
1924 return codecvt_base::partial;
1925 uint8_t c2 = frm_nxt[1];
1926 uint8_t c3 = frm_nxt[2];
1927 switch (c1)
1928 {
1929 case 0xE0:
1930 if ((c2 & 0xE0) != 0xA0)
1931 return codecvt_base::error;
1932 break;
1933 case 0xED:
1934 if ((c2 & 0xE0) != 0x80)
1935 return codecvt_base::error;
1936 break;
1937 default:
1938 if ((c2 & 0xC0) != 0x80)
1939 return codecvt_base::error;
1940 break;
1941 }
1942 if ((c3 & 0xC0) != 0x80)
1943 return codecvt_base::error;
1944 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1945 | ((c2 & 0x3F) << 6)
1946 | (c3 & 0x3F));
1947 if (t > Maxcode)
1948 return codecvt_base::error;
1949 *to_nxt = t;
1950 frm_nxt += 3;
1951 }
1952 else if (c1 < 0xF5)
1953 {
1954 if (frm_end-frm_nxt < 4)
1955 return codecvt_base::partial;
1956 uint8_t c2 = frm_nxt[1];
1957 uint8_t c3 = frm_nxt[2];
1958 uint8_t c4 = frm_nxt[3];
1959 switch (c1)
1960 {
1961 case 0xF0:
1962 if (!(0x90 <= c2 && c2 <= 0xBF))
1963 return codecvt_base::error;
1964 break;
1965 case 0xF4:
1966 if ((c2 & 0xF0) != 0x80)
1967 return codecvt_base::error;
1968 break;
1969 default:
1970 if ((c2 & 0xC0) != 0x80)
1971 return codecvt_base::error;
1972 break;
1973 }
1974 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1975 return codecvt_base::error;
1976 if (to_end-to_nxt < 2)
1977 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001978 if ((((c1 & 7UL) << 18) +
1979 ((c2 & 0x3FUL) << 12) +
1980 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001981 return codecvt_base::error;
1982 *to_nxt = static_cast<uint16_t>(
1983 0xD800
1984 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1985 | ((c2 & 0x0F) << 2)
1986 | ((c3 & 0x30) >> 4));
1987 *++to_nxt = static_cast<uint16_t>(
1988 0xDC00
1989 | ((c3 & 0x0F) << 6)
1990 | (c4 & 0x3F));
1991 frm_nxt += 4;
1992 }
1993 else
1994 {
1995 return codecvt_base::error;
1996 }
1997 }
1998 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1999}
2000
2001static
2002codecvt_base::result
2003utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2004 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2005 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2006{
2007 frm_nxt = frm;
2008 to_nxt = to;
2009 if (mode & consume_header)
2010 {
2011 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2012 frm_nxt[2] == 0xBF)
2013 frm_nxt += 3;
2014 }
2015 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2016 {
2017 uint8_t c1 = *frm_nxt;
2018 if (c1 > Maxcode)
2019 return codecvt_base::error;
2020 if (c1 < 0x80)
2021 {
2022 *to_nxt = static_cast<uint32_t>(c1);
2023 ++frm_nxt;
2024 }
2025 else if (c1 < 0xC2)
2026 {
2027 return codecvt_base::error;
2028 }
2029 else if (c1 < 0xE0)
2030 {
2031 if (frm_end-frm_nxt < 2)
2032 return codecvt_base::partial;
2033 uint8_t c2 = frm_nxt[1];
2034 if ((c2 & 0xC0) != 0x80)
2035 return codecvt_base::error;
2036 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2037 if (t > Maxcode)
2038 return codecvt_base::error;
2039 *to_nxt = static_cast<uint32_t>(t);
2040 frm_nxt += 2;
2041 }
2042 else if (c1 < 0xF0)
2043 {
2044 if (frm_end-frm_nxt < 3)
2045 return codecvt_base::partial;
2046 uint8_t c2 = frm_nxt[1];
2047 uint8_t c3 = frm_nxt[2];
2048 switch (c1)
2049 {
2050 case 0xE0:
2051 if ((c2 & 0xE0) != 0xA0)
2052 return codecvt_base::error;
2053 break;
2054 case 0xED:
2055 if ((c2 & 0xE0) != 0x80)
2056 return codecvt_base::error;
2057 break;
2058 default:
2059 if ((c2 & 0xC0) != 0x80)
2060 return codecvt_base::error;
2061 break;
2062 }
2063 if ((c3 & 0xC0) != 0x80)
2064 return codecvt_base::error;
2065 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2066 | ((c2 & 0x3F) << 6)
2067 | (c3 & 0x3F));
2068 if (t > Maxcode)
2069 return codecvt_base::error;
2070 *to_nxt = static_cast<uint32_t>(t);
2071 frm_nxt += 3;
2072 }
2073 else if (c1 < 0xF5)
2074 {
2075 if (frm_end-frm_nxt < 4)
2076 return codecvt_base::partial;
2077 uint8_t c2 = frm_nxt[1];
2078 uint8_t c3 = frm_nxt[2];
2079 uint8_t c4 = frm_nxt[3];
2080 switch (c1)
2081 {
2082 case 0xF0:
2083 if (!(0x90 <= c2 && c2 <= 0xBF))
2084 return codecvt_base::error;
2085 break;
2086 case 0xF4:
2087 if ((c2 & 0xF0) != 0x80)
2088 return codecvt_base::error;
2089 break;
2090 default:
2091 if ((c2 & 0xC0) != 0x80)
2092 return codecvt_base::error;
2093 break;
2094 }
2095 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2096 return codecvt_base::error;
2097 if (to_end-to_nxt < 2)
2098 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002099 if ((((c1 & 7UL) << 18) +
2100 ((c2 & 0x3FUL) << 12) +
2101 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002102 return codecvt_base::error;
2103 *to_nxt = static_cast<uint32_t>(
2104 0xD800
2105 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2106 | ((c2 & 0x0F) << 2)
2107 | ((c3 & 0x30) >> 4));
2108 *++to_nxt = static_cast<uint32_t>(
2109 0xDC00
2110 | ((c3 & 0x0F) << 6)
2111 | (c4 & 0x3F));
2112 frm_nxt += 4;
2113 }
2114 else
2115 {
2116 return codecvt_base::error;
2117 }
2118 }
2119 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2120}
2121
2122static
2123int
2124utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2125 size_t mx, unsigned long Maxcode = 0x10FFFF,
2126 codecvt_mode mode = codecvt_mode(0))
2127{
2128 const uint8_t* frm_nxt = frm;
2129 if (mode & consume_header)
2130 {
2131 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2132 frm_nxt[2] == 0xBF)
2133 frm_nxt += 3;
2134 }
2135 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2136 {
2137 uint8_t c1 = *frm_nxt;
2138 if (c1 > Maxcode)
2139 break;
2140 if (c1 < 0x80)
2141 {
2142 ++frm_nxt;
2143 }
2144 else if (c1 < 0xC2)
2145 {
2146 break;
2147 }
2148 else if (c1 < 0xE0)
2149 {
2150 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2151 break;
2152 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2153 if (t > Maxcode)
2154 break;
2155 frm_nxt += 2;
2156 }
2157 else if (c1 < 0xF0)
2158 {
2159 if (frm_end-frm_nxt < 3)
2160 break;
2161 uint8_t c2 = frm_nxt[1];
2162 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002163 switch (c1)
2164 {
2165 case 0xE0:
2166 if ((c2 & 0xE0) != 0xA0)
2167 return static_cast<int>(frm_nxt - frm);
2168 break;
2169 case 0xED:
2170 if ((c2 & 0xE0) != 0x80)
2171 return static_cast<int>(frm_nxt - frm);
2172 break;
2173 default:
2174 if ((c2 & 0xC0) != 0x80)
2175 return static_cast<int>(frm_nxt - frm);
2176 break;
2177 }
2178 if ((c3 & 0xC0) != 0x80)
2179 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002180 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002181 break;
2182 frm_nxt += 3;
2183 }
2184 else if (c1 < 0xF5)
2185 {
2186 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2187 break;
2188 uint8_t c2 = frm_nxt[1];
2189 uint8_t c3 = frm_nxt[2];
2190 uint8_t c4 = frm_nxt[3];
2191 switch (c1)
2192 {
2193 case 0xF0:
2194 if (!(0x90 <= c2 && c2 <= 0xBF))
2195 return static_cast<int>(frm_nxt - frm);
2196 break;
2197 case 0xF4:
2198 if ((c2 & 0xF0) != 0x80)
2199 return static_cast<int>(frm_nxt - frm);
2200 break;
2201 default:
2202 if ((c2 & 0xC0) != 0x80)
2203 return static_cast<int>(frm_nxt - frm);
2204 break;
2205 }
2206 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2207 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002208 if ((((c1 & 7UL) << 18) +
2209 ((c2 & 0x3FUL) << 12) +
2210 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002211 break;
2212 ++nchar16_t;
2213 frm_nxt += 4;
2214 }
2215 else
2216 {
2217 break;
2218 }
2219 }
2220 return static_cast<int>(frm_nxt - frm);
2221}
2222
2223static
2224codecvt_base::result
2225ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2226 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2227 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2228{
2229 frm_nxt = frm;
2230 to_nxt = to;
2231 if (mode & generate_header)
2232 {
2233 if (to_end-to_nxt < 3)
2234 return codecvt_base::partial;
2235 *to_nxt++ = static_cast<uint8_t>(0xEF);
2236 *to_nxt++ = static_cast<uint8_t>(0xBB);
2237 *to_nxt++ = static_cast<uint8_t>(0xBF);
2238 }
2239 for (; frm_nxt < frm_end; ++frm_nxt)
2240 {
2241 uint32_t wc = *frm_nxt;
2242 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2243 return codecvt_base::error;
2244 if (wc < 0x000080)
2245 {
2246 if (to_end-to_nxt < 1)
2247 return codecvt_base::partial;
2248 *to_nxt++ = static_cast<uint8_t>(wc);
2249 }
2250 else if (wc < 0x000800)
2251 {
2252 if (to_end-to_nxt < 2)
2253 return codecvt_base::partial;
2254 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2255 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2256 }
2257 else if (wc < 0x010000)
2258 {
2259 if (to_end-to_nxt < 3)
2260 return codecvt_base::partial;
2261 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2262 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2263 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2264 }
2265 else // if (wc < 0x110000)
2266 {
2267 if (to_end-to_nxt < 4)
2268 return codecvt_base::partial;
2269 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2270 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2271 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2272 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2273 }
2274 }
2275 return codecvt_base::ok;
2276}
2277
2278static
2279codecvt_base::result
2280utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2281 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2282 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2283{
2284 frm_nxt = frm;
2285 to_nxt = to;
2286 if (mode & consume_header)
2287 {
2288 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2289 frm_nxt[2] == 0xBF)
2290 frm_nxt += 3;
2291 }
2292 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2293 {
2294 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2295 if (c1 < 0x80)
2296 {
2297 if (c1 > Maxcode)
2298 return codecvt_base::error;
2299 *to_nxt = static_cast<uint32_t>(c1);
2300 ++frm_nxt;
2301 }
2302 else if (c1 < 0xC2)
2303 {
2304 return codecvt_base::error;
2305 }
2306 else if (c1 < 0xE0)
2307 {
2308 if (frm_end-frm_nxt < 2)
2309 return codecvt_base::partial;
2310 uint8_t c2 = frm_nxt[1];
2311 if ((c2 & 0xC0) != 0x80)
2312 return codecvt_base::error;
2313 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2314 | (c2 & 0x3F));
2315 if (t > Maxcode)
2316 return codecvt_base::error;
2317 *to_nxt = t;
2318 frm_nxt += 2;
2319 }
2320 else if (c1 < 0xF0)
2321 {
2322 if (frm_end-frm_nxt < 3)
2323 return codecvt_base::partial;
2324 uint8_t c2 = frm_nxt[1];
2325 uint8_t c3 = frm_nxt[2];
2326 switch (c1)
2327 {
2328 case 0xE0:
2329 if ((c2 & 0xE0) != 0xA0)
2330 return codecvt_base::error;
2331 break;
2332 case 0xED:
2333 if ((c2 & 0xE0) != 0x80)
2334 return codecvt_base::error;
2335 break;
2336 default:
2337 if ((c2 & 0xC0) != 0x80)
2338 return codecvt_base::error;
2339 break;
2340 }
2341 if ((c3 & 0xC0) != 0x80)
2342 return codecvt_base::error;
2343 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2344 | ((c2 & 0x3F) << 6)
2345 | (c3 & 0x3F));
2346 if (t > Maxcode)
2347 return codecvt_base::error;
2348 *to_nxt = t;
2349 frm_nxt += 3;
2350 }
2351 else if (c1 < 0xF5)
2352 {
2353 if (frm_end-frm_nxt < 4)
2354 return codecvt_base::partial;
2355 uint8_t c2 = frm_nxt[1];
2356 uint8_t c3 = frm_nxt[2];
2357 uint8_t c4 = frm_nxt[3];
2358 switch (c1)
2359 {
2360 case 0xF0:
2361 if (!(0x90 <= c2 && c2 <= 0xBF))
2362 return codecvt_base::error;
2363 break;
2364 case 0xF4:
2365 if ((c2 & 0xF0) != 0x80)
2366 return codecvt_base::error;
2367 break;
2368 default:
2369 if ((c2 & 0xC0) != 0x80)
2370 return codecvt_base::error;
2371 break;
2372 }
2373 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2374 return codecvt_base::error;
2375 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2376 | ((c2 & 0x3F) << 12)
2377 | ((c3 & 0x3F) << 6)
2378 | (c4 & 0x3F));
2379 if (t > Maxcode)
2380 return codecvt_base::error;
2381 *to_nxt = t;
2382 frm_nxt += 4;
2383 }
2384 else
2385 {
2386 return codecvt_base::error;
2387 }
2388 }
2389 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2390}
2391
2392static
2393int
2394utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2395 size_t mx, unsigned long Maxcode = 0x10FFFF,
2396 codecvt_mode mode = codecvt_mode(0))
2397{
2398 const uint8_t* frm_nxt = frm;
2399 if (mode & consume_header)
2400 {
2401 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2402 frm_nxt[2] == 0xBF)
2403 frm_nxt += 3;
2404 }
2405 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2406 {
2407 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2408 if (c1 < 0x80)
2409 {
2410 if (c1 > Maxcode)
2411 break;
2412 ++frm_nxt;
2413 }
2414 else if (c1 < 0xC2)
2415 {
2416 break;
2417 }
2418 else if (c1 < 0xE0)
2419 {
2420 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2421 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002422 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002423 break;
2424 frm_nxt += 2;
2425 }
2426 else if (c1 < 0xF0)
2427 {
2428 if (frm_end-frm_nxt < 3)
2429 break;
2430 uint8_t c2 = frm_nxt[1];
2431 uint8_t c3 = frm_nxt[2];
2432 switch (c1)
2433 {
2434 case 0xE0:
2435 if ((c2 & 0xE0) != 0xA0)
2436 return static_cast<int>(frm_nxt - frm);
2437 break;
2438 case 0xED:
2439 if ((c2 & 0xE0) != 0x80)
2440 return static_cast<int>(frm_nxt - frm);
2441 break;
2442 default:
2443 if ((c2 & 0xC0) != 0x80)
2444 return static_cast<int>(frm_nxt - frm);
2445 break;
2446 }
2447 if ((c3 & 0xC0) != 0x80)
2448 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002449 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002450 break;
2451 frm_nxt += 3;
2452 }
2453 else if (c1 < 0xF5)
2454 {
2455 if (frm_end-frm_nxt < 4)
2456 break;
2457 uint8_t c2 = frm_nxt[1];
2458 uint8_t c3 = frm_nxt[2];
2459 uint8_t c4 = frm_nxt[3];
2460 switch (c1)
2461 {
2462 case 0xF0:
2463 if (!(0x90 <= c2 && c2 <= 0xBF))
2464 return static_cast<int>(frm_nxt - frm);
2465 break;
2466 case 0xF4:
2467 if ((c2 & 0xF0) != 0x80)
2468 return static_cast<int>(frm_nxt - frm);
2469 break;
2470 default:
2471 if ((c2 & 0xC0) != 0x80)
2472 return static_cast<int>(frm_nxt - frm);
2473 break;
2474 }
2475 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2476 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002477 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2478 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002479 break;
2480 frm_nxt += 4;
2481 }
2482 else
2483 {
2484 break;
2485 }
2486 }
2487 return static_cast<int>(frm_nxt - frm);
2488}
2489
2490static
2491codecvt_base::result
2492ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2493 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2494 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2495{
2496 frm_nxt = frm;
2497 to_nxt = to;
2498 if (mode & generate_header)
2499 {
2500 if (to_end-to_nxt < 3)
2501 return codecvt_base::partial;
2502 *to_nxt++ = static_cast<uint8_t>(0xEF);
2503 *to_nxt++ = static_cast<uint8_t>(0xBB);
2504 *to_nxt++ = static_cast<uint8_t>(0xBF);
2505 }
2506 for (; frm_nxt < frm_end; ++frm_nxt)
2507 {
2508 uint16_t wc = *frm_nxt;
2509 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2510 return codecvt_base::error;
2511 if (wc < 0x0080)
2512 {
2513 if (to_end-to_nxt < 1)
2514 return codecvt_base::partial;
2515 *to_nxt++ = static_cast<uint8_t>(wc);
2516 }
2517 else if (wc < 0x0800)
2518 {
2519 if (to_end-to_nxt < 2)
2520 return codecvt_base::partial;
2521 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2522 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2523 }
2524 else // if (wc <= 0xFFFF)
2525 {
2526 if (to_end-to_nxt < 3)
2527 return codecvt_base::partial;
2528 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2529 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2530 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2531 }
2532 }
2533 return codecvt_base::ok;
2534}
2535
2536static
2537codecvt_base::result
2538utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2539 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2540 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2541{
2542 frm_nxt = frm;
2543 to_nxt = to;
2544 if (mode & consume_header)
2545 {
2546 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2547 frm_nxt[2] == 0xBF)
2548 frm_nxt += 3;
2549 }
2550 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2551 {
2552 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2553 if (c1 < 0x80)
2554 {
2555 if (c1 > Maxcode)
2556 return codecvt_base::error;
2557 *to_nxt = static_cast<uint16_t>(c1);
2558 ++frm_nxt;
2559 }
2560 else if (c1 < 0xC2)
2561 {
2562 return codecvt_base::error;
2563 }
2564 else if (c1 < 0xE0)
2565 {
2566 if (frm_end-frm_nxt < 2)
2567 return codecvt_base::partial;
2568 uint8_t c2 = frm_nxt[1];
2569 if ((c2 & 0xC0) != 0x80)
2570 return codecvt_base::error;
2571 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2572 | (c2 & 0x3F));
2573 if (t > Maxcode)
2574 return codecvt_base::error;
2575 *to_nxt = t;
2576 frm_nxt += 2;
2577 }
2578 else if (c1 < 0xF0)
2579 {
2580 if (frm_end-frm_nxt < 3)
2581 return codecvt_base::partial;
2582 uint8_t c2 = frm_nxt[1];
2583 uint8_t c3 = frm_nxt[2];
2584 switch (c1)
2585 {
2586 case 0xE0:
2587 if ((c2 & 0xE0) != 0xA0)
2588 return codecvt_base::error;
2589 break;
2590 case 0xED:
2591 if ((c2 & 0xE0) != 0x80)
2592 return codecvt_base::error;
2593 break;
2594 default:
2595 if ((c2 & 0xC0) != 0x80)
2596 return codecvt_base::error;
2597 break;
2598 }
2599 if ((c3 & 0xC0) != 0x80)
2600 return codecvt_base::error;
2601 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2602 | ((c2 & 0x3F) << 6)
2603 | (c3 & 0x3F));
2604 if (t > Maxcode)
2605 return codecvt_base::error;
2606 *to_nxt = t;
2607 frm_nxt += 3;
2608 }
2609 else
2610 {
2611 return codecvt_base::error;
2612 }
2613 }
2614 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2615}
2616
2617static
2618int
2619utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2620 size_t mx, unsigned long Maxcode = 0x10FFFF,
2621 codecvt_mode mode = codecvt_mode(0))
2622{
2623 const uint8_t* frm_nxt = frm;
2624 if (mode & consume_header)
2625 {
2626 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2627 frm_nxt[2] == 0xBF)
2628 frm_nxt += 3;
2629 }
2630 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2631 {
2632 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2633 if (c1 < 0x80)
2634 {
2635 if (c1 > Maxcode)
2636 break;
2637 ++frm_nxt;
2638 }
2639 else if (c1 < 0xC2)
2640 {
2641 break;
2642 }
2643 else if (c1 < 0xE0)
2644 {
2645 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2646 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002647 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002648 break;
2649 frm_nxt += 2;
2650 }
2651 else if (c1 < 0xF0)
2652 {
2653 if (frm_end-frm_nxt < 3)
2654 break;
2655 uint8_t c2 = frm_nxt[1];
2656 uint8_t c3 = frm_nxt[2];
2657 switch (c1)
2658 {
2659 case 0xE0:
2660 if ((c2 & 0xE0) != 0xA0)
2661 return static_cast<int>(frm_nxt - frm);
2662 break;
2663 case 0xED:
2664 if ((c2 & 0xE0) != 0x80)
2665 return static_cast<int>(frm_nxt - frm);
2666 break;
2667 default:
2668 if ((c2 & 0xC0) != 0x80)
2669 return static_cast<int>(frm_nxt - frm);
2670 break;
2671 }
2672 if ((c3 & 0xC0) != 0x80)
2673 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002674 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002675 break;
2676 frm_nxt += 3;
2677 }
2678 else
2679 {
2680 break;
2681 }
2682 }
2683 return static_cast<int>(frm_nxt - frm);
2684}
2685
2686static
2687codecvt_base::result
2688ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2689 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2690 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2691{
2692 frm_nxt = frm;
2693 to_nxt = to;
2694 if (mode & generate_header)
2695 {
2696 if (to_end-to_nxt < 2)
2697 return codecvt_base::partial;
2698 *to_nxt++ = static_cast<uint8_t>(0xFE);
2699 *to_nxt++ = static_cast<uint8_t>(0xFF);
2700 }
2701 for (; frm_nxt < frm_end; ++frm_nxt)
2702 {
2703 uint32_t wc = *frm_nxt;
2704 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2705 return codecvt_base::error;
2706 if (wc < 0x010000)
2707 {
2708 if (to_end-to_nxt < 2)
2709 return codecvt_base::partial;
2710 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2711 *to_nxt++ = static_cast<uint8_t>(wc);
2712 }
2713 else
2714 {
2715 if (to_end-to_nxt < 4)
2716 return codecvt_base::partial;
2717 uint16_t t = static_cast<uint16_t>(
2718 0xD800
2719 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2720 | ((wc & 0x00FC00) >> 10));
2721 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2722 *to_nxt++ = static_cast<uint8_t>(t);
2723 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2724 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2725 *to_nxt++ = static_cast<uint8_t>(t);
2726 }
2727 }
2728 return codecvt_base::ok;
2729}
2730
2731static
2732codecvt_base::result
2733utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2734 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2735 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2736{
2737 frm_nxt = frm;
2738 to_nxt = to;
2739 if (mode & consume_header)
2740 {
2741 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2742 frm_nxt += 2;
2743 }
2744 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2745 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002746 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002747 if ((c1 & 0xFC00) == 0xDC00)
2748 return codecvt_base::error;
2749 if ((c1 & 0xFC00) != 0xD800)
2750 {
2751 if (c1 > Maxcode)
2752 return codecvt_base::error;
2753 *to_nxt = static_cast<uint32_t>(c1);
2754 frm_nxt += 2;
2755 }
2756 else
2757 {
2758 if (frm_end-frm_nxt < 4)
2759 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002760 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002761 if ((c2 & 0xFC00) != 0xDC00)
2762 return codecvt_base::error;
2763 uint32_t t = static_cast<uint32_t>(
2764 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2765 | ((c1 & 0x003F) << 10)
2766 | (c2 & 0x03FF));
2767 if (t > Maxcode)
2768 return codecvt_base::error;
2769 *to_nxt = t;
2770 frm_nxt += 4;
2771 }
2772 }
2773 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2774}
2775
2776static
2777int
2778utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2779 size_t mx, unsigned long Maxcode = 0x10FFFF,
2780 codecvt_mode mode = codecvt_mode(0))
2781{
2782 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002783 if (mode & consume_header)
2784 {
2785 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2786 frm_nxt += 2;
2787 }
2788 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2789 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002790 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002791 if ((c1 & 0xFC00) == 0xDC00)
2792 break;
2793 if ((c1 & 0xFC00) != 0xD800)
2794 {
2795 if (c1 > Maxcode)
2796 break;
2797 frm_nxt += 2;
2798 }
2799 else
2800 {
2801 if (frm_end-frm_nxt < 4)
2802 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002803 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002804 if ((c2 & 0xFC00) != 0xDC00)
2805 break;
2806 uint32_t t = static_cast<uint32_t>(
2807 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2808 | ((c1 & 0x003F) << 10)
2809 | (c2 & 0x03FF));
2810 if (t > Maxcode)
2811 break;
2812 frm_nxt += 4;
2813 }
2814 }
2815 return static_cast<int>(frm_nxt - frm);
2816}
2817
2818static
2819codecvt_base::result
2820ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2821 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2822 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2823{
2824 frm_nxt = frm;
2825 to_nxt = to;
2826 if (mode & generate_header)
2827 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002828 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002829 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002830 *to_nxt++ = static_cast<uint8_t>(0xFF);
2831 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002832 }
2833 for (; frm_nxt < frm_end; ++frm_nxt)
2834 {
2835 uint32_t wc = *frm_nxt;
2836 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2837 return codecvt_base::error;
2838 if (wc < 0x010000)
2839 {
2840 if (to_end-to_nxt < 2)
2841 return codecvt_base::partial;
2842 *to_nxt++ = static_cast<uint8_t>(wc);
2843 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2844 }
2845 else
2846 {
2847 if (to_end-to_nxt < 4)
2848 return codecvt_base::partial;
2849 uint16_t t = static_cast<uint16_t>(
2850 0xD800
2851 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2852 | ((wc & 0x00FC00) >> 10));
2853 *to_nxt++ = static_cast<uint8_t>(t);
2854 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2855 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2856 *to_nxt++ = static_cast<uint8_t>(t);
2857 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2858 }
2859 }
2860 return codecvt_base::ok;
2861}
2862
2863static
2864codecvt_base::result
2865utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2866 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2867 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2868{
2869 frm_nxt = frm;
2870 to_nxt = to;
2871 if (mode & consume_header)
2872 {
2873 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2874 frm_nxt += 2;
2875 }
2876 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2877 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002878 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002879 if ((c1 & 0xFC00) == 0xDC00)
2880 return codecvt_base::error;
2881 if ((c1 & 0xFC00) != 0xD800)
2882 {
2883 if (c1 > Maxcode)
2884 return codecvt_base::error;
2885 *to_nxt = static_cast<uint32_t>(c1);
2886 frm_nxt += 2;
2887 }
2888 else
2889 {
2890 if (frm_end-frm_nxt < 4)
2891 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002892 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002893 if ((c2 & 0xFC00) != 0xDC00)
2894 return codecvt_base::error;
2895 uint32_t t = static_cast<uint32_t>(
2896 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2897 | ((c1 & 0x003F) << 10)
2898 | (c2 & 0x03FF));
2899 if (t > Maxcode)
2900 return codecvt_base::error;
2901 *to_nxt = t;
2902 frm_nxt += 4;
2903 }
2904 }
2905 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2906}
2907
2908static
2909int
2910utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2911 size_t mx, unsigned long Maxcode = 0x10FFFF,
2912 codecvt_mode mode = codecvt_mode(0))
2913{
2914 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002915 if (mode & consume_header)
2916 {
2917 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2918 frm_nxt += 2;
2919 }
2920 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2921 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002922 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002923 if ((c1 & 0xFC00) == 0xDC00)
2924 break;
2925 if ((c1 & 0xFC00) != 0xD800)
2926 {
2927 if (c1 > Maxcode)
2928 break;
2929 frm_nxt += 2;
2930 }
2931 else
2932 {
2933 if (frm_end-frm_nxt < 4)
2934 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002935 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002936 if ((c2 & 0xFC00) != 0xDC00)
2937 break;
2938 uint32_t t = static_cast<uint32_t>(
2939 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2940 | ((c1 & 0x003F) << 10)
2941 | (c2 & 0x03FF));
2942 if (t > Maxcode)
2943 break;
2944 frm_nxt += 4;
2945 }
2946 }
2947 return static_cast<int>(frm_nxt - frm);
2948}
2949
2950static
2951codecvt_base::result
2952ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2953 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2954 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2955{
2956 frm_nxt = frm;
2957 to_nxt = to;
2958 if (mode & generate_header)
2959 {
2960 if (to_end-to_nxt < 2)
2961 return codecvt_base::partial;
2962 *to_nxt++ = static_cast<uint8_t>(0xFE);
2963 *to_nxt++ = static_cast<uint8_t>(0xFF);
2964 }
2965 for (; frm_nxt < frm_end; ++frm_nxt)
2966 {
2967 uint16_t wc = *frm_nxt;
2968 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2969 return codecvt_base::error;
2970 if (to_end-to_nxt < 2)
2971 return codecvt_base::partial;
2972 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2973 *to_nxt++ = static_cast<uint8_t>(wc);
2974 }
2975 return codecvt_base::ok;
2976}
2977
2978static
2979codecvt_base::result
2980utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2981 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2982 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2983{
2984 frm_nxt = frm;
2985 to_nxt = to;
2986 if (mode & consume_header)
2987 {
2988 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2989 frm_nxt += 2;
2990 }
2991 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2992 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002993 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002994 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2995 return codecvt_base::error;
2996 *to_nxt = c1;
2997 frm_nxt += 2;
2998 }
2999 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3000}
3001
3002static
3003int
3004utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3005 size_t mx, unsigned long Maxcode = 0x10FFFF,
3006 codecvt_mode mode = codecvt_mode(0))
3007{
3008 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003009 if (mode & consume_header)
3010 {
3011 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3012 frm_nxt += 2;
3013 }
3014 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3015 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003016 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003017 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3018 break;
3019 frm_nxt += 2;
3020 }
3021 return static_cast<int>(frm_nxt - frm);
3022}
3023
3024static
3025codecvt_base::result
3026ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3027 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3028 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3029{
3030 frm_nxt = frm;
3031 to_nxt = to;
3032 if (mode & generate_header)
3033 {
3034 if (to_end-to_nxt < 2)
3035 return codecvt_base::partial;
3036 *to_nxt++ = static_cast<uint8_t>(0xFF);
3037 *to_nxt++ = static_cast<uint8_t>(0xFE);
3038 }
3039 for (; frm_nxt < frm_end; ++frm_nxt)
3040 {
3041 uint16_t wc = *frm_nxt;
3042 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3043 return codecvt_base::error;
3044 if (to_end-to_nxt < 2)
3045 return codecvt_base::partial;
3046 *to_nxt++ = static_cast<uint8_t>(wc);
3047 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3048 }
3049 return codecvt_base::ok;
3050}
3051
3052static
3053codecvt_base::result
3054utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3055 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3056 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3057{
3058 frm_nxt = frm;
3059 to_nxt = to;
3060 if (mode & consume_header)
3061 {
3062 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3063 frm_nxt += 2;
3064 }
3065 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3066 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003067 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003068 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3069 return codecvt_base::error;
3070 *to_nxt = c1;
3071 frm_nxt += 2;
3072 }
3073 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3074}
3075
3076static
3077int
3078utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3079 size_t mx, unsigned long Maxcode = 0x10FFFF,
3080 codecvt_mode mode = codecvt_mode(0))
3081{
3082 const uint8_t* frm_nxt = frm;
3083 frm_nxt = frm;
3084 if (mode & consume_header)
3085 {
3086 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3087 frm_nxt += 2;
3088 }
3089 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3090 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003091 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003092 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3093 break;
3094 frm_nxt += 2;
3095 }
3096 return static_cast<int>(frm_nxt - frm);
3097}
3098
Howard Hinnantc51e1022010-05-11 19:42:16 +00003099// template <> class codecvt<char16_t, char, mbstate_t>
3100
Howard Hinnantffb308e2010-08-22 00:03:27 +00003101locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003102
3103codecvt<char16_t, char, mbstate_t>::~codecvt()
3104{
3105}
3106
3107codecvt<char16_t, char, mbstate_t>::result
3108codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003109 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003110 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3111{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003112 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3113 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3114 const uint16_t* _frm_nxt = _frm;
3115 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3116 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3117 uint8_t* _to_nxt = _to;
3118 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3119 frm_nxt = frm + (_frm_nxt - _frm);
3120 to_nxt = to + (_to_nxt - _to);
3121 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003122}
3123
3124codecvt<char16_t, char, mbstate_t>::result
3125codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003126 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003127 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3128{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003129 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3130 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3131 const uint8_t* _frm_nxt = _frm;
3132 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3133 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3134 uint16_t* _to_nxt = _to;
3135 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3136 frm_nxt = frm + (_frm_nxt - _frm);
3137 to_nxt = to + (_to_nxt - _to);
3138 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003139}
3140
3141codecvt<char16_t, char, mbstate_t>::result
3142codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3143 extern_type* to, extern_type*, extern_type*& to_nxt) const
3144{
3145 to_nxt = to;
3146 return noconv;
3147}
3148
3149int
Louis Dionne65358e12021-03-01 12:09:45 -05003150codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003151{
3152 return 0;
3153}
3154
3155bool
Louis Dionne65358e12021-03-01 12:09:45 -05003156codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003157{
3158 return false;
3159}
3160
3161int
3162codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3163 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3164{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003165 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3166 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3167 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003168}
3169
3170int
Louis Dionne65358e12021-03-01 12:09:45 -05003171codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003172{
3173 return 4;
3174}
3175
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003176#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003177
3178// template <> class codecvt<char16_t, char8_t, mbstate_t>
3179
3180locale::id codecvt<char16_t, char8_t, mbstate_t>::id;
3181
3182codecvt<char16_t, char8_t, mbstate_t>::~codecvt()
3183{
3184}
3185
3186codecvt<char16_t, char8_t, mbstate_t>::result
3187codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&,
3188 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3189 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3190{
3191 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3192 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3193 const uint16_t* _frm_nxt = _frm;
3194 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3195 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3196 uint8_t* _to_nxt = _to;
3197 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3198 frm_nxt = frm + (_frm_nxt - _frm);
3199 to_nxt = to + (_to_nxt - _to);
3200 return r;
3201}
3202
3203codecvt<char16_t, char8_t, mbstate_t>::result
3204codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&,
3205 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3206 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3207{
3208 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3209 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3210 const uint8_t* _frm_nxt = _frm;
3211 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3212 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3213 uint16_t* _to_nxt = _to;
3214 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3215 frm_nxt = frm + (_frm_nxt - _frm);
3216 to_nxt = to + (_to_nxt - _to);
3217 return r;
3218}
3219
3220codecvt<char16_t, char8_t, mbstate_t>::result
3221codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&,
3222 extern_type* to, extern_type*, extern_type*& to_nxt) const
3223{
3224 to_nxt = to;
3225 return noconv;
3226}
3227
3228int
Louis Dionne65358e12021-03-01 12:09:45 -05003229codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003230{
3231 return 0;
3232}
3233
3234bool
Louis Dionne65358e12021-03-01 12:09:45 -05003235codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003236{
3237 return false;
3238}
3239
3240int
3241codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&,
3242 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3243{
3244 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3245 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3246 return utf8_to_utf16_length(_frm, _frm_end, mx);
3247}
3248
3249int
Louis Dionne65358e12021-03-01 12:09:45 -05003250codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003251{
3252 return 4;
3253}
3254
3255#endif
3256
Howard Hinnantc51e1022010-05-11 19:42:16 +00003257// template <> class codecvt<char32_t, char, mbstate_t>
3258
Howard Hinnantffb308e2010-08-22 00:03:27 +00003259locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003260
3261codecvt<char32_t, char, mbstate_t>::~codecvt()
3262{
3263}
3264
3265codecvt<char32_t, char, mbstate_t>::result
3266codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003267 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003268 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3269{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003270 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3271 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3272 const uint32_t* _frm_nxt = _frm;
3273 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3274 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3275 uint8_t* _to_nxt = _to;
3276 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3277 frm_nxt = frm + (_frm_nxt - _frm);
3278 to_nxt = to + (_to_nxt - _to);
3279 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003280}
3281
3282codecvt<char32_t, char, mbstate_t>::result
3283codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003284 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003285 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3286{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003287 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3288 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3289 const uint8_t* _frm_nxt = _frm;
3290 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3291 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3292 uint32_t* _to_nxt = _to;
3293 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3294 frm_nxt = frm + (_frm_nxt - _frm);
3295 to_nxt = to + (_to_nxt - _to);
3296 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003297}
3298
3299codecvt<char32_t, char, mbstate_t>::result
3300codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3301 extern_type* to, extern_type*, extern_type*& to_nxt) const
3302{
3303 to_nxt = to;
3304 return noconv;
3305}
3306
3307int
Louis Dionne65358e12021-03-01 12:09:45 -05003308codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003309{
3310 return 0;
3311}
3312
3313bool
Louis Dionne65358e12021-03-01 12:09:45 -05003314codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003315{
3316 return false;
3317}
3318
3319int
3320codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3321 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3322{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003323 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3324 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3325 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003326}
3327
3328int
Louis Dionne65358e12021-03-01 12:09:45 -05003329codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003330{
3331 return 4;
3332}
3333
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -04003334#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01003335
3336// template <> class codecvt<char32_t, char8_t, mbstate_t>
3337
3338locale::id codecvt<char32_t, char8_t, mbstate_t>::id;
3339
3340codecvt<char32_t, char8_t, mbstate_t>::~codecvt()
3341{
3342}
3343
3344codecvt<char32_t, char8_t, mbstate_t>::result
3345codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&,
3346 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3347 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3348{
3349 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3350 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3351 const uint32_t* _frm_nxt = _frm;
3352 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3353 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3354 uint8_t* _to_nxt = _to;
3355 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3356 frm_nxt = frm + (_frm_nxt - _frm);
3357 to_nxt = to + (_to_nxt - _to);
3358 return r;
3359}
3360
3361codecvt<char32_t, char8_t, mbstate_t>::result
3362codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&,
3363 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3364 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3365{
3366 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3367 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3368 const uint8_t* _frm_nxt = _frm;
3369 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3370 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3371 uint32_t* _to_nxt = _to;
3372 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3373 frm_nxt = frm + (_frm_nxt - _frm);
3374 to_nxt = to + (_to_nxt - _to);
3375 return r;
3376}
3377
3378codecvt<char32_t, char8_t, mbstate_t>::result
3379codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&,
3380 extern_type* to, extern_type*, extern_type*& to_nxt) const
3381{
3382 to_nxt = to;
3383 return noconv;
3384}
3385
3386int
Louis Dionne65358e12021-03-01 12:09:45 -05003387codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003388{
3389 return 0;
3390}
3391
3392bool
Louis Dionne65358e12021-03-01 12:09:45 -05003393codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003394{
3395 return false;
3396}
3397
3398int
3399codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&,
3400 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3401{
3402 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3403 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3404 return utf8_to_ucs4_length(_frm, _frm_end, mx);
3405}
3406
3407int
Louis Dionne65358e12021-03-01 12:09:45 -05003408codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept
Marek Kurdej718b62c2020-12-02 08:57:02 +01003409{
3410 return 4;
3411}
3412
3413#endif
3414
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003415// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003416
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003417__codecvt_utf8<wchar_t>::result
3418__codecvt_utf8<wchar_t>::do_out(state_type&,
3419 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003420 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3421{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003422#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003423 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3424 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3425 const uint16_t* _frm_nxt = _frm;
3426#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003427 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3428 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3429 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003430#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003431 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3432 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3433 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003434#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003435 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3436 _Maxcode_, _Mode_);
3437#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003438 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3439 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003440#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003441 frm_nxt = frm + (_frm_nxt - _frm);
3442 to_nxt = to + (_to_nxt - _to);
3443 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003444}
3445
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003446__codecvt_utf8<wchar_t>::result
3447__codecvt_utf8<wchar_t>::do_in(state_type&,
3448 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003449 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3450{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003451 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3452 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3453 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003454#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003455 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3456 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3457 uint16_t* _to_nxt = _to;
3458 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3459 _Maxcode_, _Mode_);
3460#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003461 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3462 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3463 uint32_t* _to_nxt = _to;
3464 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3465 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003466#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003467 frm_nxt = frm + (_frm_nxt - _frm);
3468 to_nxt = to + (_to_nxt - _to);
3469 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003470}
3471
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003472__codecvt_utf8<wchar_t>::result
3473__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003474 extern_type* to, extern_type*, extern_type*& to_nxt) const
3475{
3476 to_nxt = to;
3477 return noconv;
3478}
3479
3480int
Louis Dionne65358e12021-03-01 12:09:45 -05003481__codecvt_utf8<wchar_t>::do_encoding() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003482{
3483 return 0;
3484}
3485
3486bool
Louis Dionne65358e12021-03-01 12:09:45 -05003487__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003488{
3489 return false;
3490}
3491
3492int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003493__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003494 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3495{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003496 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3497 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3498 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003499}
3500
3501int
Louis Dionne65358e12021-03-01 12:09:45 -05003502__codecvt_utf8<wchar_t>::do_max_length() const noexcept
Howard Hinnantc51e1022010-05-11 19:42:16 +00003503{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003504 if (_Mode_ & consume_header)
3505 return 7;
3506 return 4;
3507}
3508
3509// __codecvt_utf8<char16_t>
3510
3511__codecvt_utf8<char16_t>::result
3512__codecvt_utf8<char16_t>::do_out(state_type&,
3513 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3514 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3515{
3516 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3517 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3518 const uint16_t* _frm_nxt = _frm;
3519 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3520 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3521 uint8_t* _to_nxt = _to;
3522 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3523 _Maxcode_, _Mode_);
3524 frm_nxt = frm + (_frm_nxt - _frm);
3525 to_nxt = to + (_to_nxt - _to);
3526 return r;
3527}
3528
3529__codecvt_utf8<char16_t>::result
3530__codecvt_utf8<char16_t>::do_in(state_type&,
3531 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3532 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3533{
3534 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3535 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3536 const uint8_t* _frm_nxt = _frm;
3537 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3538 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3539 uint16_t* _to_nxt = _to;
3540 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3541 _Maxcode_, _Mode_);
3542 frm_nxt = frm + (_frm_nxt - _frm);
3543 to_nxt = to + (_to_nxt - _to);
3544 return r;
3545}
3546
3547__codecvt_utf8<char16_t>::result
3548__codecvt_utf8<char16_t>::do_unshift(state_type&,
3549 extern_type* to, extern_type*, extern_type*& to_nxt) const
3550{
3551 to_nxt = to;
3552 return noconv;
3553}
3554
3555int
Louis Dionne65358e12021-03-01 12:09:45 -05003556__codecvt_utf8<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003557{
3558 return 0;
3559}
3560
3561bool
Louis Dionne65358e12021-03-01 12:09:45 -05003562__codecvt_utf8<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003563{
3564 return false;
3565}
3566
3567int
3568__codecvt_utf8<char16_t>::do_length(state_type&,
3569 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3570{
3571 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3572 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3573 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3574}
3575
3576int
Louis Dionne65358e12021-03-01 12:09:45 -05003577__codecvt_utf8<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003578{
3579 if (_Mode_ & consume_header)
3580 return 6;
3581 return 3;
3582}
3583
3584// __codecvt_utf8<char32_t>
3585
3586__codecvt_utf8<char32_t>::result
3587__codecvt_utf8<char32_t>::do_out(state_type&,
3588 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3589 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3590{
3591 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3592 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3593 const uint32_t* _frm_nxt = _frm;
3594 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3595 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3596 uint8_t* _to_nxt = _to;
3597 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3598 _Maxcode_, _Mode_);
3599 frm_nxt = frm + (_frm_nxt - _frm);
3600 to_nxt = to + (_to_nxt - _to);
3601 return r;
3602}
3603
3604__codecvt_utf8<char32_t>::result
3605__codecvt_utf8<char32_t>::do_in(state_type&,
3606 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3607 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3608{
3609 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3610 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3611 const uint8_t* _frm_nxt = _frm;
3612 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3613 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3614 uint32_t* _to_nxt = _to;
3615 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3616 _Maxcode_, _Mode_);
3617 frm_nxt = frm + (_frm_nxt - _frm);
3618 to_nxt = to + (_to_nxt - _to);
3619 return r;
3620}
3621
3622__codecvt_utf8<char32_t>::result
3623__codecvt_utf8<char32_t>::do_unshift(state_type&,
3624 extern_type* to, extern_type*, extern_type*& to_nxt) const
3625{
3626 to_nxt = to;
3627 return noconv;
3628}
3629
3630int
Louis Dionne65358e12021-03-01 12:09:45 -05003631__codecvt_utf8<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003632{
3633 return 0;
3634}
3635
3636bool
Louis Dionne65358e12021-03-01 12:09:45 -05003637__codecvt_utf8<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003638{
3639 return false;
3640}
3641
3642int
3643__codecvt_utf8<char32_t>::do_length(state_type&,
3644 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3645{
3646 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3647 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3648 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3649}
3650
3651int
Louis Dionne65358e12021-03-01 12:09:45 -05003652__codecvt_utf8<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003653{
3654 if (_Mode_ & consume_header)
3655 return 7;
3656 return 4;
3657}
3658
3659// __codecvt_utf16<wchar_t, false>
3660
3661__codecvt_utf16<wchar_t, false>::result
3662__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3663 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3664 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3665{
3666 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3667 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3668 const uint32_t* _frm_nxt = _frm;
3669 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3670 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3671 uint8_t* _to_nxt = _to;
3672 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3673 _Maxcode_, _Mode_);
3674 frm_nxt = frm + (_frm_nxt - _frm);
3675 to_nxt = to + (_to_nxt - _to);
3676 return r;
3677}
3678
3679__codecvt_utf16<wchar_t, false>::result
3680__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3681 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3682 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3683{
3684 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3685 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3686 const uint8_t* _frm_nxt = _frm;
3687 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3688 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3689 uint32_t* _to_nxt = _to;
3690 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3691 _Maxcode_, _Mode_);
3692 frm_nxt = frm + (_frm_nxt - _frm);
3693 to_nxt = to + (_to_nxt - _to);
3694 return r;
3695}
3696
3697__codecvt_utf16<wchar_t, false>::result
3698__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3699 extern_type* to, extern_type*, extern_type*& to_nxt) const
3700{
3701 to_nxt = to;
3702 return noconv;
3703}
3704
3705int
Louis Dionne65358e12021-03-01 12:09:45 -05003706__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003707{
3708 return 0;
3709}
3710
3711bool
Louis Dionne65358e12021-03-01 12:09:45 -05003712__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003713{
3714 return false;
3715}
3716
3717int
3718__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3719 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3720{
3721 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3722 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3723 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3724}
3725
3726int
Louis Dionne65358e12021-03-01 12:09:45 -05003727__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003728{
3729 if (_Mode_ & consume_header)
3730 return 6;
3731 return 4;
3732}
3733
3734// __codecvt_utf16<wchar_t, true>
3735
3736__codecvt_utf16<wchar_t, true>::result
3737__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3738 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3739 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3740{
3741 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3742 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3743 const uint32_t* _frm_nxt = _frm;
3744 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3745 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3746 uint8_t* _to_nxt = _to;
3747 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3748 _Maxcode_, _Mode_);
3749 frm_nxt = frm + (_frm_nxt - _frm);
3750 to_nxt = to + (_to_nxt - _to);
3751 return r;
3752}
3753
3754__codecvt_utf16<wchar_t, true>::result
3755__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3756 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3757 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3758{
3759 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3760 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3761 const uint8_t* _frm_nxt = _frm;
3762 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3763 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3764 uint32_t* _to_nxt = _to;
3765 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3766 _Maxcode_, _Mode_);
3767 frm_nxt = frm + (_frm_nxt - _frm);
3768 to_nxt = to + (_to_nxt - _to);
3769 return r;
3770}
3771
3772__codecvt_utf16<wchar_t, true>::result
3773__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3774 extern_type* to, extern_type*, extern_type*& to_nxt) const
3775{
3776 to_nxt = to;
3777 return noconv;
3778}
3779
3780int
Louis Dionne65358e12021-03-01 12:09:45 -05003781__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003782{
3783 return 0;
3784}
3785
3786bool
Louis Dionne65358e12021-03-01 12:09:45 -05003787__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003788{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003789 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003790}
3791
3792int
3793__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3794 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3795{
3796 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3797 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3798 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3799}
3800
3801int
Louis Dionne65358e12021-03-01 12:09:45 -05003802__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003803{
3804 if (_Mode_ & consume_header)
3805 return 6;
3806 return 4;
3807}
3808
3809// __codecvt_utf16<char16_t, false>
3810
3811__codecvt_utf16<char16_t, false>::result
3812__codecvt_utf16<char16_t, false>::do_out(state_type&,
3813 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3814 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3815{
3816 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3817 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3818 const uint16_t* _frm_nxt = _frm;
3819 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3820 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3821 uint8_t* _to_nxt = _to;
3822 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3823 _Maxcode_, _Mode_);
3824 frm_nxt = frm + (_frm_nxt - _frm);
3825 to_nxt = to + (_to_nxt - _to);
3826 return r;
3827}
3828
3829__codecvt_utf16<char16_t, false>::result
3830__codecvt_utf16<char16_t, false>::do_in(state_type&,
3831 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3832 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3833{
3834 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3835 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3836 const uint8_t* _frm_nxt = _frm;
3837 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3838 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3839 uint16_t* _to_nxt = _to;
3840 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3841 _Maxcode_, _Mode_);
3842 frm_nxt = frm + (_frm_nxt - _frm);
3843 to_nxt = to + (_to_nxt - _to);
3844 return r;
3845}
3846
3847__codecvt_utf16<char16_t, false>::result
3848__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3849 extern_type* to, extern_type*, extern_type*& to_nxt) const
3850{
3851 to_nxt = to;
3852 return noconv;
3853}
3854
3855int
Louis Dionne65358e12021-03-01 12:09:45 -05003856__codecvt_utf16<char16_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003857{
3858 return 0;
3859}
3860
3861bool
Louis Dionne65358e12021-03-01 12:09:45 -05003862__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003863{
3864 return false;
3865}
3866
3867int
3868__codecvt_utf16<char16_t, false>::do_length(state_type&,
3869 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3870{
3871 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3872 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3873 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3874}
3875
3876int
Louis Dionne65358e12021-03-01 12:09:45 -05003877__codecvt_utf16<char16_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003878{
3879 if (_Mode_ & consume_header)
3880 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003881 return 2;
3882}
3883
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003884// __codecvt_utf16<char16_t, true>
3885
3886__codecvt_utf16<char16_t, true>::result
3887__codecvt_utf16<char16_t, true>::do_out(state_type&,
3888 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3889 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3890{
3891 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3892 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3893 const uint16_t* _frm_nxt = _frm;
3894 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3895 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3896 uint8_t* _to_nxt = _to;
3897 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3898 _Maxcode_, _Mode_);
3899 frm_nxt = frm + (_frm_nxt - _frm);
3900 to_nxt = to + (_to_nxt - _to);
3901 return r;
3902}
3903
3904__codecvt_utf16<char16_t, true>::result
3905__codecvt_utf16<char16_t, true>::do_in(state_type&,
3906 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3907 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3908{
3909 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3910 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3911 const uint8_t* _frm_nxt = _frm;
3912 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3913 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3914 uint16_t* _to_nxt = _to;
3915 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3916 _Maxcode_, _Mode_);
3917 frm_nxt = frm + (_frm_nxt - _frm);
3918 to_nxt = to + (_to_nxt - _to);
3919 return r;
3920}
3921
3922__codecvt_utf16<char16_t, true>::result
3923__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3924 extern_type* to, extern_type*, extern_type*& to_nxt) const
3925{
3926 to_nxt = to;
3927 return noconv;
3928}
3929
3930int
Louis Dionne65358e12021-03-01 12:09:45 -05003931__codecvt_utf16<char16_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003932{
3933 return 0;
3934}
3935
3936bool
Louis Dionne65358e12021-03-01 12:09:45 -05003937__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003938{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003939 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003940}
3941
3942int
3943__codecvt_utf16<char16_t, true>::do_length(state_type&,
3944 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3945{
3946 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3947 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3948 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3949}
3950
3951int
Louis Dionne65358e12021-03-01 12:09:45 -05003952__codecvt_utf16<char16_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003953{
3954 if (_Mode_ & consume_header)
3955 return 4;
3956 return 2;
3957}
3958
3959// __codecvt_utf16<char32_t, false>
3960
3961__codecvt_utf16<char32_t, false>::result
3962__codecvt_utf16<char32_t, false>::do_out(state_type&,
3963 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3964 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3965{
3966 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3967 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3968 const uint32_t* _frm_nxt = _frm;
3969 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3970 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3971 uint8_t* _to_nxt = _to;
3972 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3973 _Maxcode_, _Mode_);
3974 frm_nxt = frm + (_frm_nxt - _frm);
3975 to_nxt = to + (_to_nxt - _to);
3976 return r;
3977}
3978
3979__codecvt_utf16<char32_t, false>::result
3980__codecvt_utf16<char32_t, false>::do_in(state_type&,
3981 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3982 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3983{
3984 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3985 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3986 const uint8_t* _frm_nxt = _frm;
3987 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3988 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3989 uint32_t* _to_nxt = _to;
3990 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3991 _Maxcode_, _Mode_);
3992 frm_nxt = frm + (_frm_nxt - _frm);
3993 to_nxt = to + (_to_nxt - _to);
3994 return r;
3995}
3996
3997__codecvt_utf16<char32_t, false>::result
3998__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3999 extern_type* to, extern_type*, extern_type*& to_nxt) const
4000{
4001 to_nxt = to;
4002 return noconv;
4003}
4004
4005int
Louis Dionne65358e12021-03-01 12:09:45 -05004006__codecvt_utf16<char32_t, false>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004007{
4008 return 0;
4009}
4010
4011bool
Louis Dionne65358e12021-03-01 12:09:45 -05004012__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004013{
4014 return false;
4015}
4016
4017int
4018__codecvt_utf16<char32_t, false>::do_length(state_type&,
4019 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4020{
4021 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4022 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4023 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4024}
4025
4026int
Louis Dionne65358e12021-03-01 12:09:45 -05004027__codecvt_utf16<char32_t, false>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004028{
4029 if (_Mode_ & consume_header)
4030 return 6;
4031 return 4;
4032}
4033
4034// __codecvt_utf16<char32_t, true>
4035
4036__codecvt_utf16<char32_t, true>::result
4037__codecvt_utf16<char32_t, true>::do_out(state_type&,
4038 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4039 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4040{
4041 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4042 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4043 const uint32_t* _frm_nxt = _frm;
4044 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4045 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4046 uint8_t* _to_nxt = _to;
4047 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4048 _Maxcode_, _Mode_);
4049 frm_nxt = frm + (_frm_nxt - _frm);
4050 to_nxt = to + (_to_nxt - _to);
4051 return r;
4052}
4053
4054__codecvt_utf16<char32_t, true>::result
4055__codecvt_utf16<char32_t, true>::do_in(state_type&,
4056 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4057 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4058{
4059 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4060 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4061 const uint8_t* _frm_nxt = _frm;
4062 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4063 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4064 uint32_t* _to_nxt = _to;
4065 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4066 _Maxcode_, _Mode_);
4067 frm_nxt = frm + (_frm_nxt - _frm);
4068 to_nxt = to + (_to_nxt - _to);
4069 return r;
4070}
4071
4072__codecvt_utf16<char32_t, true>::result
4073__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
4074 extern_type* to, extern_type*, extern_type*& to_nxt) const
4075{
4076 to_nxt = to;
4077 return noconv;
4078}
4079
4080int
Louis Dionne65358e12021-03-01 12:09:45 -05004081__codecvt_utf16<char32_t, true>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004082{
4083 return 0;
4084}
4085
4086bool
Louis Dionne65358e12021-03-01 12:09:45 -05004087__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004088{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004089 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004090}
4091
4092int
4093__codecvt_utf16<char32_t, true>::do_length(state_type&,
4094 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4095{
4096 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4097 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4098 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4099}
4100
4101int
Louis Dionne65358e12021-03-01 12:09:45 -05004102__codecvt_utf16<char32_t, true>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004103{
4104 if (_Mode_ & consume_header)
4105 return 6;
4106 return 4;
4107}
4108
4109// __codecvt_utf8_utf16<wchar_t>
4110
4111__codecvt_utf8_utf16<wchar_t>::result
4112__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4113 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4114 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4115{
4116 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4117 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4118 const uint32_t* _frm_nxt = _frm;
4119 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4120 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4121 uint8_t* _to_nxt = _to;
4122 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4123 _Maxcode_, _Mode_);
4124 frm_nxt = frm + (_frm_nxt - _frm);
4125 to_nxt = to + (_to_nxt - _to);
4126 return r;
4127}
4128
4129__codecvt_utf8_utf16<wchar_t>::result
4130__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4131 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4132 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4133{
4134 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4135 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4136 const uint8_t* _frm_nxt = _frm;
4137 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4138 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4139 uint32_t* _to_nxt = _to;
4140 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4141 _Maxcode_, _Mode_);
4142 frm_nxt = frm + (_frm_nxt - _frm);
4143 to_nxt = to + (_to_nxt - _to);
4144 return r;
4145}
4146
4147__codecvt_utf8_utf16<wchar_t>::result
4148__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4149 extern_type* to, extern_type*, extern_type*& to_nxt) const
4150{
4151 to_nxt = to;
4152 return noconv;
4153}
4154
4155int
Louis Dionne65358e12021-03-01 12:09:45 -05004156__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004157{
4158 return 0;
4159}
4160
4161bool
Louis Dionne65358e12021-03-01 12:09:45 -05004162__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004163{
4164 return false;
4165}
4166
4167int
4168__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4169 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4170{
4171 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4172 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4173 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4174}
4175
4176int
Louis Dionne65358e12021-03-01 12:09:45 -05004177__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004178{
4179 if (_Mode_ & consume_header)
4180 return 7;
4181 return 4;
4182}
4183
4184// __codecvt_utf8_utf16<char16_t>
4185
4186__codecvt_utf8_utf16<char16_t>::result
4187__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4188 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4189 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4190{
4191 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4192 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4193 const uint16_t* _frm_nxt = _frm;
4194 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4195 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4196 uint8_t* _to_nxt = _to;
4197 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4198 _Maxcode_, _Mode_);
4199 frm_nxt = frm + (_frm_nxt - _frm);
4200 to_nxt = to + (_to_nxt - _to);
4201 return r;
4202}
4203
4204__codecvt_utf8_utf16<char16_t>::result
4205__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4206 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4207 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4208{
4209 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4210 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4211 const uint8_t* _frm_nxt = _frm;
4212 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4213 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4214 uint16_t* _to_nxt = _to;
4215 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4216 _Maxcode_, _Mode_);
4217 frm_nxt = frm + (_frm_nxt - _frm);
4218 to_nxt = to + (_to_nxt - _to);
4219 return r;
4220}
4221
4222__codecvt_utf8_utf16<char16_t>::result
4223__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4224 extern_type* to, extern_type*, extern_type*& to_nxt) const
4225{
4226 to_nxt = to;
4227 return noconv;
4228}
4229
4230int
Louis Dionne65358e12021-03-01 12:09:45 -05004231__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004232{
4233 return 0;
4234}
4235
4236bool
Louis Dionne65358e12021-03-01 12:09:45 -05004237__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004238{
4239 return false;
4240}
4241
4242int
4243__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4244 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4245{
4246 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4247 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4248 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4249}
4250
4251int
Louis Dionne65358e12021-03-01 12:09:45 -05004252__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004253{
4254 if (_Mode_ & consume_header)
4255 return 7;
4256 return 4;
4257}
4258
4259// __codecvt_utf8_utf16<char32_t>
4260
4261__codecvt_utf8_utf16<char32_t>::result
4262__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4263 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4264 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4265{
4266 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4267 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4268 const uint32_t* _frm_nxt = _frm;
4269 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4270 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4271 uint8_t* _to_nxt = _to;
4272 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4273 _Maxcode_, _Mode_);
4274 frm_nxt = frm + (_frm_nxt - _frm);
4275 to_nxt = to + (_to_nxt - _to);
4276 return r;
4277}
4278
4279__codecvt_utf8_utf16<char32_t>::result
4280__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4281 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4282 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4283{
4284 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4285 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4286 const uint8_t* _frm_nxt = _frm;
4287 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4288 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4289 uint32_t* _to_nxt = _to;
4290 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4291 _Maxcode_, _Mode_);
4292 frm_nxt = frm + (_frm_nxt - _frm);
4293 to_nxt = to + (_to_nxt - _to);
4294 return r;
4295}
4296
4297__codecvt_utf8_utf16<char32_t>::result
4298__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4299 extern_type* to, extern_type*, extern_type*& to_nxt) const
4300{
4301 to_nxt = to;
4302 return noconv;
4303}
4304
4305int
Louis Dionne65358e12021-03-01 12:09:45 -05004306__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004307{
4308 return 0;
4309}
4310
4311bool
Louis Dionne65358e12021-03-01 12:09:45 -05004312__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004313{
4314 return false;
4315}
4316
4317int
4318__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4319 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4320{
4321 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4322 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4323 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4324}
4325
4326int
Louis Dionne65358e12021-03-01 12:09:45 -05004327__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004328{
4329 if (_Mode_ & consume_header)
4330 return 7;
4331 return 4;
4332}
4333
Howard Hinnantc51e1022010-05-11 19:42:16 +00004334// __narrow_to_utf8<16>
4335
4336__narrow_to_utf8<16>::~__narrow_to_utf8()
4337{
4338}
4339
4340// __narrow_to_utf8<32>
4341
4342__narrow_to_utf8<32>::~__narrow_to_utf8()
4343{
4344}
4345
4346// __widen_from_utf8<16>
4347
4348__widen_from_utf8<16>::~__widen_from_utf8()
4349{
4350}
4351
4352// __widen_from_utf8<32>
4353
4354__widen_from_utf8<32>::~__widen_from_utf8()
4355{
4356}
4357
Eric Fiselierbf945a22016-12-11 00:20:59 +00004358
4359static bool checked_string_to_wchar_convert(wchar_t& dest,
4360 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004361 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004362 if (*ptr == '\0')
4363 return false;
4364 mbstate_t mb = {};
4365 wchar_t out;
4366 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4367 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4368 return false;
4369 }
4370 dest = out;
4371 return true;
4372}
4373
4374static bool checked_string_to_char_convert(char& dest,
4375 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004376 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004377 if (*ptr == '\0')
4378 return false;
4379 if (!ptr[1]) {
4380 dest = *ptr;
4381 return true;
4382 }
4383 // First convert the MBS into a wide char then attempt to narrow it using
4384 // wctob_l.
4385 wchar_t wout;
4386 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4387 return false;
4388 int res;
4389 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4390 dest = res;
4391 return true;
4392 }
4393 // FIXME: Work around specific multibyte sequences that we can reasonable
4394 // translate into a different single byte.
4395 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004396 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004397 case L'\u00A0': // non-breaking space
4398 dest = ' ';
4399 return true;
4400 default:
4401 return false;
4402 }
4403 _LIBCPP_UNREACHABLE();
4404}
4405
4406
Howard Hinnantc51e1022010-05-11 19:42:16 +00004407// numpunct<char> && numpunct<wchar_t>
4408
4409locale::id numpunct< char >::id;
4410locale::id numpunct<wchar_t>::id;
4411
4412numpunct<char>::numpunct(size_t refs)
4413 : locale::facet(refs),
4414 __decimal_point_('.'),
4415 __thousands_sep_(',')
4416{
4417}
4418
4419numpunct<wchar_t>::numpunct(size_t refs)
4420 : locale::facet(refs),
4421 __decimal_point_(L'.'),
4422 __thousands_sep_(L',')
4423{
4424}
4425
4426numpunct<char>::~numpunct()
4427{
4428}
4429
4430numpunct<wchar_t>::~numpunct()
4431{
4432}
4433
4434 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4435wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4436
4437 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4438wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4439
4440string numpunct< char >::do_grouping() const {return __grouping_;}
4441string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4442
4443 string numpunct< char >::do_truename() const {return "true";}
4444wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4445
4446 string numpunct< char >::do_falsename() const {return "false";}
4447wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4448
4449// numpunct_byname<char>
4450
4451numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4452 : numpunct<char>(refs)
4453{
4454 __init(nm);
4455}
4456
4457numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4458 : numpunct<char>(refs)
4459{
4460 __init(nm.c_str());
4461}
4462
4463numpunct_byname<char>::~numpunct_byname()
4464{
4465}
4466
4467void
4468numpunct_byname<char>::__init(const char* nm)
4469{
4470 if (strcmp(nm, "C") != 0)
4471 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004472 __libcpp_unique_locale loc(nm);
4473 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004474 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004475 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004476
Ben Craig3756b922016-03-09 15:39:39 +00004477 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004478 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4479 loc.get());
4480 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4481 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004482 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004483 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004484 }
4485}
4486
4487// numpunct_byname<wchar_t>
4488
4489numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4490 : numpunct<wchar_t>(refs)
4491{
4492 __init(nm);
4493}
4494
4495numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4496 : numpunct<wchar_t>(refs)
4497{
4498 __init(nm.c_str());
4499}
4500
4501numpunct_byname<wchar_t>::~numpunct_byname()
4502{
4503}
4504
4505void
4506numpunct_byname<wchar_t>::__init(const char* nm)
4507{
4508 if (strcmp(nm, "C") != 0)
4509 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004510 __libcpp_unique_locale loc(nm);
4511 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004512 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004513 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004514
Ben Craig3756b922016-03-09 15:39:39 +00004515 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004516 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4517 loc.get());
4518 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4519 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004520 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004521 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004522 }
4523}
4524
4525// num_get helpers
4526
4527int
4528__num_get_base::__get_base(ios_base& iob)
4529{
4530 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4531 if (__basefield == ios_base::oct)
4532 return 8;
4533 else if (__basefield == ios_base::hex)
4534 return 16;
4535 else if (__basefield == 0)
4536 return 0;
4537 return 10;
4538}
4539
4540const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4541
4542void
4543__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4544 ios_base::iostate& __err)
4545{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004546// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4547// 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 +00004548 if (__grouping.size() != 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004549 {
4550 reverse(__g, __g_end);
4551 const char* __ig = __grouping.data();
4552 const char* __eg = __ig + __grouping.size();
4553 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4554 {
4555 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4556 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004557 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004558 {
4559 __err = ios_base::failbit;
4560 return;
4561 }
4562 }
4563 if (__eg - __ig > 1)
4564 ++__ig;
4565 }
4566 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4567 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004568 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004569 __err = ios_base::failbit;
4570 }
4571 }
4572}
4573
4574void
4575__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4576 ios_base::fmtflags __flags)
4577{
Martin Storsjöc1faeee2021-06-01 09:04:58 +00004578 if ((__flags & ios_base::showpos) &&
4579 (__flags & ios_base::basefield) != ios_base::oct &&
4580 (__flags & ios_base::basefield) != ios_base::hex &&
4581 __signd)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004582 *__fmtp++ = '+';
4583 if (__flags & ios_base::showbase)
4584 *__fmtp++ = '#';
4585 while(*__len)
4586 *__fmtp++ = *__len++;
4587 if ((__flags & ios_base::basefield) == ios_base::oct)
4588 *__fmtp = 'o';
4589 else if ((__flags & ios_base::basefield) == ios_base::hex)
4590 {
4591 if (__flags & ios_base::uppercase)
4592 *__fmtp = 'X';
4593 else
4594 *__fmtp = 'x';
4595 }
4596 else if (__signd)
4597 *__fmtp = 'd';
4598 else
4599 *__fmtp = 'u';
4600}
4601
4602bool
4603__num_put_base::__format_float(char* __fmtp, const char* __len,
4604 ios_base::fmtflags __flags)
4605{
4606 bool specify_precision = true;
4607 if (__flags & ios_base::showpos)
4608 *__fmtp++ = '+';
4609 if (__flags & ios_base::showpoint)
4610 *__fmtp++ = '#';
4611 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004612 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004613 if (floatfield == (ios_base::fixed | ios_base::scientific))
4614 specify_precision = false;
4615 else
4616 {
4617 *__fmtp++ = '.';
4618 *__fmtp++ = '*';
4619 }
4620 while(*__len)
4621 *__fmtp++ = *__len++;
4622 if (floatfield == ios_base::fixed)
4623 {
4624 if (uppercase)
4625 *__fmtp = 'F';
4626 else
4627 *__fmtp = 'f';
4628 }
4629 else if (floatfield == ios_base::scientific)
4630 {
4631 if (uppercase)
4632 *__fmtp = 'E';
4633 else
4634 *__fmtp = 'e';
4635 }
4636 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4637 {
4638 if (uppercase)
4639 *__fmtp = 'A';
4640 else
4641 *__fmtp = 'a';
4642 }
4643 else
4644 {
4645 if (uppercase)
4646 *__fmtp = 'G';
4647 else
4648 *__fmtp = 'g';
4649 }
4650 return specify_precision;
4651}
4652
4653char*
4654__num_put_base::__identify_padding(char* __nb, char* __ne,
4655 const ios_base& __iob)
4656{
4657 switch (__iob.flags() & ios_base::adjustfield)
4658 {
4659 case ios_base::internal:
4660 if (__nb[0] == '-' || __nb[0] == '+')
4661 return __nb+1;
4662 if (__ne - __nb >= 2 && __nb[0] == '0'
4663 && (__nb[1] == 'x' || __nb[1] == 'X'))
4664 return __nb+2;
4665 break;
4666 case ios_base::left:
4667 return __ne;
4668 case ios_base::right:
4669 default:
4670 break;
4671 }
4672 return __nb;
4673}
4674
4675// time_get
4676
4677static
4678string*
4679init_weeks()
4680{
4681 static string weeks[14];
4682 weeks[0] = "Sunday";
4683 weeks[1] = "Monday";
4684 weeks[2] = "Tuesday";
4685 weeks[3] = "Wednesday";
4686 weeks[4] = "Thursday";
4687 weeks[5] = "Friday";
4688 weeks[6] = "Saturday";
4689 weeks[7] = "Sun";
4690 weeks[8] = "Mon";
4691 weeks[9] = "Tue";
4692 weeks[10] = "Wed";
4693 weeks[11] = "Thu";
4694 weeks[12] = "Fri";
4695 weeks[13] = "Sat";
4696 return weeks;
4697}
4698
4699static
4700wstring*
4701init_wweeks()
4702{
4703 static wstring weeks[14];
4704 weeks[0] = L"Sunday";
4705 weeks[1] = L"Monday";
4706 weeks[2] = L"Tuesday";
4707 weeks[3] = L"Wednesday";
4708 weeks[4] = L"Thursday";
4709 weeks[5] = L"Friday";
4710 weeks[6] = L"Saturday";
4711 weeks[7] = L"Sun";
4712 weeks[8] = L"Mon";
4713 weeks[9] = L"Tue";
4714 weeks[10] = L"Wed";
4715 weeks[11] = L"Thu";
4716 weeks[12] = L"Fri";
4717 weeks[13] = L"Sat";
4718 return weeks;
4719}
4720
4721template <>
4722const string*
4723__time_get_c_storage<char>::__weeks() const
4724{
4725 static const string* weeks = init_weeks();
4726 return weeks;
4727}
4728
4729template <>
4730const wstring*
4731__time_get_c_storage<wchar_t>::__weeks() const
4732{
4733 static const wstring* weeks = init_wweeks();
4734 return weeks;
4735}
4736
4737static
4738string*
4739init_months()
4740{
4741 static string months[24];
4742 months[0] = "January";
4743 months[1] = "February";
4744 months[2] = "March";
4745 months[3] = "April";
4746 months[4] = "May";
4747 months[5] = "June";
4748 months[6] = "July";
4749 months[7] = "August";
4750 months[8] = "September";
4751 months[9] = "October";
4752 months[10] = "November";
4753 months[11] = "December";
4754 months[12] = "Jan";
4755 months[13] = "Feb";
4756 months[14] = "Mar";
4757 months[15] = "Apr";
4758 months[16] = "May";
4759 months[17] = "Jun";
4760 months[18] = "Jul";
4761 months[19] = "Aug";
4762 months[20] = "Sep";
4763 months[21] = "Oct";
4764 months[22] = "Nov";
4765 months[23] = "Dec";
4766 return months;
4767}
4768
4769static
4770wstring*
4771init_wmonths()
4772{
4773 static wstring months[24];
4774 months[0] = L"January";
4775 months[1] = L"February";
4776 months[2] = L"March";
4777 months[3] = L"April";
4778 months[4] = L"May";
4779 months[5] = L"June";
4780 months[6] = L"July";
4781 months[7] = L"August";
4782 months[8] = L"September";
4783 months[9] = L"October";
4784 months[10] = L"November";
4785 months[11] = L"December";
4786 months[12] = L"Jan";
4787 months[13] = L"Feb";
4788 months[14] = L"Mar";
4789 months[15] = L"Apr";
4790 months[16] = L"May";
4791 months[17] = L"Jun";
4792 months[18] = L"Jul";
4793 months[19] = L"Aug";
4794 months[20] = L"Sep";
4795 months[21] = L"Oct";
4796 months[22] = L"Nov";
4797 months[23] = L"Dec";
4798 return months;
4799}
4800
4801template <>
4802const string*
4803__time_get_c_storage<char>::__months() const
4804{
4805 static const string* months = init_months();
4806 return months;
4807}
4808
4809template <>
4810const wstring*
4811__time_get_c_storage<wchar_t>::__months() const
4812{
4813 static const wstring* months = init_wmonths();
4814 return months;
4815}
4816
4817static
4818string*
4819init_am_pm()
4820{
Marshall Clow5cc04922018-01-11 17:16:52 +00004821 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004822 am_pm[0] = "AM";
4823 am_pm[1] = "PM";
4824 return am_pm;
4825}
4826
4827static
4828wstring*
4829init_wam_pm()
4830{
Marshall Clow5cc04922018-01-11 17:16:52 +00004831 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004832 am_pm[0] = L"AM";
4833 am_pm[1] = L"PM";
4834 return am_pm;
4835}
4836
4837template <>
4838const string*
4839__time_get_c_storage<char>::__am_pm() const
4840{
4841 static const string* am_pm = init_am_pm();
4842 return am_pm;
4843}
4844
4845template <>
4846const wstring*
4847__time_get_c_storage<wchar_t>::__am_pm() const
4848{
4849 static const wstring* am_pm = init_wam_pm();
4850 return am_pm;
4851}
4852
4853template <>
4854const string&
4855__time_get_c_storage<char>::__x() const
4856{
4857 static string s("%m/%d/%y");
4858 return s;
4859}
4860
4861template <>
4862const wstring&
4863__time_get_c_storage<wchar_t>::__x() const
4864{
4865 static wstring s(L"%m/%d/%y");
4866 return s;
4867}
4868
4869template <>
4870const string&
4871__time_get_c_storage<char>::__X() const
4872{
4873 static string s("%H:%M:%S");
4874 return s;
4875}
4876
4877template <>
4878const wstring&
4879__time_get_c_storage<wchar_t>::__X() const
4880{
4881 static wstring s(L"%H:%M:%S");
4882 return s;
4883}
4884
4885template <>
4886const string&
4887__time_get_c_storage<char>::__c() const
4888{
4889 static string s("%a %b %d %H:%M:%S %Y");
4890 return s;
4891}
4892
4893template <>
4894const wstring&
4895__time_get_c_storage<wchar_t>::__c() const
4896{
4897 static wstring s(L"%a %b %d %H:%M:%S %Y");
4898 return s;
4899}
4900
4901template <>
4902const string&
4903__time_get_c_storage<char>::__r() const
4904{
4905 static string s("%I:%M:%S %p");
4906 return s;
4907}
4908
4909template <>
4910const wstring&
4911__time_get_c_storage<wchar_t>::__r() const
4912{
4913 static wstring s(L"%I:%M:%S %p");
4914 return s;
4915}
4916
4917// time_get_byname
4918
4919__time_get::__time_get(const char* nm)
4920 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4921{
4922 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004923 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004924 " failed to construct for " + string(nm));
4925}
4926
4927__time_get::__time_get(const string& nm)
4928 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4929{
4930 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004931 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004932 " failed to construct for " + nm);
4933}
4934
4935__time_get::~__time_get()
4936{
4937 freelocale(__loc_);
4938}
Marshall Clowd920eea2013-10-21 15:07:28 +00004939#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004940#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004941#endif
4942#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004943#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004944#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004945
Howard Hinnantc51e1022010-05-11 19:42:16 +00004946template <>
4947string
4948__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4949{
Howard Hinnant990207c2012-02-19 14:55:32 +00004950 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004951 t.tm_sec = 59;
4952 t.tm_min = 55;
4953 t.tm_hour = 23;
4954 t.tm_mday = 31;
4955 t.tm_mon = 11;
4956 t.tm_year = 161;
4957 t.tm_wday = 6;
4958 t.tm_yday = 364;
4959 t.tm_isdst = -1;
4960 char buf[100];
4961 char f[3] = {0};
4962 f[0] = '%';
4963 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004964 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004965 char* bb = buf;
4966 char* be = buf + n;
4967 string result;
4968 while (bb != be)
4969 {
4970 if (ct.is(ctype_base::space, *bb))
4971 {
4972 result.push_back(' ');
4973 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4974 ;
4975 continue;
4976 }
4977 char* w = bb;
4978 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004979 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004980 ct, err, false)
4981 - this->__weeks_;
4982 if (i < 14)
4983 {
4984 result.push_back('%');
4985 if (i < 7)
4986 result.push_back('A');
4987 else
4988 result.push_back('a');
4989 bb = w;
4990 continue;
4991 }
4992 w = bb;
4993 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4994 ct, err, false)
4995 - this->__months_;
4996 if (i < 24)
4997 {
4998 result.push_back('%');
4999 if (i < 12)
5000 result.push_back('B');
5001 else
5002 result.push_back('b');
5003 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5004 result.back() = 'm';
5005 bb = w;
5006 continue;
5007 }
5008 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5009 {
5010 w = bb;
5011 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
5012 ct, err, false) - this->__am_pm_;
5013 if (i < 2)
5014 {
5015 result.push_back('%');
5016 result.push_back('p');
5017 bb = w;
5018 continue;
5019 }
5020 }
5021 w = bb;
5022 if (ct.is(ctype_base::digit, *bb))
5023 {
5024 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
5025 {
5026 case 6:
5027 result.push_back('%');
5028 result.push_back('w');
5029 break;
5030 case 7:
5031 result.push_back('%');
5032 result.push_back('u');
5033 break;
5034 case 11:
5035 result.push_back('%');
5036 result.push_back('I');
5037 break;
5038 case 12:
5039 result.push_back('%');
5040 result.push_back('m');
5041 break;
5042 case 23:
5043 result.push_back('%');
5044 result.push_back('H');
5045 break;
5046 case 31:
5047 result.push_back('%');
5048 result.push_back('d');
5049 break;
5050 case 55:
5051 result.push_back('%');
5052 result.push_back('M');
5053 break;
5054 case 59:
5055 result.push_back('%');
5056 result.push_back('S');
5057 break;
5058 case 61:
5059 result.push_back('%');
5060 result.push_back('y');
5061 break;
5062 case 364:
5063 result.push_back('%');
5064 result.push_back('j');
5065 break;
5066 case 2061:
5067 result.push_back('%');
5068 result.push_back('Y');
5069 break;
5070 default:
5071 for (; w != bb; ++w)
5072 result.push_back(*w);
5073 break;
5074 }
5075 continue;
5076 }
5077 if (*bb == '%')
5078 {
5079 result.push_back('%');
5080 result.push_back('%');
5081 ++bb;
5082 continue;
5083 }
5084 result.push_back(*bb);
5085 ++bb;
5086 }
5087 return result;
5088}
5089
Marshall Clowd920eea2013-10-21 15:07:28 +00005090#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00005091#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00005092#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005093
Howard Hinnantc51e1022010-05-11 19:42:16 +00005094template <>
5095wstring
5096__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
5097{
Howard Hinnant990207c2012-02-19 14:55:32 +00005098 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005099 t.tm_sec = 59;
5100 t.tm_min = 55;
5101 t.tm_hour = 23;
5102 t.tm_mday = 31;
5103 t.tm_mon = 11;
5104 t.tm_year = 161;
5105 t.tm_wday = 6;
5106 t.tm_yday = 364;
5107 t.tm_isdst = -1;
5108 char buf[100];
5109 char f[3] = {0};
5110 f[0] = '%';
5111 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005112 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005113 wchar_t wbuf[100];
5114 wchar_t* wbb = wbuf;
5115 mbstate_t mb = {0};
5116 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005117 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005118 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005119 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00005120 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005121 wstring result;
5122 while (wbb != wbe)
5123 {
5124 if (ct.is(ctype_base::space, *wbb))
5125 {
5126 result.push_back(L' ');
5127 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
5128 ;
5129 continue;
5130 }
5131 wchar_t* w = wbb;
5132 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00005133 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00005134 ct, err, false)
5135 - this->__weeks_;
5136 if (i < 14)
5137 {
5138 result.push_back(L'%');
5139 if (i < 7)
5140 result.push_back(L'A');
5141 else
5142 result.push_back(L'a');
5143 wbb = w;
5144 continue;
5145 }
5146 w = wbb;
5147 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5148 ct, err, false)
5149 - this->__months_;
5150 if (i < 24)
5151 {
5152 result.push_back(L'%');
5153 if (i < 12)
5154 result.push_back(L'B');
5155 else
5156 result.push_back(L'b');
5157 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5158 result.back() = L'm';
5159 wbb = w;
5160 continue;
5161 }
5162 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5163 {
5164 w = wbb;
5165 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5166 ct, err, false) - this->__am_pm_;
5167 if (i < 2)
5168 {
5169 result.push_back(L'%');
5170 result.push_back(L'p');
5171 wbb = w;
5172 continue;
5173 }
5174 }
5175 w = wbb;
5176 if (ct.is(ctype_base::digit, *wbb))
5177 {
5178 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5179 {
5180 case 6:
5181 result.push_back(L'%');
5182 result.push_back(L'w');
5183 break;
5184 case 7:
5185 result.push_back(L'%');
5186 result.push_back(L'u');
5187 break;
5188 case 11:
5189 result.push_back(L'%');
5190 result.push_back(L'I');
5191 break;
5192 case 12:
5193 result.push_back(L'%');
5194 result.push_back(L'm');
5195 break;
5196 case 23:
5197 result.push_back(L'%');
5198 result.push_back(L'H');
5199 break;
5200 case 31:
5201 result.push_back(L'%');
5202 result.push_back(L'd');
5203 break;
5204 case 55:
5205 result.push_back(L'%');
5206 result.push_back(L'M');
5207 break;
5208 case 59:
5209 result.push_back(L'%');
5210 result.push_back(L'S');
5211 break;
5212 case 61:
5213 result.push_back(L'%');
5214 result.push_back(L'y');
5215 break;
5216 case 364:
5217 result.push_back(L'%');
5218 result.push_back(L'j');
5219 break;
5220 case 2061:
5221 result.push_back(L'%');
5222 result.push_back(L'Y');
5223 break;
5224 default:
5225 for (; w != wbb; ++w)
5226 result.push_back(*w);
5227 break;
5228 }
5229 continue;
5230 }
5231 if (ct.narrow(*wbb, 0) == '%')
5232 {
5233 result.push_back(L'%');
5234 result.push_back(L'%');
5235 ++wbb;
5236 continue;
5237 }
5238 result.push_back(*wbb);
5239 ++wbb;
5240 }
5241 return result;
5242}
5243
5244template <>
5245void
5246__time_get_storage<char>::init(const ctype<char>& ct)
5247{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005248 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005249 char buf[100];
5250 // __weeks_
5251 for (int i = 0; i < 7; ++i)
5252 {
5253 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005254 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005255 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005256 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005257 __weeks_[i+7] = buf;
5258 }
5259 // __months_
5260 for (int i = 0; i < 12; ++i)
5261 {
5262 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005263 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005264 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005265 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005266 __months_[i+12] = buf;
5267 }
5268 // __am_pm_
5269 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005270 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005271 __am_pm_[0] = buf;
5272 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005273 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005274 __am_pm_[1] = buf;
5275 __c_ = __analyze('c', ct);
5276 __r_ = __analyze('r', ct);
5277 __x_ = __analyze('x', ct);
5278 __X_ = __analyze('X', ct);
5279}
5280
5281template <>
5282void
5283__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5284{
5285 tm t = {0};
5286 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005287 wchar_t wbuf[100];
5288 wchar_t* wbe;
5289 mbstate_t mb = {0};
5290 // __weeks_
5291 for (int i = 0; i < 7; ++i)
5292 {
5293 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005294 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005295 mb = mbstate_t();
5296 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005297 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005298 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005299 __throw_runtime_error("locale not supported");
5300 wbe = wbuf + j;
5301 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005302 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005303 mb = mbstate_t();
5304 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005305 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005306 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005307 __throw_runtime_error("locale not supported");
5308 wbe = wbuf + j;
5309 __weeks_[i+7].assign(wbuf, wbe);
5310 }
5311 // __months_
5312 for (int i = 0; i < 12; ++i)
5313 {
5314 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005315 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005316 mb = mbstate_t();
5317 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005318 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005319 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005320 __throw_runtime_error("locale not supported");
5321 wbe = wbuf + j;
5322 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005323 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005324 mb = mbstate_t();
5325 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005326 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Martin Storsjö2f9fec72019-10-28 23:46:34 +02005327 if (j == size_t(-1) || j == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005328 __throw_runtime_error("locale not supported");
5329 wbe = wbuf + j;
5330 __months_[i+12].assign(wbuf, wbe);
5331 }
5332 // __am_pm_
5333 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005334 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005335 mb = mbstate_t();
5336 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005337 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005338 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005339 __throw_runtime_error("locale not supported");
5340 wbe = wbuf + j;
5341 __am_pm_[0].assign(wbuf, wbe);
5342 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005343 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005344 mb = mbstate_t();
5345 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005346 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005347 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005348 __throw_runtime_error("locale not supported");
5349 wbe = wbuf + j;
5350 __am_pm_[1].assign(wbuf, wbe);
5351 __c_ = __analyze('c', ct);
5352 __r_ = __analyze('r', ct);
5353 __x_ = __analyze('x', ct);
5354 __X_ = __analyze('X', ct);
5355}
5356
5357template <class CharT>
5358struct _LIBCPP_HIDDEN __time_get_temp
5359 : public ctype_byname<CharT>
5360{
5361 explicit __time_get_temp(const char* nm)
5362 : ctype_byname<CharT>(nm, 1) {}
5363 explicit __time_get_temp(const string& nm)
5364 : ctype_byname<CharT>(nm, 1) {}
5365};
5366
5367template <>
5368__time_get_storage<char>::__time_get_storage(const char* __nm)
5369 : __time_get(__nm)
5370{
5371 const __time_get_temp<char> ct(__nm);
5372 init(ct);
5373}
5374
5375template <>
5376__time_get_storage<char>::__time_get_storage(const string& __nm)
5377 : __time_get(__nm)
5378{
5379 const __time_get_temp<char> ct(__nm);
5380 init(ct);
5381}
5382
5383template <>
5384__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5385 : __time_get(__nm)
5386{
5387 const __time_get_temp<wchar_t> ct(__nm);
5388 init(ct);
5389}
5390
5391template <>
5392__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5393 : __time_get(__nm)
5394{
5395 const __time_get_temp<wchar_t> ct(__nm);
5396 init(ct);
5397}
5398
5399template <>
5400time_base::dateorder
5401__time_get_storage<char>::__do_date_order() const
5402{
5403 unsigned i;
5404 for (i = 0; i < __x_.size(); ++i)
5405 if (__x_[i] == '%')
5406 break;
5407 ++i;
5408 switch (__x_[i])
5409 {
5410 case 'y':
5411 case 'Y':
5412 for (++i; i < __x_.size(); ++i)
5413 if (__x_[i] == '%')
5414 break;
5415 if (i == __x_.size())
5416 break;
5417 ++i;
5418 switch (__x_[i])
5419 {
5420 case 'm':
5421 for (++i; i < __x_.size(); ++i)
5422 if (__x_[i] == '%')
5423 break;
5424 if (i == __x_.size())
5425 break;
5426 ++i;
5427 if (__x_[i] == 'd')
5428 return time_base::ymd;
5429 break;
5430 case 'd':
5431 for (++i; i < __x_.size(); ++i)
5432 if (__x_[i] == '%')
5433 break;
5434 if (i == __x_.size())
5435 break;
5436 ++i;
5437 if (__x_[i] == 'm')
5438 return time_base::ydm;
5439 break;
5440 }
5441 break;
5442 case 'm':
5443 for (++i; i < __x_.size(); ++i)
5444 if (__x_[i] == '%')
5445 break;
5446 if (i == __x_.size())
5447 break;
5448 ++i;
5449 if (__x_[i] == 'd')
5450 {
5451 for (++i; i < __x_.size(); ++i)
5452 if (__x_[i] == '%')
5453 break;
5454 if (i == __x_.size())
5455 break;
5456 ++i;
5457 if (__x_[i] == 'y' || __x_[i] == 'Y')
5458 return time_base::mdy;
5459 break;
5460 }
5461 break;
5462 case 'd':
5463 for (++i; i < __x_.size(); ++i)
5464 if (__x_[i] == '%')
5465 break;
5466 if (i == __x_.size())
5467 break;
5468 ++i;
5469 if (__x_[i] == 'm')
5470 {
5471 for (++i; i < __x_.size(); ++i)
5472 if (__x_[i] == '%')
5473 break;
5474 if (i == __x_.size())
5475 break;
5476 ++i;
5477 if (__x_[i] == 'y' || __x_[i] == 'Y')
5478 return time_base::dmy;
5479 break;
5480 }
5481 break;
5482 }
5483 return time_base::no_order;
5484}
5485
5486template <>
5487time_base::dateorder
5488__time_get_storage<wchar_t>::__do_date_order() const
5489{
5490 unsigned i;
5491 for (i = 0; i < __x_.size(); ++i)
5492 if (__x_[i] == L'%')
5493 break;
5494 ++i;
5495 switch (__x_[i])
5496 {
5497 case L'y':
5498 case L'Y':
5499 for (++i; i < __x_.size(); ++i)
5500 if (__x_[i] == L'%')
5501 break;
5502 if (i == __x_.size())
5503 break;
5504 ++i;
5505 switch (__x_[i])
5506 {
5507 case L'm':
5508 for (++i; i < __x_.size(); ++i)
5509 if (__x_[i] == L'%')
5510 break;
5511 if (i == __x_.size())
5512 break;
5513 ++i;
5514 if (__x_[i] == L'd')
5515 return time_base::ymd;
5516 break;
5517 case L'd':
5518 for (++i; i < __x_.size(); ++i)
5519 if (__x_[i] == L'%')
5520 break;
5521 if (i == __x_.size())
5522 break;
5523 ++i;
5524 if (__x_[i] == L'm')
5525 return time_base::ydm;
5526 break;
5527 }
5528 break;
5529 case L'm':
5530 for (++i; i < __x_.size(); ++i)
5531 if (__x_[i] == L'%')
5532 break;
5533 if (i == __x_.size())
5534 break;
5535 ++i;
5536 if (__x_[i] == L'd')
5537 {
5538 for (++i; i < __x_.size(); ++i)
5539 if (__x_[i] == L'%')
5540 break;
5541 if (i == __x_.size())
5542 break;
5543 ++i;
5544 if (__x_[i] == L'y' || __x_[i] == L'Y')
5545 return time_base::mdy;
5546 break;
5547 }
5548 break;
5549 case L'd':
5550 for (++i; i < __x_.size(); ++i)
5551 if (__x_[i] == L'%')
5552 break;
5553 if (i == __x_.size())
5554 break;
5555 ++i;
5556 if (__x_[i] == L'm')
5557 {
5558 for (++i; i < __x_.size(); ++i)
5559 if (__x_[i] == L'%')
5560 break;
5561 if (i == __x_.size())
5562 break;
5563 ++i;
5564 if (__x_[i] == L'y' || __x_[i] == L'Y')
5565 return time_base::dmy;
5566 break;
5567 }
5568 break;
5569 }
5570 return time_base::no_order;
5571}
5572
5573// time_put
5574
5575__time_put::__time_put(const char* nm)
5576 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5577{
5578 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005579 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005580 " failed to construct for " + string(nm));
5581}
5582
5583__time_put::__time_put(const string& nm)
5584 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5585{
5586 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005587 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005588 " failed to construct for " + nm);
5589}
5590
5591__time_put::~__time_put()
5592{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005593 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005594 freelocale(__loc_);
5595}
5596
5597void
5598__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5599 char __fmt, char __mod) const
5600{
5601 char fmt[] = {'%', __fmt, __mod, 0};
5602 if (__mod != 0)
5603 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005604 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005605 __ne = __nb + n;
5606}
5607
5608void
5609__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5610 char __fmt, char __mod) const
5611{
5612 char __nar[100];
5613 char* __ne = __nar + 100;
5614 __do_put(__nar, __ne, __tm, __fmt, __mod);
5615 mbstate_t mb = {0};
5616 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005617 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005618 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005619 __throw_runtime_error("locale not supported");
5620 __we = __wb + j;
5621}
5622
5623// moneypunct_byname
5624
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005625template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005626static
5627void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005628__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5629 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5630 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005631{
5632 const char sign = static_cast<char>(money_base::sign);
5633 const char space = static_cast<char>(money_base::space);
5634 const char none = static_cast<char>(money_base::none);
5635 const char symbol = static_cast<char>(money_base::symbol);
5636 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005637 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5638
5639 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5640 // function'. "Space between sign and symbol or value" means that
5641 // if the sign is adjacent to the symbol, there's a space between
5642 // them, and otherwise there's a space between the sign and value.
5643 //
5644 // C11's localeconv specifies that the fourth character of an
5645 // international curr_symbol is used to separate the sign and
5646 // value when sep_by_space says to do so. C++ can't represent
5647 // that, so we just use a space. When sep_by_space says to
5648 // separate the symbol and value-or-sign with a space, we rearrange the
5649 // curr_symbol to put its spacing character on the correct side of
5650 // the symbol.
5651 //
5652 // We also need to avoid adding an extra space between the sign
5653 // and value when the currency symbol is suppressed (by not
5654 // setting showbase). We match glibc's strfmon by interpreting
5655 // sep_by_space==1 as "omit the space when the currency symbol is
5656 // absent".
5657 //
5658 // Users who want to get this right should use ICU instead.
5659
Howard Hinnantc51e1022010-05-11 19:42:16 +00005660 switch (cs_precedes)
5661 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005662 case 0: // value before curr_symbol
5663 if (symbol_contains_sep) {
5664 // Move the separator to before the symbol, to place it
5665 // between the value and symbol.
5666 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5667 __curr_symbol_.end());
5668 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005669 switch (sign_posn)
5670 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005671 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005672 pat.field[0] = sign;
5673 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005674 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005675 pat.field[3] = symbol;
5676 switch (sep_by_space)
5677 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005678 case 0: // No space separates the currency symbol and value.
5679 // This case may have changed between C99 and C11;
5680 // assume the currency symbol matches the intention.
5681 case 2: // Space between sign and currency or value.
5682 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005683 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005684 case 1: // Space between currency-and-sign or currency and value.
5685 if (!symbol_contains_sep) {
5686 // We insert the space into the symbol instead of
5687 // setting pat.field[2]=space so that when
5688 // showbase is not set, the space goes away too.
5689 __curr_symbol_.insert(0, 1, space_char);
5690 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005691 return;
5692 default:
5693 break;
5694 }
5695 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005696 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005697 pat.field[0] = sign;
5698 pat.field[3] = symbol;
5699 switch (sep_by_space)
5700 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005701 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005702 pat.field[1] = value;
5703 pat.field[2] = none;
5704 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005705 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005706 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005707 pat.field[2] = none;
5708 if (!symbol_contains_sep) {
5709 // We insert the space into the symbol instead of
5710 // setting pat.field[2]=space so that when
5711 // showbase is not set, the space goes away too.
5712 __curr_symbol_.insert(0, 1, space_char);
5713 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005714 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005715 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005716 pat.field[1] = space;
5717 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005718 if (symbol_contains_sep) {
5719 // Remove the separator from the symbol, since it
5720 // has already appeared after the sign.
5721 __curr_symbol_.erase(__curr_symbol_.begin());
5722 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005723 return;
5724 default:
5725 break;
5726 }
5727 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005728 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005729 pat.field[0] = value;
5730 pat.field[3] = sign;
5731 switch (sep_by_space)
5732 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005733 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005734 pat.field[1] = none;
5735 pat.field[2] = symbol;
5736 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005737 case 1: // Space between currency-and-sign or currency and value.
5738 if (!symbol_contains_sep) {
5739 // We insert the space into the symbol instead of
5740 // setting pat.field[1]=space so that when
5741 // showbase is not set, the space goes away too.
5742 __curr_symbol_.insert(0, 1, space_char);
5743 }
5744 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 pat.field[2] = symbol;
5746 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005747 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005748 pat.field[1] = symbol;
5749 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005750 if (symbol_contains_sep) {
5751 // Remove the separator from the symbol, since it
5752 // should not be removed if showbase is absent.
5753 __curr_symbol_.erase(__curr_symbol_.begin());
5754 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005755 return;
5756 default:
5757 break;
5758 }
5759 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005760 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005761 pat.field[0] = value;
5762 pat.field[3] = symbol;
5763 switch (sep_by_space)
5764 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005765 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005766 pat.field[1] = none;
5767 pat.field[2] = sign;
5768 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005769 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005770 pat.field[1] = space;
5771 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005772 if (symbol_contains_sep) {
5773 // Remove the separator from the symbol, since it
5774 // has already appeared before the sign.
5775 __curr_symbol_.erase(__curr_symbol_.begin());
5776 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005777 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005778 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005779 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005780 pat.field[2] = none;
5781 if (!symbol_contains_sep) {
5782 // We insert the space into the symbol instead of
5783 // setting pat.field[2]=space so that when
5784 // showbase is not set, the space goes away too.
5785 __curr_symbol_.insert(0, 1, space_char);
5786 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005787 return;
5788 default:
5789 break;
5790 }
5791 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005792 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005793 pat.field[0] = value;
5794 pat.field[3] = sign;
5795 switch (sep_by_space)
5796 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005797 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005798 pat.field[1] = none;
5799 pat.field[2] = symbol;
5800 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005801 case 1: // Space between currency-and-sign or currency and value.
5802 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005803 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005804 if (!symbol_contains_sep) {
5805 // We insert the space into the symbol instead of
5806 // setting pat.field[1]=space so that when
5807 // showbase is not set, the space goes away too.
5808 __curr_symbol_.insert(0, 1, space_char);
5809 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005810 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005811 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005812 pat.field[1] = symbol;
5813 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005814 if (symbol_contains_sep) {
5815 // Remove the separator from the symbol, since it
5816 // should not disappear when showbase is absent.
5817 __curr_symbol_.erase(__curr_symbol_.begin());
5818 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005819 return;
5820 default:
5821 break;
5822 }
5823 break;
5824 default:
5825 break;
5826 }
5827 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005828 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005829 switch (sign_posn)
5830 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005831 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005832 pat.field[0] = sign;
5833 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005834 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005835 pat.field[3] = value;
5836 switch (sep_by_space)
5837 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005838 case 0: // No space separates the currency symbol and value.
5839 // This case may have changed between C99 and C11;
5840 // assume the currency symbol matches the intention.
5841 case 2: // Space between sign and currency or value.
5842 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005843 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005844 case 1: // Space between currency-and-sign or currency and value.
5845 if (!symbol_contains_sep) {
5846 // We insert the space into the symbol instead of
5847 // setting pat.field[2]=space so that when
5848 // showbase is not set, the space goes away too.
5849 __curr_symbol_.insert(0, 1, space_char);
5850 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005851 return;
5852 default:
5853 break;
5854 }
5855 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005856 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005857 pat.field[0] = sign;
5858 pat.field[3] = value;
5859 switch (sep_by_space)
5860 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005861 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005862 pat.field[1] = symbol;
5863 pat.field[2] = none;
5864 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005865 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005866 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005867 pat.field[2] = none;
5868 if (!symbol_contains_sep) {
5869 // We insert the space into the symbol instead of
5870 // setting pat.field[2]=space so that when
5871 // showbase is not set, the space goes away too.
5872 __curr_symbol_.push_back(space_char);
5873 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005874 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005875 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005876 pat.field[1] = space;
5877 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005878 if (symbol_contains_sep) {
5879 // Remove the separator from the symbol, since it
5880 // has already appeared after the sign.
5881 __curr_symbol_.pop_back();
5882 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005883 return;
5884 default:
5885 break;
5886 }
5887 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005888 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005889 pat.field[0] = symbol;
5890 pat.field[3] = sign;
5891 switch (sep_by_space)
5892 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005893 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005894 pat.field[1] = none;
5895 pat.field[2] = value;
5896 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005897 case 1: // Space between currency-and-sign or currency and value.
5898 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005899 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005900 if (!symbol_contains_sep) {
5901 // We insert the space into the symbol instead of
5902 // setting pat.field[1]=space so that when
5903 // showbase is not set, the space goes away too.
5904 __curr_symbol_.push_back(space_char);
5905 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005906 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005907 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005908 pat.field[1] = value;
5909 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005910 if (symbol_contains_sep) {
5911 // Remove the separator from the symbol, since it
5912 // will appear before the sign.
5913 __curr_symbol_.pop_back();
5914 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005915 return;
5916 default:
5917 break;
5918 }
5919 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005920 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005921 pat.field[0] = sign;
5922 pat.field[3] = value;
5923 switch (sep_by_space)
5924 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005925 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005926 pat.field[1] = symbol;
5927 pat.field[2] = none;
5928 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005930 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005931 pat.field[2] = none;
5932 if (!symbol_contains_sep) {
5933 // We insert the space into the symbol instead of
5934 // setting pat.field[2]=space so that when
5935 // showbase is not set, the space goes away too.
5936 __curr_symbol_.push_back(space_char);
5937 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005938 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005939 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005940 pat.field[1] = space;
5941 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005942 if (symbol_contains_sep) {
5943 // Remove the separator from the symbol, since it
5944 // has already appeared after the sign.
5945 __curr_symbol_.pop_back();
5946 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 return;
5948 default:
5949 break;
5950 }
5951 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005952 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005953 pat.field[0] = symbol;
5954 pat.field[3] = value;
5955 switch (sep_by_space)
5956 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005957 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005958 pat.field[1] = sign;
5959 pat.field[2] = none;
5960 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005961 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005962 pat.field[1] = sign;
5963 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005964 if (symbol_contains_sep) {
5965 // Remove the separator from the symbol, since it
5966 // should not disappear when showbase is absent.
5967 __curr_symbol_.pop_back();
5968 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005970 case 2: // Space between sign and currency or value.
5971 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005972 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005973 if (!symbol_contains_sep) {
5974 // We insert the space into the symbol instead of
5975 // setting pat.field[1]=space so that when
5976 // showbase is not set, the space goes away too.
5977 __curr_symbol_.push_back(space_char);
5978 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005979 return;
5980 default:
5981 break;
5982 }
5983 break;
5984 default:
5985 break;
5986 }
5987 break;
5988 default:
5989 break;
5990 }
5991 pat.field[0] = symbol;
5992 pat.field[1] = sign;
5993 pat.field[2] = none;
5994 pat.field[3] = value;
5995}
5996
5997template<>
5998void
5999moneypunct_byname<char, false>::init(const char* nm)
6000{
6001 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006002 __libcpp_unique_locale loc(nm);
6003 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006004 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006005 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006006
Ben Craig3756b922016-03-09 15:39:39 +00006007 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006008 if (!checked_string_to_char_convert(__decimal_point_,
6009 lc->mon_decimal_point,
6010 loc.get()))
6011 __decimal_point_ = base::do_decimal_point();
6012 if (!checked_string_to_char_convert(__thousands_sep_,
6013 lc->mon_thousands_sep,
6014 loc.get()))
6015 __thousands_sep_ = base::do_thousands_sep();
6016
Howard Hinnantc51e1022010-05-11 19:42:16 +00006017 __grouping_ = lc->mon_grouping;
6018 __curr_symbol_ = lc->currency_symbol;
6019 if (lc->frac_digits != CHAR_MAX)
6020 __frac_digits_ = lc->frac_digits;
6021 else
6022 __frac_digits_ = base::do_frac_digits();
6023 if (lc->p_sign_posn == 0)
6024 __positive_sign_ = "()";
6025 else
6026 __positive_sign_ = lc->positive_sign;
6027 if (lc->n_sign_posn == 0)
6028 __negative_sign_ = "()";
6029 else
6030 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006031 // Assume the positive and negative formats will want spaces in
6032 // the same places in curr_symbol since there's no way to
6033 // represent anything else.
6034 string_type __dummy_curr_symbol = __curr_symbol_;
6035 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6036 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6037 __init_pat(__neg_format_, __curr_symbol_, false,
6038 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039}
6040
6041template<>
6042void
6043moneypunct_byname<char, true>::init(const char* nm)
6044{
6045 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006046 __libcpp_unique_locale loc(nm);
6047 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006048 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006049 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006050
Ben Craig3756b922016-03-09 15:39:39 +00006051 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006052 if (!checked_string_to_char_convert(__decimal_point_,
6053 lc->mon_decimal_point,
6054 loc.get()))
6055 __decimal_point_ = base::do_decimal_point();
6056 if (!checked_string_to_char_convert(__thousands_sep_,
6057 lc->mon_thousands_sep,
6058 loc.get()))
6059 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006060 __grouping_ = lc->mon_grouping;
6061 __curr_symbol_ = lc->int_curr_symbol;
6062 if (lc->int_frac_digits != CHAR_MAX)
6063 __frac_digits_ = lc->int_frac_digits;
6064 else
6065 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006066#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006067 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006068#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006069 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006070#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006071 __positive_sign_ = "()";
6072 else
6073 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006074#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006075 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006076#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006077 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006078#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006079 __negative_sign_ = "()";
6080 else
6081 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006082 // Assume the positive and negative formats will want spaces in
6083 // the same places in curr_symbol since there's no way to
6084 // represent anything else.
6085 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006086#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006087 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6088 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6089 __init_pat(__neg_format_, __curr_symbol_, true,
6090 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006091#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006092 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6093 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6094 lc->int_p_sign_posn, ' ');
6095 __init_pat(__neg_format_, __curr_symbol_, true,
6096 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6097 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006098#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006099}
6100
6101template<>
6102void
6103moneypunct_byname<wchar_t, false>::init(const char* nm)
6104{
6105 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006106 __libcpp_unique_locale loc(nm);
6107 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006108 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006109 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00006110 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006111 if (!checked_string_to_wchar_convert(__decimal_point_,
6112 lc->mon_decimal_point,
6113 loc.get()))
6114 __decimal_point_ = base::do_decimal_point();
6115 if (!checked_string_to_wchar_convert(__thousands_sep_,
6116 lc->mon_thousands_sep,
6117 loc.get()))
6118 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006119 __grouping_ = lc->mon_grouping;
6120 wchar_t wbuf[100];
6121 mbstate_t mb = {0};
6122 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006123 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006124 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125 __throw_runtime_error("locale not supported");
6126 wchar_t* wbe = wbuf + j;
6127 __curr_symbol_.assign(wbuf, wbe);
6128 if (lc->frac_digits != CHAR_MAX)
6129 __frac_digits_ = lc->frac_digits;
6130 else
6131 __frac_digits_ = base::do_frac_digits();
6132 if (lc->p_sign_posn == 0)
6133 __positive_sign_ = L"()";
6134 else
6135 {
6136 mb = mbstate_t();
6137 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006138 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006139 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006140 __throw_runtime_error("locale not supported");
6141 wbe = wbuf + j;
6142 __positive_sign_.assign(wbuf, wbe);
6143 }
6144 if (lc->n_sign_posn == 0)
6145 __negative_sign_ = L"()";
6146 else
6147 {
6148 mb = mbstate_t();
6149 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006150 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006151 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006152 __throw_runtime_error("locale not supported");
6153 wbe = wbuf + j;
6154 __negative_sign_.assign(wbuf, wbe);
6155 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006156 // Assume the positive and negative formats will want spaces in
6157 // the same places in curr_symbol since there's no way to
6158 // represent anything else.
6159 string_type __dummy_curr_symbol = __curr_symbol_;
6160 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6161 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6162 __init_pat(__neg_format_, __curr_symbol_, false,
6163 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006164}
6165
6166template<>
6167void
6168moneypunct_byname<wchar_t, true>::init(const char* nm)
6169{
6170 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006171 __libcpp_unique_locale loc(nm);
6172 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006173 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006174 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006175
Ben Craig3756b922016-03-09 15:39:39 +00006176 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006177 if (!checked_string_to_wchar_convert(__decimal_point_,
6178 lc->mon_decimal_point,
6179 loc.get()))
6180 __decimal_point_ = base::do_decimal_point();
6181 if (!checked_string_to_wchar_convert(__thousands_sep_,
6182 lc->mon_thousands_sep,
6183 loc.get()))
6184 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006185 __grouping_ = lc->mon_grouping;
6186 wchar_t wbuf[100];
6187 mbstate_t mb = {0};
6188 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006189 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006190 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006191 __throw_runtime_error("locale not supported");
6192 wchar_t* wbe = wbuf + j;
6193 __curr_symbol_.assign(wbuf, wbe);
6194 if (lc->int_frac_digits != CHAR_MAX)
6195 __frac_digits_ = lc->int_frac_digits;
6196 else
6197 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006198#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006199 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006200#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006201 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006202#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006203 __positive_sign_ = L"()";
6204 else
6205 {
6206 mb = mbstate_t();
6207 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006208 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006209 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006210 __throw_runtime_error("locale not supported");
6211 wbe = wbuf + j;
6212 __positive_sign_.assign(wbuf, wbe);
6213 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006214#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006215 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006216#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006217 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006218#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006219 __negative_sign_ = L"()";
6220 else
6221 {
6222 mb = mbstate_t();
6223 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006224 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006225 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006226 __throw_runtime_error("locale not supported");
6227 wbe = wbuf + j;
6228 __negative_sign_.assign(wbuf, wbe);
6229 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006230 // Assume the positive and negative formats will want spaces in
6231 // the same places in curr_symbol since there's no way to
6232 // represent anything else.
6233 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006234#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006235 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6236 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6237 __init_pat(__neg_format_, __curr_symbol_, true,
6238 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006239#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006240 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6241 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6242 lc->int_p_sign_posn, L' ');
6243 __init_pat(__neg_format_, __curr_symbol_, true,
6244 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6245 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006246#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006247}
6248
6249void __do_nothing(void*) {}
6250
6251void __throw_runtime_error(const char* msg)
6252{
Howard Hinnant72f73582010-08-11 17:04:31 +00006253#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006254 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006255#else
6256 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006257 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006258#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006259}
6260
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006261template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6262template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006263
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006264template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6265template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006266
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006267template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6268template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006269
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006270template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6271template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006272
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006273template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6274template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006275
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006276template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6277template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006278
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006279template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6280template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006281
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006282template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6283template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006284
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006285template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6286template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006287
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006288template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6289template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6290template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6291template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006292
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006293template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6294template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6295template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6296template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006297
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006298template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6299template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006300
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006301template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6302template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006303
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006304template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6305template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006306
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006307template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6308template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006309
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006310template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6311template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006312
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006313template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6314template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006315
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006316template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6317template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
Reid Klecknerbc2a2ce2021-01-15 08:56:34 -08006318template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6319template 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 -04006320#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marek Kurdej718b62c2020-12-02 08:57:02 +01006321template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>;
6322template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>;
6323#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006324
Howard Hinnantc51e1022010-05-11 19:42:16 +00006325_LIBCPP_END_NAMESPACE_STD