blob: ca0a1c9b15fcab8b174921ff306524b5933731ed [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"
30#include "__sso_allocator"
Howard Hinnant8ad70912013-09-17 01:34:47 +000031#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Marshall Clowccb92572015-06-23 14:45:02 +000032#include "support/win32/locale_win32.h"
Dan Albert21800dc2016-09-19 18:00:45 +000033#elif !defined(__BIONIC__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000034#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000035#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000036#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000037#include <stdio.h>
Weiming Zhaob613db72017-09-19 23:18:03 +000038#include "include/atomic_support.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
42// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000043#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000044#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000045#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000046
Howard Hinnantc51e1022010-05-11 19:42:16 +000047_LIBCPP_BEGIN_NAMESPACE_STD
48
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000049struct __libcpp_unique_locale {
50 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
51
52 ~__libcpp_unique_locale() {
53 if (__loc_)
54 freelocale(__loc_);
55 }
56
57 explicit operator bool() const { return __loc_; }
58
59 locale_t& get() { return __loc_; }
60
61 locale_t __loc_;
62private:
63 __libcpp_unique_locale(__libcpp_unique_locale const&);
64 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
65};
66
Howard Hinnantf312e3e2011-09-28 23:39:33 +000067#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000068locale_t __cloc() {
69 // In theory this could create a race condition. In practice
70 // the race condition is non-fatal since it will just create
71 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000072 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
73 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000074}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000075#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000076
Howard Hinnantc51e1022010-05-11 19:42:16 +000077namespace {
78
79struct release
80{
81 void operator()(locale::facet* p) {p->__release_shared();}
82};
83
84template <class T, class A0>
85inline
86T&
87make(A0 a0)
88{
89 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +000090 auto *obj = ::new (&buf) T(a0);
91 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000092}
93
94template <class T, class A0, class A1>
95inline
96T&
97make(A0 a0, A1 a1)
98{
99 static typename aligned_storage<sizeof(T)>::type buf;
100 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000101 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000102}
103
104template <class T, class A0, class A1, class A2>
105inline
106T&
107make(A0 a0, A1 a1, A2 a2)
108{
109 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000110 auto *obj = ::new (&buf) T(a0, a1, a2);
111 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000112}
113
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000114template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000115inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000116_LIBCPP_CONSTEXPR
117size_t
118countof(const T (&)[N])
119{
120 return N;
121}
122
123template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000124inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000125_LIBCPP_CONSTEXPR
126size_t
127countof(const T * const begin, const T * const end)
128{
129 return static_cast<size_t>(end - begin);
130}
131
Marshall Clow8fea1612016-08-25 15:09:01 +0000132_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
133{
134#ifndef _LIBCPP_NO_EXCEPTIONS
135 throw runtime_error(msg);
136#else
137 (void)msg;
138 _VSTD::abort();
139#endif
140}
141
Howard Hinnantc51e1022010-05-11 19:42:16 +0000142}
143
Howard Hinnantdd099492013-08-29 23:37:50 +0000144#if defined(_AIX)
145// Set priority to INT_MIN + 256 + 150
146# pragma priority ( -2147483242 )
147#endif
148
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000149const locale::category locale::none;
150const locale::category locale::collate;
151const locale::category locale::ctype;
152const locale::category locale::monetary;
153const locale::category locale::numeric;
154const locale::category locale::time;
155const locale::category locale::messages;
156const locale::category locale::all;
157
Howard Hinnantc51e1022010-05-11 19:42:16 +0000158class _LIBCPP_HIDDEN locale::__imp
159 : public facet
160{
161 enum {N = 28};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000162#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000163// FIXME: MSVC doesn't support aligned parameters by value.
164// I can't get the __sso_allocator to work here
165// for MSVC I think for this reason.
166 vector<facet*> facets_;
167#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000168 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000169#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000170 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000171public:
172 explicit __imp(size_t refs = 0);
173 explicit __imp(const string& name, size_t refs = 0);
174 __imp(const __imp&);
175 __imp(const __imp&, const string&, locale::category c);
176 __imp(const __imp& other, const __imp& one, locale::category c);
177 __imp(const __imp&, facet* f, long id);
178 ~__imp();
179
180 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000181 bool has_facet(long id) const
182 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000183 const locale::facet* use_facet(long id) const;
184
185 static const locale& make_classic();
186 static locale& make_global();
187private:
188 void install(facet* f, long id);
189 template <class F> void install(F* f) {install(f, f->id.__get());}
190 template <class F> void install_from(const __imp& other);
191};
192
193locale::__imp::__imp(size_t refs)
194 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000195 facets_(N),
196 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000197{
198 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000199 install(&make<_VSTD::collate<char> >(1u));
200 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000201 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000202 install(&make<_VSTD::ctype<wchar_t> >(1u));
203 install(&make<codecvt<char, char, mbstate_t> >(1u));
204 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
205 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
206 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
207 install(&make<numpunct<char> >(1u));
208 install(&make<numpunct<wchar_t> >(1u));
209 install(&make<num_get<char> >(1u));
210 install(&make<num_get<wchar_t> >(1u));
211 install(&make<num_put<char> >(1u));
212 install(&make<num_put<wchar_t> >(1u));
213 install(&make<moneypunct<char, false> >(1u));
214 install(&make<moneypunct<char, true> >(1u));
215 install(&make<moneypunct<wchar_t, false> >(1u));
216 install(&make<moneypunct<wchar_t, true> >(1u));
217 install(&make<money_get<char> >(1u));
218 install(&make<money_get<wchar_t> >(1u));
219 install(&make<money_put<char> >(1u));
220 install(&make<money_put<wchar_t> >(1u));
221 install(&make<time_get<char> >(1u));
222 install(&make<time_get<wchar_t> >(1u));
223 install(&make<time_put<char> >(1u));
224 install(&make<time_put<wchar_t> >(1u));
225 install(&make<_VSTD::messages<char> >(1u));
226 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000227}
228
229locale::__imp::__imp(const string& name, size_t refs)
230 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000231 facets_(N),
232 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000233{
Howard Hinnant72f73582010-08-11 17:04:31 +0000234#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000235 try
236 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000237#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000238 facets_ = locale::classic().__locale_->facets_;
239 for (unsigned i = 0; i < facets_.size(); ++i)
240 if (facets_[i])
241 facets_[i]->__add_shared();
242 install(new collate_byname<char>(name_));
243 install(new collate_byname<wchar_t>(name_));
244 install(new ctype_byname<char>(name_));
245 install(new ctype_byname<wchar_t>(name_));
246 install(new codecvt_byname<char, char, mbstate_t>(name_));
247 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
248 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
249 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
250 install(new numpunct_byname<char>(name_));
251 install(new numpunct_byname<wchar_t>(name_));
252 install(new moneypunct_byname<char, false>(name_));
253 install(new moneypunct_byname<char, true>(name_));
254 install(new moneypunct_byname<wchar_t, false>(name_));
255 install(new moneypunct_byname<wchar_t, true>(name_));
256 install(new time_get_byname<char>(name_));
257 install(new time_get_byname<wchar_t>(name_));
258 install(new time_put_byname<char>(name_));
259 install(new time_put_byname<wchar_t>(name_));
260 install(new messages_byname<char>(name_));
261 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000262#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000263 }
264 catch (...)
265 {
266 for (unsigned i = 0; i < facets_.size(); ++i)
267 if (facets_[i])
268 facets_[i]->__release_shared();
269 throw;
270 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000271#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000272}
273
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000274// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000275// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000276#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000277#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000278#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000279#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000280
Howard Hinnantc51e1022010-05-11 19:42:16 +0000281locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000282 : facets_(max<size_t>(N, other.facets_.size())),
283 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284{
285 facets_ = other.facets_;
286 for (unsigned i = 0; i < facets_.size(); ++i)
287 if (facets_[i])
288 facets_[i]->__add_shared();
289}
290
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000291#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000292#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000293#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000294
Howard Hinnantc51e1022010-05-11 19:42:16 +0000295locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000296 : facets_(N),
297 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000298{
299 facets_ = other.facets_;
300 for (unsigned i = 0; i < facets_.size(); ++i)
301 if (facets_[i])
302 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000303#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000304 try
305 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000306#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000307 if (c & locale::collate)
308 {
309 install(new collate_byname<char>(name));
310 install(new collate_byname<wchar_t>(name));
311 }
312 if (c & locale::ctype)
313 {
314 install(new ctype_byname<char>(name));
315 install(new ctype_byname<wchar_t>(name));
316 install(new codecvt_byname<char, char, mbstate_t>(name));
317 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
318 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
319 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
320 }
321 if (c & locale::monetary)
322 {
323 install(new moneypunct_byname<char, false>(name));
324 install(new moneypunct_byname<char, true>(name));
325 install(new moneypunct_byname<wchar_t, false>(name));
326 install(new moneypunct_byname<wchar_t, true>(name));
327 }
328 if (c & locale::numeric)
329 {
330 install(new numpunct_byname<char>(name));
331 install(new numpunct_byname<wchar_t>(name));
332 }
333 if (c & locale::time)
334 {
335 install(new time_get_byname<char>(name));
336 install(new time_get_byname<wchar_t>(name));
337 install(new time_put_byname<char>(name));
338 install(new time_put_byname<wchar_t>(name));
339 }
340 if (c & locale::messages)
341 {
342 install(new messages_byname<char>(name));
343 install(new messages_byname<wchar_t>(name));
344 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000345#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000346 }
347 catch (...)
348 {
349 for (unsigned i = 0; i < facets_.size(); ++i)
350 if (facets_[i])
351 facets_[i]->__release_shared();
352 throw;
353 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000354#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000355}
356
357template<class F>
358inline
359void
360locale::__imp::install_from(const locale::__imp& one)
361{
362 long id = F::id.__get();
363 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
364}
365
366locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000367 : facets_(N),
368 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000369{
370 facets_ = other.facets_;
371 for (unsigned i = 0; i < facets_.size(); ++i)
372 if (facets_[i])
373 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000374#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000375 try
376 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000377#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000378 if (c & locale::collate)
379 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000380 install_from<_VSTD::collate<char> >(one);
381 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000382 }
383 if (c & locale::ctype)
384 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000385 install_from<_VSTD::ctype<char> >(one);
386 install_from<_VSTD::ctype<wchar_t> >(one);
387 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
388 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
389 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
390 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000391 }
392 if (c & locale::monetary)
393 {
394 install_from<moneypunct<char, false> >(one);
395 install_from<moneypunct<char, true> >(one);
396 install_from<moneypunct<wchar_t, false> >(one);
397 install_from<moneypunct<wchar_t, true> >(one);
398 install_from<money_get<char> >(one);
399 install_from<money_get<wchar_t> >(one);
400 install_from<money_put<char> >(one);
401 install_from<money_put<wchar_t> >(one);
402 }
403 if (c & locale::numeric)
404 {
405 install_from<numpunct<char> >(one);
406 install_from<numpunct<wchar_t> >(one);
407 install_from<num_get<char> >(one);
408 install_from<num_get<wchar_t> >(one);
409 install_from<num_put<char> >(one);
410 install_from<num_put<wchar_t> >(one);
411 }
412 if (c & locale::time)
413 {
414 install_from<time_get<char> >(one);
415 install_from<time_get<wchar_t> >(one);
416 install_from<time_put<char> >(one);
417 install_from<time_put<wchar_t> >(one);
418 }
419 if (c & locale::messages)
420 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000421 install_from<_VSTD::messages<char> >(one);
422 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000423 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000424#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000425 }
426 catch (...)
427 {
428 for (unsigned i = 0; i < facets_.size(); ++i)
429 if (facets_[i])
430 facets_[i]->__release_shared();
431 throw;
432 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000433#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000434}
435
436locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000437 : facets_(max<size_t>(N, other.facets_.size()+1)),
438 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000439{
440 f->__add_shared();
441 unique_ptr<facet, release> hold(f);
442 facets_ = other.facets_;
443 for (unsigned i = 0; i < other.facets_.size(); ++i)
444 if (facets_[i])
445 facets_[i]->__add_shared();
446 install(hold.get(), id);
447}
448
449locale::__imp::~__imp()
450{
451 for (unsigned i = 0; i < facets_.size(); ++i)
452 if (facets_[i])
453 facets_[i]->__release_shared();
454}
455
456void
457locale::__imp::install(facet* f, long id)
458{
459 f->__add_shared();
460 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000461 if (static_cast<size_t>(id) >= facets_.size())
462 facets_.resize(static_cast<size_t>(id+1));
463 if (facets_[static_cast<size_t>(id)])
464 facets_[static_cast<size_t>(id)]->__release_shared();
465 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000466}
467
468const locale::facet*
469locale::__imp::use_facet(long id) const
470{
471 if (!has_facet(id))
Louis Dionne2b239162019-02-12 16:06:02 +0000472 __throw_bad_cast();
Howard Hinnant28b24882011-12-01 20:21:04 +0000473 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000474}
475
476// locale
477
478const locale&
479locale::__imp::make_classic()
480{
481 // only one thread can get in here and it only gets in once
482 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000483 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000484 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000485 return *c;
486}
487
488const locale&
489locale::classic()
490{
491 static const locale& c = __imp::make_classic();
492 return c;
493}
494
495locale&
496locale::__imp::make_global()
497{
498 // only one thread can get in here and it only gets in once
499 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000500 auto *obj = ::new (&buf) locale(locale::classic());
501 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000502}
503
504locale&
505locale::__global()
506{
507 static locale& g = __imp::make_global();
508 return g;
509}
510
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000511locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000512 : __locale_(__global().__locale_)
513{
514 __locale_->__add_shared();
515}
516
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000517locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000518 : __locale_(l.__locale_)
519{
520 __locale_->__add_shared();
521}
522
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000523locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000524{
525 __locale_->__release_shared();
526}
527
528const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000529locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000530{
531 other.__locale_->__add_shared();
532 __locale_->__release_shared();
533 __locale_ = other.__locale_;
534 return *this;
535}
536
537locale::locale(const char* name)
538 : __locale_(name ? new __imp(name)
Louis Dionne2b239162019-02-12 16:06:02 +0000539 : (__throw_runtime_error("locale constructed with null"), (__imp*)0))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000540{
541 __locale_->__add_shared();
542}
543
544locale::locale(const string& name)
545 : __locale_(new __imp(name))
546{
547 __locale_->__add_shared();
548}
549
550locale::locale(const locale& other, const char* name, category c)
551 : __locale_(name ? new __imp(*other.__locale_, name, c)
Louis Dionne2b239162019-02-12 16:06:02 +0000552 : (__throw_runtime_error("locale constructed with null"), (__imp*)0))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000553{
554 __locale_->__add_shared();
555}
556
557locale::locale(const locale& other, const string& name, category c)
558 : __locale_(new __imp(*other.__locale_, name, c))
559{
560 __locale_->__add_shared();
561}
562
563locale::locale(const locale& other, const locale& one, category c)
564 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
565{
566 __locale_->__add_shared();
567}
568
569string
570locale::name() const
571{
572 return __locale_->name();
573}
574
575void
576locale::__install_ctor(const locale& other, facet* f, long id)
577{
578 if (f)
579 __locale_ = new __imp(*other.__locale_, f, id);
580 else
581 __locale_ = other.__locale_;
582 __locale_->__add_shared();
583}
584
585locale
586locale::global(const locale& loc)
587{
588 locale& g = __global();
589 locale r = g;
590 g = loc;
591 if (g.name() != "*")
592 setlocale(LC_ALL, g.name().c_str());
593 return r;
594}
595
596bool
597locale::has_facet(id& x) const
598{
599 return __locale_->has_facet(x.__get());
600}
601
602const locale::facet*
603locale::use_facet(id& x) const
604{
605 return __locale_->use_facet(x.__get());
606}
607
608bool
609locale::operator==(const locale& y) const
610{
611 return (__locale_ == y.__locale_)
612 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
613}
614
615// locale::facet
616
617locale::facet::~facet()
618{
619}
620
621void
Howard Hinnant719bda32011-05-28 14:41:13 +0000622locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000623{
624 delete this;
625}
626
627// locale::id
628
629int32_t locale::id::__next_id = 0;
630
631namespace
632{
633
634class __fake_bind
635{
636 locale::id* id_;
637 void (locale::id::* pmf_)();
638public:
639 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
640 : id_(id), pmf_(pmf) {}
641
642 void operator()() const
643 {
644 (id_->*pmf_)();
645 }
646};
647
648}
649
650long
651locale::id::__get()
652{
653 call_once(__flag_, __fake_bind(&locale::id::__init, this));
654 return __id_ - 1;
655}
656
657void
658locale::id::__init()
659{
Weiming Zhaob613db72017-09-19 23:18:03 +0000660 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000661}
662
663// template <> class collate_byname<char>
664
665collate_byname<char>::collate_byname(const char* n, size_t refs)
666 : collate<char>(refs),
667 __l(newlocale(LC_ALL_MASK, n, 0))
668{
669 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000670 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000671 " failed to construct for " + string(n));
672}
673
674collate_byname<char>::collate_byname(const string& name, size_t refs)
675 : collate<char>(refs),
676 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
677{
678 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000679 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000680 " failed to construct for " + name);
681}
682
683collate_byname<char>::~collate_byname()
684{
685 freelocale(__l);
686}
687
688int
689collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
690 const char_type* __lo2, const char_type* __hi2) const
691{
692 string_type lhs(__lo1, __hi1);
693 string_type rhs(__lo2, __hi2);
694 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
695 if (r < 0)
696 return -1;
697 if (r > 0)
698 return 1;
699 return r;
700}
701
702collate_byname<char>::string_type
703collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
704{
705 const string_type in(lo, hi);
706 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
707 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
708 return out;
709}
710
711// template <> class collate_byname<wchar_t>
712
713collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
714 : collate<wchar_t>(refs),
715 __l(newlocale(LC_ALL_MASK, n, 0))
716{
717 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000718 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000719 " failed to construct for " + string(n));
720}
721
722collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
723 : collate<wchar_t>(refs),
724 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
725{
726 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000727 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000728 " failed to construct for " + name);
729}
730
731collate_byname<wchar_t>::~collate_byname()
732{
733 freelocale(__l);
734}
735
736int
737collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
738 const char_type* __lo2, const char_type* __hi2) const
739{
740 string_type lhs(__lo1, __hi1);
741 string_type rhs(__lo2, __hi2);
742 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
743 if (r < 0)
744 return -1;
745 if (r > 0)
746 return 1;
747 return r;
748}
749
750collate_byname<wchar_t>::string_type
751collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
752{
753 const string_type in(lo, hi);
754 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
755 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
756 return out;
757}
758
759// template <> class ctype<wchar_t>;
760
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000761const ctype_base::mask ctype_base::space;
762const ctype_base::mask ctype_base::print;
763const ctype_base::mask ctype_base::cntrl;
764const ctype_base::mask ctype_base::upper;
765const ctype_base::mask ctype_base::lower;
766const ctype_base::mask ctype_base::alpha;
767const ctype_base::mask ctype_base::digit;
768const ctype_base::mask ctype_base::punct;
769const ctype_base::mask ctype_base::xdigit;
770const ctype_base::mask ctype_base::blank;
771const ctype_base::mask ctype_base::alnum;
772const ctype_base::mask ctype_base::graph;
773
Howard Hinnantc51e1022010-05-11 19:42:16 +0000774locale::id ctype<wchar_t>::id;
775
776ctype<wchar_t>::~ctype()
777{
778}
779
780bool
781ctype<wchar_t>::do_is(mask m, char_type c) const
782{
Marshall Clowd920eea2013-10-21 15:07:28 +0000783 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000784}
785
786const wchar_t*
787ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
788{
789 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000790 *vec = static_cast<mask>(isascii(*low) ?
791 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000792 return low;
793}
794
795const wchar_t*
796ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
797{
798 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000799 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000800 break;
801 return low;
802}
803
804const wchar_t*
805ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
806{
807 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000808 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000809 break;
810 return low;
811}
812
813wchar_t
814ctype<wchar_t>::do_toupper(char_type c) const
815{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000816#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
817 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000818#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000819 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000820 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000821#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000822 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000823#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000824}
825
826const wchar_t*
827ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
828{
829 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000830#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
831 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000832#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000833 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000834 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
835 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000836#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000837 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000838#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000839 return low;
840}
841
842wchar_t
843ctype<wchar_t>::do_tolower(char_type c) const
844{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000845#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
846 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000847#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000848 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000849 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000850#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000851 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000852#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000853}
854
855const wchar_t*
856ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
857{
858 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000859#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
860 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000861#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000862 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000863 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
864 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000865#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000866 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000867#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000868 return low;
869}
870
871wchar_t
872ctype<wchar_t>::do_widen(char c) const
873{
874 return c;
875}
876
877const char*
878ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
879{
880 for (; low != high; ++low, ++dest)
881 *dest = *low;
882 return low;
883}
884
885char
886ctype<wchar_t>::do_narrow(char_type c, char dfault) const
887{
888 if (isascii(c))
889 return static_cast<char>(c);
890 return dfault;
891}
892
893const wchar_t*
894ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
895{
896 for (; low != high; ++low, ++dest)
897 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000898 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000899 else
900 *dest = dfault;
901 return low;
902}
903
904// template <> class ctype<char>;
905
906locale::id ctype<char>::id;
907
908ctype<char>::ctype(const mask* tab, bool del, size_t refs)
909 : locale::facet(refs),
910 __tab_(tab),
911 __del_(del)
912{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000913 if (__tab_ == 0)
914 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000915}
916
917ctype<char>::~ctype()
918{
919 if (__tab_ && __del_)
920 delete [] __tab_;
921}
922
923char
924ctype<char>::do_toupper(char_type c) const
925{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000926#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000927 return isascii(c) ?
928 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000929#elif defined(__NetBSD__)
930 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000931#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000932 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000933 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000934#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000935 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000936#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000937}
938
939const char*
940ctype<char>::do_toupper(char_type* low, const char_type* high) const
941{
942 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000943#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000944 *low = isascii(*low) ?
945 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000946#elif defined(__NetBSD__)
947 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000948#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000949 *low = isascii(*low) ?
950 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000951#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000952 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000953#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000954 return low;
955}
956
957char
958ctype<char>::do_tolower(char_type c) const
959{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000960#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000961 return isascii(c) ?
962 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000963#elif defined(__NetBSD__)
964 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000965#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000966 return isascii(c) ?
967 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000968#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000969 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000970#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000971}
972
973const char*
974ctype<char>::do_tolower(char_type* low, const char_type* high) const
975{
976 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000977#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000978 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000979#elif defined(__NetBSD__)
980 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000981#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000982 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000983#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000984 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000985#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000986 return low;
987}
988
989char
990ctype<char>::do_widen(char c) const
991{
992 return c;
993}
994
995const char*
996ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
997{
998 for (; low != high; ++low, ++dest)
999 *dest = *low;
1000 return low;
1001}
1002
1003char
1004ctype<char>::do_narrow(char_type c, char dfault) const
1005{
1006 if (isascii(c))
1007 return static_cast<char>(c);
1008 return dfault;
1009}
1010
1011const char*
1012ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1013{
1014 for (; low != high; ++low, ++dest)
1015 if (isascii(*low))
1016 *dest = *low;
1017 else
1018 *dest = dfault;
1019 return low;
1020}
1021
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001022#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001023extern "C" const unsigned short ** __ctype_b_loc();
1024extern "C" const int ** __ctype_tolower_loc();
1025extern "C" const int ** __ctype_toupper_loc();
1026#endif
1027
Marshall Clow8f870232015-03-04 16:50:02 +00001028#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001029const ctype<char>::mask*
1030ctype<char>::classic_table() _NOEXCEPT
1031{
1032 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl | space | blank,
1038 cntrl | space, cntrl | space,
1039 cntrl | space, cntrl | space,
1040 cntrl, cntrl,
1041 cntrl, cntrl,
1042 cntrl, cntrl,
1043 cntrl, cntrl,
1044 cntrl, cntrl,
1045 cntrl, cntrl,
1046 cntrl, cntrl,
1047 cntrl, cntrl,
1048 cntrl, cntrl,
1049 space | blank | print, punct | print,
1050 punct | print, punct | print,
1051 punct | 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 digit | print | xdigit, digit | print | xdigit,
1058 digit | print | xdigit, digit | print | xdigit,
1059 digit | print | xdigit, digit | print | xdigit,
1060 digit | print | xdigit, digit | print | xdigit,
1061 digit | print | xdigit, digit | print | xdigit,
1062 punct | print, punct | print,
1063 punct | print, punct | print,
1064 punct | print, punct | print,
1065 punct | print, upper | xdigit | print | alpha,
1066 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1067 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1068 upper | xdigit | print | alpha, upper | print | alpha,
1069 upper | print | alpha, upper | print | alpha,
1070 upper | 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, punct | print,
1079 punct | print, punct | print,
1080 punct | print, punct | print,
1081 punct | print, lower | xdigit | print | alpha,
1082 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1083 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1084 lower | xdigit | print | alpha, lower | print | alpha,
1085 lower | print | alpha, lower | print | alpha,
1086 lower | 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, punct | print,
1095 punct | print, punct | print,
1096 punct | print, cntrl,
1097 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1098 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 };
1106 return builtin_table;
1107}
1108#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001109const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001110ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001111{
David Chisnall1d581062011-09-21 08:39:44 +00001112#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001113 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001114#elif defined(__NetBSD__)
1115 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001116#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001117 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001118#elif __sun__
1119 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001120#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001121 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001122#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001123 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001124#elif defined(_NEWLIB_VERSION)
1125 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1126 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001127#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001128 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001129#else
David Chisnall8074c342012-02-29 13:05:08 +00001130 // Platform not supported: abort so the person doing the port knows what to
1131 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001132# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001133 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001134 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001135 return NULL;
1136#endif
1137}
Marshall Clowb3f62842015-03-04 16:10:14 +00001138#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001139
Howard Hinnantd7a78632011-09-29 13:33:15 +00001140#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001141const int*
1142ctype<char>::__classic_lower_table() _NOEXCEPT
1143{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001144 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001145}
1146
1147const int*
1148ctype<char>::__classic_upper_table() _NOEXCEPT
1149{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001150 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001151}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001152#elif __NetBSD__
1153const short*
1154ctype<char>::__classic_lower_table() _NOEXCEPT
1155{
1156 return _C_tolower_tab_ + 1;
1157}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001158
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001159const short*
1160ctype<char>::__classic_upper_table() _NOEXCEPT
1161{
1162 return _C_toupper_tab_ + 1;
1163}
1164
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001165#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001166const int*
1167ctype<char>::__classic_lower_table() _NOEXCEPT
1168{
1169 return *__ctype_tolower_loc();
1170}
1171
1172const int*
1173ctype<char>::__classic_upper_table() _NOEXCEPT
1174{
1175 return *__ctype_toupper_loc();
1176}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001177#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001178
Howard Hinnantc51e1022010-05-11 19:42:16 +00001179// template <> class ctype_byname<char>
1180
1181ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1182 : ctype<char>(0, false, refs),
1183 __l(newlocale(LC_ALL_MASK, name, 0))
1184{
1185 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001186 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001187 " failed to construct for " + string(name));
1188}
1189
1190ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1191 : ctype<char>(0, false, refs),
1192 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1193{
1194 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001195 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001196 " failed to construct for " + name);
1197}
1198
1199ctype_byname<char>::~ctype_byname()
1200{
1201 freelocale(__l);
1202}
1203
1204char
1205ctype_byname<char>::do_toupper(char_type c) const
1206{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001207 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001208}
1209
1210const char*
1211ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1212{
1213 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001214 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001215 return low;
1216}
1217
1218char
1219ctype_byname<char>::do_tolower(char_type c) const
1220{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001221 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001222}
1223
1224const char*
1225ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1226{
1227 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001228 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001229 return low;
1230}
1231
1232// template <> class ctype_byname<wchar_t>
1233
1234ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1235 : ctype<wchar_t>(refs),
1236 __l(newlocale(LC_ALL_MASK, name, 0))
1237{
1238 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001239 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001240 " failed to construct for " + string(name));
1241}
1242
1243ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1244 : ctype<wchar_t>(refs),
1245 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1246{
1247 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001248 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001249 " failed to construct for " + name);
1250}
1251
1252ctype_byname<wchar_t>::~ctype_byname()
1253{
1254 freelocale(__l);
1255}
1256
1257bool
1258ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1259{
Alexis Huntc2017f12011-07-09 03:40:04 +00001260#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001261 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001262#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001263 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001264 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001265 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1266 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1267 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1268 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1269 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1270 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1271 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1272 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1273 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1274 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001275 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001276#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001277}
1278
1279const wchar_t*
1280ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1281{
1282 for (; low != high; ++low, ++vec)
1283 {
1284 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001285 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001286 else
1287 {
1288 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001289 wint_t ch = static_cast<wint_t>(*low);
1290 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001291 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001292#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001293 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001294 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001295#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001296 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001297 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001298 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001299 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001300 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001302#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001303 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001304 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001305#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001306 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001307 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001308 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001309 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001310#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001311 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001312 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001313#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001314#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001315 if (iswblank_l(ch, __l))
1316 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001317#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001318 }
1319 }
1320 return low;
1321}
1322
1323const wchar_t*
1324ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1325{
1326 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001327 {
1328#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001329 if (iswctype_l(*low, m, __l))
1330 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001331#else
Marshall Clowada0f732013-02-07 14:22:51 +00001332 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001333 if ((m & space) == space && iswspace_l(ch, __l)) break;
1334 if ((m & print) == print && iswprint_l(ch, __l)) break;
1335 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1336 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1337 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1338 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1339 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1340 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1341 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1342 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001343#endif
1344 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345 return low;
1346}
1347
1348const wchar_t*
1349ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1350{
1351 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001352 {
1353#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001354 if (!iswctype_l(*low, m, __l))
1355 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001356#else
Marshall Clowada0f732013-02-07 14:22:51 +00001357 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001358 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1359 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1360 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1361 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1362 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1363 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1364 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1365 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1366 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1367 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001368 break;
1369#endif
1370 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001371 return low;
1372}
1373
1374wchar_t
1375ctype_byname<wchar_t>::do_toupper(char_type c) const
1376{
1377 return towupper_l(c, __l);
1378}
1379
1380const wchar_t*
1381ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1382{
1383 for (; low != high; ++low)
1384 *low = towupper_l(*low, __l);
1385 return low;
1386}
1387
1388wchar_t
1389ctype_byname<wchar_t>::do_tolower(char_type c) const
1390{
1391 return towlower_l(c, __l);
1392}
1393
1394const wchar_t*
1395ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1396{
1397 for (; low != high; ++low)
1398 *low = towlower_l(*low, __l);
1399 return low;
1400}
1401
1402wchar_t
1403ctype_byname<wchar_t>::do_widen(char c) const
1404{
Ben Craig3756b922016-03-09 15:39:39 +00001405 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001406}
1407
1408const char*
1409ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1410{
1411 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001412 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001413 return low;
1414}
1415
1416char
1417ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1418{
Ben Craig3756b922016-03-09 15:39:39 +00001419 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001420 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001421}
1422
1423const wchar_t*
1424ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1425{
1426 for (; low != high; ++low, ++dest)
1427 {
Ben Craig3756b922016-03-09 15:39:39 +00001428 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001429 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001430 }
1431 return low;
1432}
1433
1434// template <> class codecvt<char, char, mbstate_t>
1435
Howard Hinnantffb308e2010-08-22 00:03:27 +00001436locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001437
1438codecvt<char, char, mbstate_t>::~codecvt()
1439{
1440}
1441
1442codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001443codecvt<char, char, mbstate_t>::do_out(state_type&,
1444 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001445 extern_type* to, extern_type*, extern_type*& to_nxt) const
1446{
1447 frm_nxt = frm;
1448 to_nxt = to;
1449 return noconv;
1450}
1451
1452codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001453codecvt<char, char, mbstate_t>::do_in(state_type&,
1454 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001455 intern_type* to, intern_type*, intern_type*& to_nxt) const
1456{
1457 frm_nxt = frm;
1458 to_nxt = to;
1459 return noconv;
1460}
1461
1462codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001463codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001464 extern_type* to, extern_type*, extern_type*& to_nxt) const
1465{
1466 to_nxt = to;
1467 return noconv;
1468}
1469
1470int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001471codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001472{
1473 return 1;
1474}
1475
1476bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001477codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001478{
1479 return true;
1480}
1481
1482int
1483codecvt<char, char, mbstate_t>::do_length(state_type&,
1484 const extern_type* frm, const extern_type* end, size_t mx) const
1485{
Howard Hinnant28b24882011-12-01 20:21:04 +00001486 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001487}
1488
1489int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001490codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001491{
1492 return 1;
1493}
1494
1495// template <> class codecvt<wchar_t, char, mbstate_t>
1496
Howard Hinnantffb308e2010-08-22 00:03:27 +00001497locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001498
1499codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1500 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001501 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001502{
1503}
1504
1505codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1506 : locale::facet(refs),
1507 __l(newlocale(LC_ALL_MASK, nm, 0))
1508{
1509 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001510 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001511 " failed to construct for " + string(nm));
1512}
1513
1514codecvt<wchar_t, char, mbstate_t>::~codecvt()
1515{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001516 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001517 freelocale(__l);
1518}
1519
1520codecvt<wchar_t, char, mbstate_t>::result
1521codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001522 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001523 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1524{
1525 // look for first internal null in frm
1526 const intern_type* fend = frm;
1527 for (; fend != frm_end; ++fend)
1528 if (*fend == 0)
1529 break;
1530 // loop over all null-terminated sequences in frm
1531 to_nxt = to;
1532 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1533 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001534 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001535 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001536 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1537 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001538 if (n == size_t(-1))
1539 {
1540 // need to recover to_nxt
1541 for (to_nxt = to; frm != frm_nxt; ++frm)
1542 {
Ben Craig3756b922016-03-09 15:39:39 +00001543 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001544 if (n == size_t(-1))
1545 break;
1546 to_nxt += n;
1547 }
1548 frm_nxt = frm;
1549 return error;
1550 }
1551 if (n == 0)
1552 return partial;
1553 to_nxt += n;
1554 if (to_nxt == to_end)
1555 break;
1556 if (fend != frm_end) // set up next null terminated sequence
1557 {
1558 // Try to write the terminating null
1559 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001560 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001561 if (n == size_t(-1)) // on error
1562 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001563 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001564 return partial;
1565 for (extern_type* p = tmp; n; --n) // write it
1566 *to_nxt++ = *p++;
1567 ++frm_nxt;
1568 // look for next null in frm
1569 for (fend = frm_nxt; fend != frm_end; ++fend)
1570 if (*fend == 0)
1571 break;
1572 }
1573 }
1574 return frm_nxt == frm_end ? ok : partial;
1575}
1576
1577codecvt<wchar_t, char, mbstate_t>::result
1578codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001579 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001580 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1581{
1582 // look for first internal null in frm
1583 const extern_type* fend = frm;
1584 for (; fend != frm_end; ++fend)
1585 if (*fend == 0)
1586 break;
1587 // loop over all null-terminated sequences in frm
1588 to_nxt = to;
1589 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1590 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001591 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001592 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001593 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1594 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001595 if (n == size_t(-1))
1596 {
1597 // need to recover to_nxt
1598 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1599 {
Ben Craig3756b922016-03-09 15:39:39 +00001600 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1601 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001602 switch (n)
1603 {
1604 case 0:
1605 ++frm;
1606 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001607 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001608 frm_nxt = frm;
1609 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001610 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611 frm_nxt = frm;
1612 return partial;
1613 default:
1614 frm += n;
1615 break;
1616 }
1617 }
1618 frm_nxt = frm;
1619 return frm_nxt == frm_end ? ok : partial;
1620 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001621 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 return error;
1623 to_nxt += n;
1624 if (to_nxt == to_end)
1625 break;
1626 if (fend != frm_end) // set up next null terminated sequence
1627 {
1628 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001629 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001630 if (n != 0) // on error
1631 return error;
1632 ++to_nxt;
1633 ++frm_nxt;
1634 // look for next null in frm
1635 for (fend = frm_nxt; fend != frm_end; ++fend)
1636 if (*fend == 0)
1637 break;
1638 }
1639 }
1640 return frm_nxt == frm_end ? ok : partial;
1641}
1642
1643codecvt<wchar_t, char, mbstate_t>::result
1644codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1645 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1646{
1647 to_nxt = to;
1648 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001649 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001650 if (n == size_t(-1) || n == 0) // on error
1651 return error;
1652 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001653 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001654 return partial;
1655 for (extern_type* p = tmp; n; --n) // write it
1656 *to_nxt++ = *p++;
1657 return ok;
1658}
1659
1660int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001661codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001662{
Ben Craig3756b922016-03-09 15:39:39 +00001663 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001664 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001665
1666 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001667 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001668 return 1; // which take more than 1 char to form a wchar_t
1669 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001670}
1671
1672bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001673codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001674{
1675 return false;
1676}
1677
1678int
1679codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1680 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1681{
1682 int nbytes = 0;
1683 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1684 {
Ben Craig3756b922016-03-09 15:39:39 +00001685 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001686 switch (n)
1687 {
1688 case 0:
1689 ++nbytes;
1690 ++frm;
1691 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001692 case size_t(-1):
1693 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001694 return nbytes;
1695 default:
1696 nbytes += n;
1697 frm += n;
1698 break;
1699 }
1700 }
1701 return nbytes;
1702}
1703
1704int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001705codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001706{
Ben Craig3756b922016-03-09 15:39:39 +00001707 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001708}
1709
1710// Valid UTF ranges
1711// UTF-32 UTF-16 UTF-8 # of code points
1712// first second first second third fourth
1713// 000000 - 00007F 0000 - 007F 00 - 7F 127
1714// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1715// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1716// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1717// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1718// 00D800 - 00DFFF invalid
1719// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1720// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1721// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1722// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1723
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001724static
1725codecvt_base::result
1726utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1727 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1728 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1729{
1730 frm_nxt = frm;
1731 to_nxt = to;
1732 if (mode & generate_header)
1733 {
1734 if (to_end-to_nxt < 3)
1735 return codecvt_base::partial;
1736 *to_nxt++ = static_cast<uint8_t>(0xEF);
1737 *to_nxt++ = static_cast<uint8_t>(0xBB);
1738 *to_nxt++ = static_cast<uint8_t>(0xBF);
1739 }
1740 for (; frm_nxt < frm_end; ++frm_nxt)
1741 {
1742 uint16_t wc1 = *frm_nxt;
1743 if (wc1 > Maxcode)
1744 return codecvt_base::error;
1745 if (wc1 < 0x0080)
1746 {
1747 if (to_end-to_nxt < 1)
1748 return codecvt_base::partial;
1749 *to_nxt++ = static_cast<uint8_t>(wc1);
1750 }
1751 else if (wc1 < 0x0800)
1752 {
1753 if (to_end-to_nxt < 2)
1754 return codecvt_base::partial;
1755 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1756 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1757 }
1758 else if (wc1 < 0xD800)
1759 {
1760 if (to_end-to_nxt < 3)
1761 return codecvt_base::partial;
1762 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1763 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1764 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1765 }
1766 else if (wc1 < 0xDC00)
1767 {
1768 if (frm_end-frm_nxt < 2)
1769 return codecvt_base::partial;
1770 uint16_t wc2 = frm_nxt[1];
1771 if ((wc2 & 0xFC00) != 0xDC00)
1772 return codecvt_base::error;
1773 if (to_end-to_nxt < 4)
1774 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001775 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1776 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001777 return codecvt_base::error;
1778 ++frm_nxt;
1779 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1780 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1781 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1782 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1783 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1784 }
1785 else if (wc1 < 0xE000)
1786 {
1787 return codecvt_base::error;
1788 }
1789 else
1790 {
1791 if (to_end-to_nxt < 3)
1792 return codecvt_base::partial;
1793 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1794 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1795 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1796 }
1797 }
1798 return codecvt_base::ok;
1799}
1800
1801static
1802codecvt_base::result
1803utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1804 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1805 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1806{
1807 frm_nxt = frm;
1808 to_nxt = to;
1809 if (mode & generate_header)
1810 {
1811 if (to_end-to_nxt < 3)
1812 return codecvt_base::partial;
1813 *to_nxt++ = static_cast<uint8_t>(0xEF);
1814 *to_nxt++ = static_cast<uint8_t>(0xBB);
1815 *to_nxt++ = static_cast<uint8_t>(0xBF);
1816 }
1817 for (; frm_nxt < frm_end; ++frm_nxt)
1818 {
1819 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1820 if (wc1 > Maxcode)
1821 return codecvt_base::error;
1822 if (wc1 < 0x0080)
1823 {
1824 if (to_end-to_nxt < 1)
1825 return codecvt_base::partial;
1826 *to_nxt++ = static_cast<uint8_t>(wc1);
1827 }
1828 else if (wc1 < 0x0800)
1829 {
1830 if (to_end-to_nxt < 2)
1831 return codecvt_base::partial;
1832 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1833 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1834 }
1835 else if (wc1 < 0xD800)
1836 {
1837 if (to_end-to_nxt < 3)
1838 return codecvt_base::partial;
1839 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1840 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1841 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1842 }
1843 else if (wc1 < 0xDC00)
1844 {
1845 if (frm_end-frm_nxt < 2)
1846 return codecvt_base::partial;
1847 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1848 if ((wc2 & 0xFC00) != 0xDC00)
1849 return codecvt_base::error;
1850 if (to_end-to_nxt < 4)
1851 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001852 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1853 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001854 return codecvt_base::error;
1855 ++frm_nxt;
1856 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1857 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1858 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1859 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1860 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1861 }
1862 else if (wc1 < 0xE000)
1863 {
1864 return codecvt_base::error;
1865 }
1866 else
1867 {
1868 if (to_end-to_nxt < 3)
1869 return codecvt_base::partial;
1870 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1871 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1872 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1873 }
1874 }
1875 return codecvt_base::ok;
1876}
1877
1878static
1879codecvt_base::result
1880utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1881 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1882 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1883{
1884 frm_nxt = frm;
1885 to_nxt = to;
1886 if (mode & consume_header)
1887 {
1888 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1889 frm_nxt[2] == 0xBF)
1890 frm_nxt += 3;
1891 }
1892 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1893 {
1894 uint8_t c1 = *frm_nxt;
1895 if (c1 > Maxcode)
1896 return codecvt_base::error;
1897 if (c1 < 0x80)
1898 {
1899 *to_nxt = static_cast<uint16_t>(c1);
1900 ++frm_nxt;
1901 }
1902 else if (c1 < 0xC2)
1903 {
1904 return codecvt_base::error;
1905 }
1906 else if (c1 < 0xE0)
1907 {
1908 if (frm_end-frm_nxt < 2)
1909 return codecvt_base::partial;
1910 uint8_t c2 = frm_nxt[1];
1911 if ((c2 & 0xC0) != 0x80)
1912 return codecvt_base::error;
1913 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1914 if (t > Maxcode)
1915 return codecvt_base::error;
1916 *to_nxt = t;
1917 frm_nxt += 2;
1918 }
1919 else if (c1 < 0xF0)
1920 {
1921 if (frm_end-frm_nxt < 3)
1922 return codecvt_base::partial;
1923 uint8_t c2 = frm_nxt[1];
1924 uint8_t c3 = frm_nxt[2];
1925 switch (c1)
1926 {
1927 case 0xE0:
1928 if ((c2 & 0xE0) != 0xA0)
1929 return codecvt_base::error;
1930 break;
1931 case 0xED:
1932 if ((c2 & 0xE0) != 0x80)
1933 return codecvt_base::error;
1934 break;
1935 default:
1936 if ((c2 & 0xC0) != 0x80)
1937 return codecvt_base::error;
1938 break;
1939 }
1940 if ((c3 & 0xC0) != 0x80)
1941 return codecvt_base::error;
1942 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1943 | ((c2 & 0x3F) << 6)
1944 | (c3 & 0x3F));
1945 if (t > Maxcode)
1946 return codecvt_base::error;
1947 *to_nxt = t;
1948 frm_nxt += 3;
1949 }
1950 else if (c1 < 0xF5)
1951 {
1952 if (frm_end-frm_nxt < 4)
1953 return codecvt_base::partial;
1954 uint8_t c2 = frm_nxt[1];
1955 uint8_t c3 = frm_nxt[2];
1956 uint8_t c4 = frm_nxt[3];
1957 switch (c1)
1958 {
1959 case 0xF0:
1960 if (!(0x90 <= c2 && c2 <= 0xBF))
1961 return codecvt_base::error;
1962 break;
1963 case 0xF4:
1964 if ((c2 & 0xF0) != 0x80)
1965 return codecvt_base::error;
1966 break;
1967 default:
1968 if ((c2 & 0xC0) != 0x80)
1969 return codecvt_base::error;
1970 break;
1971 }
1972 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1973 return codecvt_base::error;
1974 if (to_end-to_nxt < 2)
1975 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001976 if ((((c1 & 7UL) << 18) +
1977 ((c2 & 0x3FUL) << 12) +
1978 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001979 return codecvt_base::error;
1980 *to_nxt = static_cast<uint16_t>(
1981 0xD800
1982 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1983 | ((c2 & 0x0F) << 2)
1984 | ((c3 & 0x30) >> 4));
1985 *++to_nxt = static_cast<uint16_t>(
1986 0xDC00
1987 | ((c3 & 0x0F) << 6)
1988 | (c4 & 0x3F));
1989 frm_nxt += 4;
1990 }
1991 else
1992 {
1993 return codecvt_base::error;
1994 }
1995 }
1996 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1997}
1998
1999static
2000codecvt_base::result
2001utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2002 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2003 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2004{
2005 frm_nxt = frm;
2006 to_nxt = to;
2007 if (mode & consume_header)
2008 {
2009 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2010 frm_nxt[2] == 0xBF)
2011 frm_nxt += 3;
2012 }
2013 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2014 {
2015 uint8_t c1 = *frm_nxt;
2016 if (c1 > Maxcode)
2017 return codecvt_base::error;
2018 if (c1 < 0x80)
2019 {
2020 *to_nxt = static_cast<uint32_t>(c1);
2021 ++frm_nxt;
2022 }
2023 else if (c1 < 0xC2)
2024 {
2025 return codecvt_base::error;
2026 }
2027 else if (c1 < 0xE0)
2028 {
2029 if (frm_end-frm_nxt < 2)
2030 return codecvt_base::partial;
2031 uint8_t c2 = frm_nxt[1];
2032 if ((c2 & 0xC0) != 0x80)
2033 return codecvt_base::error;
2034 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2035 if (t > Maxcode)
2036 return codecvt_base::error;
2037 *to_nxt = static_cast<uint32_t>(t);
2038 frm_nxt += 2;
2039 }
2040 else if (c1 < 0xF0)
2041 {
2042 if (frm_end-frm_nxt < 3)
2043 return codecvt_base::partial;
2044 uint8_t c2 = frm_nxt[1];
2045 uint8_t c3 = frm_nxt[2];
2046 switch (c1)
2047 {
2048 case 0xE0:
2049 if ((c2 & 0xE0) != 0xA0)
2050 return codecvt_base::error;
2051 break;
2052 case 0xED:
2053 if ((c2 & 0xE0) != 0x80)
2054 return codecvt_base::error;
2055 break;
2056 default:
2057 if ((c2 & 0xC0) != 0x80)
2058 return codecvt_base::error;
2059 break;
2060 }
2061 if ((c3 & 0xC0) != 0x80)
2062 return codecvt_base::error;
2063 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2064 | ((c2 & 0x3F) << 6)
2065 | (c3 & 0x3F));
2066 if (t > Maxcode)
2067 return codecvt_base::error;
2068 *to_nxt = static_cast<uint32_t>(t);
2069 frm_nxt += 3;
2070 }
2071 else if (c1 < 0xF5)
2072 {
2073 if (frm_end-frm_nxt < 4)
2074 return codecvt_base::partial;
2075 uint8_t c2 = frm_nxt[1];
2076 uint8_t c3 = frm_nxt[2];
2077 uint8_t c4 = frm_nxt[3];
2078 switch (c1)
2079 {
2080 case 0xF0:
2081 if (!(0x90 <= c2 && c2 <= 0xBF))
2082 return codecvt_base::error;
2083 break;
2084 case 0xF4:
2085 if ((c2 & 0xF0) != 0x80)
2086 return codecvt_base::error;
2087 break;
2088 default:
2089 if ((c2 & 0xC0) != 0x80)
2090 return codecvt_base::error;
2091 break;
2092 }
2093 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2094 return codecvt_base::error;
2095 if (to_end-to_nxt < 2)
2096 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002097 if ((((c1 & 7UL) << 18) +
2098 ((c2 & 0x3FUL) << 12) +
2099 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002100 return codecvt_base::error;
2101 *to_nxt = static_cast<uint32_t>(
2102 0xD800
2103 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2104 | ((c2 & 0x0F) << 2)
2105 | ((c3 & 0x30) >> 4));
2106 *++to_nxt = static_cast<uint32_t>(
2107 0xDC00
2108 | ((c3 & 0x0F) << 6)
2109 | (c4 & 0x3F));
2110 frm_nxt += 4;
2111 }
2112 else
2113 {
2114 return codecvt_base::error;
2115 }
2116 }
2117 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2118}
2119
2120static
2121int
2122utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2123 size_t mx, unsigned long Maxcode = 0x10FFFF,
2124 codecvt_mode mode = codecvt_mode(0))
2125{
2126 const uint8_t* frm_nxt = frm;
2127 if (mode & consume_header)
2128 {
2129 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2130 frm_nxt[2] == 0xBF)
2131 frm_nxt += 3;
2132 }
2133 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2134 {
2135 uint8_t c1 = *frm_nxt;
2136 if (c1 > Maxcode)
2137 break;
2138 if (c1 < 0x80)
2139 {
2140 ++frm_nxt;
2141 }
2142 else if (c1 < 0xC2)
2143 {
2144 break;
2145 }
2146 else if (c1 < 0xE0)
2147 {
2148 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2149 break;
2150 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2151 if (t > Maxcode)
2152 break;
2153 frm_nxt += 2;
2154 }
2155 else if (c1 < 0xF0)
2156 {
2157 if (frm_end-frm_nxt < 3)
2158 break;
2159 uint8_t c2 = frm_nxt[1];
2160 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002161 switch (c1)
2162 {
2163 case 0xE0:
2164 if ((c2 & 0xE0) != 0xA0)
2165 return static_cast<int>(frm_nxt - frm);
2166 break;
2167 case 0xED:
2168 if ((c2 & 0xE0) != 0x80)
2169 return static_cast<int>(frm_nxt - frm);
2170 break;
2171 default:
2172 if ((c2 & 0xC0) != 0x80)
2173 return static_cast<int>(frm_nxt - frm);
2174 break;
2175 }
2176 if ((c3 & 0xC0) != 0x80)
2177 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002178 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002179 break;
2180 frm_nxt += 3;
2181 }
2182 else if (c1 < 0xF5)
2183 {
2184 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2185 break;
2186 uint8_t c2 = frm_nxt[1];
2187 uint8_t c3 = frm_nxt[2];
2188 uint8_t c4 = frm_nxt[3];
2189 switch (c1)
2190 {
2191 case 0xF0:
2192 if (!(0x90 <= c2 && c2 <= 0xBF))
2193 return static_cast<int>(frm_nxt - frm);
2194 break;
2195 case 0xF4:
2196 if ((c2 & 0xF0) != 0x80)
2197 return static_cast<int>(frm_nxt - frm);
2198 break;
2199 default:
2200 if ((c2 & 0xC0) != 0x80)
2201 return static_cast<int>(frm_nxt - frm);
2202 break;
2203 }
2204 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2205 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002206 if ((((c1 & 7UL) << 18) +
2207 ((c2 & 0x3FUL) << 12) +
2208 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002209 break;
2210 ++nchar16_t;
2211 frm_nxt += 4;
2212 }
2213 else
2214 {
2215 break;
2216 }
2217 }
2218 return static_cast<int>(frm_nxt - frm);
2219}
2220
2221static
2222codecvt_base::result
2223ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2224 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2225 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2226{
2227 frm_nxt = frm;
2228 to_nxt = to;
2229 if (mode & generate_header)
2230 {
2231 if (to_end-to_nxt < 3)
2232 return codecvt_base::partial;
2233 *to_nxt++ = static_cast<uint8_t>(0xEF);
2234 *to_nxt++ = static_cast<uint8_t>(0xBB);
2235 *to_nxt++ = static_cast<uint8_t>(0xBF);
2236 }
2237 for (; frm_nxt < frm_end; ++frm_nxt)
2238 {
2239 uint32_t wc = *frm_nxt;
2240 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2241 return codecvt_base::error;
2242 if (wc < 0x000080)
2243 {
2244 if (to_end-to_nxt < 1)
2245 return codecvt_base::partial;
2246 *to_nxt++ = static_cast<uint8_t>(wc);
2247 }
2248 else if (wc < 0x000800)
2249 {
2250 if (to_end-to_nxt < 2)
2251 return codecvt_base::partial;
2252 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2253 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2254 }
2255 else if (wc < 0x010000)
2256 {
2257 if (to_end-to_nxt < 3)
2258 return codecvt_base::partial;
2259 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2260 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2261 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2262 }
2263 else // if (wc < 0x110000)
2264 {
2265 if (to_end-to_nxt < 4)
2266 return codecvt_base::partial;
2267 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2268 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2269 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2270 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2271 }
2272 }
2273 return codecvt_base::ok;
2274}
2275
2276static
2277codecvt_base::result
2278utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2279 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2280 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2281{
2282 frm_nxt = frm;
2283 to_nxt = to;
2284 if (mode & consume_header)
2285 {
2286 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2287 frm_nxt[2] == 0xBF)
2288 frm_nxt += 3;
2289 }
2290 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2291 {
2292 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2293 if (c1 < 0x80)
2294 {
2295 if (c1 > Maxcode)
2296 return codecvt_base::error;
2297 *to_nxt = static_cast<uint32_t>(c1);
2298 ++frm_nxt;
2299 }
2300 else if (c1 < 0xC2)
2301 {
2302 return codecvt_base::error;
2303 }
2304 else if (c1 < 0xE0)
2305 {
2306 if (frm_end-frm_nxt < 2)
2307 return codecvt_base::partial;
2308 uint8_t c2 = frm_nxt[1];
2309 if ((c2 & 0xC0) != 0x80)
2310 return codecvt_base::error;
2311 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2312 | (c2 & 0x3F));
2313 if (t > Maxcode)
2314 return codecvt_base::error;
2315 *to_nxt = t;
2316 frm_nxt += 2;
2317 }
2318 else if (c1 < 0xF0)
2319 {
2320 if (frm_end-frm_nxt < 3)
2321 return codecvt_base::partial;
2322 uint8_t c2 = frm_nxt[1];
2323 uint8_t c3 = frm_nxt[2];
2324 switch (c1)
2325 {
2326 case 0xE0:
2327 if ((c2 & 0xE0) != 0xA0)
2328 return codecvt_base::error;
2329 break;
2330 case 0xED:
2331 if ((c2 & 0xE0) != 0x80)
2332 return codecvt_base::error;
2333 break;
2334 default:
2335 if ((c2 & 0xC0) != 0x80)
2336 return codecvt_base::error;
2337 break;
2338 }
2339 if ((c3 & 0xC0) != 0x80)
2340 return codecvt_base::error;
2341 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2342 | ((c2 & 0x3F) << 6)
2343 | (c3 & 0x3F));
2344 if (t > Maxcode)
2345 return codecvt_base::error;
2346 *to_nxt = t;
2347 frm_nxt += 3;
2348 }
2349 else if (c1 < 0xF5)
2350 {
2351 if (frm_end-frm_nxt < 4)
2352 return codecvt_base::partial;
2353 uint8_t c2 = frm_nxt[1];
2354 uint8_t c3 = frm_nxt[2];
2355 uint8_t c4 = frm_nxt[3];
2356 switch (c1)
2357 {
2358 case 0xF0:
2359 if (!(0x90 <= c2 && c2 <= 0xBF))
2360 return codecvt_base::error;
2361 break;
2362 case 0xF4:
2363 if ((c2 & 0xF0) != 0x80)
2364 return codecvt_base::error;
2365 break;
2366 default:
2367 if ((c2 & 0xC0) != 0x80)
2368 return codecvt_base::error;
2369 break;
2370 }
2371 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2372 return codecvt_base::error;
2373 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2374 | ((c2 & 0x3F) << 12)
2375 | ((c3 & 0x3F) << 6)
2376 | (c4 & 0x3F));
2377 if (t > Maxcode)
2378 return codecvt_base::error;
2379 *to_nxt = t;
2380 frm_nxt += 4;
2381 }
2382 else
2383 {
2384 return codecvt_base::error;
2385 }
2386 }
2387 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2388}
2389
2390static
2391int
2392utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2393 size_t mx, unsigned long Maxcode = 0x10FFFF,
2394 codecvt_mode mode = codecvt_mode(0))
2395{
2396 const uint8_t* frm_nxt = frm;
2397 if (mode & consume_header)
2398 {
2399 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2400 frm_nxt[2] == 0xBF)
2401 frm_nxt += 3;
2402 }
2403 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2404 {
2405 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2406 if (c1 < 0x80)
2407 {
2408 if (c1 > Maxcode)
2409 break;
2410 ++frm_nxt;
2411 }
2412 else if (c1 < 0xC2)
2413 {
2414 break;
2415 }
2416 else if (c1 < 0xE0)
2417 {
2418 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2419 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002420 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002421 break;
2422 frm_nxt += 2;
2423 }
2424 else if (c1 < 0xF0)
2425 {
2426 if (frm_end-frm_nxt < 3)
2427 break;
2428 uint8_t c2 = frm_nxt[1];
2429 uint8_t c3 = frm_nxt[2];
2430 switch (c1)
2431 {
2432 case 0xE0:
2433 if ((c2 & 0xE0) != 0xA0)
2434 return static_cast<int>(frm_nxt - frm);
2435 break;
2436 case 0xED:
2437 if ((c2 & 0xE0) != 0x80)
2438 return static_cast<int>(frm_nxt - frm);
2439 break;
2440 default:
2441 if ((c2 & 0xC0) != 0x80)
2442 return static_cast<int>(frm_nxt - frm);
2443 break;
2444 }
2445 if ((c3 & 0xC0) != 0x80)
2446 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002447 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002448 break;
2449 frm_nxt += 3;
2450 }
2451 else if (c1 < 0xF5)
2452 {
2453 if (frm_end-frm_nxt < 4)
2454 break;
2455 uint8_t c2 = frm_nxt[1];
2456 uint8_t c3 = frm_nxt[2];
2457 uint8_t c4 = frm_nxt[3];
2458 switch (c1)
2459 {
2460 case 0xF0:
2461 if (!(0x90 <= c2 && c2 <= 0xBF))
2462 return static_cast<int>(frm_nxt - frm);
2463 break;
2464 case 0xF4:
2465 if ((c2 & 0xF0) != 0x80)
2466 return static_cast<int>(frm_nxt - frm);
2467 break;
2468 default:
2469 if ((c2 & 0xC0) != 0x80)
2470 return static_cast<int>(frm_nxt - frm);
2471 break;
2472 }
2473 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2474 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002475 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2476 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002477 break;
2478 frm_nxt += 4;
2479 }
2480 else
2481 {
2482 break;
2483 }
2484 }
2485 return static_cast<int>(frm_nxt - frm);
2486}
2487
2488static
2489codecvt_base::result
2490ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2491 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2492 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2493{
2494 frm_nxt = frm;
2495 to_nxt = to;
2496 if (mode & generate_header)
2497 {
2498 if (to_end-to_nxt < 3)
2499 return codecvt_base::partial;
2500 *to_nxt++ = static_cast<uint8_t>(0xEF);
2501 *to_nxt++ = static_cast<uint8_t>(0xBB);
2502 *to_nxt++ = static_cast<uint8_t>(0xBF);
2503 }
2504 for (; frm_nxt < frm_end; ++frm_nxt)
2505 {
2506 uint16_t wc = *frm_nxt;
2507 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2508 return codecvt_base::error;
2509 if (wc < 0x0080)
2510 {
2511 if (to_end-to_nxt < 1)
2512 return codecvt_base::partial;
2513 *to_nxt++ = static_cast<uint8_t>(wc);
2514 }
2515 else if (wc < 0x0800)
2516 {
2517 if (to_end-to_nxt < 2)
2518 return codecvt_base::partial;
2519 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2520 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2521 }
2522 else // if (wc <= 0xFFFF)
2523 {
2524 if (to_end-to_nxt < 3)
2525 return codecvt_base::partial;
2526 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2527 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2528 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2529 }
2530 }
2531 return codecvt_base::ok;
2532}
2533
2534static
2535codecvt_base::result
2536utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2537 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2538 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2539{
2540 frm_nxt = frm;
2541 to_nxt = to;
2542 if (mode & consume_header)
2543 {
2544 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2545 frm_nxt[2] == 0xBF)
2546 frm_nxt += 3;
2547 }
2548 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2549 {
2550 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2551 if (c1 < 0x80)
2552 {
2553 if (c1 > Maxcode)
2554 return codecvt_base::error;
2555 *to_nxt = static_cast<uint16_t>(c1);
2556 ++frm_nxt;
2557 }
2558 else if (c1 < 0xC2)
2559 {
2560 return codecvt_base::error;
2561 }
2562 else if (c1 < 0xE0)
2563 {
2564 if (frm_end-frm_nxt < 2)
2565 return codecvt_base::partial;
2566 uint8_t c2 = frm_nxt[1];
2567 if ((c2 & 0xC0) != 0x80)
2568 return codecvt_base::error;
2569 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2570 | (c2 & 0x3F));
2571 if (t > Maxcode)
2572 return codecvt_base::error;
2573 *to_nxt = t;
2574 frm_nxt += 2;
2575 }
2576 else if (c1 < 0xF0)
2577 {
2578 if (frm_end-frm_nxt < 3)
2579 return codecvt_base::partial;
2580 uint8_t c2 = frm_nxt[1];
2581 uint8_t c3 = frm_nxt[2];
2582 switch (c1)
2583 {
2584 case 0xE0:
2585 if ((c2 & 0xE0) != 0xA0)
2586 return codecvt_base::error;
2587 break;
2588 case 0xED:
2589 if ((c2 & 0xE0) != 0x80)
2590 return codecvt_base::error;
2591 break;
2592 default:
2593 if ((c2 & 0xC0) != 0x80)
2594 return codecvt_base::error;
2595 break;
2596 }
2597 if ((c3 & 0xC0) != 0x80)
2598 return codecvt_base::error;
2599 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2600 | ((c2 & 0x3F) << 6)
2601 | (c3 & 0x3F));
2602 if (t > Maxcode)
2603 return codecvt_base::error;
2604 *to_nxt = t;
2605 frm_nxt += 3;
2606 }
2607 else
2608 {
2609 return codecvt_base::error;
2610 }
2611 }
2612 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2613}
2614
2615static
2616int
2617utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2618 size_t mx, unsigned long Maxcode = 0x10FFFF,
2619 codecvt_mode mode = codecvt_mode(0))
2620{
2621 const uint8_t* frm_nxt = frm;
2622 if (mode & consume_header)
2623 {
2624 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2625 frm_nxt[2] == 0xBF)
2626 frm_nxt += 3;
2627 }
2628 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2629 {
2630 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2631 if (c1 < 0x80)
2632 {
2633 if (c1 > Maxcode)
2634 break;
2635 ++frm_nxt;
2636 }
2637 else if (c1 < 0xC2)
2638 {
2639 break;
2640 }
2641 else if (c1 < 0xE0)
2642 {
2643 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2644 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002645 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002646 break;
2647 frm_nxt += 2;
2648 }
2649 else if (c1 < 0xF0)
2650 {
2651 if (frm_end-frm_nxt < 3)
2652 break;
2653 uint8_t c2 = frm_nxt[1];
2654 uint8_t c3 = frm_nxt[2];
2655 switch (c1)
2656 {
2657 case 0xE0:
2658 if ((c2 & 0xE0) != 0xA0)
2659 return static_cast<int>(frm_nxt - frm);
2660 break;
2661 case 0xED:
2662 if ((c2 & 0xE0) != 0x80)
2663 return static_cast<int>(frm_nxt - frm);
2664 break;
2665 default:
2666 if ((c2 & 0xC0) != 0x80)
2667 return static_cast<int>(frm_nxt - frm);
2668 break;
2669 }
2670 if ((c3 & 0xC0) != 0x80)
2671 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002672 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002673 break;
2674 frm_nxt += 3;
2675 }
2676 else
2677 {
2678 break;
2679 }
2680 }
2681 return static_cast<int>(frm_nxt - frm);
2682}
2683
2684static
2685codecvt_base::result
2686ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2687 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2688 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2689{
2690 frm_nxt = frm;
2691 to_nxt = to;
2692 if (mode & generate_header)
2693 {
2694 if (to_end-to_nxt < 2)
2695 return codecvt_base::partial;
2696 *to_nxt++ = static_cast<uint8_t>(0xFE);
2697 *to_nxt++ = static_cast<uint8_t>(0xFF);
2698 }
2699 for (; frm_nxt < frm_end; ++frm_nxt)
2700 {
2701 uint32_t wc = *frm_nxt;
2702 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2703 return codecvt_base::error;
2704 if (wc < 0x010000)
2705 {
2706 if (to_end-to_nxt < 2)
2707 return codecvt_base::partial;
2708 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2709 *to_nxt++ = static_cast<uint8_t>(wc);
2710 }
2711 else
2712 {
2713 if (to_end-to_nxt < 4)
2714 return codecvt_base::partial;
2715 uint16_t t = static_cast<uint16_t>(
2716 0xD800
2717 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2718 | ((wc & 0x00FC00) >> 10));
2719 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2720 *to_nxt++ = static_cast<uint8_t>(t);
2721 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2722 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2723 *to_nxt++ = static_cast<uint8_t>(t);
2724 }
2725 }
2726 return codecvt_base::ok;
2727}
2728
2729static
2730codecvt_base::result
2731utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2732 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2733 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2734{
2735 frm_nxt = frm;
2736 to_nxt = to;
2737 if (mode & consume_header)
2738 {
2739 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2740 frm_nxt += 2;
2741 }
2742 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2743 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002744 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002745 if ((c1 & 0xFC00) == 0xDC00)
2746 return codecvt_base::error;
2747 if ((c1 & 0xFC00) != 0xD800)
2748 {
2749 if (c1 > Maxcode)
2750 return codecvt_base::error;
2751 *to_nxt = static_cast<uint32_t>(c1);
2752 frm_nxt += 2;
2753 }
2754 else
2755 {
2756 if (frm_end-frm_nxt < 4)
2757 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002758 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002759 if ((c2 & 0xFC00) != 0xDC00)
2760 return codecvt_base::error;
2761 uint32_t t = static_cast<uint32_t>(
2762 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2763 | ((c1 & 0x003F) << 10)
2764 | (c2 & 0x03FF));
2765 if (t > Maxcode)
2766 return codecvt_base::error;
2767 *to_nxt = t;
2768 frm_nxt += 4;
2769 }
2770 }
2771 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2772}
2773
2774static
2775int
2776utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2777 size_t mx, unsigned long Maxcode = 0x10FFFF,
2778 codecvt_mode mode = codecvt_mode(0))
2779{
2780 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002781 if (mode & consume_header)
2782 {
2783 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2784 frm_nxt += 2;
2785 }
2786 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2787 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002788 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002789 if ((c1 & 0xFC00) == 0xDC00)
2790 break;
2791 if ((c1 & 0xFC00) != 0xD800)
2792 {
2793 if (c1 > Maxcode)
2794 break;
2795 frm_nxt += 2;
2796 }
2797 else
2798 {
2799 if (frm_end-frm_nxt < 4)
2800 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002801 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002802 if ((c2 & 0xFC00) != 0xDC00)
2803 break;
2804 uint32_t t = static_cast<uint32_t>(
2805 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2806 | ((c1 & 0x003F) << 10)
2807 | (c2 & 0x03FF));
2808 if (t > Maxcode)
2809 break;
2810 frm_nxt += 4;
2811 }
2812 }
2813 return static_cast<int>(frm_nxt - frm);
2814}
2815
2816static
2817codecvt_base::result
2818ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2819 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2820 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2821{
2822 frm_nxt = frm;
2823 to_nxt = to;
2824 if (mode & generate_header)
2825 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002826 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002827 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002828 *to_nxt++ = static_cast<uint8_t>(0xFF);
2829 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002830 }
2831 for (; frm_nxt < frm_end; ++frm_nxt)
2832 {
2833 uint32_t wc = *frm_nxt;
2834 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2835 return codecvt_base::error;
2836 if (wc < 0x010000)
2837 {
2838 if (to_end-to_nxt < 2)
2839 return codecvt_base::partial;
2840 *to_nxt++ = static_cast<uint8_t>(wc);
2841 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2842 }
2843 else
2844 {
2845 if (to_end-to_nxt < 4)
2846 return codecvt_base::partial;
2847 uint16_t t = static_cast<uint16_t>(
2848 0xD800
2849 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2850 | ((wc & 0x00FC00) >> 10));
2851 *to_nxt++ = static_cast<uint8_t>(t);
2852 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2853 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2854 *to_nxt++ = static_cast<uint8_t>(t);
2855 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2856 }
2857 }
2858 return codecvt_base::ok;
2859}
2860
2861static
2862codecvt_base::result
2863utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2864 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2865 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2866{
2867 frm_nxt = frm;
2868 to_nxt = to;
2869 if (mode & consume_header)
2870 {
2871 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2872 frm_nxt += 2;
2873 }
2874 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2875 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002876 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002877 if ((c1 & 0xFC00) == 0xDC00)
2878 return codecvt_base::error;
2879 if ((c1 & 0xFC00) != 0xD800)
2880 {
2881 if (c1 > Maxcode)
2882 return codecvt_base::error;
2883 *to_nxt = static_cast<uint32_t>(c1);
2884 frm_nxt += 2;
2885 }
2886 else
2887 {
2888 if (frm_end-frm_nxt < 4)
2889 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002890 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002891 if ((c2 & 0xFC00) != 0xDC00)
2892 return codecvt_base::error;
2893 uint32_t t = static_cast<uint32_t>(
2894 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2895 | ((c1 & 0x003F) << 10)
2896 | (c2 & 0x03FF));
2897 if (t > Maxcode)
2898 return codecvt_base::error;
2899 *to_nxt = t;
2900 frm_nxt += 4;
2901 }
2902 }
2903 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2904}
2905
2906static
2907int
2908utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2909 size_t mx, unsigned long Maxcode = 0x10FFFF,
2910 codecvt_mode mode = codecvt_mode(0))
2911{
2912 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002913 if (mode & consume_header)
2914 {
2915 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2916 frm_nxt += 2;
2917 }
2918 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2919 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002920 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002921 if ((c1 & 0xFC00) == 0xDC00)
2922 break;
2923 if ((c1 & 0xFC00) != 0xD800)
2924 {
2925 if (c1 > Maxcode)
2926 break;
2927 frm_nxt += 2;
2928 }
2929 else
2930 {
2931 if (frm_end-frm_nxt < 4)
2932 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002933 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002934 if ((c2 & 0xFC00) != 0xDC00)
2935 break;
2936 uint32_t t = static_cast<uint32_t>(
2937 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2938 | ((c1 & 0x003F) << 10)
2939 | (c2 & 0x03FF));
2940 if (t > Maxcode)
2941 break;
2942 frm_nxt += 4;
2943 }
2944 }
2945 return static_cast<int>(frm_nxt - frm);
2946}
2947
2948static
2949codecvt_base::result
2950ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2951 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2952 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2953{
2954 frm_nxt = frm;
2955 to_nxt = to;
2956 if (mode & generate_header)
2957 {
2958 if (to_end-to_nxt < 2)
2959 return codecvt_base::partial;
2960 *to_nxt++ = static_cast<uint8_t>(0xFE);
2961 *to_nxt++ = static_cast<uint8_t>(0xFF);
2962 }
2963 for (; frm_nxt < frm_end; ++frm_nxt)
2964 {
2965 uint16_t wc = *frm_nxt;
2966 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2967 return codecvt_base::error;
2968 if (to_end-to_nxt < 2)
2969 return codecvt_base::partial;
2970 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2971 *to_nxt++ = static_cast<uint8_t>(wc);
2972 }
2973 return codecvt_base::ok;
2974}
2975
2976static
2977codecvt_base::result
2978utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2979 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2980 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2981{
2982 frm_nxt = frm;
2983 to_nxt = to;
2984 if (mode & consume_header)
2985 {
2986 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2987 frm_nxt += 2;
2988 }
2989 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2990 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002991 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002992 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2993 return codecvt_base::error;
2994 *to_nxt = c1;
2995 frm_nxt += 2;
2996 }
2997 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2998}
2999
3000static
3001int
3002utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3003 size_t mx, unsigned long Maxcode = 0x10FFFF,
3004 codecvt_mode mode = codecvt_mode(0))
3005{
3006 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003007 if (mode & consume_header)
3008 {
3009 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3010 frm_nxt += 2;
3011 }
3012 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3013 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003014 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003015 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3016 break;
3017 frm_nxt += 2;
3018 }
3019 return static_cast<int>(frm_nxt - frm);
3020}
3021
3022static
3023codecvt_base::result
3024ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3025 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3026 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3027{
3028 frm_nxt = frm;
3029 to_nxt = to;
3030 if (mode & generate_header)
3031 {
3032 if (to_end-to_nxt < 2)
3033 return codecvt_base::partial;
3034 *to_nxt++ = static_cast<uint8_t>(0xFF);
3035 *to_nxt++ = static_cast<uint8_t>(0xFE);
3036 }
3037 for (; frm_nxt < frm_end; ++frm_nxt)
3038 {
3039 uint16_t wc = *frm_nxt;
3040 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3041 return codecvt_base::error;
3042 if (to_end-to_nxt < 2)
3043 return codecvt_base::partial;
3044 *to_nxt++ = static_cast<uint8_t>(wc);
3045 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3046 }
3047 return codecvt_base::ok;
3048}
3049
3050static
3051codecvt_base::result
3052utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3053 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3054 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3055{
3056 frm_nxt = frm;
3057 to_nxt = to;
3058 if (mode & consume_header)
3059 {
3060 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3061 frm_nxt += 2;
3062 }
3063 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3064 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003065 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003066 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3067 return codecvt_base::error;
3068 *to_nxt = c1;
3069 frm_nxt += 2;
3070 }
3071 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3072}
3073
3074static
3075int
3076utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3077 size_t mx, unsigned long Maxcode = 0x10FFFF,
3078 codecvt_mode mode = codecvt_mode(0))
3079{
3080 const uint8_t* frm_nxt = frm;
3081 frm_nxt = frm;
3082 if (mode & consume_header)
3083 {
3084 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3085 frm_nxt += 2;
3086 }
3087 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3088 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003089 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003090 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3091 break;
3092 frm_nxt += 2;
3093 }
3094 return static_cast<int>(frm_nxt - frm);
3095}
3096
Howard Hinnantc51e1022010-05-11 19:42:16 +00003097// template <> class codecvt<char16_t, char, mbstate_t>
3098
Howard Hinnantffb308e2010-08-22 00:03:27 +00003099locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003100
3101codecvt<char16_t, char, mbstate_t>::~codecvt()
3102{
3103}
3104
3105codecvt<char16_t, char, mbstate_t>::result
3106codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003107 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003108 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3109{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003110 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3111 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3112 const uint16_t* _frm_nxt = _frm;
3113 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3114 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3115 uint8_t* _to_nxt = _to;
3116 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3117 frm_nxt = frm + (_frm_nxt - _frm);
3118 to_nxt = to + (_to_nxt - _to);
3119 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003120}
3121
3122codecvt<char16_t, char, mbstate_t>::result
3123codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003124 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003125 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3126{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003127 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3128 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3129 const uint8_t* _frm_nxt = _frm;
3130 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3131 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3132 uint16_t* _to_nxt = _to;
3133 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3134 frm_nxt = frm + (_frm_nxt - _frm);
3135 to_nxt = to + (_to_nxt - _to);
3136 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003137}
3138
3139codecvt<char16_t, char, mbstate_t>::result
3140codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3141 extern_type* to, extern_type*, extern_type*& to_nxt) const
3142{
3143 to_nxt = to;
3144 return noconv;
3145}
3146
3147int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003148codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003149{
3150 return 0;
3151}
3152
3153bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003154codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003155{
3156 return false;
3157}
3158
3159int
3160codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3161 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3162{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003163 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3164 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3165 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003166}
3167
3168int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003169codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003170{
3171 return 4;
3172}
3173
3174// template <> class codecvt<char32_t, char, mbstate_t>
3175
Howard Hinnantffb308e2010-08-22 00:03:27 +00003176locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003177
3178codecvt<char32_t, char, mbstate_t>::~codecvt()
3179{
3180}
3181
3182codecvt<char32_t, char, mbstate_t>::result
3183codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003184 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003185 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3186{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003187 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3188 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3189 const uint32_t* _frm_nxt = _frm;
3190 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3191 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3192 uint8_t* _to_nxt = _to;
3193 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3194 frm_nxt = frm + (_frm_nxt - _frm);
3195 to_nxt = to + (_to_nxt - _to);
3196 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003197}
3198
3199codecvt<char32_t, char, mbstate_t>::result
3200codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003201 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003202 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3203{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003204 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3205 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3206 const uint8_t* _frm_nxt = _frm;
3207 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3208 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3209 uint32_t* _to_nxt = _to;
3210 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3211 frm_nxt = frm + (_frm_nxt - _frm);
3212 to_nxt = to + (_to_nxt - _to);
3213 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003214}
3215
3216codecvt<char32_t, char, mbstate_t>::result
3217codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3218 extern_type* to, extern_type*, extern_type*& to_nxt) const
3219{
3220 to_nxt = to;
3221 return noconv;
3222}
3223
3224int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003225codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003226{
3227 return 0;
3228}
3229
3230bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003231codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003232{
3233 return false;
3234}
3235
3236int
3237codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3238 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3239{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003240 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3241 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3242 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003243}
3244
3245int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003246codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003247{
3248 return 4;
3249}
3250
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003251// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003252
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003253__codecvt_utf8<wchar_t>::result
3254__codecvt_utf8<wchar_t>::do_out(state_type&,
3255 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003256 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3257{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003258#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003259 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3260 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3261 const uint16_t* _frm_nxt = _frm;
3262#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003263 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3264 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3265 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003266#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003267 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3268 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3269 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003270#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003271 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3272 _Maxcode_, _Mode_);
3273#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003274 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3275 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003276#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003277 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
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003282__codecvt_utf8<wchar_t>::result
3283__codecvt_utf8<wchar_t>::do_in(state_type&,
3284 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;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003290#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003291 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3292 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3293 uint16_t* _to_nxt = _to;
3294 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3295 _Maxcode_, _Mode_);
3296#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003297 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3298 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3299 uint32_t* _to_nxt = _to;
3300 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3301 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003302#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003303 frm_nxt = frm + (_frm_nxt - _frm);
3304 to_nxt = to + (_to_nxt - _to);
3305 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003306}
3307
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003308__codecvt_utf8<wchar_t>::result
3309__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003310 extern_type* to, extern_type*, extern_type*& to_nxt) const
3311{
3312 to_nxt = to;
3313 return noconv;
3314}
3315
3316int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003317__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003318{
3319 return 0;
3320}
3321
3322bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003323__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003324{
3325 return false;
3326}
3327
3328int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003329__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003330 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3331{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003332 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3333 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3334 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003335}
3336
3337int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003338__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003339{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003340 if (_Mode_ & consume_header)
3341 return 7;
3342 return 4;
3343}
3344
3345// __codecvt_utf8<char16_t>
3346
3347__codecvt_utf8<char16_t>::result
3348__codecvt_utf8<char16_t>::do_out(state_type&,
3349 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3350 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3351{
3352 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3353 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3354 const uint16_t* _frm_nxt = _frm;
3355 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3356 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3357 uint8_t* _to_nxt = _to;
3358 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3359 _Maxcode_, _Mode_);
3360 frm_nxt = frm + (_frm_nxt - _frm);
3361 to_nxt = to + (_to_nxt - _to);
3362 return r;
3363}
3364
3365__codecvt_utf8<char16_t>::result
3366__codecvt_utf8<char16_t>::do_in(state_type&,
3367 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3368 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3369{
3370 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3371 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3372 const uint8_t* _frm_nxt = _frm;
3373 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3374 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3375 uint16_t* _to_nxt = _to;
3376 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3377 _Maxcode_, _Mode_);
3378 frm_nxt = frm + (_frm_nxt - _frm);
3379 to_nxt = to + (_to_nxt - _to);
3380 return r;
3381}
3382
3383__codecvt_utf8<char16_t>::result
3384__codecvt_utf8<char16_t>::do_unshift(state_type&,
3385 extern_type* to, extern_type*, extern_type*& to_nxt) const
3386{
3387 to_nxt = to;
3388 return noconv;
3389}
3390
3391int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003392__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003393{
3394 return 0;
3395}
3396
3397bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003398__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003399{
3400 return false;
3401}
3402
3403int
3404__codecvt_utf8<char16_t>::do_length(state_type&,
3405 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3406{
3407 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3408 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3409 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3410}
3411
3412int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003413__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003414{
3415 if (_Mode_ & consume_header)
3416 return 6;
3417 return 3;
3418}
3419
3420// __codecvt_utf8<char32_t>
3421
3422__codecvt_utf8<char32_t>::result
3423__codecvt_utf8<char32_t>::do_out(state_type&,
3424 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3425 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3426{
3427 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;
3430 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3431 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3432 uint8_t* _to_nxt = _to;
3433 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3434 _Maxcode_, _Mode_);
3435 frm_nxt = frm + (_frm_nxt - _frm);
3436 to_nxt = to + (_to_nxt - _to);
3437 return r;
3438}
3439
3440__codecvt_utf8<char32_t>::result
3441__codecvt_utf8<char32_t>::do_in(state_type&,
3442 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3443 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3444{
3445 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3446 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3447 const uint8_t* _frm_nxt = _frm;
3448 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3449 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3450 uint32_t* _to_nxt = _to;
3451 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3452 _Maxcode_, _Mode_);
3453 frm_nxt = frm + (_frm_nxt - _frm);
3454 to_nxt = to + (_to_nxt - _to);
3455 return r;
3456}
3457
3458__codecvt_utf8<char32_t>::result
3459__codecvt_utf8<char32_t>::do_unshift(state_type&,
3460 extern_type* to, extern_type*, extern_type*& to_nxt) const
3461{
3462 to_nxt = to;
3463 return noconv;
3464}
3465
3466int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003467__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003468{
3469 return 0;
3470}
3471
3472bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003473__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003474{
3475 return false;
3476}
3477
3478int
3479__codecvt_utf8<char32_t>::do_length(state_type&,
3480 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3481{
3482 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3483 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3484 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3485}
3486
3487int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003488__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003489{
3490 if (_Mode_ & consume_header)
3491 return 7;
3492 return 4;
3493}
3494
3495// __codecvt_utf16<wchar_t, false>
3496
3497__codecvt_utf16<wchar_t, false>::result
3498__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3499 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3500 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3501{
3502 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3503 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3504 const uint32_t* _frm_nxt = _frm;
3505 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3506 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3507 uint8_t* _to_nxt = _to;
3508 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3509 _Maxcode_, _Mode_);
3510 frm_nxt = frm + (_frm_nxt - _frm);
3511 to_nxt = to + (_to_nxt - _to);
3512 return r;
3513}
3514
3515__codecvt_utf16<wchar_t, false>::result
3516__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3517 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3518 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3519{
3520 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3521 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3522 const uint8_t* _frm_nxt = _frm;
3523 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3524 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3525 uint32_t* _to_nxt = _to;
3526 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3527 _Maxcode_, _Mode_);
3528 frm_nxt = frm + (_frm_nxt - _frm);
3529 to_nxt = to + (_to_nxt - _to);
3530 return r;
3531}
3532
3533__codecvt_utf16<wchar_t, false>::result
3534__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3535 extern_type* to, extern_type*, extern_type*& to_nxt) const
3536{
3537 to_nxt = to;
3538 return noconv;
3539}
3540
3541int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003542__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003543{
3544 return 0;
3545}
3546
3547bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003548__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003549{
3550 return false;
3551}
3552
3553int
3554__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3555 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3556{
3557 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3558 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3559 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3560}
3561
3562int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003563__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003564{
3565 if (_Mode_ & consume_header)
3566 return 6;
3567 return 4;
3568}
3569
3570// __codecvt_utf16<wchar_t, true>
3571
3572__codecvt_utf16<wchar_t, true>::result
3573__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3574 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3575 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3576{
3577 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3578 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3579 const uint32_t* _frm_nxt = _frm;
3580 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3581 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3582 uint8_t* _to_nxt = _to;
3583 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3584 _Maxcode_, _Mode_);
3585 frm_nxt = frm + (_frm_nxt - _frm);
3586 to_nxt = to + (_to_nxt - _to);
3587 return r;
3588}
3589
3590__codecvt_utf16<wchar_t, true>::result
3591__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3592 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3593 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3594{
3595 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3596 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3597 const uint8_t* _frm_nxt = _frm;
3598 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3599 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3600 uint32_t* _to_nxt = _to;
3601 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3602 _Maxcode_, _Mode_);
3603 frm_nxt = frm + (_frm_nxt - _frm);
3604 to_nxt = to + (_to_nxt - _to);
3605 return r;
3606}
3607
3608__codecvt_utf16<wchar_t, true>::result
3609__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3610 extern_type* to, extern_type*, extern_type*& to_nxt) const
3611{
3612 to_nxt = to;
3613 return noconv;
3614}
3615
3616int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003617__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003618{
3619 return 0;
3620}
3621
3622bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003623__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003624{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003625 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003626}
3627
3628int
3629__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3630 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3631{
3632 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3633 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3634 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3635}
3636
3637int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003638__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003639{
3640 if (_Mode_ & consume_header)
3641 return 6;
3642 return 4;
3643}
3644
3645// __codecvt_utf16<char16_t, false>
3646
3647__codecvt_utf16<char16_t, false>::result
3648__codecvt_utf16<char16_t, false>::do_out(state_type&,
3649 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3650 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3651{
3652 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3653 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3654 const uint16_t* _frm_nxt = _frm;
3655 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3656 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3657 uint8_t* _to_nxt = _to;
3658 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3659 _Maxcode_, _Mode_);
3660 frm_nxt = frm + (_frm_nxt - _frm);
3661 to_nxt = to + (_to_nxt - _to);
3662 return r;
3663}
3664
3665__codecvt_utf16<char16_t, false>::result
3666__codecvt_utf16<char16_t, false>::do_in(state_type&,
3667 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3668 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3669{
3670 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3671 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3672 const uint8_t* _frm_nxt = _frm;
3673 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3674 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3675 uint16_t* _to_nxt = _to;
3676 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3677 _Maxcode_, _Mode_);
3678 frm_nxt = frm + (_frm_nxt - _frm);
3679 to_nxt = to + (_to_nxt - _to);
3680 return r;
3681}
3682
3683__codecvt_utf16<char16_t, false>::result
3684__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3685 extern_type* to, extern_type*, extern_type*& to_nxt) const
3686{
3687 to_nxt = to;
3688 return noconv;
3689}
3690
3691int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003692__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003693{
3694 return 0;
3695}
3696
3697bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003698__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003699{
3700 return false;
3701}
3702
3703int
3704__codecvt_utf16<char16_t, false>::do_length(state_type&,
3705 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3706{
3707 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3708 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3709 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3710}
3711
3712int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003713__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003714{
3715 if (_Mode_ & consume_header)
3716 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003717 return 2;
3718}
3719
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003720// __codecvt_utf16<char16_t, true>
3721
3722__codecvt_utf16<char16_t, true>::result
3723__codecvt_utf16<char16_t, true>::do_out(state_type&,
3724 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3725 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3726{
3727 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3728 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3729 const uint16_t* _frm_nxt = _frm;
3730 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3731 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3732 uint8_t* _to_nxt = _to;
3733 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3734 _Maxcode_, _Mode_);
3735 frm_nxt = frm + (_frm_nxt - _frm);
3736 to_nxt = to + (_to_nxt - _to);
3737 return r;
3738}
3739
3740__codecvt_utf16<char16_t, true>::result
3741__codecvt_utf16<char16_t, true>::do_in(state_type&,
3742 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3743 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3744{
3745 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3746 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3747 const uint8_t* _frm_nxt = _frm;
3748 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3749 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3750 uint16_t* _to_nxt = _to;
3751 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3752 _Maxcode_, _Mode_);
3753 frm_nxt = frm + (_frm_nxt - _frm);
3754 to_nxt = to + (_to_nxt - _to);
3755 return r;
3756}
3757
3758__codecvt_utf16<char16_t, true>::result
3759__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3760 extern_type* to, extern_type*, extern_type*& to_nxt) const
3761{
3762 to_nxt = to;
3763 return noconv;
3764}
3765
3766int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003767__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003768{
3769 return 0;
3770}
3771
3772bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003773__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003774{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003775 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003776}
3777
3778int
3779__codecvt_utf16<char16_t, true>::do_length(state_type&,
3780 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3781{
3782 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3783 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3784 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3785}
3786
3787int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003788__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003789{
3790 if (_Mode_ & consume_header)
3791 return 4;
3792 return 2;
3793}
3794
3795// __codecvt_utf16<char32_t, false>
3796
3797__codecvt_utf16<char32_t, false>::result
3798__codecvt_utf16<char32_t, false>::do_out(state_type&,
3799 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3800 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3801{
3802 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3803 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3804 const uint32_t* _frm_nxt = _frm;
3805 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3806 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3807 uint8_t* _to_nxt = _to;
3808 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3809 _Maxcode_, _Mode_);
3810 frm_nxt = frm + (_frm_nxt - _frm);
3811 to_nxt = to + (_to_nxt - _to);
3812 return r;
3813}
3814
3815__codecvt_utf16<char32_t, false>::result
3816__codecvt_utf16<char32_t, false>::do_in(state_type&,
3817 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3818 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3819{
3820 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3821 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3822 const uint8_t* _frm_nxt = _frm;
3823 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3824 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3825 uint32_t* _to_nxt = _to;
3826 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3827 _Maxcode_, _Mode_);
3828 frm_nxt = frm + (_frm_nxt - _frm);
3829 to_nxt = to + (_to_nxt - _to);
3830 return r;
3831}
3832
3833__codecvt_utf16<char32_t, false>::result
3834__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3835 extern_type* to, extern_type*, extern_type*& to_nxt) const
3836{
3837 to_nxt = to;
3838 return noconv;
3839}
3840
3841int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003842__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003843{
3844 return 0;
3845}
3846
3847bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003848__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003849{
3850 return false;
3851}
3852
3853int
3854__codecvt_utf16<char32_t, false>::do_length(state_type&,
3855 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3856{
3857 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3858 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3859 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3860}
3861
3862int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003863__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003864{
3865 if (_Mode_ & consume_header)
3866 return 6;
3867 return 4;
3868}
3869
3870// __codecvt_utf16<char32_t, true>
3871
3872__codecvt_utf16<char32_t, true>::result
3873__codecvt_utf16<char32_t, true>::do_out(state_type&,
3874 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3875 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3876{
3877 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3878 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3879 const uint32_t* _frm_nxt = _frm;
3880 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3881 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3882 uint8_t* _to_nxt = _to;
3883 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3884 _Maxcode_, _Mode_);
3885 frm_nxt = frm + (_frm_nxt - _frm);
3886 to_nxt = to + (_to_nxt - _to);
3887 return r;
3888}
3889
3890__codecvt_utf16<char32_t, true>::result
3891__codecvt_utf16<char32_t, true>::do_in(state_type&,
3892 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3893 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3894{
3895 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3896 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3897 const uint8_t* _frm_nxt = _frm;
3898 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3899 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3900 uint32_t* _to_nxt = _to;
3901 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3902 _Maxcode_, _Mode_);
3903 frm_nxt = frm + (_frm_nxt - _frm);
3904 to_nxt = to + (_to_nxt - _to);
3905 return r;
3906}
3907
3908__codecvt_utf16<char32_t, true>::result
3909__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3910 extern_type* to, extern_type*, extern_type*& to_nxt) const
3911{
3912 to_nxt = to;
3913 return noconv;
3914}
3915
3916int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003917__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003918{
3919 return 0;
3920}
3921
3922bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003923__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003924{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003925 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003926}
3927
3928int
3929__codecvt_utf16<char32_t, true>::do_length(state_type&,
3930 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3931{
3932 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3933 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3934 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3935}
3936
3937int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003938__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003939{
3940 if (_Mode_ & consume_header)
3941 return 6;
3942 return 4;
3943}
3944
3945// __codecvt_utf8_utf16<wchar_t>
3946
3947__codecvt_utf8_utf16<wchar_t>::result
3948__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3949 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3950 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3951{
3952 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3953 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3954 const uint32_t* _frm_nxt = _frm;
3955 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3956 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3957 uint8_t* _to_nxt = _to;
3958 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3959 _Maxcode_, _Mode_);
3960 frm_nxt = frm + (_frm_nxt - _frm);
3961 to_nxt = to + (_to_nxt - _to);
3962 return r;
3963}
3964
3965__codecvt_utf8_utf16<wchar_t>::result
3966__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3967 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3968 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3969{
3970 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3971 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3972 const uint8_t* _frm_nxt = _frm;
3973 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3974 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3975 uint32_t* _to_nxt = _to;
3976 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3977 _Maxcode_, _Mode_);
3978 frm_nxt = frm + (_frm_nxt - _frm);
3979 to_nxt = to + (_to_nxt - _to);
3980 return r;
3981}
3982
3983__codecvt_utf8_utf16<wchar_t>::result
3984__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3985 extern_type* to, extern_type*, extern_type*& to_nxt) const
3986{
3987 to_nxt = to;
3988 return noconv;
3989}
3990
3991int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003992__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003993{
3994 return 0;
3995}
3996
3997bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003998__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003999{
4000 return false;
4001}
4002
4003int
4004__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4005 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4006{
4007 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4008 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4009 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4010}
4011
4012int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004013__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004014{
4015 if (_Mode_ & consume_header)
4016 return 7;
4017 return 4;
4018}
4019
4020// __codecvt_utf8_utf16<char16_t>
4021
4022__codecvt_utf8_utf16<char16_t>::result
4023__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4024 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4025 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4026{
4027 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4028 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4029 const uint16_t* _frm_nxt = _frm;
4030 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4031 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4032 uint8_t* _to_nxt = _to;
4033 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4034 _Maxcode_, _Mode_);
4035 frm_nxt = frm + (_frm_nxt - _frm);
4036 to_nxt = to + (_to_nxt - _to);
4037 return r;
4038}
4039
4040__codecvt_utf8_utf16<char16_t>::result
4041__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4042 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4043 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4044{
4045 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4046 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4047 const uint8_t* _frm_nxt = _frm;
4048 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4049 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4050 uint16_t* _to_nxt = _to;
4051 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4052 _Maxcode_, _Mode_);
4053 frm_nxt = frm + (_frm_nxt - _frm);
4054 to_nxt = to + (_to_nxt - _to);
4055 return r;
4056}
4057
4058__codecvt_utf8_utf16<char16_t>::result
4059__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4060 extern_type* to, extern_type*, extern_type*& to_nxt) const
4061{
4062 to_nxt = to;
4063 return noconv;
4064}
4065
4066int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004067__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004068{
4069 return 0;
4070}
4071
4072bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004073__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004074{
4075 return false;
4076}
4077
4078int
4079__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4080 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4081{
4082 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4083 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4084 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4085}
4086
4087int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004088__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004089{
4090 if (_Mode_ & consume_header)
4091 return 7;
4092 return 4;
4093}
4094
4095// __codecvt_utf8_utf16<char32_t>
4096
4097__codecvt_utf8_utf16<char32_t>::result
4098__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4099 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4100 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4101{
4102 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4103 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4104 const uint32_t* _frm_nxt = _frm;
4105 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4106 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4107 uint8_t* _to_nxt = _to;
4108 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4109 _Maxcode_, _Mode_);
4110 frm_nxt = frm + (_frm_nxt - _frm);
4111 to_nxt = to + (_to_nxt - _to);
4112 return r;
4113}
4114
4115__codecvt_utf8_utf16<char32_t>::result
4116__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4117 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4118 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4119{
4120 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4121 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4122 const uint8_t* _frm_nxt = _frm;
4123 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4124 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4125 uint32_t* _to_nxt = _to;
4126 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4127 _Maxcode_, _Mode_);
4128 frm_nxt = frm + (_frm_nxt - _frm);
4129 to_nxt = to + (_to_nxt - _to);
4130 return r;
4131}
4132
4133__codecvt_utf8_utf16<char32_t>::result
4134__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4135 extern_type* to, extern_type*, extern_type*& to_nxt) const
4136{
4137 to_nxt = to;
4138 return noconv;
4139}
4140
4141int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004142__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004143{
4144 return 0;
4145}
4146
4147bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004148__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004149{
4150 return false;
4151}
4152
4153int
4154__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4155 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4156{
4157 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4158 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4159 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4160}
4161
4162int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004163__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004164{
4165 if (_Mode_ & consume_header)
4166 return 7;
4167 return 4;
4168}
4169
Howard Hinnantc51e1022010-05-11 19:42:16 +00004170// __narrow_to_utf8<16>
4171
4172__narrow_to_utf8<16>::~__narrow_to_utf8()
4173{
4174}
4175
4176// __narrow_to_utf8<32>
4177
4178__narrow_to_utf8<32>::~__narrow_to_utf8()
4179{
4180}
4181
4182// __widen_from_utf8<16>
4183
4184__widen_from_utf8<16>::~__widen_from_utf8()
4185{
4186}
4187
4188// __widen_from_utf8<32>
4189
4190__widen_from_utf8<32>::~__widen_from_utf8()
4191{
4192}
4193
Eric Fiselierbf945a22016-12-11 00:20:59 +00004194
4195static bool checked_string_to_wchar_convert(wchar_t& dest,
4196 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004197 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004198 if (*ptr == '\0')
4199 return false;
4200 mbstate_t mb = {};
4201 wchar_t out;
4202 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4203 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4204 return false;
4205 }
4206 dest = out;
4207 return true;
4208}
4209
4210static bool checked_string_to_char_convert(char& dest,
4211 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004212 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004213 if (*ptr == '\0')
4214 return false;
4215 if (!ptr[1]) {
4216 dest = *ptr;
4217 return true;
4218 }
4219 // First convert the MBS into a wide char then attempt to narrow it using
4220 // wctob_l.
4221 wchar_t wout;
4222 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4223 return false;
4224 int res;
4225 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4226 dest = res;
4227 return true;
4228 }
4229 // FIXME: Work around specific multibyte sequences that we can reasonable
4230 // translate into a different single byte.
4231 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004232 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004233 case L'\u00A0': // non-breaking space
4234 dest = ' ';
4235 return true;
4236 default:
4237 return false;
4238 }
4239 _LIBCPP_UNREACHABLE();
4240}
4241
4242
Howard Hinnantc51e1022010-05-11 19:42:16 +00004243// numpunct<char> && numpunct<wchar_t>
4244
4245locale::id numpunct< char >::id;
4246locale::id numpunct<wchar_t>::id;
4247
4248numpunct<char>::numpunct(size_t refs)
4249 : locale::facet(refs),
4250 __decimal_point_('.'),
4251 __thousands_sep_(',')
4252{
4253}
4254
4255numpunct<wchar_t>::numpunct(size_t refs)
4256 : locale::facet(refs),
4257 __decimal_point_(L'.'),
4258 __thousands_sep_(L',')
4259{
4260}
4261
4262numpunct<char>::~numpunct()
4263{
4264}
4265
4266numpunct<wchar_t>::~numpunct()
4267{
4268}
4269
4270 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4271wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4272
4273 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4274wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4275
4276string numpunct< char >::do_grouping() const {return __grouping_;}
4277string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4278
4279 string numpunct< char >::do_truename() const {return "true";}
4280wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4281
4282 string numpunct< char >::do_falsename() const {return "false";}
4283wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4284
4285// numpunct_byname<char>
4286
4287numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4288 : numpunct<char>(refs)
4289{
4290 __init(nm);
4291}
4292
4293numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4294 : numpunct<char>(refs)
4295{
4296 __init(nm.c_str());
4297}
4298
4299numpunct_byname<char>::~numpunct_byname()
4300{
4301}
4302
4303void
4304numpunct_byname<char>::__init(const char* nm)
4305{
4306 if (strcmp(nm, "C") != 0)
4307 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004308 __libcpp_unique_locale loc(nm);
4309 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004310 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004311 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004312
Ben Craig3756b922016-03-09 15:39:39 +00004313 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004314 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4315 loc.get());
4316 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4317 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004318 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004319 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004320 }
4321}
4322
4323// numpunct_byname<wchar_t>
4324
4325numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4326 : numpunct<wchar_t>(refs)
4327{
4328 __init(nm);
4329}
4330
4331numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4332 : numpunct<wchar_t>(refs)
4333{
4334 __init(nm.c_str());
4335}
4336
4337numpunct_byname<wchar_t>::~numpunct_byname()
4338{
4339}
4340
4341void
4342numpunct_byname<wchar_t>::__init(const char* nm)
4343{
4344 if (strcmp(nm, "C") != 0)
4345 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004346 __libcpp_unique_locale loc(nm);
4347 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004348 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004349 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004350
Ben Craig3756b922016-03-09 15:39:39 +00004351 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004352 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4353 loc.get());
4354 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4355 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004356 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004357 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004358 }
4359}
4360
4361// num_get helpers
4362
4363int
4364__num_get_base::__get_base(ios_base& iob)
4365{
4366 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4367 if (__basefield == ios_base::oct)
4368 return 8;
4369 else if (__basefield == ios_base::hex)
4370 return 16;
4371 else if (__basefield == 0)
4372 return 0;
4373 return 10;
4374}
4375
4376const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4377
4378void
4379__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4380 ios_base::iostate& __err)
4381{
Marshall Clowff9db6d2019-06-04 15:18:46 +00004382// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing
4383// we always have at least a single entry in [__g, __g_end); the end of the input sequence
4384 if (__grouping.size() >= 0 && __g_end - __g > 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004385 {
4386 reverse(__g, __g_end);
4387 const char* __ig = __grouping.data();
4388 const char* __eg = __ig + __grouping.size();
4389 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4390 {
4391 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4392 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004393 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004394 {
4395 __err = ios_base::failbit;
4396 return;
4397 }
4398 }
4399 if (__eg - __ig > 1)
4400 ++__ig;
4401 }
4402 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4403 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004404 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004405 __err = ios_base::failbit;
4406 }
4407 }
4408}
4409
4410void
4411__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4412 ios_base::fmtflags __flags)
4413{
4414 if (__flags & ios_base::showpos)
4415 *__fmtp++ = '+';
4416 if (__flags & ios_base::showbase)
4417 *__fmtp++ = '#';
4418 while(*__len)
4419 *__fmtp++ = *__len++;
4420 if ((__flags & ios_base::basefield) == ios_base::oct)
4421 *__fmtp = 'o';
4422 else if ((__flags & ios_base::basefield) == ios_base::hex)
4423 {
4424 if (__flags & ios_base::uppercase)
4425 *__fmtp = 'X';
4426 else
4427 *__fmtp = 'x';
4428 }
4429 else if (__signd)
4430 *__fmtp = 'd';
4431 else
4432 *__fmtp = 'u';
4433}
4434
4435bool
4436__num_put_base::__format_float(char* __fmtp, const char* __len,
4437 ios_base::fmtflags __flags)
4438{
4439 bool specify_precision = true;
4440 if (__flags & ios_base::showpos)
4441 *__fmtp++ = '+';
4442 if (__flags & ios_base::showpoint)
4443 *__fmtp++ = '#';
4444 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004445 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004446 if (floatfield == (ios_base::fixed | ios_base::scientific))
4447 specify_precision = false;
4448 else
4449 {
4450 *__fmtp++ = '.';
4451 *__fmtp++ = '*';
4452 }
4453 while(*__len)
4454 *__fmtp++ = *__len++;
4455 if (floatfield == ios_base::fixed)
4456 {
4457 if (uppercase)
4458 *__fmtp = 'F';
4459 else
4460 *__fmtp = 'f';
4461 }
4462 else if (floatfield == ios_base::scientific)
4463 {
4464 if (uppercase)
4465 *__fmtp = 'E';
4466 else
4467 *__fmtp = 'e';
4468 }
4469 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4470 {
4471 if (uppercase)
4472 *__fmtp = 'A';
4473 else
4474 *__fmtp = 'a';
4475 }
4476 else
4477 {
4478 if (uppercase)
4479 *__fmtp = 'G';
4480 else
4481 *__fmtp = 'g';
4482 }
4483 return specify_precision;
4484}
4485
4486char*
4487__num_put_base::__identify_padding(char* __nb, char* __ne,
4488 const ios_base& __iob)
4489{
4490 switch (__iob.flags() & ios_base::adjustfield)
4491 {
4492 case ios_base::internal:
4493 if (__nb[0] == '-' || __nb[0] == '+')
4494 return __nb+1;
4495 if (__ne - __nb >= 2 && __nb[0] == '0'
4496 && (__nb[1] == 'x' || __nb[1] == 'X'))
4497 return __nb+2;
4498 break;
4499 case ios_base::left:
4500 return __ne;
4501 case ios_base::right:
4502 default:
4503 break;
4504 }
4505 return __nb;
4506}
4507
4508// time_get
4509
4510static
4511string*
4512init_weeks()
4513{
4514 static string weeks[14];
4515 weeks[0] = "Sunday";
4516 weeks[1] = "Monday";
4517 weeks[2] = "Tuesday";
4518 weeks[3] = "Wednesday";
4519 weeks[4] = "Thursday";
4520 weeks[5] = "Friday";
4521 weeks[6] = "Saturday";
4522 weeks[7] = "Sun";
4523 weeks[8] = "Mon";
4524 weeks[9] = "Tue";
4525 weeks[10] = "Wed";
4526 weeks[11] = "Thu";
4527 weeks[12] = "Fri";
4528 weeks[13] = "Sat";
4529 return weeks;
4530}
4531
4532static
4533wstring*
4534init_wweeks()
4535{
4536 static wstring weeks[14];
4537 weeks[0] = L"Sunday";
4538 weeks[1] = L"Monday";
4539 weeks[2] = L"Tuesday";
4540 weeks[3] = L"Wednesday";
4541 weeks[4] = L"Thursday";
4542 weeks[5] = L"Friday";
4543 weeks[6] = L"Saturday";
4544 weeks[7] = L"Sun";
4545 weeks[8] = L"Mon";
4546 weeks[9] = L"Tue";
4547 weeks[10] = L"Wed";
4548 weeks[11] = L"Thu";
4549 weeks[12] = L"Fri";
4550 weeks[13] = L"Sat";
4551 return weeks;
4552}
4553
4554template <>
4555const string*
4556__time_get_c_storage<char>::__weeks() const
4557{
4558 static const string* weeks = init_weeks();
4559 return weeks;
4560}
4561
4562template <>
4563const wstring*
4564__time_get_c_storage<wchar_t>::__weeks() const
4565{
4566 static const wstring* weeks = init_wweeks();
4567 return weeks;
4568}
4569
4570static
4571string*
4572init_months()
4573{
4574 static string months[24];
4575 months[0] = "January";
4576 months[1] = "February";
4577 months[2] = "March";
4578 months[3] = "April";
4579 months[4] = "May";
4580 months[5] = "June";
4581 months[6] = "July";
4582 months[7] = "August";
4583 months[8] = "September";
4584 months[9] = "October";
4585 months[10] = "November";
4586 months[11] = "December";
4587 months[12] = "Jan";
4588 months[13] = "Feb";
4589 months[14] = "Mar";
4590 months[15] = "Apr";
4591 months[16] = "May";
4592 months[17] = "Jun";
4593 months[18] = "Jul";
4594 months[19] = "Aug";
4595 months[20] = "Sep";
4596 months[21] = "Oct";
4597 months[22] = "Nov";
4598 months[23] = "Dec";
4599 return months;
4600}
4601
4602static
4603wstring*
4604init_wmonths()
4605{
4606 static wstring months[24];
4607 months[0] = L"January";
4608 months[1] = L"February";
4609 months[2] = L"March";
4610 months[3] = L"April";
4611 months[4] = L"May";
4612 months[5] = L"June";
4613 months[6] = L"July";
4614 months[7] = L"August";
4615 months[8] = L"September";
4616 months[9] = L"October";
4617 months[10] = L"November";
4618 months[11] = L"December";
4619 months[12] = L"Jan";
4620 months[13] = L"Feb";
4621 months[14] = L"Mar";
4622 months[15] = L"Apr";
4623 months[16] = L"May";
4624 months[17] = L"Jun";
4625 months[18] = L"Jul";
4626 months[19] = L"Aug";
4627 months[20] = L"Sep";
4628 months[21] = L"Oct";
4629 months[22] = L"Nov";
4630 months[23] = L"Dec";
4631 return months;
4632}
4633
4634template <>
4635const string*
4636__time_get_c_storage<char>::__months() const
4637{
4638 static const string* months = init_months();
4639 return months;
4640}
4641
4642template <>
4643const wstring*
4644__time_get_c_storage<wchar_t>::__months() const
4645{
4646 static const wstring* months = init_wmonths();
4647 return months;
4648}
4649
4650static
4651string*
4652init_am_pm()
4653{
Marshall Clow5cc04922018-01-11 17:16:52 +00004654 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004655 am_pm[0] = "AM";
4656 am_pm[1] = "PM";
4657 return am_pm;
4658}
4659
4660static
4661wstring*
4662init_wam_pm()
4663{
Marshall Clow5cc04922018-01-11 17:16:52 +00004664 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004665 am_pm[0] = L"AM";
4666 am_pm[1] = L"PM";
4667 return am_pm;
4668}
4669
4670template <>
4671const string*
4672__time_get_c_storage<char>::__am_pm() const
4673{
4674 static const string* am_pm = init_am_pm();
4675 return am_pm;
4676}
4677
4678template <>
4679const wstring*
4680__time_get_c_storage<wchar_t>::__am_pm() const
4681{
4682 static const wstring* am_pm = init_wam_pm();
4683 return am_pm;
4684}
4685
4686template <>
4687const string&
4688__time_get_c_storage<char>::__x() const
4689{
4690 static string s("%m/%d/%y");
4691 return s;
4692}
4693
4694template <>
4695const wstring&
4696__time_get_c_storage<wchar_t>::__x() const
4697{
4698 static wstring s(L"%m/%d/%y");
4699 return s;
4700}
4701
4702template <>
4703const string&
4704__time_get_c_storage<char>::__X() const
4705{
4706 static string s("%H:%M:%S");
4707 return s;
4708}
4709
4710template <>
4711const wstring&
4712__time_get_c_storage<wchar_t>::__X() const
4713{
4714 static wstring s(L"%H:%M:%S");
4715 return s;
4716}
4717
4718template <>
4719const string&
4720__time_get_c_storage<char>::__c() const
4721{
4722 static string s("%a %b %d %H:%M:%S %Y");
4723 return s;
4724}
4725
4726template <>
4727const wstring&
4728__time_get_c_storage<wchar_t>::__c() const
4729{
4730 static wstring s(L"%a %b %d %H:%M:%S %Y");
4731 return s;
4732}
4733
4734template <>
4735const string&
4736__time_get_c_storage<char>::__r() const
4737{
4738 static string s("%I:%M:%S %p");
4739 return s;
4740}
4741
4742template <>
4743const wstring&
4744__time_get_c_storage<wchar_t>::__r() const
4745{
4746 static wstring s(L"%I:%M:%S %p");
4747 return s;
4748}
4749
4750// time_get_byname
4751
4752__time_get::__time_get(const char* nm)
4753 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4754{
4755 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004756 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004757 " failed to construct for " + string(nm));
4758}
4759
4760__time_get::__time_get(const string& nm)
4761 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4762{
4763 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004764 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004765 " failed to construct for " + nm);
4766}
4767
4768__time_get::~__time_get()
4769{
4770 freelocale(__loc_);
4771}
Marshall Clowd920eea2013-10-21 15:07:28 +00004772#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004773#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004774#endif
4775#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004776#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004777#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004778
Howard Hinnantc51e1022010-05-11 19:42:16 +00004779template <>
4780string
4781__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4782{
Howard Hinnant990207c2012-02-19 14:55:32 +00004783 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004784 t.tm_sec = 59;
4785 t.tm_min = 55;
4786 t.tm_hour = 23;
4787 t.tm_mday = 31;
4788 t.tm_mon = 11;
4789 t.tm_year = 161;
4790 t.tm_wday = 6;
4791 t.tm_yday = 364;
4792 t.tm_isdst = -1;
4793 char buf[100];
4794 char f[3] = {0};
4795 f[0] = '%';
4796 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004797 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004798 char* bb = buf;
4799 char* be = buf + n;
4800 string result;
4801 while (bb != be)
4802 {
4803 if (ct.is(ctype_base::space, *bb))
4804 {
4805 result.push_back(' ');
4806 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4807 ;
4808 continue;
4809 }
4810 char* w = bb;
4811 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004812 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004813 ct, err, false)
4814 - this->__weeks_;
4815 if (i < 14)
4816 {
4817 result.push_back('%');
4818 if (i < 7)
4819 result.push_back('A');
4820 else
4821 result.push_back('a');
4822 bb = w;
4823 continue;
4824 }
4825 w = bb;
4826 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4827 ct, err, false)
4828 - this->__months_;
4829 if (i < 24)
4830 {
4831 result.push_back('%');
4832 if (i < 12)
4833 result.push_back('B');
4834 else
4835 result.push_back('b');
4836 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4837 result.back() = 'm';
4838 bb = w;
4839 continue;
4840 }
4841 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4842 {
4843 w = bb;
4844 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4845 ct, err, false) - this->__am_pm_;
4846 if (i < 2)
4847 {
4848 result.push_back('%');
4849 result.push_back('p');
4850 bb = w;
4851 continue;
4852 }
4853 }
4854 w = bb;
4855 if (ct.is(ctype_base::digit, *bb))
4856 {
4857 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4858 {
4859 case 6:
4860 result.push_back('%');
4861 result.push_back('w');
4862 break;
4863 case 7:
4864 result.push_back('%');
4865 result.push_back('u');
4866 break;
4867 case 11:
4868 result.push_back('%');
4869 result.push_back('I');
4870 break;
4871 case 12:
4872 result.push_back('%');
4873 result.push_back('m');
4874 break;
4875 case 23:
4876 result.push_back('%');
4877 result.push_back('H');
4878 break;
4879 case 31:
4880 result.push_back('%');
4881 result.push_back('d');
4882 break;
4883 case 55:
4884 result.push_back('%');
4885 result.push_back('M');
4886 break;
4887 case 59:
4888 result.push_back('%');
4889 result.push_back('S');
4890 break;
4891 case 61:
4892 result.push_back('%');
4893 result.push_back('y');
4894 break;
4895 case 364:
4896 result.push_back('%');
4897 result.push_back('j');
4898 break;
4899 case 2061:
4900 result.push_back('%');
4901 result.push_back('Y');
4902 break;
4903 default:
4904 for (; w != bb; ++w)
4905 result.push_back(*w);
4906 break;
4907 }
4908 continue;
4909 }
4910 if (*bb == '%')
4911 {
4912 result.push_back('%');
4913 result.push_back('%');
4914 ++bb;
4915 continue;
4916 }
4917 result.push_back(*bb);
4918 ++bb;
4919 }
4920 return result;
4921}
4922
Marshall Clowd920eea2013-10-21 15:07:28 +00004923#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004924#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004925#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004926
Howard Hinnantc51e1022010-05-11 19:42:16 +00004927template <>
4928wstring
4929__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4930{
Howard Hinnant990207c2012-02-19 14:55:32 +00004931 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004932 t.tm_sec = 59;
4933 t.tm_min = 55;
4934 t.tm_hour = 23;
4935 t.tm_mday = 31;
4936 t.tm_mon = 11;
4937 t.tm_year = 161;
4938 t.tm_wday = 6;
4939 t.tm_yday = 364;
4940 t.tm_isdst = -1;
4941 char buf[100];
4942 char f[3] = {0};
4943 f[0] = '%';
4944 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004945 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004946 wchar_t wbuf[100];
4947 wchar_t* wbb = wbuf;
4948 mbstate_t mb = {0};
4949 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004950 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004951 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004952 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004953 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004954 wstring result;
4955 while (wbb != wbe)
4956 {
4957 if (ct.is(ctype_base::space, *wbb))
4958 {
4959 result.push_back(L' ');
4960 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4961 ;
4962 continue;
4963 }
4964 wchar_t* w = wbb;
4965 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004966 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004967 ct, err, false)
4968 - this->__weeks_;
4969 if (i < 14)
4970 {
4971 result.push_back(L'%');
4972 if (i < 7)
4973 result.push_back(L'A');
4974 else
4975 result.push_back(L'a');
4976 wbb = w;
4977 continue;
4978 }
4979 w = wbb;
4980 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4981 ct, err, false)
4982 - this->__months_;
4983 if (i < 24)
4984 {
4985 result.push_back(L'%');
4986 if (i < 12)
4987 result.push_back(L'B');
4988 else
4989 result.push_back(L'b');
4990 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4991 result.back() = L'm';
4992 wbb = w;
4993 continue;
4994 }
4995 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4996 {
4997 w = wbb;
4998 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4999 ct, err, false) - this->__am_pm_;
5000 if (i < 2)
5001 {
5002 result.push_back(L'%');
5003 result.push_back(L'p');
5004 wbb = w;
5005 continue;
5006 }
5007 }
5008 w = wbb;
5009 if (ct.is(ctype_base::digit, *wbb))
5010 {
5011 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5012 {
5013 case 6:
5014 result.push_back(L'%');
5015 result.push_back(L'w');
5016 break;
5017 case 7:
5018 result.push_back(L'%');
5019 result.push_back(L'u');
5020 break;
5021 case 11:
5022 result.push_back(L'%');
5023 result.push_back(L'I');
5024 break;
5025 case 12:
5026 result.push_back(L'%');
5027 result.push_back(L'm');
5028 break;
5029 case 23:
5030 result.push_back(L'%');
5031 result.push_back(L'H');
5032 break;
5033 case 31:
5034 result.push_back(L'%');
5035 result.push_back(L'd');
5036 break;
5037 case 55:
5038 result.push_back(L'%');
5039 result.push_back(L'M');
5040 break;
5041 case 59:
5042 result.push_back(L'%');
5043 result.push_back(L'S');
5044 break;
5045 case 61:
5046 result.push_back(L'%');
5047 result.push_back(L'y');
5048 break;
5049 case 364:
5050 result.push_back(L'%');
5051 result.push_back(L'j');
5052 break;
5053 case 2061:
5054 result.push_back(L'%');
5055 result.push_back(L'Y');
5056 break;
5057 default:
5058 for (; w != wbb; ++w)
5059 result.push_back(*w);
5060 break;
5061 }
5062 continue;
5063 }
5064 if (ct.narrow(*wbb, 0) == '%')
5065 {
5066 result.push_back(L'%');
5067 result.push_back(L'%');
5068 ++wbb;
5069 continue;
5070 }
5071 result.push_back(*wbb);
5072 ++wbb;
5073 }
5074 return result;
5075}
5076
5077template <>
5078void
5079__time_get_storage<char>::init(const ctype<char>& ct)
5080{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005081 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005082 char buf[100];
5083 // __weeks_
5084 for (int i = 0; i < 7; ++i)
5085 {
5086 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005087 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005088 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005089 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005090 __weeks_[i+7] = buf;
5091 }
5092 // __months_
5093 for (int i = 0; i < 12; ++i)
5094 {
5095 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005096 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005097 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005098 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005099 __months_[i+12] = buf;
5100 }
5101 // __am_pm_
5102 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005103 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005104 __am_pm_[0] = buf;
5105 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005106 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005107 __am_pm_[1] = buf;
5108 __c_ = __analyze('c', ct);
5109 __r_ = __analyze('r', ct);
5110 __x_ = __analyze('x', ct);
5111 __X_ = __analyze('X', ct);
5112}
5113
5114template <>
5115void
5116__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5117{
5118 tm t = {0};
5119 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005120 wchar_t wbuf[100];
5121 wchar_t* wbe;
5122 mbstate_t mb = {0};
5123 // __weeks_
5124 for (int i = 0; i < 7; ++i)
5125 {
5126 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005127 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005128 mb = mbstate_t();
5129 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005130 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005131 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005132 __throw_runtime_error("locale not supported");
5133 wbe = wbuf + j;
5134 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005135 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005136 mb = mbstate_t();
5137 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005138 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005139 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005140 __throw_runtime_error("locale not supported");
5141 wbe = wbuf + j;
5142 __weeks_[i+7].assign(wbuf, wbe);
5143 }
5144 // __months_
5145 for (int i = 0; i < 12; ++i)
5146 {
5147 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005148 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005149 mb = mbstate_t();
5150 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005151 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005152 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005153 __throw_runtime_error("locale not supported");
5154 wbe = wbuf + j;
5155 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005156 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005157 mb = mbstate_t();
5158 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005159 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005160 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005161 __throw_runtime_error("locale not supported");
5162 wbe = wbuf + j;
5163 __months_[i+12].assign(wbuf, wbe);
5164 }
5165 // __am_pm_
5166 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005167 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005168 mb = mbstate_t();
5169 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005170 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005171 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005172 __throw_runtime_error("locale not supported");
5173 wbe = wbuf + j;
5174 __am_pm_[0].assign(wbuf, wbe);
5175 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005176 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005177 mb = mbstate_t();
5178 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005179 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005180 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005181 __throw_runtime_error("locale not supported");
5182 wbe = wbuf + j;
5183 __am_pm_[1].assign(wbuf, wbe);
5184 __c_ = __analyze('c', ct);
5185 __r_ = __analyze('r', ct);
5186 __x_ = __analyze('x', ct);
5187 __X_ = __analyze('X', ct);
5188}
5189
5190template <class CharT>
5191struct _LIBCPP_HIDDEN __time_get_temp
5192 : public ctype_byname<CharT>
5193{
5194 explicit __time_get_temp(const char* nm)
5195 : ctype_byname<CharT>(nm, 1) {}
5196 explicit __time_get_temp(const string& nm)
5197 : ctype_byname<CharT>(nm, 1) {}
5198};
5199
5200template <>
5201__time_get_storage<char>::__time_get_storage(const char* __nm)
5202 : __time_get(__nm)
5203{
5204 const __time_get_temp<char> ct(__nm);
5205 init(ct);
5206}
5207
5208template <>
5209__time_get_storage<char>::__time_get_storage(const string& __nm)
5210 : __time_get(__nm)
5211{
5212 const __time_get_temp<char> ct(__nm);
5213 init(ct);
5214}
5215
5216template <>
5217__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5218 : __time_get(__nm)
5219{
5220 const __time_get_temp<wchar_t> ct(__nm);
5221 init(ct);
5222}
5223
5224template <>
5225__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5226 : __time_get(__nm)
5227{
5228 const __time_get_temp<wchar_t> ct(__nm);
5229 init(ct);
5230}
5231
5232template <>
5233time_base::dateorder
5234__time_get_storage<char>::__do_date_order() const
5235{
5236 unsigned i;
5237 for (i = 0; i < __x_.size(); ++i)
5238 if (__x_[i] == '%')
5239 break;
5240 ++i;
5241 switch (__x_[i])
5242 {
5243 case 'y':
5244 case 'Y':
5245 for (++i; i < __x_.size(); ++i)
5246 if (__x_[i] == '%')
5247 break;
5248 if (i == __x_.size())
5249 break;
5250 ++i;
5251 switch (__x_[i])
5252 {
5253 case 'm':
5254 for (++i; i < __x_.size(); ++i)
5255 if (__x_[i] == '%')
5256 break;
5257 if (i == __x_.size())
5258 break;
5259 ++i;
5260 if (__x_[i] == 'd')
5261 return time_base::ymd;
5262 break;
5263 case 'd':
5264 for (++i; i < __x_.size(); ++i)
5265 if (__x_[i] == '%')
5266 break;
5267 if (i == __x_.size())
5268 break;
5269 ++i;
5270 if (__x_[i] == 'm')
5271 return time_base::ydm;
5272 break;
5273 }
5274 break;
5275 case 'm':
5276 for (++i; i < __x_.size(); ++i)
5277 if (__x_[i] == '%')
5278 break;
5279 if (i == __x_.size())
5280 break;
5281 ++i;
5282 if (__x_[i] == 'd')
5283 {
5284 for (++i; i < __x_.size(); ++i)
5285 if (__x_[i] == '%')
5286 break;
5287 if (i == __x_.size())
5288 break;
5289 ++i;
5290 if (__x_[i] == 'y' || __x_[i] == 'Y')
5291 return time_base::mdy;
5292 break;
5293 }
5294 break;
5295 case 'd':
5296 for (++i; i < __x_.size(); ++i)
5297 if (__x_[i] == '%')
5298 break;
5299 if (i == __x_.size())
5300 break;
5301 ++i;
5302 if (__x_[i] == 'm')
5303 {
5304 for (++i; i < __x_.size(); ++i)
5305 if (__x_[i] == '%')
5306 break;
5307 if (i == __x_.size())
5308 break;
5309 ++i;
5310 if (__x_[i] == 'y' || __x_[i] == 'Y')
5311 return time_base::dmy;
5312 break;
5313 }
5314 break;
5315 }
5316 return time_base::no_order;
5317}
5318
5319template <>
5320time_base::dateorder
5321__time_get_storage<wchar_t>::__do_date_order() const
5322{
5323 unsigned i;
5324 for (i = 0; i < __x_.size(); ++i)
5325 if (__x_[i] == L'%')
5326 break;
5327 ++i;
5328 switch (__x_[i])
5329 {
5330 case L'y':
5331 case L'Y':
5332 for (++i; i < __x_.size(); ++i)
5333 if (__x_[i] == L'%')
5334 break;
5335 if (i == __x_.size())
5336 break;
5337 ++i;
5338 switch (__x_[i])
5339 {
5340 case L'm':
5341 for (++i; i < __x_.size(); ++i)
5342 if (__x_[i] == L'%')
5343 break;
5344 if (i == __x_.size())
5345 break;
5346 ++i;
5347 if (__x_[i] == L'd')
5348 return time_base::ymd;
5349 break;
5350 case L'd':
5351 for (++i; i < __x_.size(); ++i)
5352 if (__x_[i] == L'%')
5353 break;
5354 if (i == __x_.size())
5355 break;
5356 ++i;
5357 if (__x_[i] == L'm')
5358 return time_base::ydm;
5359 break;
5360 }
5361 break;
5362 case L'm':
5363 for (++i; i < __x_.size(); ++i)
5364 if (__x_[i] == L'%')
5365 break;
5366 if (i == __x_.size())
5367 break;
5368 ++i;
5369 if (__x_[i] == L'd')
5370 {
5371 for (++i; i < __x_.size(); ++i)
5372 if (__x_[i] == L'%')
5373 break;
5374 if (i == __x_.size())
5375 break;
5376 ++i;
5377 if (__x_[i] == L'y' || __x_[i] == L'Y')
5378 return time_base::mdy;
5379 break;
5380 }
5381 break;
5382 case L'd':
5383 for (++i; i < __x_.size(); ++i)
5384 if (__x_[i] == L'%')
5385 break;
5386 if (i == __x_.size())
5387 break;
5388 ++i;
5389 if (__x_[i] == L'm')
5390 {
5391 for (++i; i < __x_.size(); ++i)
5392 if (__x_[i] == L'%')
5393 break;
5394 if (i == __x_.size())
5395 break;
5396 ++i;
5397 if (__x_[i] == L'y' || __x_[i] == L'Y')
5398 return time_base::dmy;
5399 break;
5400 }
5401 break;
5402 }
5403 return time_base::no_order;
5404}
5405
5406// time_put
5407
5408__time_put::__time_put(const char* nm)
5409 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5410{
5411 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005412 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005413 " failed to construct for " + string(nm));
5414}
5415
5416__time_put::__time_put(const string& nm)
5417 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5418{
5419 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005420 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005421 " failed to construct for " + nm);
5422}
5423
5424__time_put::~__time_put()
5425{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005426 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005427 freelocale(__loc_);
5428}
5429
5430void
5431__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5432 char __fmt, char __mod) const
5433{
5434 char fmt[] = {'%', __fmt, __mod, 0};
5435 if (__mod != 0)
5436 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005437 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005438 __ne = __nb + n;
5439}
5440
5441void
5442__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5443 char __fmt, char __mod) const
5444{
5445 char __nar[100];
5446 char* __ne = __nar + 100;
5447 __do_put(__nar, __ne, __tm, __fmt, __mod);
5448 mbstate_t mb = {0};
5449 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005450 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005451 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005452 __throw_runtime_error("locale not supported");
5453 __we = __wb + j;
5454}
5455
5456// moneypunct_byname
5457
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005458template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005459static
5460void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005461__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5462 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5463 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005464{
5465 const char sign = static_cast<char>(money_base::sign);
5466 const char space = static_cast<char>(money_base::space);
5467 const char none = static_cast<char>(money_base::none);
5468 const char symbol = static_cast<char>(money_base::symbol);
5469 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005470 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5471
5472 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5473 // function'. "Space between sign and symbol or value" means that
5474 // if the sign is adjacent to the symbol, there's a space between
5475 // them, and otherwise there's a space between the sign and value.
5476 //
5477 // C11's localeconv specifies that the fourth character of an
5478 // international curr_symbol is used to separate the sign and
5479 // value when sep_by_space says to do so. C++ can't represent
5480 // that, so we just use a space. When sep_by_space says to
5481 // separate the symbol and value-or-sign with a space, we rearrange the
5482 // curr_symbol to put its spacing character on the correct side of
5483 // the symbol.
5484 //
5485 // We also need to avoid adding an extra space between the sign
5486 // and value when the currency symbol is suppressed (by not
5487 // setting showbase). We match glibc's strfmon by interpreting
5488 // sep_by_space==1 as "omit the space when the currency symbol is
5489 // absent".
5490 //
5491 // Users who want to get this right should use ICU instead.
5492
Howard Hinnantc51e1022010-05-11 19:42:16 +00005493 switch (cs_precedes)
5494 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005495 case 0: // value before curr_symbol
5496 if (symbol_contains_sep) {
5497 // Move the separator to before the symbol, to place it
5498 // between the value and symbol.
5499 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5500 __curr_symbol_.end());
5501 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005502 switch (sign_posn)
5503 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005504 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005505 pat.field[0] = sign;
5506 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005507 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005508 pat.field[3] = symbol;
5509 switch (sep_by_space)
5510 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005511 case 0: // No space separates the currency symbol and value.
5512 // This case may have changed between C99 and C11;
5513 // assume the currency symbol matches the intention.
5514 case 2: // Space between sign and currency or value.
5515 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005516 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005517 case 1: // Space between currency-and-sign or currency and value.
5518 if (!symbol_contains_sep) {
5519 // We insert the space into the symbol instead of
5520 // setting pat.field[2]=space so that when
5521 // showbase is not set, the space goes away too.
5522 __curr_symbol_.insert(0, 1, space_char);
5523 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005524 return;
5525 default:
5526 break;
5527 }
5528 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005529 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005530 pat.field[0] = sign;
5531 pat.field[3] = symbol;
5532 switch (sep_by_space)
5533 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005534 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005535 pat.field[1] = value;
5536 pat.field[2] = none;
5537 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005538 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005539 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005540 pat.field[2] = none;
5541 if (!symbol_contains_sep) {
5542 // We insert the space into the symbol instead of
5543 // setting pat.field[2]=space so that when
5544 // showbase is not set, the space goes away too.
5545 __curr_symbol_.insert(0, 1, space_char);
5546 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005547 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005548 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005549 pat.field[1] = space;
5550 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005551 if (symbol_contains_sep) {
5552 // Remove the separator from the symbol, since it
5553 // has already appeared after the sign.
5554 __curr_symbol_.erase(__curr_symbol_.begin());
5555 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005556 return;
5557 default:
5558 break;
5559 }
5560 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005561 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005562 pat.field[0] = value;
5563 pat.field[3] = sign;
5564 switch (sep_by_space)
5565 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005566 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005567 pat.field[1] = none;
5568 pat.field[2] = symbol;
5569 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005570 case 1: // Space between currency-and-sign or currency and value.
5571 if (!symbol_contains_sep) {
5572 // We insert the space into the symbol instead of
5573 // setting pat.field[1]=space so that when
5574 // showbase is not set, the space goes away too.
5575 __curr_symbol_.insert(0, 1, space_char);
5576 }
5577 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005578 pat.field[2] = symbol;
5579 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005580 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005581 pat.field[1] = symbol;
5582 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005583 if (symbol_contains_sep) {
5584 // Remove the separator from the symbol, since it
5585 // should not be removed if showbase is absent.
5586 __curr_symbol_.erase(__curr_symbol_.begin());
5587 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005588 return;
5589 default:
5590 break;
5591 }
5592 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005593 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005594 pat.field[0] = value;
5595 pat.field[3] = symbol;
5596 switch (sep_by_space)
5597 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005598 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599 pat.field[1] = none;
5600 pat.field[2] = sign;
5601 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005602 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005603 pat.field[1] = space;
5604 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005605 if (symbol_contains_sep) {
5606 // Remove the separator from the symbol, since it
5607 // has already appeared before the sign.
5608 __curr_symbol_.erase(__curr_symbol_.begin());
5609 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005610 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005611 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005612 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005613 pat.field[2] = none;
5614 if (!symbol_contains_sep) {
5615 // We insert the space into the symbol instead of
5616 // setting pat.field[2]=space so that when
5617 // showbase is not set, the space goes away too.
5618 __curr_symbol_.insert(0, 1, space_char);
5619 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005620 return;
5621 default:
5622 break;
5623 }
5624 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005625 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005626 pat.field[0] = value;
5627 pat.field[3] = sign;
5628 switch (sep_by_space)
5629 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005630 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005631 pat.field[1] = none;
5632 pat.field[2] = symbol;
5633 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005634 case 1: // Space between currency-and-sign or currency and value.
5635 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005636 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005637 if (!symbol_contains_sep) {
5638 // We insert the space into the symbol instead of
5639 // setting pat.field[1]=space so that when
5640 // showbase is not set, the space goes away too.
5641 __curr_symbol_.insert(0, 1, space_char);
5642 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005643 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005644 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005645 pat.field[1] = symbol;
5646 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005647 if (symbol_contains_sep) {
5648 // Remove the separator from the symbol, since it
5649 // should not disappear when showbase is absent.
5650 __curr_symbol_.erase(__curr_symbol_.begin());
5651 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005652 return;
5653 default:
5654 break;
5655 }
5656 break;
5657 default:
5658 break;
5659 }
5660 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005661 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005662 switch (sign_posn)
5663 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005664 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005665 pat.field[0] = sign;
5666 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005667 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005668 pat.field[3] = value;
5669 switch (sep_by_space)
5670 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005671 case 0: // No space separates the currency symbol and value.
5672 // This case may have changed between C99 and C11;
5673 // assume the currency symbol matches the intention.
5674 case 2: // Space between sign and currency or value.
5675 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005676 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005677 case 1: // Space between currency-and-sign or currency and value.
5678 if (!symbol_contains_sep) {
5679 // We insert the space into the symbol instead of
5680 // setting pat.field[2]=space so that when
5681 // showbase is not set, the space goes away too.
5682 __curr_symbol_.insert(0, 1, space_char);
5683 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005684 return;
5685 default:
5686 break;
5687 }
5688 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005689 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005690 pat.field[0] = sign;
5691 pat.field[3] = value;
5692 switch (sep_by_space)
5693 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005694 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005695 pat.field[1] = symbol;
5696 pat.field[2] = none;
5697 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005698 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005699 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005700 pat.field[2] = none;
5701 if (!symbol_contains_sep) {
5702 // We insert the space into the symbol instead of
5703 // setting pat.field[2]=space so that when
5704 // showbase is not set, the space goes away too.
5705 __curr_symbol_.push_back(space_char);
5706 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005707 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005708 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005709 pat.field[1] = space;
5710 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005711 if (symbol_contains_sep) {
5712 // Remove the separator from the symbol, since it
5713 // has already appeared after the sign.
5714 __curr_symbol_.pop_back();
5715 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005716 return;
5717 default:
5718 break;
5719 }
5720 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005721 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005722 pat.field[0] = symbol;
5723 pat.field[3] = sign;
5724 switch (sep_by_space)
5725 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005726 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005727 pat.field[1] = none;
5728 pat.field[2] = value;
5729 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005730 case 1: // Space between currency-and-sign or currency and value.
5731 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005732 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005733 if (!symbol_contains_sep) {
5734 // We insert the space into the symbol instead of
5735 // setting pat.field[1]=space so that when
5736 // showbase is not set, the space goes away too.
5737 __curr_symbol_.push_back(space_char);
5738 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005739 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005740 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005741 pat.field[1] = value;
5742 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005743 if (symbol_contains_sep) {
5744 // Remove the separator from the symbol, since it
5745 // will appear before the sign.
5746 __curr_symbol_.pop_back();
5747 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005748 return;
5749 default:
5750 break;
5751 }
5752 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005753 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005754 pat.field[0] = sign;
5755 pat.field[3] = value;
5756 switch (sep_by_space)
5757 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005758 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005759 pat.field[1] = symbol;
5760 pat.field[2] = none;
5761 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005762 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005763 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005764 pat.field[2] = none;
5765 if (!symbol_contains_sep) {
5766 // We insert the space into the symbol instead of
5767 // setting pat.field[2]=space so that when
5768 // showbase is not set, the space goes away too.
5769 __curr_symbol_.push_back(space_char);
5770 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005771 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005772 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005773 pat.field[1] = space;
5774 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005775 if (symbol_contains_sep) {
5776 // Remove the separator from the symbol, since it
5777 // has already appeared after the sign.
5778 __curr_symbol_.pop_back();
5779 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005780 return;
5781 default:
5782 break;
5783 }
5784 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005785 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005786 pat.field[0] = symbol;
5787 pat.field[3] = value;
5788 switch (sep_by_space)
5789 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005790 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005791 pat.field[1] = sign;
5792 pat.field[2] = none;
5793 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005794 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005795 pat.field[1] = sign;
5796 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005797 if (symbol_contains_sep) {
5798 // Remove the separator from the symbol, since it
5799 // should not disappear when showbase is absent.
5800 __curr_symbol_.pop_back();
5801 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005802 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005803 case 2: // Space between sign and currency or value.
5804 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005805 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005806 if (!symbol_contains_sep) {
5807 // We insert the space into the symbol instead of
5808 // setting pat.field[1]=space so that when
5809 // showbase is not set, the space goes away too.
5810 __curr_symbol_.push_back(space_char);
5811 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005812 return;
5813 default:
5814 break;
5815 }
5816 break;
5817 default:
5818 break;
5819 }
5820 break;
5821 default:
5822 break;
5823 }
5824 pat.field[0] = symbol;
5825 pat.field[1] = sign;
5826 pat.field[2] = none;
5827 pat.field[3] = value;
5828}
5829
5830template<>
5831void
5832moneypunct_byname<char, false>::init(const char* nm)
5833{
5834 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005835 __libcpp_unique_locale loc(nm);
5836 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005837 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005838 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005839
Ben Craig3756b922016-03-09 15:39:39 +00005840 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005841 if (!checked_string_to_char_convert(__decimal_point_,
5842 lc->mon_decimal_point,
5843 loc.get()))
5844 __decimal_point_ = base::do_decimal_point();
5845 if (!checked_string_to_char_convert(__thousands_sep_,
5846 lc->mon_thousands_sep,
5847 loc.get()))
5848 __thousands_sep_ = base::do_thousands_sep();
5849
Howard Hinnantc51e1022010-05-11 19:42:16 +00005850 __grouping_ = lc->mon_grouping;
5851 __curr_symbol_ = lc->currency_symbol;
5852 if (lc->frac_digits != CHAR_MAX)
5853 __frac_digits_ = lc->frac_digits;
5854 else
5855 __frac_digits_ = base::do_frac_digits();
5856 if (lc->p_sign_posn == 0)
5857 __positive_sign_ = "()";
5858 else
5859 __positive_sign_ = lc->positive_sign;
5860 if (lc->n_sign_posn == 0)
5861 __negative_sign_ = "()";
5862 else
5863 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005864 // Assume the positive and negative formats will want spaces in
5865 // the same places in curr_symbol since there's no way to
5866 // represent anything else.
5867 string_type __dummy_curr_symbol = __curr_symbol_;
5868 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5869 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5870 __init_pat(__neg_format_, __curr_symbol_, false,
5871 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005872}
5873
5874template<>
5875void
5876moneypunct_byname<char, true>::init(const char* nm)
5877{
5878 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005879 __libcpp_unique_locale loc(nm);
5880 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005881 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005882 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005883
Ben Craig3756b922016-03-09 15:39:39 +00005884 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005885 if (!checked_string_to_char_convert(__decimal_point_,
5886 lc->mon_decimal_point,
5887 loc.get()))
5888 __decimal_point_ = base::do_decimal_point();
5889 if (!checked_string_to_char_convert(__thousands_sep_,
5890 lc->mon_thousands_sep,
5891 loc.get()))
5892 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005893 __grouping_ = lc->mon_grouping;
5894 __curr_symbol_ = lc->int_curr_symbol;
5895 if (lc->int_frac_digits != CHAR_MAX)
5896 __frac_digits_ = lc->int_frac_digits;
5897 else
5898 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005899#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005900 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005901#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005902 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005903#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005904 __positive_sign_ = "()";
5905 else
5906 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005907#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005908 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005909#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005910 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005911#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005912 __negative_sign_ = "()";
5913 else
5914 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005915 // Assume the positive and negative formats will want spaces in
5916 // the same places in curr_symbol since there's no way to
5917 // represent anything else.
5918 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005919#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005920 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5921 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5922 __init_pat(__neg_format_, __curr_symbol_, true,
5923 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005924#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005925 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5926 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5927 lc->int_p_sign_posn, ' ');
5928 __init_pat(__neg_format_, __curr_symbol_, true,
5929 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5930 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005931#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005932}
5933
5934template<>
5935void
5936moneypunct_byname<wchar_t, false>::init(const char* nm)
5937{
5938 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005939 __libcpp_unique_locale loc(nm);
5940 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005941 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005942 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005943 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005944 if (!checked_string_to_wchar_convert(__decimal_point_,
5945 lc->mon_decimal_point,
5946 loc.get()))
5947 __decimal_point_ = base::do_decimal_point();
5948 if (!checked_string_to_wchar_convert(__thousands_sep_,
5949 lc->mon_thousands_sep,
5950 loc.get()))
5951 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005952 __grouping_ = lc->mon_grouping;
5953 wchar_t wbuf[100];
5954 mbstate_t mb = {0};
5955 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005956 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005957 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005958 __throw_runtime_error("locale not supported");
5959 wchar_t* wbe = wbuf + j;
5960 __curr_symbol_.assign(wbuf, wbe);
5961 if (lc->frac_digits != CHAR_MAX)
5962 __frac_digits_ = lc->frac_digits;
5963 else
5964 __frac_digits_ = base::do_frac_digits();
5965 if (lc->p_sign_posn == 0)
5966 __positive_sign_ = L"()";
5967 else
5968 {
5969 mb = mbstate_t();
5970 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005971 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005972 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005973 __throw_runtime_error("locale not supported");
5974 wbe = wbuf + j;
5975 __positive_sign_.assign(wbuf, wbe);
5976 }
5977 if (lc->n_sign_posn == 0)
5978 __negative_sign_ = L"()";
5979 else
5980 {
5981 mb = mbstate_t();
5982 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005983 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005984 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005985 __throw_runtime_error("locale not supported");
5986 wbe = wbuf + j;
5987 __negative_sign_.assign(wbuf, wbe);
5988 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005989 // Assume the positive and negative formats will want spaces in
5990 // the same places in curr_symbol since there's no way to
5991 // represent anything else.
5992 string_type __dummy_curr_symbol = __curr_symbol_;
5993 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5994 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5995 __init_pat(__neg_format_, __curr_symbol_, false,
5996 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005997}
5998
5999template<>
6000void
6001moneypunct_byname<wchar_t, true>::init(const char* nm)
6002{
6003 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006004 __libcpp_unique_locale loc(nm);
6005 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006006 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006007 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006008
Ben Craig3756b922016-03-09 15:39:39 +00006009 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006010 if (!checked_string_to_wchar_convert(__decimal_point_,
6011 lc->mon_decimal_point,
6012 loc.get()))
6013 __decimal_point_ = base::do_decimal_point();
6014 if (!checked_string_to_wchar_convert(__thousands_sep_,
6015 lc->mon_thousands_sep,
6016 loc.get()))
6017 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006018 __grouping_ = lc->mon_grouping;
6019 wchar_t wbuf[100];
6020 mbstate_t mb = {0};
6021 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006022 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006023 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006024 __throw_runtime_error("locale not supported");
6025 wchar_t* wbe = wbuf + j;
6026 __curr_symbol_.assign(wbuf, wbe);
6027 if (lc->int_frac_digits != CHAR_MAX)
6028 __frac_digits_ = lc->int_frac_digits;
6029 else
6030 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006031#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006032 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006033#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006034 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006035#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006036 __positive_sign_ = L"()";
6037 else
6038 {
6039 mb = mbstate_t();
6040 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006041 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006042 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006043 __throw_runtime_error("locale not supported");
6044 wbe = wbuf + j;
6045 __positive_sign_.assign(wbuf, wbe);
6046 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006047#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006048 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006049#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006050 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006051#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006052 __negative_sign_ = L"()";
6053 else
6054 {
6055 mb = mbstate_t();
6056 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006057 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006058 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006059 __throw_runtime_error("locale not supported");
6060 wbe = wbuf + j;
6061 __negative_sign_.assign(wbuf, wbe);
6062 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006063 // Assume the positive and negative formats will want spaces in
6064 // the same places in curr_symbol since there's no way to
6065 // represent anything else.
6066 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006067#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006068 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6069 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6070 __init_pat(__neg_format_, __curr_symbol_, true,
6071 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006072#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006073 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6074 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6075 lc->int_p_sign_posn, L' ');
6076 __init_pat(__neg_format_, __curr_symbol_, true,
6077 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6078 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006079#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006080}
6081
6082void __do_nothing(void*) {}
6083
6084void __throw_runtime_error(const char* msg)
6085{
Howard Hinnant72f73582010-08-11 17:04:31 +00006086#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006087 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006088#else
6089 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006090 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006091#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006092}
6093
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006094template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6095template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006096
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006097template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6098template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006099
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006100template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6101template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006102
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006103template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6104template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006105
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006106template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6107template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006108
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006109template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6110template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006111
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006112template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6113template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006114
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006115template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6116template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006117
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006118template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6119template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006120
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006121template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6122template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6123template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6124template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006126template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6127template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6128template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6129template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006130
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006131template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6132template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006133
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006134template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6135template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006136
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006137template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6138template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006139
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006140template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6141template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006142
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006143template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6144template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006145
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006146template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6147template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006148
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006149template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6150template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6151template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6152template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006153
Howard Hinnantc51e1022010-05-11 19:42:16 +00006154_LIBCPP_END_NAMESPACE_STD