blob: 18edad73f5b49535cc41ba25c7d4fb98e0db23a0 [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{
Howard Hinnant72f73582010-08-11 17:04:31 +0000471#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000472 if (!has_facet(id))
473 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000474#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000475 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000476}
477
478// locale
479
480const locale&
481locale::__imp::make_classic()
482{
483 // only one thread can get in here and it only gets in once
484 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000485 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000486 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000487 return *c;
488}
489
490const locale&
491locale::classic()
492{
493 static const locale& c = __imp::make_classic();
494 return c;
495}
496
497locale&
498locale::__imp::make_global()
499{
500 // only one thread can get in here and it only gets in once
501 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000502 auto *obj = ::new (&buf) locale(locale::classic());
503 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000504}
505
506locale&
507locale::__global()
508{
509 static locale& g = __imp::make_global();
510 return g;
511}
512
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000513locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000514 : __locale_(__global().__locale_)
515{
516 __locale_->__add_shared();
517}
518
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000519locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000520 : __locale_(l.__locale_)
521{
522 __locale_->__add_shared();
523}
524
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000525locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000526{
527 __locale_->__release_shared();
528}
529
530const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000531locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000532{
533 other.__locale_->__add_shared();
534 __locale_->__release_shared();
535 __locale_ = other.__locale_;
536 return *this;
537}
538
539locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000540#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000541 : __locale_(name ? new __imp(name)
542 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000543#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000544 : __locale_(new __imp(name))
545#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000546{
547 __locale_->__add_shared();
548}
549
550locale::locale(const string& name)
551 : __locale_(new __imp(name))
552{
553 __locale_->__add_shared();
554}
555
556locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000557#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000558 : __locale_(name ? new __imp(*other.__locale_, name, c)
559 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000560#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000561 : __locale_(new __imp(*other.__locale_, name, c))
562#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000563{
564 __locale_->__add_shared();
565}
566
567locale::locale(const locale& other, const string& name, category c)
568 : __locale_(new __imp(*other.__locale_, name, c))
569{
570 __locale_->__add_shared();
571}
572
573locale::locale(const locale& other, const locale& one, category c)
574 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
575{
576 __locale_->__add_shared();
577}
578
579string
580locale::name() const
581{
582 return __locale_->name();
583}
584
585void
586locale::__install_ctor(const locale& other, facet* f, long id)
587{
588 if (f)
589 __locale_ = new __imp(*other.__locale_, f, id);
590 else
591 __locale_ = other.__locale_;
592 __locale_->__add_shared();
593}
594
595locale
596locale::global(const locale& loc)
597{
598 locale& g = __global();
599 locale r = g;
600 g = loc;
601 if (g.name() != "*")
602 setlocale(LC_ALL, g.name().c_str());
603 return r;
604}
605
606bool
607locale::has_facet(id& x) const
608{
609 return __locale_->has_facet(x.__get());
610}
611
612const locale::facet*
613locale::use_facet(id& x) const
614{
615 return __locale_->use_facet(x.__get());
616}
617
618bool
619locale::operator==(const locale& y) const
620{
621 return (__locale_ == y.__locale_)
622 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
623}
624
625// locale::facet
626
627locale::facet::~facet()
628{
629}
630
631void
Howard Hinnant719bda32011-05-28 14:41:13 +0000632locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000633{
634 delete this;
635}
636
637// locale::id
638
639int32_t locale::id::__next_id = 0;
640
641namespace
642{
643
644class __fake_bind
645{
646 locale::id* id_;
647 void (locale::id::* pmf_)();
648public:
649 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
650 : id_(id), pmf_(pmf) {}
651
652 void operator()() const
653 {
654 (id_->*pmf_)();
655 }
656};
657
658}
659
660long
661locale::id::__get()
662{
663 call_once(__flag_, __fake_bind(&locale::id::__init, this));
664 return __id_ - 1;
665}
666
667void
668locale::id::__init()
669{
Weiming Zhaob613db72017-09-19 23:18:03 +0000670 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000671}
672
673// template <> class collate_byname<char>
674
675collate_byname<char>::collate_byname(const char* n, size_t refs)
676 : collate<char>(refs),
677 __l(newlocale(LC_ALL_MASK, n, 0))
678{
679 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000680 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000681 " failed to construct for " + string(n));
682}
683
684collate_byname<char>::collate_byname(const string& name, size_t refs)
685 : collate<char>(refs),
686 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
687{
688 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000689 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000690 " failed to construct for " + name);
691}
692
693collate_byname<char>::~collate_byname()
694{
695 freelocale(__l);
696}
697
698int
699collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
700 const char_type* __lo2, const char_type* __hi2) const
701{
702 string_type lhs(__lo1, __hi1);
703 string_type rhs(__lo2, __hi2);
704 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
705 if (r < 0)
706 return -1;
707 if (r > 0)
708 return 1;
709 return r;
710}
711
712collate_byname<char>::string_type
713collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
714{
715 const string_type in(lo, hi);
716 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
717 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
718 return out;
719}
720
721// template <> class collate_byname<wchar_t>
722
723collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
724 : collate<wchar_t>(refs),
725 __l(newlocale(LC_ALL_MASK, n, 0))
726{
727 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000728 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000729 " failed to construct for " + string(n));
730}
731
732collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
733 : collate<wchar_t>(refs),
734 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
735{
736 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000737 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000738 " failed to construct for " + name);
739}
740
741collate_byname<wchar_t>::~collate_byname()
742{
743 freelocale(__l);
744}
745
746int
747collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
748 const char_type* __lo2, const char_type* __hi2) const
749{
750 string_type lhs(__lo1, __hi1);
751 string_type rhs(__lo2, __hi2);
752 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
753 if (r < 0)
754 return -1;
755 if (r > 0)
756 return 1;
757 return r;
758}
759
760collate_byname<wchar_t>::string_type
761collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
762{
763 const string_type in(lo, hi);
764 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
765 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
766 return out;
767}
768
769// template <> class ctype<wchar_t>;
770
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000771const ctype_base::mask ctype_base::space;
772const ctype_base::mask ctype_base::print;
773const ctype_base::mask ctype_base::cntrl;
774const ctype_base::mask ctype_base::upper;
775const ctype_base::mask ctype_base::lower;
776const ctype_base::mask ctype_base::alpha;
777const ctype_base::mask ctype_base::digit;
778const ctype_base::mask ctype_base::punct;
779const ctype_base::mask ctype_base::xdigit;
780const ctype_base::mask ctype_base::blank;
781const ctype_base::mask ctype_base::alnum;
782const ctype_base::mask ctype_base::graph;
783
Howard Hinnantc51e1022010-05-11 19:42:16 +0000784locale::id ctype<wchar_t>::id;
785
786ctype<wchar_t>::~ctype()
787{
788}
789
790bool
791ctype<wchar_t>::do_is(mask m, char_type c) const
792{
Marshall Clowd920eea2013-10-21 15:07:28 +0000793 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000794}
795
796const wchar_t*
797ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
798{
799 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000800 *vec = static_cast<mask>(isascii(*low) ?
801 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000802 return low;
803}
804
805const wchar_t*
806ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
807{
808 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000809 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000810 break;
811 return low;
812}
813
814const wchar_t*
815ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
816{
817 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000818 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000819 break;
820 return low;
821}
822
823wchar_t
824ctype<wchar_t>::do_toupper(char_type c) const
825{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000826#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
827 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000828#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000829 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000830 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000831#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000832 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000833#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000834}
835
836const wchar_t*
837ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
838{
839 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000840#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
841 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000842#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000843 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000844 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
845 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000846#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000847 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000848#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000849 return low;
850}
851
852wchar_t
853ctype<wchar_t>::do_tolower(char_type c) const
854{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000855#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
856 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000857#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000858 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000859 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000860#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000861 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000862#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000863}
864
865const wchar_t*
866ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
867{
868 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000869#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
870 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000871#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000872 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000873 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
874 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000875#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000876 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000877#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000878 return low;
879}
880
881wchar_t
882ctype<wchar_t>::do_widen(char c) const
883{
884 return c;
885}
886
887const char*
888ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
889{
890 for (; low != high; ++low, ++dest)
891 *dest = *low;
892 return low;
893}
894
895char
896ctype<wchar_t>::do_narrow(char_type c, char dfault) const
897{
898 if (isascii(c))
899 return static_cast<char>(c);
900 return dfault;
901}
902
903const wchar_t*
904ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
905{
906 for (; low != high; ++low, ++dest)
907 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000908 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000909 else
910 *dest = dfault;
911 return low;
912}
913
914// template <> class ctype<char>;
915
916locale::id ctype<char>::id;
917
918ctype<char>::ctype(const mask* tab, bool del, size_t refs)
919 : locale::facet(refs),
920 __tab_(tab),
921 __del_(del)
922{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000923 if (__tab_ == 0)
924 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000925}
926
927ctype<char>::~ctype()
928{
929 if (__tab_ && __del_)
930 delete [] __tab_;
931}
932
933char
934ctype<char>::do_toupper(char_type c) const
935{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000936#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000937 return isascii(c) ?
938 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000939#elif defined(__NetBSD__)
940 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000941#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000942 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000943 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000944#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000945 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000946#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000947}
948
949const char*
950ctype<char>::do_toupper(char_type* low, const char_type* high) const
951{
952 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000953#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000954 *low = isascii(*low) ?
955 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000956#elif defined(__NetBSD__)
957 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000958#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000959 *low = isascii(*low) ?
960 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000961#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000962 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000963#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000964 return low;
965}
966
967char
968ctype<char>::do_tolower(char_type c) const
969{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000970#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000971 return isascii(c) ?
972 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000973#elif defined(__NetBSD__)
974 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000975#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000976 return isascii(c) ?
977 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000978#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000979 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000980#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000981}
982
983const char*
984ctype<char>::do_tolower(char_type* low, const char_type* high) const
985{
986 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000987#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000988 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000989#elif defined(__NetBSD__)
990 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000991#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000992 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000993#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000994 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000995#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000996 return low;
997}
998
999char
1000ctype<char>::do_widen(char c) const
1001{
1002 return c;
1003}
1004
1005const char*
1006ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1007{
1008 for (; low != high; ++low, ++dest)
1009 *dest = *low;
1010 return low;
1011}
1012
1013char
1014ctype<char>::do_narrow(char_type c, char dfault) const
1015{
1016 if (isascii(c))
1017 return static_cast<char>(c);
1018 return dfault;
1019}
1020
1021const char*
1022ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1023{
1024 for (; low != high; ++low, ++dest)
1025 if (isascii(*low))
1026 *dest = *low;
1027 else
1028 *dest = dfault;
1029 return low;
1030}
1031
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001032#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001033extern "C" const unsigned short ** __ctype_b_loc();
1034extern "C" const int ** __ctype_tolower_loc();
1035extern "C" const int ** __ctype_toupper_loc();
1036#endif
1037
Marshall Clow8f870232015-03-04 16:50:02 +00001038#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001039const ctype<char>::mask*
1040ctype<char>::classic_table() _NOEXCEPT
1041{
1042 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1043 cntrl, cntrl,
1044 cntrl, cntrl,
1045 cntrl, cntrl,
1046 cntrl, cntrl,
1047 cntrl, cntrl | space | blank,
1048 cntrl | space, cntrl | space,
1049 cntrl | space, cntrl | space,
1050 cntrl, cntrl,
1051 cntrl, cntrl,
1052 cntrl, cntrl,
1053 cntrl, cntrl,
1054 cntrl, cntrl,
1055 cntrl, cntrl,
1056 cntrl, cntrl,
1057 cntrl, cntrl,
1058 cntrl, cntrl,
1059 space | blank | print, punct | print,
1060 punct | print, punct | print,
1061 punct | print, punct | print,
1062 punct | print, punct | print,
1063 punct | print, punct | print,
1064 punct | print, punct | print,
1065 punct | print, punct | print,
1066 punct | print, punct | print,
1067 digit | print | xdigit, digit | print | xdigit,
1068 digit | print | xdigit, digit | print | xdigit,
1069 digit | print | xdigit, digit | print | xdigit,
1070 digit | print | xdigit, digit | print | xdigit,
1071 digit | print | xdigit, digit | print | xdigit,
1072 punct | print, punct | print,
1073 punct | print, punct | print,
1074 punct | print, punct | print,
1075 punct | print, upper | xdigit | print | alpha,
1076 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1077 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1078 upper | xdigit | print | alpha, upper | print | alpha,
1079 upper | print | alpha, upper | print | alpha,
1080 upper | print | alpha, upper | print | alpha,
1081 upper | print | alpha, upper | print | alpha,
1082 upper | print | alpha, upper | print | alpha,
1083 upper | print | alpha, upper | print | alpha,
1084 upper | print | alpha, upper | print | alpha,
1085 upper | print | alpha, upper | print | alpha,
1086 upper | print | alpha, upper | print | alpha,
1087 upper | print | alpha, upper | print | alpha,
1088 upper | print | alpha, punct | print,
1089 punct | print, punct | print,
1090 punct | print, punct | print,
1091 punct | print, lower | xdigit | print | alpha,
1092 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1093 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1094 lower | xdigit | print | alpha, lower | print | alpha,
1095 lower | print | alpha, lower | print | alpha,
1096 lower | print | alpha, lower | print | alpha,
1097 lower | print | alpha, lower | print | alpha,
1098 lower | print | alpha, lower | print | alpha,
1099 lower | print | alpha, lower | print | alpha,
1100 lower | print | alpha, lower | print | alpha,
1101 lower | print | alpha, lower | print | alpha,
1102 lower | print | alpha, lower | print | alpha,
1103 lower | print | alpha, lower | print | alpha,
1104 lower | print | alpha, punct | print,
1105 punct | print, punct | print,
1106 punct | print, cntrl,
1107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1115 };
1116 return builtin_table;
1117}
1118#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001119const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001120ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001121{
David Chisnall1d581062011-09-21 08:39:44 +00001122#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001123 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001124#elif defined(__NetBSD__)
1125 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001126#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001127 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001128#elif __sun__
1129 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001130#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001131 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001132#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001133 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001134#elif defined(_NEWLIB_VERSION)
1135 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1136 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001137#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001138 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001139#else
David Chisnall8074c342012-02-29 13:05:08 +00001140 // Platform not supported: abort so the person doing the port knows what to
1141 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001142# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001143 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001144 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001145 return NULL;
1146#endif
1147}
Marshall Clowb3f62842015-03-04 16:10:14 +00001148#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001149
Howard Hinnantd7a78632011-09-29 13:33:15 +00001150#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001151const int*
1152ctype<char>::__classic_lower_table() _NOEXCEPT
1153{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001154 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001155}
1156
1157const int*
1158ctype<char>::__classic_upper_table() _NOEXCEPT
1159{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001160 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001161}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001162#elif __NetBSD__
1163const short*
1164ctype<char>::__classic_lower_table() _NOEXCEPT
1165{
1166 return _C_tolower_tab_ + 1;
1167}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001168
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001169const short*
1170ctype<char>::__classic_upper_table() _NOEXCEPT
1171{
1172 return _C_toupper_tab_ + 1;
1173}
1174
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001175#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001176const int*
1177ctype<char>::__classic_lower_table() _NOEXCEPT
1178{
1179 return *__ctype_tolower_loc();
1180}
1181
1182const int*
1183ctype<char>::__classic_upper_table() _NOEXCEPT
1184{
1185 return *__ctype_toupper_loc();
1186}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001187#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001188
Howard Hinnantc51e1022010-05-11 19:42:16 +00001189// template <> class ctype_byname<char>
1190
1191ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1192 : ctype<char>(0, false, refs),
1193 __l(newlocale(LC_ALL_MASK, name, 0))
1194{
1195 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001196 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001197 " failed to construct for " + string(name));
1198}
1199
1200ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1201 : ctype<char>(0, false, refs),
1202 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1203{
1204 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001205 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001206 " failed to construct for " + name);
1207}
1208
1209ctype_byname<char>::~ctype_byname()
1210{
1211 freelocale(__l);
1212}
1213
1214char
1215ctype_byname<char>::do_toupper(char_type c) const
1216{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001217 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001218}
1219
1220const char*
1221ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1222{
1223 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001224 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001225 return low;
1226}
1227
1228char
1229ctype_byname<char>::do_tolower(char_type c) const
1230{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001231 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001232}
1233
1234const char*
1235ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1236{
1237 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001238 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001239 return low;
1240}
1241
1242// template <> class ctype_byname<wchar_t>
1243
1244ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1245 : ctype<wchar_t>(refs),
1246 __l(newlocale(LC_ALL_MASK, name, 0))
1247{
1248 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001249 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001250 " failed to construct for " + string(name));
1251}
1252
1253ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1254 : ctype<wchar_t>(refs),
1255 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1256{
1257 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001258 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001259 " failed to construct for " + name);
1260}
1261
1262ctype_byname<wchar_t>::~ctype_byname()
1263{
1264 freelocale(__l);
1265}
1266
1267bool
1268ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1269{
Alexis Huntc2017f12011-07-09 03:40:04 +00001270#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001271 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001272#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001273 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001274 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001275 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1276 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1277 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1278 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1279 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1280 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1281 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1282 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1283 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1284 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001285 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001286#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001287}
1288
1289const wchar_t*
1290ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1291{
1292 for (; low != high; ++low, ++vec)
1293 {
1294 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001295 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 else
1297 {
1298 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001299 wint_t ch = static_cast<wint_t>(*low);
1300 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001301 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001302#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001303 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001304 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001305#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001306 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001307 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001308 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001309 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001310 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001311 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001312#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001313 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001314 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001315#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001316 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001317 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001318 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001319 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001320#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001321 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001322 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001323#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001324#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001325 if (iswblank_l(ch, __l))
1326 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001327#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001328 }
1329 }
1330 return low;
1331}
1332
1333const wchar_t*
1334ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1335{
1336 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001337 {
1338#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001339 if (iswctype_l(*low, m, __l))
1340 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001341#else
Marshall Clowada0f732013-02-07 14:22:51 +00001342 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001343 if ((m & space) == space && iswspace_l(ch, __l)) break;
1344 if ((m & print) == print && iswprint_l(ch, __l)) break;
1345 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1346 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1347 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1348 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1349 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1350 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1351 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1352 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001353#endif
1354 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001355 return low;
1356}
1357
1358const wchar_t*
1359ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1360{
1361 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001362 {
1363#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001364 if (!iswctype_l(*low, m, __l))
1365 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001366#else
Marshall Clowada0f732013-02-07 14:22:51 +00001367 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001368 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1369 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1370 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1371 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1372 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1373 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1374 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1375 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1376 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1377 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001378 break;
1379#endif
1380 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001381 return low;
1382}
1383
1384wchar_t
1385ctype_byname<wchar_t>::do_toupper(char_type c) const
1386{
1387 return towupper_l(c, __l);
1388}
1389
1390const wchar_t*
1391ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1392{
1393 for (; low != high; ++low)
1394 *low = towupper_l(*low, __l);
1395 return low;
1396}
1397
1398wchar_t
1399ctype_byname<wchar_t>::do_tolower(char_type c) const
1400{
1401 return towlower_l(c, __l);
1402}
1403
1404const wchar_t*
1405ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1406{
1407 for (; low != high; ++low)
1408 *low = towlower_l(*low, __l);
1409 return low;
1410}
1411
1412wchar_t
1413ctype_byname<wchar_t>::do_widen(char c) const
1414{
Ben Craig3756b922016-03-09 15:39:39 +00001415 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001416}
1417
1418const char*
1419ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1420{
1421 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001422 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001423 return low;
1424}
1425
1426char
1427ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1428{
Ben Craig3756b922016-03-09 15:39:39 +00001429 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001430 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001431}
1432
1433const wchar_t*
1434ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1435{
1436 for (; low != high; ++low, ++dest)
1437 {
Ben Craig3756b922016-03-09 15:39:39 +00001438 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001439 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001440 }
1441 return low;
1442}
1443
1444// template <> class codecvt<char, char, mbstate_t>
1445
Howard Hinnantffb308e2010-08-22 00:03:27 +00001446locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001447
1448codecvt<char, char, mbstate_t>::~codecvt()
1449{
1450}
1451
1452codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001453codecvt<char, char, mbstate_t>::do_out(state_type&,
1454 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001455 extern_type* to, extern_type*, extern_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_in(state_type&,
1464 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001465 intern_type* to, intern_type*, intern_type*& to_nxt) const
1466{
1467 frm_nxt = frm;
1468 to_nxt = to;
1469 return noconv;
1470}
1471
1472codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001473codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001474 extern_type* to, extern_type*, extern_type*& to_nxt) const
1475{
1476 to_nxt = to;
1477 return noconv;
1478}
1479
1480int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001481codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001482{
1483 return 1;
1484}
1485
1486bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001487codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001488{
1489 return true;
1490}
1491
1492int
1493codecvt<char, char, mbstate_t>::do_length(state_type&,
1494 const extern_type* frm, const extern_type* end, size_t mx) const
1495{
Howard Hinnant28b24882011-12-01 20:21:04 +00001496 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001497}
1498
1499int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001500codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001501{
1502 return 1;
1503}
1504
1505// template <> class codecvt<wchar_t, char, mbstate_t>
1506
Howard Hinnantffb308e2010-08-22 00:03:27 +00001507locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001508
1509codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1510 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001511 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001512{
1513}
1514
1515codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1516 : locale::facet(refs),
1517 __l(newlocale(LC_ALL_MASK, nm, 0))
1518{
1519 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001520 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001521 " failed to construct for " + string(nm));
1522}
1523
1524codecvt<wchar_t, char, mbstate_t>::~codecvt()
1525{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001526 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001527 freelocale(__l);
1528}
1529
1530codecvt<wchar_t, char, mbstate_t>::result
1531codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001532 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001533 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1534{
1535 // look for first internal null in frm
1536 const intern_type* fend = frm;
1537 for (; fend != frm_end; ++fend)
1538 if (*fend == 0)
1539 break;
1540 // loop over all null-terminated sequences in frm
1541 to_nxt = to;
1542 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1543 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001544 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001545 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001546 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1547 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001548 if (n == size_t(-1))
1549 {
1550 // need to recover to_nxt
1551 for (to_nxt = to; frm != frm_nxt; ++frm)
1552 {
Ben Craig3756b922016-03-09 15:39:39 +00001553 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001554 if (n == size_t(-1))
1555 break;
1556 to_nxt += n;
1557 }
1558 frm_nxt = frm;
1559 return error;
1560 }
1561 if (n == 0)
1562 return partial;
1563 to_nxt += n;
1564 if (to_nxt == to_end)
1565 break;
1566 if (fend != frm_end) // set up next null terminated sequence
1567 {
1568 // Try to write the terminating null
1569 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001570 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001571 if (n == size_t(-1)) // on error
1572 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001573 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001574 return partial;
1575 for (extern_type* p = tmp; n; --n) // write it
1576 *to_nxt++ = *p++;
1577 ++frm_nxt;
1578 // look for next null in frm
1579 for (fend = frm_nxt; fend != frm_end; ++fend)
1580 if (*fend == 0)
1581 break;
1582 }
1583 }
1584 return frm_nxt == frm_end ? ok : partial;
1585}
1586
1587codecvt<wchar_t, char, mbstate_t>::result
1588codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001589 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001590 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1591{
1592 // look for first internal null in frm
1593 const extern_type* fend = frm;
1594 for (; fend != frm_end; ++fend)
1595 if (*fend == 0)
1596 break;
1597 // loop over all null-terminated sequences in frm
1598 to_nxt = to;
1599 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1600 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001601 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001602 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001603 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1604 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001605 if (n == size_t(-1))
1606 {
1607 // need to recover to_nxt
1608 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1609 {
Ben Craig3756b922016-03-09 15:39:39 +00001610 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1611 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001612 switch (n)
1613 {
1614 case 0:
1615 ++frm;
1616 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001617 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001618 frm_nxt = frm;
1619 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001620 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001621 frm_nxt = frm;
1622 return partial;
1623 default:
1624 frm += n;
1625 break;
1626 }
1627 }
1628 frm_nxt = frm;
1629 return frm_nxt == frm_end ? ok : partial;
1630 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001631 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001632 return error;
1633 to_nxt += n;
1634 if (to_nxt == to_end)
1635 break;
1636 if (fend != frm_end) // set up next null terminated sequence
1637 {
1638 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001639 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001640 if (n != 0) // on error
1641 return error;
1642 ++to_nxt;
1643 ++frm_nxt;
1644 // look for next null in frm
1645 for (fend = frm_nxt; fend != frm_end; ++fend)
1646 if (*fend == 0)
1647 break;
1648 }
1649 }
1650 return frm_nxt == frm_end ? ok : partial;
1651}
1652
1653codecvt<wchar_t, char, mbstate_t>::result
1654codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1655 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1656{
1657 to_nxt = to;
1658 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001659 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001660 if (n == size_t(-1) || n == 0) // on error
1661 return error;
1662 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001663 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001664 return partial;
1665 for (extern_type* p = tmp; n; --n) // write it
1666 *to_nxt++ = *p++;
1667 return ok;
1668}
1669
1670int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001671codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001672{
Ben Craig3756b922016-03-09 15:39:39 +00001673 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001674 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001675
1676 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001677 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001678 return 1; // which take more than 1 char to form a wchar_t
1679 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001680}
1681
1682bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001683codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001684{
1685 return false;
1686}
1687
1688int
1689codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1690 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1691{
1692 int nbytes = 0;
1693 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1694 {
Ben Craig3756b922016-03-09 15:39:39 +00001695 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001696 switch (n)
1697 {
1698 case 0:
1699 ++nbytes;
1700 ++frm;
1701 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001702 case size_t(-1):
1703 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001704 return nbytes;
1705 default:
1706 nbytes += n;
1707 frm += n;
1708 break;
1709 }
1710 }
1711 return nbytes;
1712}
1713
1714int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001715codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001716{
Ben Craig3756b922016-03-09 15:39:39 +00001717 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001718}
1719
1720// Valid UTF ranges
1721// UTF-32 UTF-16 UTF-8 # of code points
1722// first second first second third fourth
1723// 000000 - 00007F 0000 - 007F 00 - 7F 127
1724// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1725// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1726// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1727// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1728// 00D800 - 00DFFF invalid
1729// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1730// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1731// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1732// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1733
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001734static
1735codecvt_base::result
1736utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1737 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1738 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1739{
1740 frm_nxt = frm;
1741 to_nxt = to;
1742 if (mode & generate_header)
1743 {
1744 if (to_end-to_nxt < 3)
1745 return codecvt_base::partial;
1746 *to_nxt++ = static_cast<uint8_t>(0xEF);
1747 *to_nxt++ = static_cast<uint8_t>(0xBB);
1748 *to_nxt++ = static_cast<uint8_t>(0xBF);
1749 }
1750 for (; frm_nxt < frm_end; ++frm_nxt)
1751 {
1752 uint16_t wc1 = *frm_nxt;
1753 if (wc1 > Maxcode)
1754 return codecvt_base::error;
1755 if (wc1 < 0x0080)
1756 {
1757 if (to_end-to_nxt < 1)
1758 return codecvt_base::partial;
1759 *to_nxt++ = static_cast<uint8_t>(wc1);
1760 }
1761 else if (wc1 < 0x0800)
1762 {
1763 if (to_end-to_nxt < 2)
1764 return codecvt_base::partial;
1765 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1766 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1767 }
1768 else if (wc1 < 0xD800)
1769 {
1770 if (to_end-to_nxt < 3)
1771 return codecvt_base::partial;
1772 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1773 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1774 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1775 }
1776 else if (wc1 < 0xDC00)
1777 {
1778 if (frm_end-frm_nxt < 2)
1779 return codecvt_base::partial;
1780 uint16_t wc2 = frm_nxt[1];
1781 if ((wc2 & 0xFC00) != 0xDC00)
1782 return codecvt_base::error;
1783 if (to_end-to_nxt < 4)
1784 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001785 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1786 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001787 return codecvt_base::error;
1788 ++frm_nxt;
1789 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1790 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1791 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1792 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1793 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1794 }
1795 else if (wc1 < 0xE000)
1796 {
1797 return codecvt_base::error;
1798 }
1799 else
1800 {
1801 if (to_end-to_nxt < 3)
1802 return codecvt_base::partial;
1803 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1804 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1805 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1806 }
1807 }
1808 return codecvt_base::ok;
1809}
1810
1811static
1812codecvt_base::result
1813utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1814 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1815 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1816{
1817 frm_nxt = frm;
1818 to_nxt = to;
1819 if (mode & generate_header)
1820 {
1821 if (to_end-to_nxt < 3)
1822 return codecvt_base::partial;
1823 *to_nxt++ = static_cast<uint8_t>(0xEF);
1824 *to_nxt++ = static_cast<uint8_t>(0xBB);
1825 *to_nxt++ = static_cast<uint8_t>(0xBF);
1826 }
1827 for (; frm_nxt < frm_end; ++frm_nxt)
1828 {
1829 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1830 if (wc1 > Maxcode)
1831 return codecvt_base::error;
1832 if (wc1 < 0x0080)
1833 {
1834 if (to_end-to_nxt < 1)
1835 return codecvt_base::partial;
1836 *to_nxt++ = static_cast<uint8_t>(wc1);
1837 }
1838 else if (wc1 < 0x0800)
1839 {
1840 if (to_end-to_nxt < 2)
1841 return codecvt_base::partial;
1842 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1843 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1844 }
1845 else if (wc1 < 0xD800)
1846 {
1847 if (to_end-to_nxt < 3)
1848 return codecvt_base::partial;
1849 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1852 }
1853 else if (wc1 < 0xDC00)
1854 {
1855 if (frm_end-frm_nxt < 2)
1856 return codecvt_base::partial;
1857 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1858 if ((wc2 & 0xFC00) != 0xDC00)
1859 return codecvt_base::error;
1860 if (to_end-to_nxt < 4)
1861 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001862 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1863 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001864 return codecvt_base::error;
1865 ++frm_nxt;
1866 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1867 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1868 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1869 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1870 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1871 }
1872 else if (wc1 < 0xE000)
1873 {
1874 return codecvt_base::error;
1875 }
1876 else
1877 {
1878 if (to_end-to_nxt < 3)
1879 return codecvt_base::partial;
1880 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1881 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1882 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1883 }
1884 }
1885 return codecvt_base::ok;
1886}
1887
1888static
1889codecvt_base::result
1890utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1891 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1892 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1893{
1894 frm_nxt = frm;
1895 to_nxt = to;
1896 if (mode & consume_header)
1897 {
1898 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1899 frm_nxt[2] == 0xBF)
1900 frm_nxt += 3;
1901 }
1902 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1903 {
1904 uint8_t c1 = *frm_nxt;
1905 if (c1 > Maxcode)
1906 return codecvt_base::error;
1907 if (c1 < 0x80)
1908 {
1909 *to_nxt = static_cast<uint16_t>(c1);
1910 ++frm_nxt;
1911 }
1912 else if (c1 < 0xC2)
1913 {
1914 return codecvt_base::error;
1915 }
1916 else if (c1 < 0xE0)
1917 {
1918 if (frm_end-frm_nxt < 2)
1919 return codecvt_base::partial;
1920 uint8_t c2 = frm_nxt[1];
1921 if ((c2 & 0xC0) != 0x80)
1922 return codecvt_base::error;
1923 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1924 if (t > Maxcode)
1925 return codecvt_base::error;
1926 *to_nxt = t;
1927 frm_nxt += 2;
1928 }
1929 else if (c1 < 0xF0)
1930 {
1931 if (frm_end-frm_nxt < 3)
1932 return codecvt_base::partial;
1933 uint8_t c2 = frm_nxt[1];
1934 uint8_t c3 = frm_nxt[2];
1935 switch (c1)
1936 {
1937 case 0xE0:
1938 if ((c2 & 0xE0) != 0xA0)
1939 return codecvt_base::error;
1940 break;
1941 case 0xED:
1942 if ((c2 & 0xE0) != 0x80)
1943 return codecvt_base::error;
1944 break;
1945 default:
1946 if ((c2 & 0xC0) != 0x80)
1947 return codecvt_base::error;
1948 break;
1949 }
1950 if ((c3 & 0xC0) != 0x80)
1951 return codecvt_base::error;
1952 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1953 | ((c2 & 0x3F) << 6)
1954 | (c3 & 0x3F));
1955 if (t > Maxcode)
1956 return codecvt_base::error;
1957 *to_nxt = t;
1958 frm_nxt += 3;
1959 }
1960 else if (c1 < 0xF5)
1961 {
1962 if (frm_end-frm_nxt < 4)
1963 return codecvt_base::partial;
1964 uint8_t c2 = frm_nxt[1];
1965 uint8_t c3 = frm_nxt[2];
1966 uint8_t c4 = frm_nxt[3];
1967 switch (c1)
1968 {
1969 case 0xF0:
1970 if (!(0x90 <= c2 && c2 <= 0xBF))
1971 return codecvt_base::error;
1972 break;
1973 case 0xF4:
1974 if ((c2 & 0xF0) != 0x80)
1975 return codecvt_base::error;
1976 break;
1977 default:
1978 if ((c2 & 0xC0) != 0x80)
1979 return codecvt_base::error;
1980 break;
1981 }
1982 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1983 return codecvt_base::error;
1984 if (to_end-to_nxt < 2)
1985 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001986 if ((((c1 & 7UL) << 18) +
1987 ((c2 & 0x3FUL) << 12) +
1988 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001989 return codecvt_base::error;
1990 *to_nxt = static_cast<uint16_t>(
1991 0xD800
1992 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1993 | ((c2 & 0x0F) << 2)
1994 | ((c3 & 0x30) >> 4));
1995 *++to_nxt = static_cast<uint16_t>(
1996 0xDC00
1997 | ((c3 & 0x0F) << 6)
1998 | (c4 & 0x3F));
1999 frm_nxt += 4;
2000 }
2001 else
2002 {
2003 return codecvt_base::error;
2004 }
2005 }
2006 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2007}
2008
2009static
2010codecvt_base::result
2011utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2012 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2013 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2014{
2015 frm_nxt = frm;
2016 to_nxt = to;
2017 if (mode & consume_header)
2018 {
2019 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2020 frm_nxt[2] == 0xBF)
2021 frm_nxt += 3;
2022 }
2023 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2024 {
2025 uint8_t c1 = *frm_nxt;
2026 if (c1 > Maxcode)
2027 return codecvt_base::error;
2028 if (c1 < 0x80)
2029 {
2030 *to_nxt = static_cast<uint32_t>(c1);
2031 ++frm_nxt;
2032 }
2033 else if (c1 < 0xC2)
2034 {
2035 return codecvt_base::error;
2036 }
2037 else if (c1 < 0xE0)
2038 {
2039 if (frm_end-frm_nxt < 2)
2040 return codecvt_base::partial;
2041 uint8_t c2 = frm_nxt[1];
2042 if ((c2 & 0xC0) != 0x80)
2043 return codecvt_base::error;
2044 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2045 if (t > Maxcode)
2046 return codecvt_base::error;
2047 *to_nxt = static_cast<uint32_t>(t);
2048 frm_nxt += 2;
2049 }
2050 else if (c1 < 0xF0)
2051 {
2052 if (frm_end-frm_nxt < 3)
2053 return codecvt_base::partial;
2054 uint8_t c2 = frm_nxt[1];
2055 uint8_t c3 = frm_nxt[2];
2056 switch (c1)
2057 {
2058 case 0xE0:
2059 if ((c2 & 0xE0) != 0xA0)
2060 return codecvt_base::error;
2061 break;
2062 case 0xED:
2063 if ((c2 & 0xE0) != 0x80)
2064 return codecvt_base::error;
2065 break;
2066 default:
2067 if ((c2 & 0xC0) != 0x80)
2068 return codecvt_base::error;
2069 break;
2070 }
2071 if ((c3 & 0xC0) != 0x80)
2072 return codecvt_base::error;
2073 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2074 | ((c2 & 0x3F) << 6)
2075 | (c3 & 0x3F));
2076 if (t > Maxcode)
2077 return codecvt_base::error;
2078 *to_nxt = static_cast<uint32_t>(t);
2079 frm_nxt += 3;
2080 }
2081 else if (c1 < 0xF5)
2082 {
2083 if (frm_end-frm_nxt < 4)
2084 return codecvt_base::partial;
2085 uint8_t c2 = frm_nxt[1];
2086 uint8_t c3 = frm_nxt[2];
2087 uint8_t c4 = frm_nxt[3];
2088 switch (c1)
2089 {
2090 case 0xF0:
2091 if (!(0x90 <= c2 && c2 <= 0xBF))
2092 return codecvt_base::error;
2093 break;
2094 case 0xF4:
2095 if ((c2 & 0xF0) != 0x80)
2096 return codecvt_base::error;
2097 break;
2098 default:
2099 if ((c2 & 0xC0) != 0x80)
2100 return codecvt_base::error;
2101 break;
2102 }
2103 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2104 return codecvt_base::error;
2105 if (to_end-to_nxt < 2)
2106 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002107 if ((((c1 & 7UL) << 18) +
2108 ((c2 & 0x3FUL) << 12) +
2109 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002110 return codecvt_base::error;
2111 *to_nxt = static_cast<uint32_t>(
2112 0xD800
2113 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2114 | ((c2 & 0x0F) << 2)
2115 | ((c3 & 0x30) >> 4));
2116 *++to_nxt = static_cast<uint32_t>(
2117 0xDC00
2118 | ((c3 & 0x0F) << 6)
2119 | (c4 & 0x3F));
2120 frm_nxt += 4;
2121 }
2122 else
2123 {
2124 return codecvt_base::error;
2125 }
2126 }
2127 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2128}
2129
2130static
2131int
2132utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2133 size_t mx, unsigned long Maxcode = 0x10FFFF,
2134 codecvt_mode mode = codecvt_mode(0))
2135{
2136 const uint8_t* frm_nxt = frm;
2137 if (mode & consume_header)
2138 {
2139 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2140 frm_nxt[2] == 0xBF)
2141 frm_nxt += 3;
2142 }
2143 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2144 {
2145 uint8_t c1 = *frm_nxt;
2146 if (c1 > Maxcode)
2147 break;
2148 if (c1 < 0x80)
2149 {
2150 ++frm_nxt;
2151 }
2152 else if (c1 < 0xC2)
2153 {
2154 break;
2155 }
2156 else if (c1 < 0xE0)
2157 {
2158 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2159 break;
2160 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2161 if (t > Maxcode)
2162 break;
2163 frm_nxt += 2;
2164 }
2165 else if (c1 < 0xF0)
2166 {
2167 if (frm_end-frm_nxt < 3)
2168 break;
2169 uint8_t c2 = frm_nxt[1];
2170 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002171 switch (c1)
2172 {
2173 case 0xE0:
2174 if ((c2 & 0xE0) != 0xA0)
2175 return static_cast<int>(frm_nxt - frm);
2176 break;
2177 case 0xED:
2178 if ((c2 & 0xE0) != 0x80)
2179 return static_cast<int>(frm_nxt - frm);
2180 break;
2181 default:
2182 if ((c2 & 0xC0) != 0x80)
2183 return static_cast<int>(frm_nxt - frm);
2184 break;
2185 }
2186 if ((c3 & 0xC0) != 0x80)
2187 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002188 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002189 break;
2190 frm_nxt += 3;
2191 }
2192 else if (c1 < 0xF5)
2193 {
2194 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2195 break;
2196 uint8_t c2 = frm_nxt[1];
2197 uint8_t c3 = frm_nxt[2];
2198 uint8_t c4 = frm_nxt[3];
2199 switch (c1)
2200 {
2201 case 0xF0:
2202 if (!(0x90 <= c2 && c2 <= 0xBF))
2203 return static_cast<int>(frm_nxt - frm);
2204 break;
2205 case 0xF4:
2206 if ((c2 & 0xF0) != 0x80)
2207 return static_cast<int>(frm_nxt - frm);
2208 break;
2209 default:
2210 if ((c2 & 0xC0) != 0x80)
2211 return static_cast<int>(frm_nxt - frm);
2212 break;
2213 }
2214 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2215 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002216 if ((((c1 & 7UL) << 18) +
2217 ((c2 & 0x3FUL) << 12) +
2218 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002219 break;
2220 ++nchar16_t;
2221 frm_nxt += 4;
2222 }
2223 else
2224 {
2225 break;
2226 }
2227 }
2228 return static_cast<int>(frm_nxt - frm);
2229}
2230
2231static
2232codecvt_base::result
2233ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2234 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2235 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2236{
2237 frm_nxt = frm;
2238 to_nxt = to;
2239 if (mode & generate_header)
2240 {
2241 if (to_end-to_nxt < 3)
2242 return codecvt_base::partial;
2243 *to_nxt++ = static_cast<uint8_t>(0xEF);
2244 *to_nxt++ = static_cast<uint8_t>(0xBB);
2245 *to_nxt++ = static_cast<uint8_t>(0xBF);
2246 }
2247 for (; frm_nxt < frm_end; ++frm_nxt)
2248 {
2249 uint32_t wc = *frm_nxt;
2250 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2251 return codecvt_base::error;
2252 if (wc < 0x000080)
2253 {
2254 if (to_end-to_nxt < 1)
2255 return codecvt_base::partial;
2256 *to_nxt++ = static_cast<uint8_t>(wc);
2257 }
2258 else if (wc < 0x000800)
2259 {
2260 if (to_end-to_nxt < 2)
2261 return codecvt_base::partial;
2262 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2263 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2264 }
2265 else if (wc < 0x010000)
2266 {
2267 if (to_end-to_nxt < 3)
2268 return codecvt_base::partial;
2269 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2270 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2271 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2272 }
2273 else // if (wc < 0x110000)
2274 {
2275 if (to_end-to_nxt < 4)
2276 return codecvt_base::partial;
2277 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2278 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2279 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2280 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2281 }
2282 }
2283 return codecvt_base::ok;
2284}
2285
2286static
2287codecvt_base::result
2288utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2289 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2290 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2291{
2292 frm_nxt = frm;
2293 to_nxt = to;
2294 if (mode & consume_header)
2295 {
2296 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2297 frm_nxt[2] == 0xBF)
2298 frm_nxt += 3;
2299 }
2300 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2301 {
2302 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2303 if (c1 < 0x80)
2304 {
2305 if (c1 > Maxcode)
2306 return codecvt_base::error;
2307 *to_nxt = static_cast<uint32_t>(c1);
2308 ++frm_nxt;
2309 }
2310 else if (c1 < 0xC2)
2311 {
2312 return codecvt_base::error;
2313 }
2314 else if (c1 < 0xE0)
2315 {
2316 if (frm_end-frm_nxt < 2)
2317 return codecvt_base::partial;
2318 uint8_t c2 = frm_nxt[1];
2319 if ((c2 & 0xC0) != 0x80)
2320 return codecvt_base::error;
2321 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2322 | (c2 & 0x3F));
2323 if (t > Maxcode)
2324 return codecvt_base::error;
2325 *to_nxt = t;
2326 frm_nxt += 2;
2327 }
2328 else if (c1 < 0xF0)
2329 {
2330 if (frm_end-frm_nxt < 3)
2331 return codecvt_base::partial;
2332 uint8_t c2 = frm_nxt[1];
2333 uint8_t c3 = frm_nxt[2];
2334 switch (c1)
2335 {
2336 case 0xE0:
2337 if ((c2 & 0xE0) != 0xA0)
2338 return codecvt_base::error;
2339 break;
2340 case 0xED:
2341 if ((c2 & 0xE0) != 0x80)
2342 return codecvt_base::error;
2343 break;
2344 default:
2345 if ((c2 & 0xC0) != 0x80)
2346 return codecvt_base::error;
2347 break;
2348 }
2349 if ((c3 & 0xC0) != 0x80)
2350 return codecvt_base::error;
2351 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2352 | ((c2 & 0x3F) << 6)
2353 | (c3 & 0x3F));
2354 if (t > Maxcode)
2355 return codecvt_base::error;
2356 *to_nxt = t;
2357 frm_nxt += 3;
2358 }
2359 else if (c1 < 0xF5)
2360 {
2361 if (frm_end-frm_nxt < 4)
2362 return codecvt_base::partial;
2363 uint8_t c2 = frm_nxt[1];
2364 uint8_t c3 = frm_nxt[2];
2365 uint8_t c4 = frm_nxt[3];
2366 switch (c1)
2367 {
2368 case 0xF0:
2369 if (!(0x90 <= c2 && c2 <= 0xBF))
2370 return codecvt_base::error;
2371 break;
2372 case 0xF4:
2373 if ((c2 & 0xF0) != 0x80)
2374 return codecvt_base::error;
2375 break;
2376 default:
2377 if ((c2 & 0xC0) != 0x80)
2378 return codecvt_base::error;
2379 break;
2380 }
2381 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2382 return codecvt_base::error;
2383 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2384 | ((c2 & 0x3F) << 12)
2385 | ((c3 & 0x3F) << 6)
2386 | (c4 & 0x3F));
2387 if (t > Maxcode)
2388 return codecvt_base::error;
2389 *to_nxt = t;
2390 frm_nxt += 4;
2391 }
2392 else
2393 {
2394 return codecvt_base::error;
2395 }
2396 }
2397 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2398}
2399
2400static
2401int
2402utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2403 size_t mx, unsigned long Maxcode = 0x10FFFF,
2404 codecvt_mode mode = codecvt_mode(0))
2405{
2406 const uint8_t* frm_nxt = frm;
2407 if (mode & consume_header)
2408 {
2409 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2410 frm_nxt[2] == 0xBF)
2411 frm_nxt += 3;
2412 }
2413 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2414 {
2415 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2416 if (c1 < 0x80)
2417 {
2418 if (c1 > Maxcode)
2419 break;
2420 ++frm_nxt;
2421 }
2422 else if (c1 < 0xC2)
2423 {
2424 break;
2425 }
2426 else if (c1 < 0xE0)
2427 {
2428 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2429 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002430 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002431 break;
2432 frm_nxt += 2;
2433 }
2434 else if (c1 < 0xF0)
2435 {
2436 if (frm_end-frm_nxt < 3)
2437 break;
2438 uint8_t c2 = frm_nxt[1];
2439 uint8_t c3 = frm_nxt[2];
2440 switch (c1)
2441 {
2442 case 0xE0:
2443 if ((c2 & 0xE0) != 0xA0)
2444 return static_cast<int>(frm_nxt - frm);
2445 break;
2446 case 0xED:
2447 if ((c2 & 0xE0) != 0x80)
2448 return static_cast<int>(frm_nxt - frm);
2449 break;
2450 default:
2451 if ((c2 & 0xC0) != 0x80)
2452 return static_cast<int>(frm_nxt - frm);
2453 break;
2454 }
2455 if ((c3 & 0xC0) != 0x80)
2456 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002457 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002458 break;
2459 frm_nxt += 3;
2460 }
2461 else if (c1 < 0xF5)
2462 {
2463 if (frm_end-frm_nxt < 4)
2464 break;
2465 uint8_t c2 = frm_nxt[1];
2466 uint8_t c3 = frm_nxt[2];
2467 uint8_t c4 = frm_nxt[3];
2468 switch (c1)
2469 {
2470 case 0xF0:
2471 if (!(0x90 <= c2 && c2 <= 0xBF))
2472 return static_cast<int>(frm_nxt - frm);
2473 break;
2474 case 0xF4:
2475 if ((c2 & 0xF0) != 0x80)
2476 return static_cast<int>(frm_nxt - frm);
2477 break;
2478 default:
2479 if ((c2 & 0xC0) != 0x80)
2480 return static_cast<int>(frm_nxt - frm);
2481 break;
2482 }
2483 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2484 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002485 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2486 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002487 break;
2488 frm_nxt += 4;
2489 }
2490 else
2491 {
2492 break;
2493 }
2494 }
2495 return static_cast<int>(frm_nxt - frm);
2496}
2497
2498static
2499codecvt_base::result
2500ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2501 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2502 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2503{
2504 frm_nxt = frm;
2505 to_nxt = to;
2506 if (mode & generate_header)
2507 {
2508 if (to_end-to_nxt < 3)
2509 return codecvt_base::partial;
2510 *to_nxt++ = static_cast<uint8_t>(0xEF);
2511 *to_nxt++ = static_cast<uint8_t>(0xBB);
2512 *to_nxt++ = static_cast<uint8_t>(0xBF);
2513 }
2514 for (; frm_nxt < frm_end; ++frm_nxt)
2515 {
2516 uint16_t wc = *frm_nxt;
2517 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2518 return codecvt_base::error;
2519 if (wc < 0x0080)
2520 {
2521 if (to_end-to_nxt < 1)
2522 return codecvt_base::partial;
2523 *to_nxt++ = static_cast<uint8_t>(wc);
2524 }
2525 else if (wc < 0x0800)
2526 {
2527 if (to_end-to_nxt < 2)
2528 return codecvt_base::partial;
2529 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2530 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2531 }
2532 else // if (wc <= 0xFFFF)
2533 {
2534 if (to_end-to_nxt < 3)
2535 return codecvt_base::partial;
2536 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2537 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2538 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2539 }
2540 }
2541 return codecvt_base::ok;
2542}
2543
2544static
2545codecvt_base::result
2546utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2547 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2548 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2549{
2550 frm_nxt = frm;
2551 to_nxt = to;
2552 if (mode & consume_header)
2553 {
2554 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2555 frm_nxt[2] == 0xBF)
2556 frm_nxt += 3;
2557 }
2558 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2559 {
2560 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2561 if (c1 < 0x80)
2562 {
2563 if (c1 > Maxcode)
2564 return codecvt_base::error;
2565 *to_nxt = static_cast<uint16_t>(c1);
2566 ++frm_nxt;
2567 }
2568 else if (c1 < 0xC2)
2569 {
2570 return codecvt_base::error;
2571 }
2572 else if (c1 < 0xE0)
2573 {
2574 if (frm_end-frm_nxt < 2)
2575 return codecvt_base::partial;
2576 uint8_t c2 = frm_nxt[1];
2577 if ((c2 & 0xC0) != 0x80)
2578 return codecvt_base::error;
2579 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2580 | (c2 & 0x3F));
2581 if (t > Maxcode)
2582 return codecvt_base::error;
2583 *to_nxt = t;
2584 frm_nxt += 2;
2585 }
2586 else if (c1 < 0xF0)
2587 {
2588 if (frm_end-frm_nxt < 3)
2589 return codecvt_base::partial;
2590 uint8_t c2 = frm_nxt[1];
2591 uint8_t c3 = frm_nxt[2];
2592 switch (c1)
2593 {
2594 case 0xE0:
2595 if ((c2 & 0xE0) != 0xA0)
2596 return codecvt_base::error;
2597 break;
2598 case 0xED:
2599 if ((c2 & 0xE0) != 0x80)
2600 return codecvt_base::error;
2601 break;
2602 default:
2603 if ((c2 & 0xC0) != 0x80)
2604 return codecvt_base::error;
2605 break;
2606 }
2607 if ((c3 & 0xC0) != 0x80)
2608 return codecvt_base::error;
2609 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2610 | ((c2 & 0x3F) << 6)
2611 | (c3 & 0x3F));
2612 if (t > Maxcode)
2613 return codecvt_base::error;
2614 *to_nxt = t;
2615 frm_nxt += 3;
2616 }
2617 else
2618 {
2619 return codecvt_base::error;
2620 }
2621 }
2622 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2623}
2624
2625static
2626int
2627utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2628 size_t mx, unsigned long Maxcode = 0x10FFFF,
2629 codecvt_mode mode = codecvt_mode(0))
2630{
2631 const uint8_t* frm_nxt = frm;
2632 if (mode & consume_header)
2633 {
2634 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2635 frm_nxt[2] == 0xBF)
2636 frm_nxt += 3;
2637 }
2638 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2639 {
2640 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2641 if (c1 < 0x80)
2642 {
2643 if (c1 > Maxcode)
2644 break;
2645 ++frm_nxt;
2646 }
2647 else if (c1 < 0xC2)
2648 {
2649 break;
2650 }
2651 else if (c1 < 0xE0)
2652 {
2653 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2654 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002655 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002656 break;
2657 frm_nxt += 2;
2658 }
2659 else if (c1 < 0xF0)
2660 {
2661 if (frm_end-frm_nxt < 3)
2662 break;
2663 uint8_t c2 = frm_nxt[1];
2664 uint8_t c3 = frm_nxt[2];
2665 switch (c1)
2666 {
2667 case 0xE0:
2668 if ((c2 & 0xE0) != 0xA0)
2669 return static_cast<int>(frm_nxt - frm);
2670 break;
2671 case 0xED:
2672 if ((c2 & 0xE0) != 0x80)
2673 return static_cast<int>(frm_nxt - frm);
2674 break;
2675 default:
2676 if ((c2 & 0xC0) != 0x80)
2677 return static_cast<int>(frm_nxt - frm);
2678 break;
2679 }
2680 if ((c3 & 0xC0) != 0x80)
2681 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002682 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002683 break;
2684 frm_nxt += 3;
2685 }
2686 else
2687 {
2688 break;
2689 }
2690 }
2691 return static_cast<int>(frm_nxt - frm);
2692}
2693
2694static
2695codecvt_base::result
2696ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2697 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2698 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2699{
2700 frm_nxt = frm;
2701 to_nxt = to;
2702 if (mode & generate_header)
2703 {
2704 if (to_end-to_nxt < 2)
2705 return codecvt_base::partial;
2706 *to_nxt++ = static_cast<uint8_t>(0xFE);
2707 *to_nxt++ = static_cast<uint8_t>(0xFF);
2708 }
2709 for (; frm_nxt < frm_end; ++frm_nxt)
2710 {
2711 uint32_t wc = *frm_nxt;
2712 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2713 return codecvt_base::error;
2714 if (wc < 0x010000)
2715 {
2716 if (to_end-to_nxt < 2)
2717 return codecvt_base::partial;
2718 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2719 *to_nxt++ = static_cast<uint8_t>(wc);
2720 }
2721 else
2722 {
2723 if (to_end-to_nxt < 4)
2724 return codecvt_base::partial;
2725 uint16_t t = static_cast<uint16_t>(
2726 0xD800
2727 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2728 | ((wc & 0x00FC00) >> 10));
2729 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2730 *to_nxt++ = static_cast<uint8_t>(t);
2731 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2732 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2733 *to_nxt++ = static_cast<uint8_t>(t);
2734 }
2735 }
2736 return codecvt_base::ok;
2737}
2738
2739static
2740codecvt_base::result
2741utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2742 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2743 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2744{
2745 frm_nxt = frm;
2746 to_nxt = to;
2747 if (mode & consume_header)
2748 {
2749 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2750 frm_nxt += 2;
2751 }
2752 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2753 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002754 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002755 if ((c1 & 0xFC00) == 0xDC00)
2756 return codecvt_base::error;
2757 if ((c1 & 0xFC00) != 0xD800)
2758 {
2759 if (c1 > Maxcode)
2760 return codecvt_base::error;
2761 *to_nxt = static_cast<uint32_t>(c1);
2762 frm_nxt += 2;
2763 }
2764 else
2765 {
2766 if (frm_end-frm_nxt < 4)
2767 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002768 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002769 if ((c2 & 0xFC00) != 0xDC00)
2770 return codecvt_base::error;
2771 uint32_t t = static_cast<uint32_t>(
2772 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2773 | ((c1 & 0x003F) << 10)
2774 | (c2 & 0x03FF));
2775 if (t > Maxcode)
2776 return codecvt_base::error;
2777 *to_nxt = t;
2778 frm_nxt += 4;
2779 }
2780 }
2781 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2782}
2783
2784static
2785int
2786utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2787 size_t mx, unsigned long Maxcode = 0x10FFFF,
2788 codecvt_mode mode = codecvt_mode(0))
2789{
2790 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002791 if (mode & consume_header)
2792 {
2793 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2794 frm_nxt += 2;
2795 }
2796 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2797 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002798 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002799 if ((c1 & 0xFC00) == 0xDC00)
2800 break;
2801 if ((c1 & 0xFC00) != 0xD800)
2802 {
2803 if (c1 > Maxcode)
2804 break;
2805 frm_nxt += 2;
2806 }
2807 else
2808 {
2809 if (frm_end-frm_nxt < 4)
2810 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002811 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002812 if ((c2 & 0xFC00) != 0xDC00)
2813 break;
2814 uint32_t t = static_cast<uint32_t>(
2815 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2816 | ((c1 & 0x003F) << 10)
2817 | (c2 & 0x03FF));
2818 if (t > Maxcode)
2819 break;
2820 frm_nxt += 4;
2821 }
2822 }
2823 return static_cast<int>(frm_nxt - frm);
2824}
2825
2826static
2827codecvt_base::result
2828ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2829 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2830 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2831{
2832 frm_nxt = frm;
2833 to_nxt = to;
2834 if (mode & generate_header)
2835 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002836 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002837 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002838 *to_nxt++ = static_cast<uint8_t>(0xFF);
2839 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002840 }
2841 for (; frm_nxt < frm_end; ++frm_nxt)
2842 {
2843 uint32_t wc = *frm_nxt;
2844 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2845 return codecvt_base::error;
2846 if (wc < 0x010000)
2847 {
2848 if (to_end-to_nxt < 2)
2849 return codecvt_base::partial;
2850 *to_nxt++ = static_cast<uint8_t>(wc);
2851 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2852 }
2853 else
2854 {
2855 if (to_end-to_nxt < 4)
2856 return codecvt_base::partial;
2857 uint16_t t = static_cast<uint16_t>(
2858 0xD800
2859 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2860 | ((wc & 0x00FC00) >> 10));
2861 *to_nxt++ = static_cast<uint8_t>(t);
2862 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2863 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2864 *to_nxt++ = static_cast<uint8_t>(t);
2865 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2866 }
2867 }
2868 return codecvt_base::ok;
2869}
2870
2871static
2872codecvt_base::result
2873utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2874 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2875 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2876{
2877 frm_nxt = frm;
2878 to_nxt = to;
2879 if (mode & consume_header)
2880 {
2881 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2882 frm_nxt += 2;
2883 }
2884 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2885 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002886 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002887 if ((c1 & 0xFC00) == 0xDC00)
2888 return codecvt_base::error;
2889 if ((c1 & 0xFC00) != 0xD800)
2890 {
2891 if (c1 > Maxcode)
2892 return codecvt_base::error;
2893 *to_nxt = static_cast<uint32_t>(c1);
2894 frm_nxt += 2;
2895 }
2896 else
2897 {
2898 if (frm_end-frm_nxt < 4)
2899 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002900 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002901 if ((c2 & 0xFC00) != 0xDC00)
2902 return codecvt_base::error;
2903 uint32_t t = static_cast<uint32_t>(
2904 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2905 | ((c1 & 0x003F) << 10)
2906 | (c2 & 0x03FF));
2907 if (t > Maxcode)
2908 return codecvt_base::error;
2909 *to_nxt = t;
2910 frm_nxt += 4;
2911 }
2912 }
2913 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2914}
2915
2916static
2917int
2918utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2919 size_t mx, unsigned long Maxcode = 0x10FFFF,
2920 codecvt_mode mode = codecvt_mode(0))
2921{
2922 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002923 if (mode & consume_header)
2924 {
2925 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2926 frm_nxt += 2;
2927 }
2928 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2929 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002930 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002931 if ((c1 & 0xFC00) == 0xDC00)
2932 break;
2933 if ((c1 & 0xFC00) != 0xD800)
2934 {
2935 if (c1 > Maxcode)
2936 break;
2937 frm_nxt += 2;
2938 }
2939 else
2940 {
2941 if (frm_end-frm_nxt < 4)
2942 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002943 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002944 if ((c2 & 0xFC00) != 0xDC00)
2945 break;
2946 uint32_t t = static_cast<uint32_t>(
2947 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2948 | ((c1 & 0x003F) << 10)
2949 | (c2 & 0x03FF));
2950 if (t > Maxcode)
2951 break;
2952 frm_nxt += 4;
2953 }
2954 }
2955 return static_cast<int>(frm_nxt - frm);
2956}
2957
2958static
2959codecvt_base::result
2960ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2961 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2962 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2963{
2964 frm_nxt = frm;
2965 to_nxt = to;
2966 if (mode & generate_header)
2967 {
2968 if (to_end-to_nxt < 2)
2969 return codecvt_base::partial;
2970 *to_nxt++ = static_cast<uint8_t>(0xFE);
2971 *to_nxt++ = static_cast<uint8_t>(0xFF);
2972 }
2973 for (; frm_nxt < frm_end; ++frm_nxt)
2974 {
2975 uint16_t wc = *frm_nxt;
2976 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2977 return codecvt_base::error;
2978 if (to_end-to_nxt < 2)
2979 return codecvt_base::partial;
2980 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2981 *to_nxt++ = static_cast<uint8_t>(wc);
2982 }
2983 return codecvt_base::ok;
2984}
2985
2986static
2987codecvt_base::result
2988utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2989 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2990 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2991{
2992 frm_nxt = frm;
2993 to_nxt = to;
2994 if (mode & consume_header)
2995 {
2996 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2997 frm_nxt += 2;
2998 }
2999 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3000 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003001 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003002 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3003 return codecvt_base::error;
3004 *to_nxt = c1;
3005 frm_nxt += 2;
3006 }
3007 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3008}
3009
3010static
3011int
3012utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3013 size_t mx, unsigned long Maxcode = 0x10FFFF,
3014 codecvt_mode mode = codecvt_mode(0))
3015{
3016 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003017 if (mode & consume_header)
3018 {
3019 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3020 frm_nxt += 2;
3021 }
3022 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3023 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003024 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003025 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3026 break;
3027 frm_nxt += 2;
3028 }
3029 return static_cast<int>(frm_nxt - frm);
3030}
3031
3032static
3033codecvt_base::result
3034ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3035 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3036 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3037{
3038 frm_nxt = frm;
3039 to_nxt = to;
3040 if (mode & generate_header)
3041 {
3042 if (to_end-to_nxt < 2)
3043 return codecvt_base::partial;
3044 *to_nxt++ = static_cast<uint8_t>(0xFF);
3045 *to_nxt++ = static_cast<uint8_t>(0xFE);
3046 }
3047 for (; frm_nxt < frm_end; ++frm_nxt)
3048 {
3049 uint16_t wc = *frm_nxt;
3050 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3051 return codecvt_base::error;
3052 if (to_end-to_nxt < 2)
3053 return codecvt_base::partial;
3054 *to_nxt++ = static_cast<uint8_t>(wc);
3055 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3056 }
3057 return codecvt_base::ok;
3058}
3059
3060static
3061codecvt_base::result
3062utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3063 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3064 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3065{
3066 frm_nxt = frm;
3067 to_nxt = to;
3068 if (mode & consume_header)
3069 {
3070 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3071 frm_nxt += 2;
3072 }
3073 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3074 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003075 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003076 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3077 return codecvt_base::error;
3078 *to_nxt = c1;
3079 frm_nxt += 2;
3080 }
3081 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3082}
3083
3084static
3085int
3086utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3087 size_t mx, unsigned long Maxcode = 0x10FFFF,
3088 codecvt_mode mode = codecvt_mode(0))
3089{
3090 const uint8_t* frm_nxt = frm;
3091 frm_nxt = frm;
3092 if (mode & consume_header)
3093 {
3094 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3095 frm_nxt += 2;
3096 }
3097 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3098 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003099 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003100 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3101 break;
3102 frm_nxt += 2;
3103 }
3104 return static_cast<int>(frm_nxt - frm);
3105}
3106
Howard Hinnantc51e1022010-05-11 19:42:16 +00003107// template <> class codecvt<char16_t, char, mbstate_t>
3108
Howard Hinnantffb308e2010-08-22 00:03:27 +00003109locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003110
3111codecvt<char16_t, char, mbstate_t>::~codecvt()
3112{
3113}
3114
3115codecvt<char16_t, char, mbstate_t>::result
3116codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003117 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003118 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3119{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003120 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3121 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3122 const uint16_t* _frm_nxt = _frm;
3123 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3124 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3125 uint8_t* _to_nxt = _to;
3126 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3127 frm_nxt = frm + (_frm_nxt - _frm);
3128 to_nxt = to + (_to_nxt - _to);
3129 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003130}
3131
3132codecvt<char16_t, char, mbstate_t>::result
3133codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003134 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003135 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3136{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003137 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3138 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3139 const uint8_t* _frm_nxt = _frm;
3140 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3141 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3142 uint16_t* _to_nxt = _to;
3143 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3144 frm_nxt = frm + (_frm_nxt - _frm);
3145 to_nxt = to + (_to_nxt - _to);
3146 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003147}
3148
3149codecvt<char16_t, char, mbstate_t>::result
3150codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3151 extern_type* to, extern_type*, extern_type*& to_nxt) const
3152{
3153 to_nxt = to;
3154 return noconv;
3155}
3156
3157int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003158codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003159{
3160 return 0;
3161}
3162
3163bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003164codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003165{
3166 return false;
3167}
3168
3169int
3170codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3171 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3172{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003173 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3174 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3175 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003176}
3177
3178int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003179codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003180{
3181 return 4;
3182}
3183
3184// template <> class codecvt<char32_t, char, mbstate_t>
3185
Howard Hinnantffb308e2010-08-22 00:03:27 +00003186locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003187
3188codecvt<char32_t, char, mbstate_t>::~codecvt()
3189{
3190}
3191
3192codecvt<char32_t, char, mbstate_t>::result
3193codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003194 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003195 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3196{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003197 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3198 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3199 const uint32_t* _frm_nxt = _frm;
3200 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3201 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3202 uint8_t* _to_nxt = _to;
3203 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3204 frm_nxt = frm + (_frm_nxt - _frm);
3205 to_nxt = to + (_to_nxt - _to);
3206 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003207}
3208
3209codecvt<char32_t, char, mbstate_t>::result
3210codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003211 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003212 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3213{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003214 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3215 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3216 const uint8_t* _frm_nxt = _frm;
3217 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3218 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3219 uint32_t* _to_nxt = _to;
3220 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3221 frm_nxt = frm + (_frm_nxt - _frm);
3222 to_nxt = to + (_to_nxt - _to);
3223 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003224}
3225
3226codecvt<char32_t, char, mbstate_t>::result
3227codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3228 extern_type* to, extern_type*, extern_type*& to_nxt) const
3229{
3230 to_nxt = to;
3231 return noconv;
3232}
3233
3234int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003235codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003236{
3237 return 0;
3238}
3239
3240bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003241codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003242{
3243 return false;
3244}
3245
3246int
3247codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3248 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3249{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003250 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3251 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3252 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003253}
3254
3255int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003256codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003257{
3258 return 4;
3259}
3260
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003261// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003262
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003263__codecvt_utf8<wchar_t>::result
3264__codecvt_utf8<wchar_t>::do_out(state_type&,
3265 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003266 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3267{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003268#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003269 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3270 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3271 const uint16_t* _frm_nxt = _frm;
3272#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003273 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3274 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3275 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003276#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003277 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3278 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3279 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003280#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003281 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3282 _Maxcode_, _Mode_);
3283#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003284 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3285 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003286#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003287 frm_nxt = frm + (_frm_nxt - _frm);
3288 to_nxt = to + (_to_nxt - _to);
3289 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003290}
3291
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003292__codecvt_utf8<wchar_t>::result
3293__codecvt_utf8<wchar_t>::do_in(state_type&,
3294 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003295 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3296{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003297 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3298 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3299 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003300#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003301 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3302 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3303 uint16_t* _to_nxt = _to;
3304 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3305 _Maxcode_, _Mode_);
3306#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003307 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3308 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3309 uint32_t* _to_nxt = _to;
3310 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3311 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003312#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003313 frm_nxt = frm + (_frm_nxt - _frm);
3314 to_nxt = to + (_to_nxt - _to);
3315 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003316}
3317
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003318__codecvt_utf8<wchar_t>::result
3319__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003320 extern_type* to, extern_type*, extern_type*& to_nxt) const
3321{
3322 to_nxt = to;
3323 return noconv;
3324}
3325
3326int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003327__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003328{
3329 return 0;
3330}
3331
3332bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003333__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003334{
3335 return false;
3336}
3337
3338int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003339__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003340 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3341{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003342 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3343 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3344 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003345}
3346
3347int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003348__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003349{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003350 if (_Mode_ & consume_header)
3351 return 7;
3352 return 4;
3353}
3354
3355// __codecvt_utf8<char16_t>
3356
3357__codecvt_utf8<char16_t>::result
3358__codecvt_utf8<char16_t>::do_out(state_type&,
3359 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3360 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3361{
3362 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3363 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3364 const uint16_t* _frm_nxt = _frm;
3365 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3366 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3367 uint8_t* _to_nxt = _to;
3368 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3369 _Maxcode_, _Mode_);
3370 frm_nxt = frm + (_frm_nxt - _frm);
3371 to_nxt = to + (_to_nxt - _to);
3372 return r;
3373}
3374
3375__codecvt_utf8<char16_t>::result
3376__codecvt_utf8<char16_t>::do_in(state_type&,
3377 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3378 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3379{
3380 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3381 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3382 const uint8_t* _frm_nxt = _frm;
3383 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3384 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3385 uint16_t* _to_nxt = _to;
3386 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3387 _Maxcode_, _Mode_);
3388 frm_nxt = frm + (_frm_nxt - _frm);
3389 to_nxt = to + (_to_nxt - _to);
3390 return r;
3391}
3392
3393__codecvt_utf8<char16_t>::result
3394__codecvt_utf8<char16_t>::do_unshift(state_type&,
3395 extern_type* to, extern_type*, extern_type*& to_nxt) const
3396{
3397 to_nxt = to;
3398 return noconv;
3399}
3400
3401int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003402__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003403{
3404 return 0;
3405}
3406
3407bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003408__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003409{
3410 return false;
3411}
3412
3413int
3414__codecvt_utf8<char16_t>::do_length(state_type&,
3415 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3416{
3417 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3418 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3419 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3420}
3421
3422int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003423__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003424{
3425 if (_Mode_ & consume_header)
3426 return 6;
3427 return 3;
3428}
3429
3430// __codecvt_utf8<char32_t>
3431
3432__codecvt_utf8<char32_t>::result
3433__codecvt_utf8<char32_t>::do_out(state_type&,
3434 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3435 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3436{
3437 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3438 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3439 const uint32_t* _frm_nxt = _frm;
3440 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3441 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3442 uint8_t* _to_nxt = _to;
3443 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3444 _Maxcode_, _Mode_);
3445 frm_nxt = frm + (_frm_nxt - _frm);
3446 to_nxt = to + (_to_nxt - _to);
3447 return r;
3448}
3449
3450__codecvt_utf8<char32_t>::result
3451__codecvt_utf8<char32_t>::do_in(state_type&,
3452 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3453 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3454{
3455 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3456 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3457 const uint8_t* _frm_nxt = _frm;
3458 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3459 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3460 uint32_t* _to_nxt = _to;
3461 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3462 _Maxcode_, _Mode_);
3463 frm_nxt = frm + (_frm_nxt - _frm);
3464 to_nxt = to + (_to_nxt - _to);
3465 return r;
3466}
3467
3468__codecvt_utf8<char32_t>::result
3469__codecvt_utf8<char32_t>::do_unshift(state_type&,
3470 extern_type* to, extern_type*, extern_type*& to_nxt) const
3471{
3472 to_nxt = to;
3473 return noconv;
3474}
3475
3476int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003477__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003478{
3479 return 0;
3480}
3481
3482bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003483__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003484{
3485 return false;
3486}
3487
3488int
3489__codecvt_utf8<char32_t>::do_length(state_type&,
3490 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3491{
3492 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3493 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3494 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3495}
3496
3497int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003498__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003499{
3500 if (_Mode_ & consume_header)
3501 return 7;
3502 return 4;
3503}
3504
3505// __codecvt_utf16<wchar_t, false>
3506
3507__codecvt_utf16<wchar_t, false>::result
3508__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3509 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3510 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3511{
3512 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3513 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3514 const uint32_t* _frm_nxt = _frm;
3515 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3516 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3517 uint8_t* _to_nxt = _to;
3518 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3519 _Maxcode_, _Mode_);
3520 frm_nxt = frm + (_frm_nxt - _frm);
3521 to_nxt = to + (_to_nxt - _to);
3522 return r;
3523}
3524
3525__codecvt_utf16<wchar_t, false>::result
3526__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3527 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3528 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3529{
3530 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3531 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3532 const uint8_t* _frm_nxt = _frm;
3533 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3534 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3535 uint32_t* _to_nxt = _to;
3536 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3537 _Maxcode_, _Mode_);
3538 frm_nxt = frm + (_frm_nxt - _frm);
3539 to_nxt = to + (_to_nxt - _to);
3540 return r;
3541}
3542
3543__codecvt_utf16<wchar_t, false>::result
3544__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3545 extern_type* to, extern_type*, extern_type*& to_nxt) const
3546{
3547 to_nxt = to;
3548 return noconv;
3549}
3550
3551int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003552__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003553{
3554 return 0;
3555}
3556
3557bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003558__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003559{
3560 return false;
3561}
3562
3563int
3564__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3565 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3566{
3567 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3568 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3569 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3570}
3571
3572int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003573__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003574{
3575 if (_Mode_ & consume_header)
3576 return 6;
3577 return 4;
3578}
3579
3580// __codecvt_utf16<wchar_t, true>
3581
3582__codecvt_utf16<wchar_t, true>::result
3583__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3584 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3585 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3586{
3587 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3588 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3589 const uint32_t* _frm_nxt = _frm;
3590 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3591 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3592 uint8_t* _to_nxt = _to;
3593 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3594 _Maxcode_, _Mode_);
3595 frm_nxt = frm + (_frm_nxt - _frm);
3596 to_nxt = to + (_to_nxt - _to);
3597 return r;
3598}
3599
3600__codecvt_utf16<wchar_t, true>::result
3601__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3602 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3603 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3604{
3605 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3606 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3607 const uint8_t* _frm_nxt = _frm;
3608 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3609 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3610 uint32_t* _to_nxt = _to;
3611 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3612 _Maxcode_, _Mode_);
3613 frm_nxt = frm + (_frm_nxt - _frm);
3614 to_nxt = to + (_to_nxt - _to);
3615 return r;
3616}
3617
3618__codecvt_utf16<wchar_t, true>::result
3619__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3620 extern_type* to, extern_type*, extern_type*& to_nxt) const
3621{
3622 to_nxt = to;
3623 return noconv;
3624}
3625
3626int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003627__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003628{
3629 return 0;
3630}
3631
3632bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003633__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003634{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003635 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003636}
3637
3638int
3639__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3640 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3641{
3642 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3643 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3644 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3645}
3646
3647int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003648__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003649{
3650 if (_Mode_ & consume_header)
3651 return 6;
3652 return 4;
3653}
3654
3655// __codecvt_utf16<char16_t, false>
3656
3657__codecvt_utf16<char16_t, false>::result
3658__codecvt_utf16<char16_t, false>::do_out(state_type&,
3659 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3660 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3661{
3662 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3663 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3664 const uint16_t* _frm_nxt = _frm;
3665 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3666 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3667 uint8_t* _to_nxt = _to;
3668 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3669 _Maxcode_, _Mode_);
3670 frm_nxt = frm + (_frm_nxt - _frm);
3671 to_nxt = to + (_to_nxt - _to);
3672 return r;
3673}
3674
3675__codecvt_utf16<char16_t, false>::result
3676__codecvt_utf16<char16_t, false>::do_in(state_type&,
3677 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3678 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3679{
3680 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3681 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3682 const uint8_t* _frm_nxt = _frm;
3683 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3684 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3685 uint16_t* _to_nxt = _to;
3686 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3687 _Maxcode_, _Mode_);
3688 frm_nxt = frm + (_frm_nxt - _frm);
3689 to_nxt = to + (_to_nxt - _to);
3690 return r;
3691}
3692
3693__codecvt_utf16<char16_t, false>::result
3694__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3695 extern_type* to, extern_type*, extern_type*& to_nxt) const
3696{
3697 to_nxt = to;
3698 return noconv;
3699}
3700
3701int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003702__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003703{
3704 return 0;
3705}
3706
3707bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003708__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003709{
3710 return false;
3711}
3712
3713int
3714__codecvt_utf16<char16_t, false>::do_length(state_type&,
3715 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3716{
3717 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3718 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3719 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3720}
3721
3722int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003723__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003724{
3725 if (_Mode_ & consume_header)
3726 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003727 return 2;
3728}
3729
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003730// __codecvt_utf16<char16_t, true>
3731
3732__codecvt_utf16<char16_t, true>::result
3733__codecvt_utf16<char16_t, true>::do_out(state_type&,
3734 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3735 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3736{
3737 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3738 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3739 const uint16_t* _frm_nxt = _frm;
3740 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3741 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3742 uint8_t* _to_nxt = _to;
3743 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3744 _Maxcode_, _Mode_);
3745 frm_nxt = frm + (_frm_nxt - _frm);
3746 to_nxt = to + (_to_nxt - _to);
3747 return r;
3748}
3749
3750__codecvt_utf16<char16_t, true>::result
3751__codecvt_utf16<char16_t, true>::do_in(state_type&,
3752 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3753 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3754{
3755 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3756 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3757 const uint8_t* _frm_nxt = _frm;
3758 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3759 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3760 uint16_t* _to_nxt = _to;
3761 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3762 _Maxcode_, _Mode_);
3763 frm_nxt = frm + (_frm_nxt - _frm);
3764 to_nxt = to + (_to_nxt - _to);
3765 return r;
3766}
3767
3768__codecvt_utf16<char16_t, true>::result
3769__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3770 extern_type* to, extern_type*, extern_type*& to_nxt) const
3771{
3772 to_nxt = to;
3773 return noconv;
3774}
3775
3776int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003777__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003778{
3779 return 0;
3780}
3781
3782bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003783__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003784{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003785 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003786}
3787
3788int
3789__codecvt_utf16<char16_t, true>::do_length(state_type&,
3790 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3791{
3792 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3793 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3794 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3795}
3796
3797int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003798__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003799{
3800 if (_Mode_ & consume_header)
3801 return 4;
3802 return 2;
3803}
3804
3805// __codecvt_utf16<char32_t, false>
3806
3807__codecvt_utf16<char32_t, false>::result
3808__codecvt_utf16<char32_t, false>::do_out(state_type&,
3809 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3810 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3811{
3812 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3813 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3814 const uint32_t* _frm_nxt = _frm;
3815 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3816 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3817 uint8_t* _to_nxt = _to;
3818 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3819 _Maxcode_, _Mode_);
3820 frm_nxt = frm + (_frm_nxt - _frm);
3821 to_nxt = to + (_to_nxt - _to);
3822 return r;
3823}
3824
3825__codecvt_utf16<char32_t, false>::result
3826__codecvt_utf16<char32_t, false>::do_in(state_type&,
3827 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3828 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3829{
3830 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3831 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3832 const uint8_t* _frm_nxt = _frm;
3833 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3834 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3835 uint32_t* _to_nxt = _to;
3836 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3837 _Maxcode_, _Mode_);
3838 frm_nxt = frm + (_frm_nxt - _frm);
3839 to_nxt = to + (_to_nxt - _to);
3840 return r;
3841}
3842
3843__codecvt_utf16<char32_t, false>::result
3844__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3845 extern_type* to, extern_type*, extern_type*& to_nxt) const
3846{
3847 to_nxt = to;
3848 return noconv;
3849}
3850
3851int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003852__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003853{
3854 return 0;
3855}
3856
3857bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003858__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003859{
3860 return false;
3861}
3862
3863int
3864__codecvt_utf16<char32_t, false>::do_length(state_type&,
3865 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3866{
3867 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3868 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3869 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3870}
3871
3872int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003873__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003874{
3875 if (_Mode_ & consume_header)
3876 return 6;
3877 return 4;
3878}
3879
3880// __codecvt_utf16<char32_t, true>
3881
3882__codecvt_utf16<char32_t, true>::result
3883__codecvt_utf16<char32_t, true>::do_out(state_type&,
3884 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3885 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3886{
3887 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3888 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3889 const uint32_t* _frm_nxt = _frm;
3890 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3891 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3892 uint8_t* _to_nxt = _to;
3893 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3894 _Maxcode_, _Mode_);
3895 frm_nxt = frm + (_frm_nxt - _frm);
3896 to_nxt = to + (_to_nxt - _to);
3897 return r;
3898}
3899
3900__codecvt_utf16<char32_t, true>::result
3901__codecvt_utf16<char32_t, true>::do_in(state_type&,
3902 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3903 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3904{
3905 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3906 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3907 const uint8_t* _frm_nxt = _frm;
3908 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3909 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3910 uint32_t* _to_nxt = _to;
3911 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3912 _Maxcode_, _Mode_);
3913 frm_nxt = frm + (_frm_nxt - _frm);
3914 to_nxt = to + (_to_nxt - _to);
3915 return r;
3916}
3917
3918__codecvt_utf16<char32_t, true>::result
3919__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3920 extern_type* to, extern_type*, extern_type*& to_nxt) const
3921{
3922 to_nxt = to;
3923 return noconv;
3924}
3925
3926int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003927__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003928{
3929 return 0;
3930}
3931
3932bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003933__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003934{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003935 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003936}
3937
3938int
3939__codecvt_utf16<char32_t, true>::do_length(state_type&,
3940 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3941{
3942 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3943 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3944 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3945}
3946
3947int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003948__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003949{
3950 if (_Mode_ & consume_header)
3951 return 6;
3952 return 4;
3953}
3954
3955// __codecvt_utf8_utf16<wchar_t>
3956
3957__codecvt_utf8_utf16<wchar_t>::result
3958__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3959 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3960 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3961{
3962 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3963 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3964 const uint32_t* _frm_nxt = _frm;
3965 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3966 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3967 uint8_t* _to_nxt = _to;
3968 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3969 _Maxcode_, _Mode_);
3970 frm_nxt = frm + (_frm_nxt - _frm);
3971 to_nxt = to + (_to_nxt - _to);
3972 return r;
3973}
3974
3975__codecvt_utf8_utf16<wchar_t>::result
3976__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3977 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3978 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3979{
3980 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3981 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3982 const uint8_t* _frm_nxt = _frm;
3983 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3984 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3985 uint32_t* _to_nxt = _to;
3986 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3987 _Maxcode_, _Mode_);
3988 frm_nxt = frm + (_frm_nxt - _frm);
3989 to_nxt = to + (_to_nxt - _to);
3990 return r;
3991}
3992
3993__codecvt_utf8_utf16<wchar_t>::result
3994__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3995 extern_type* to, extern_type*, extern_type*& to_nxt) const
3996{
3997 to_nxt = to;
3998 return noconv;
3999}
4000
4001int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004002__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004003{
4004 return 0;
4005}
4006
4007bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004008__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004009{
4010 return false;
4011}
4012
4013int
4014__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4015 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4016{
4017 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4018 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4019 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4020}
4021
4022int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004023__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004024{
4025 if (_Mode_ & consume_header)
4026 return 7;
4027 return 4;
4028}
4029
4030// __codecvt_utf8_utf16<char16_t>
4031
4032__codecvt_utf8_utf16<char16_t>::result
4033__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4034 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4035 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4036{
4037 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4038 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4039 const uint16_t* _frm_nxt = _frm;
4040 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4041 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4042 uint8_t* _to_nxt = _to;
4043 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4044 _Maxcode_, _Mode_);
4045 frm_nxt = frm + (_frm_nxt - _frm);
4046 to_nxt = to + (_to_nxt - _to);
4047 return r;
4048}
4049
4050__codecvt_utf8_utf16<char16_t>::result
4051__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4052 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4053 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4054{
4055 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4056 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4057 const uint8_t* _frm_nxt = _frm;
4058 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4059 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4060 uint16_t* _to_nxt = _to;
4061 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4062 _Maxcode_, _Mode_);
4063 frm_nxt = frm + (_frm_nxt - _frm);
4064 to_nxt = to + (_to_nxt - _to);
4065 return r;
4066}
4067
4068__codecvt_utf8_utf16<char16_t>::result
4069__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4070 extern_type* to, extern_type*, extern_type*& to_nxt) const
4071{
4072 to_nxt = to;
4073 return noconv;
4074}
4075
4076int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004077__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004078{
4079 return 0;
4080}
4081
4082bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004083__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004084{
4085 return false;
4086}
4087
4088int
4089__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4090 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4091{
4092 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4093 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4094 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4095}
4096
4097int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004098__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004099{
4100 if (_Mode_ & consume_header)
4101 return 7;
4102 return 4;
4103}
4104
4105// __codecvt_utf8_utf16<char32_t>
4106
4107__codecvt_utf8_utf16<char32_t>::result
4108__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4109 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4110 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4111{
4112 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4113 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4114 const uint32_t* _frm_nxt = _frm;
4115 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4116 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4117 uint8_t* _to_nxt = _to;
4118 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4119 _Maxcode_, _Mode_);
4120 frm_nxt = frm + (_frm_nxt - _frm);
4121 to_nxt = to + (_to_nxt - _to);
4122 return r;
4123}
4124
4125__codecvt_utf8_utf16<char32_t>::result
4126__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4127 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4128 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4129{
4130 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4131 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4132 const uint8_t* _frm_nxt = _frm;
4133 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4134 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4135 uint32_t* _to_nxt = _to;
4136 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4137 _Maxcode_, _Mode_);
4138 frm_nxt = frm + (_frm_nxt - _frm);
4139 to_nxt = to + (_to_nxt - _to);
4140 return r;
4141}
4142
4143__codecvt_utf8_utf16<char32_t>::result
4144__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4145 extern_type* to, extern_type*, extern_type*& to_nxt) const
4146{
4147 to_nxt = to;
4148 return noconv;
4149}
4150
4151int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004152__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004153{
4154 return 0;
4155}
4156
4157bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004158__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004159{
4160 return false;
4161}
4162
4163int
4164__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4165 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4166{
4167 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4168 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4169 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4170}
4171
4172int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004173__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004174{
4175 if (_Mode_ & consume_header)
4176 return 7;
4177 return 4;
4178}
4179
Howard Hinnantc51e1022010-05-11 19:42:16 +00004180// __narrow_to_utf8<16>
4181
4182__narrow_to_utf8<16>::~__narrow_to_utf8()
4183{
4184}
4185
4186// __narrow_to_utf8<32>
4187
4188__narrow_to_utf8<32>::~__narrow_to_utf8()
4189{
4190}
4191
4192// __widen_from_utf8<16>
4193
4194__widen_from_utf8<16>::~__widen_from_utf8()
4195{
4196}
4197
4198// __widen_from_utf8<32>
4199
4200__widen_from_utf8<32>::~__widen_from_utf8()
4201{
4202}
4203
Eric Fiselierbf945a22016-12-11 00:20:59 +00004204
4205static bool checked_string_to_wchar_convert(wchar_t& dest,
4206 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004207 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004208 if (*ptr == '\0')
4209 return false;
4210 mbstate_t mb = {};
4211 wchar_t out;
4212 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4213 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4214 return false;
4215 }
4216 dest = out;
4217 return true;
4218}
4219
4220static bool checked_string_to_char_convert(char& dest,
4221 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004222 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004223 if (*ptr == '\0')
4224 return false;
4225 if (!ptr[1]) {
4226 dest = *ptr;
4227 return true;
4228 }
4229 // First convert the MBS into a wide char then attempt to narrow it using
4230 // wctob_l.
4231 wchar_t wout;
4232 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4233 return false;
4234 int res;
4235 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4236 dest = res;
4237 return true;
4238 }
4239 // FIXME: Work around specific multibyte sequences that we can reasonable
4240 // translate into a different single byte.
4241 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004242 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004243 case L'\u00A0': // non-breaking space
4244 dest = ' ';
4245 return true;
4246 default:
4247 return false;
4248 }
4249 _LIBCPP_UNREACHABLE();
4250}
4251
4252
Howard Hinnantc51e1022010-05-11 19:42:16 +00004253// numpunct<char> && numpunct<wchar_t>
4254
4255locale::id numpunct< char >::id;
4256locale::id numpunct<wchar_t>::id;
4257
4258numpunct<char>::numpunct(size_t refs)
4259 : locale::facet(refs),
4260 __decimal_point_('.'),
4261 __thousands_sep_(',')
4262{
4263}
4264
4265numpunct<wchar_t>::numpunct(size_t refs)
4266 : locale::facet(refs),
4267 __decimal_point_(L'.'),
4268 __thousands_sep_(L',')
4269{
4270}
4271
4272numpunct<char>::~numpunct()
4273{
4274}
4275
4276numpunct<wchar_t>::~numpunct()
4277{
4278}
4279
4280 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4281wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4282
4283 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4284wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4285
4286string numpunct< char >::do_grouping() const {return __grouping_;}
4287string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4288
4289 string numpunct< char >::do_truename() const {return "true";}
4290wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4291
4292 string numpunct< char >::do_falsename() const {return "false";}
4293wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4294
4295// numpunct_byname<char>
4296
4297numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4298 : numpunct<char>(refs)
4299{
4300 __init(nm);
4301}
4302
4303numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4304 : numpunct<char>(refs)
4305{
4306 __init(nm.c_str());
4307}
4308
4309numpunct_byname<char>::~numpunct_byname()
4310{
4311}
4312
4313void
4314numpunct_byname<char>::__init(const char* nm)
4315{
4316 if (strcmp(nm, "C") != 0)
4317 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004318 __libcpp_unique_locale loc(nm);
4319 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004320 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004321 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004322
Ben Craig3756b922016-03-09 15:39:39 +00004323 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004324 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4325 loc.get());
4326 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4327 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004328 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004329 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004330 }
4331}
4332
4333// numpunct_byname<wchar_t>
4334
4335numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4336 : numpunct<wchar_t>(refs)
4337{
4338 __init(nm);
4339}
4340
4341numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4342 : numpunct<wchar_t>(refs)
4343{
4344 __init(nm.c_str());
4345}
4346
4347numpunct_byname<wchar_t>::~numpunct_byname()
4348{
4349}
4350
4351void
4352numpunct_byname<wchar_t>::__init(const char* nm)
4353{
4354 if (strcmp(nm, "C") != 0)
4355 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004356 __libcpp_unique_locale loc(nm);
4357 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004358 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004359 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004360
Ben Craig3756b922016-03-09 15:39:39 +00004361 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004362 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4363 loc.get());
4364 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4365 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004366 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004367 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004368 }
4369}
4370
4371// num_get helpers
4372
4373int
4374__num_get_base::__get_base(ios_base& iob)
4375{
4376 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4377 if (__basefield == ios_base::oct)
4378 return 8;
4379 else if (__basefield == ios_base::hex)
4380 return 16;
4381 else if (__basefield == 0)
4382 return 0;
4383 return 10;
4384}
4385
4386const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4387
4388void
4389__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4390 ios_base::iostate& __err)
4391{
4392 if (__grouping.size() != 0)
4393 {
4394 reverse(__g, __g_end);
4395 const char* __ig = __grouping.data();
4396 const char* __eg = __ig + __grouping.size();
4397 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4398 {
4399 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4400 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004401 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004402 {
4403 __err = ios_base::failbit;
4404 return;
4405 }
4406 }
4407 if (__eg - __ig > 1)
4408 ++__ig;
4409 }
4410 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4411 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004412 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004413 __err = ios_base::failbit;
4414 }
4415 }
4416}
4417
4418void
4419__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4420 ios_base::fmtflags __flags)
4421{
4422 if (__flags & ios_base::showpos)
4423 *__fmtp++ = '+';
4424 if (__flags & ios_base::showbase)
4425 *__fmtp++ = '#';
4426 while(*__len)
4427 *__fmtp++ = *__len++;
4428 if ((__flags & ios_base::basefield) == ios_base::oct)
4429 *__fmtp = 'o';
4430 else if ((__flags & ios_base::basefield) == ios_base::hex)
4431 {
4432 if (__flags & ios_base::uppercase)
4433 *__fmtp = 'X';
4434 else
4435 *__fmtp = 'x';
4436 }
4437 else if (__signd)
4438 *__fmtp = 'd';
4439 else
4440 *__fmtp = 'u';
4441}
4442
4443bool
4444__num_put_base::__format_float(char* __fmtp, const char* __len,
4445 ios_base::fmtflags __flags)
4446{
4447 bool specify_precision = true;
4448 if (__flags & ios_base::showpos)
4449 *__fmtp++ = '+';
4450 if (__flags & ios_base::showpoint)
4451 *__fmtp++ = '#';
4452 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004453 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004454 if (floatfield == (ios_base::fixed | ios_base::scientific))
4455 specify_precision = false;
4456 else
4457 {
4458 *__fmtp++ = '.';
4459 *__fmtp++ = '*';
4460 }
4461 while(*__len)
4462 *__fmtp++ = *__len++;
4463 if (floatfield == ios_base::fixed)
4464 {
4465 if (uppercase)
4466 *__fmtp = 'F';
4467 else
4468 *__fmtp = 'f';
4469 }
4470 else if (floatfield == ios_base::scientific)
4471 {
4472 if (uppercase)
4473 *__fmtp = 'E';
4474 else
4475 *__fmtp = 'e';
4476 }
4477 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4478 {
4479 if (uppercase)
4480 *__fmtp = 'A';
4481 else
4482 *__fmtp = 'a';
4483 }
4484 else
4485 {
4486 if (uppercase)
4487 *__fmtp = 'G';
4488 else
4489 *__fmtp = 'g';
4490 }
4491 return specify_precision;
4492}
4493
4494char*
4495__num_put_base::__identify_padding(char* __nb, char* __ne,
4496 const ios_base& __iob)
4497{
4498 switch (__iob.flags() & ios_base::adjustfield)
4499 {
4500 case ios_base::internal:
4501 if (__nb[0] == '-' || __nb[0] == '+')
4502 return __nb+1;
4503 if (__ne - __nb >= 2 && __nb[0] == '0'
4504 && (__nb[1] == 'x' || __nb[1] == 'X'))
4505 return __nb+2;
4506 break;
4507 case ios_base::left:
4508 return __ne;
4509 case ios_base::right:
4510 default:
4511 break;
4512 }
4513 return __nb;
4514}
4515
4516// time_get
4517
4518static
4519string*
4520init_weeks()
4521{
4522 static string weeks[14];
4523 weeks[0] = "Sunday";
4524 weeks[1] = "Monday";
4525 weeks[2] = "Tuesday";
4526 weeks[3] = "Wednesday";
4527 weeks[4] = "Thursday";
4528 weeks[5] = "Friday";
4529 weeks[6] = "Saturday";
4530 weeks[7] = "Sun";
4531 weeks[8] = "Mon";
4532 weeks[9] = "Tue";
4533 weeks[10] = "Wed";
4534 weeks[11] = "Thu";
4535 weeks[12] = "Fri";
4536 weeks[13] = "Sat";
4537 return weeks;
4538}
4539
4540static
4541wstring*
4542init_wweeks()
4543{
4544 static wstring weeks[14];
4545 weeks[0] = L"Sunday";
4546 weeks[1] = L"Monday";
4547 weeks[2] = L"Tuesday";
4548 weeks[3] = L"Wednesday";
4549 weeks[4] = L"Thursday";
4550 weeks[5] = L"Friday";
4551 weeks[6] = L"Saturday";
4552 weeks[7] = L"Sun";
4553 weeks[8] = L"Mon";
4554 weeks[9] = L"Tue";
4555 weeks[10] = L"Wed";
4556 weeks[11] = L"Thu";
4557 weeks[12] = L"Fri";
4558 weeks[13] = L"Sat";
4559 return weeks;
4560}
4561
4562template <>
4563const string*
4564__time_get_c_storage<char>::__weeks() const
4565{
4566 static const string* weeks = init_weeks();
4567 return weeks;
4568}
4569
4570template <>
4571const wstring*
4572__time_get_c_storage<wchar_t>::__weeks() const
4573{
4574 static const wstring* weeks = init_wweeks();
4575 return weeks;
4576}
4577
4578static
4579string*
4580init_months()
4581{
4582 static string months[24];
4583 months[0] = "January";
4584 months[1] = "February";
4585 months[2] = "March";
4586 months[3] = "April";
4587 months[4] = "May";
4588 months[5] = "June";
4589 months[6] = "July";
4590 months[7] = "August";
4591 months[8] = "September";
4592 months[9] = "October";
4593 months[10] = "November";
4594 months[11] = "December";
4595 months[12] = "Jan";
4596 months[13] = "Feb";
4597 months[14] = "Mar";
4598 months[15] = "Apr";
4599 months[16] = "May";
4600 months[17] = "Jun";
4601 months[18] = "Jul";
4602 months[19] = "Aug";
4603 months[20] = "Sep";
4604 months[21] = "Oct";
4605 months[22] = "Nov";
4606 months[23] = "Dec";
4607 return months;
4608}
4609
4610static
4611wstring*
4612init_wmonths()
4613{
4614 static wstring months[24];
4615 months[0] = L"January";
4616 months[1] = L"February";
4617 months[2] = L"March";
4618 months[3] = L"April";
4619 months[4] = L"May";
4620 months[5] = L"June";
4621 months[6] = L"July";
4622 months[7] = L"August";
4623 months[8] = L"September";
4624 months[9] = L"October";
4625 months[10] = L"November";
4626 months[11] = L"December";
4627 months[12] = L"Jan";
4628 months[13] = L"Feb";
4629 months[14] = L"Mar";
4630 months[15] = L"Apr";
4631 months[16] = L"May";
4632 months[17] = L"Jun";
4633 months[18] = L"Jul";
4634 months[19] = L"Aug";
4635 months[20] = L"Sep";
4636 months[21] = L"Oct";
4637 months[22] = L"Nov";
4638 months[23] = L"Dec";
4639 return months;
4640}
4641
4642template <>
4643const string*
4644__time_get_c_storage<char>::__months() const
4645{
4646 static const string* months = init_months();
4647 return months;
4648}
4649
4650template <>
4651const wstring*
4652__time_get_c_storage<wchar_t>::__months() const
4653{
4654 static const wstring* months = init_wmonths();
4655 return months;
4656}
4657
4658static
4659string*
4660init_am_pm()
4661{
Marshall Clow5cc04922018-01-11 17:16:52 +00004662 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004663 am_pm[0] = "AM";
4664 am_pm[1] = "PM";
4665 return am_pm;
4666}
4667
4668static
4669wstring*
4670init_wam_pm()
4671{
Marshall Clow5cc04922018-01-11 17:16:52 +00004672 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004673 am_pm[0] = L"AM";
4674 am_pm[1] = L"PM";
4675 return am_pm;
4676}
4677
4678template <>
4679const string*
4680__time_get_c_storage<char>::__am_pm() const
4681{
4682 static const string* am_pm = init_am_pm();
4683 return am_pm;
4684}
4685
4686template <>
4687const wstring*
4688__time_get_c_storage<wchar_t>::__am_pm() const
4689{
4690 static const wstring* am_pm = init_wam_pm();
4691 return am_pm;
4692}
4693
4694template <>
4695const string&
4696__time_get_c_storage<char>::__x() const
4697{
4698 static string s("%m/%d/%y");
4699 return s;
4700}
4701
4702template <>
4703const wstring&
4704__time_get_c_storage<wchar_t>::__x() const
4705{
4706 static wstring s(L"%m/%d/%y");
4707 return s;
4708}
4709
4710template <>
4711const string&
4712__time_get_c_storage<char>::__X() const
4713{
4714 static string s("%H:%M:%S");
4715 return s;
4716}
4717
4718template <>
4719const wstring&
4720__time_get_c_storage<wchar_t>::__X() const
4721{
4722 static wstring s(L"%H:%M:%S");
4723 return s;
4724}
4725
4726template <>
4727const string&
4728__time_get_c_storage<char>::__c() const
4729{
4730 static string s("%a %b %d %H:%M:%S %Y");
4731 return s;
4732}
4733
4734template <>
4735const wstring&
4736__time_get_c_storage<wchar_t>::__c() const
4737{
4738 static wstring s(L"%a %b %d %H:%M:%S %Y");
4739 return s;
4740}
4741
4742template <>
4743const string&
4744__time_get_c_storage<char>::__r() const
4745{
4746 static string s("%I:%M:%S %p");
4747 return s;
4748}
4749
4750template <>
4751const wstring&
4752__time_get_c_storage<wchar_t>::__r() const
4753{
4754 static wstring s(L"%I:%M:%S %p");
4755 return s;
4756}
4757
4758// time_get_byname
4759
4760__time_get::__time_get(const char* nm)
4761 : __loc_(newlocale(LC_ALL_MASK, nm, 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 " + string(nm));
4766}
4767
4768__time_get::__time_get(const string& nm)
4769 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4770{
4771 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004772 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004773 " failed to construct for " + nm);
4774}
4775
4776__time_get::~__time_get()
4777{
4778 freelocale(__loc_);
4779}
Marshall Clowd920eea2013-10-21 15:07:28 +00004780#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004781#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004782#endif
4783#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004784#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004785#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004786
Howard Hinnantc51e1022010-05-11 19:42:16 +00004787template <>
4788string
4789__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4790{
Howard Hinnant990207c2012-02-19 14:55:32 +00004791 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004792 t.tm_sec = 59;
4793 t.tm_min = 55;
4794 t.tm_hour = 23;
4795 t.tm_mday = 31;
4796 t.tm_mon = 11;
4797 t.tm_year = 161;
4798 t.tm_wday = 6;
4799 t.tm_yday = 364;
4800 t.tm_isdst = -1;
4801 char buf[100];
4802 char f[3] = {0};
4803 f[0] = '%';
4804 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004805 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004806 char* bb = buf;
4807 char* be = buf + n;
4808 string result;
4809 while (bb != be)
4810 {
4811 if (ct.is(ctype_base::space, *bb))
4812 {
4813 result.push_back(' ');
4814 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4815 ;
4816 continue;
4817 }
4818 char* w = bb;
4819 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004820 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004821 ct, err, false)
4822 - this->__weeks_;
4823 if (i < 14)
4824 {
4825 result.push_back('%');
4826 if (i < 7)
4827 result.push_back('A');
4828 else
4829 result.push_back('a');
4830 bb = w;
4831 continue;
4832 }
4833 w = bb;
4834 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4835 ct, err, false)
4836 - this->__months_;
4837 if (i < 24)
4838 {
4839 result.push_back('%');
4840 if (i < 12)
4841 result.push_back('B');
4842 else
4843 result.push_back('b');
4844 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4845 result.back() = 'm';
4846 bb = w;
4847 continue;
4848 }
4849 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4850 {
4851 w = bb;
4852 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4853 ct, err, false) - this->__am_pm_;
4854 if (i < 2)
4855 {
4856 result.push_back('%');
4857 result.push_back('p');
4858 bb = w;
4859 continue;
4860 }
4861 }
4862 w = bb;
4863 if (ct.is(ctype_base::digit, *bb))
4864 {
4865 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4866 {
4867 case 6:
4868 result.push_back('%');
4869 result.push_back('w');
4870 break;
4871 case 7:
4872 result.push_back('%');
4873 result.push_back('u');
4874 break;
4875 case 11:
4876 result.push_back('%');
4877 result.push_back('I');
4878 break;
4879 case 12:
4880 result.push_back('%');
4881 result.push_back('m');
4882 break;
4883 case 23:
4884 result.push_back('%');
4885 result.push_back('H');
4886 break;
4887 case 31:
4888 result.push_back('%');
4889 result.push_back('d');
4890 break;
4891 case 55:
4892 result.push_back('%');
4893 result.push_back('M');
4894 break;
4895 case 59:
4896 result.push_back('%');
4897 result.push_back('S');
4898 break;
4899 case 61:
4900 result.push_back('%');
4901 result.push_back('y');
4902 break;
4903 case 364:
4904 result.push_back('%');
4905 result.push_back('j');
4906 break;
4907 case 2061:
4908 result.push_back('%');
4909 result.push_back('Y');
4910 break;
4911 default:
4912 for (; w != bb; ++w)
4913 result.push_back(*w);
4914 break;
4915 }
4916 continue;
4917 }
4918 if (*bb == '%')
4919 {
4920 result.push_back('%');
4921 result.push_back('%');
4922 ++bb;
4923 continue;
4924 }
4925 result.push_back(*bb);
4926 ++bb;
4927 }
4928 return result;
4929}
4930
Marshall Clowd920eea2013-10-21 15:07:28 +00004931#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004932#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004933#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004934
Howard Hinnantc51e1022010-05-11 19:42:16 +00004935template <>
4936wstring
4937__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4938{
Howard Hinnant990207c2012-02-19 14:55:32 +00004939 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004940 t.tm_sec = 59;
4941 t.tm_min = 55;
4942 t.tm_hour = 23;
4943 t.tm_mday = 31;
4944 t.tm_mon = 11;
4945 t.tm_year = 161;
4946 t.tm_wday = 6;
4947 t.tm_yday = 364;
4948 t.tm_isdst = -1;
4949 char buf[100];
4950 char f[3] = {0};
4951 f[0] = '%';
4952 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004953 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004954 wchar_t wbuf[100];
4955 wchar_t* wbb = wbuf;
4956 mbstate_t mb = {0};
4957 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004958 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004959 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004960 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004961 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004962 wstring result;
4963 while (wbb != wbe)
4964 {
4965 if (ct.is(ctype_base::space, *wbb))
4966 {
4967 result.push_back(L' ');
4968 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4969 ;
4970 continue;
4971 }
4972 wchar_t* w = wbb;
4973 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004974 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004975 ct, err, false)
4976 - this->__weeks_;
4977 if (i < 14)
4978 {
4979 result.push_back(L'%');
4980 if (i < 7)
4981 result.push_back(L'A');
4982 else
4983 result.push_back(L'a');
4984 wbb = w;
4985 continue;
4986 }
4987 w = wbb;
4988 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4989 ct, err, false)
4990 - this->__months_;
4991 if (i < 24)
4992 {
4993 result.push_back(L'%');
4994 if (i < 12)
4995 result.push_back(L'B');
4996 else
4997 result.push_back(L'b');
4998 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4999 result.back() = L'm';
5000 wbb = w;
5001 continue;
5002 }
5003 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5004 {
5005 w = wbb;
5006 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5007 ct, err, false) - this->__am_pm_;
5008 if (i < 2)
5009 {
5010 result.push_back(L'%');
5011 result.push_back(L'p');
5012 wbb = w;
5013 continue;
5014 }
5015 }
5016 w = wbb;
5017 if (ct.is(ctype_base::digit, *wbb))
5018 {
5019 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5020 {
5021 case 6:
5022 result.push_back(L'%');
5023 result.push_back(L'w');
5024 break;
5025 case 7:
5026 result.push_back(L'%');
5027 result.push_back(L'u');
5028 break;
5029 case 11:
5030 result.push_back(L'%');
5031 result.push_back(L'I');
5032 break;
5033 case 12:
5034 result.push_back(L'%');
5035 result.push_back(L'm');
5036 break;
5037 case 23:
5038 result.push_back(L'%');
5039 result.push_back(L'H');
5040 break;
5041 case 31:
5042 result.push_back(L'%');
5043 result.push_back(L'd');
5044 break;
5045 case 55:
5046 result.push_back(L'%');
5047 result.push_back(L'M');
5048 break;
5049 case 59:
5050 result.push_back(L'%');
5051 result.push_back(L'S');
5052 break;
5053 case 61:
5054 result.push_back(L'%');
5055 result.push_back(L'y');
5056 break;
5057 case 364:
5058 result.push_back(L'%');
5059 result.push_back(L'j');
5060 break;
5061 case 2061:
5062 result.push_back(L'%');
5063 result.push_back(L'Y');
5064 break;
5065 default:
5066 for (; w != wbb; ++w)
5067 result.push_back(*w);
5068 break;
5069 }
5070 continue;
5071 }
5072 if (ct.narrow(*wbb, 0) == '%')
5073 {
5074 result.push_back(L'%');
5075 result.push_back(L'%');
5076 ++wbb;
5077 continue;
5078 }
5079 result.push_back(*wbb);
5080 ++wbb;
5081 }
5082 return result;
5083}
5084
5085template <>
5086void
5087__time_get_storage<char>::init(const ctype<char>& ct)
5088{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005089 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005090 char buf[100];
5091 // __weeks_
5092 for (int i = 0; i < 7; ++i)
5093 {
5094 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005095 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005096 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005097 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005098 __weeks_[i+7] = buf;
5099 }
5100 // __months_
5101 for (int i = 0; i < 12; ++i)
5102 {
5103 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005104 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005105 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005106 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005107 __months_[i+12] = buf;
5108 }
5109 // __am_pm_
5110 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005111 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005112 __am_pm_[0] = buf;
5113 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005114 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005115 __am_pm_[1] = buf;
5116 __c_ = __analyze('c', ct);
5117 __r_ = __analyze('r', ct);
5118 __x_ = __analyze('x', ct);
5119 __X_ = __analyze('X', ct);
5120}
5121
5122template <>
5123void
5124__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5125{
5126 tm t = {0};
5127 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005128 wchar_t wbuf[100];
5129 wchar_t* wbe;
5130 mbstate_t mb = {0};
5131 // __weeks_
5132 for (int i = 0; i < 7; ++i)
5133 {
5134 t.tm_wday = i;
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 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005138 size_t 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].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005143 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005144 mb = mbstate_t();
5145 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005146 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005147 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005148 __throw_runtime_error("locale not supported");
5149 wbe = wbuf + j;
5150 __weeks_[i+7].assign(wbuf, wbe);
5151 }
5152 // __months_
5153 for (int i = 0; i < 12; ++i)
5154 {
5155 t.tm_mon = i;
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 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005159 size_t 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].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005164 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005165 mb = mbstate_t();
5166 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005167 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005168 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005169 __throw_runtime_error("locale not supported");
5170 wbe = wbuf + j;
5171 __months_[i+12].assign(wbuf, wbe);
5172 }
5173 // __am_pm_
5174 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005175 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005176 mb = mbstate_t();
5177 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005178 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005179 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005180 __throw_runtime_error("locale not supported");
5181 wbe = wbuf + j;
5182 __am_pm_[0].assign(wbuf, wbe);
5183 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005184 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005185 mb = mbstate_t();
5186 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005187 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005188 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005189 __throw_runtime_error("locale not supported");
5190 wbe = wbuf + j;
5191 __am_pm_[1].assign(wbuf, wbe);
5192 __c_ = __analyze('c', ct);
5193 __r_ = __analyze('r', ct);
5194 __x_ = __analyze('x', ct);
5195 __X_ = __analyze('X', ct);
5196}
5197
5198template <class CharT>
5199struct _LIBCPP_HIDDEN __time_get_temp
5200 : public ctype_byname<CharT>
5201{
5202 explicit __time_get_temp(const char* nm)
5203 : ctype_byname<CharT>(nm, 1) {}
5204 explicit __time_get_temp(const string& nm)
5205 : ctype_byname<CharT>(nm, 1) {}
5206};
5207
5208template <>
5209__time_get_storage<char>::__time_get_storage(const char* __nm)
5210 : __time_get(__nm)
5211{
5212 const __time_get_temp<char> ct(__nm);
5213 init(ct);
5214}
5215
5216template <>
5217__time_get_storage<char>::__time_get_storage(const string& __nm)
5218 : __time_get(__nm)
5219{
5220 const __time_get_temp<char> ct(__nm);
5221 init(ct);
5222}
5223
5224template <>
5225__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5226 : __time_get(__nm)
5227{
5228 const __time_get_temp<wchar_t> ct(__nm);
5229 init(ct);
5230}
5231
5232template <>
5233__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5234 : __time_get(__nm)
5235{
5236 const __time_get_temp<wchar_t> ct(__nm);
5237 init(ct);
5238}
5239
5240template <>
5241time_base::dateorder
5242__time_get_storage<char>::__do_date_order() const
5243{
5244 unsigned i;
5245 for (i = 0; i < __x_.size(); ++i)
5246 if (__x_[i] == '%')
5247 break;
5248 ++i;
5249 switch (__x_[i])
5250 {
5251 case 'y':
5252 case 'Y':
5253 for (++i; i < __x_.size(); ++i)
5254 if (__x_[i] == '%')
5255 break;
5256 if (i == __x_.size())
5257 break;
5258 ++i;
5259 switch (__x_[i])
5260 {
5261 case 'm':
5262 for (++i; i < __x_.size(); ++i)
5263 if (__x_[i] == '%')
5264 break;
5265 if (i == __x_.size())
5266 break;
5267 ++i;
5268 if (__x_[i] == 'd')
5269 return time_base::ymd;
5270 break;
5271 case 'd':
5272 for (++i; i < __x_.size(); ++i)
5273 if (__x_[i] == '%')
5274 break;
5275 if (i == __x_.size())
5276 break;
5277 ++i;
5278 if (__x_[i] == 'm')
5279 return time_base::ydm;
5280 break;
5281 }
5282 break;
5283 case 'm':
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] == 'd')
5291 {
5292 for (++i; i < __x_.size(); ++i)
5293 if (__x_[i] == '%')
5294 break;
5295 if (i == __x_.size())
5296 break;
5297 ++i;
5298 if (__x_[i] == 'y' || __x_[i] == 'Y')
5299 return time_base::mdy;
5300 break;
5301 }
5302 break;
5303 case 'd':
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] == 'm')
5311 {
5312 for (++i; i < __x_.size(); ++i)
5313 if (__x_[i] == '%')
5314 break;
5315 if (i == __x_.size())
5316 break;
5317 ++i;
5318 if (__x_[i] == 'y' || __x_[i] == 'Y')
5319 return time_base::dmy;
5320 break;
5321 }
5322 break;
5323 }
5324 return time_base::no_order;
5325}
5326
5327template <>
5328time_base::dateorder
5329__time_get_storage<wchar_t>::__do_date_order() const
5330{
5331 unsigned i;
5332 for (i = 0; i < __x_.size(); ++i)
5333 if (__x_[i] == L'%')
5334 break;
5335 ++i;
5336 switch (__x_[i])
5337 {
5338 case L'y':
5339 case L'Y':
5340 for (++i; i < __x_.size(); ++i)
5341 if (__x_[i] == L'%')
5342 break;
5343 if (i == __x_.size())
5344 break;
5345 ++i;
5346 switch (__x_[i])
5347 {
5348 case L'm':
5349 for (++i; i < __x_.size(); ++i)
5350 if (__x_[i] == L'%')
5351 break;
5352 if (i == __x_.size())
5353 break;
5354 ++i;
5355 if (__x_[i] == L'd')
5356 return time_base::ymd;
5357 break;
5358 case L'd':
5359 for (++i; i < __x_.size(); ++i)
5360 if (__x_[i] == L'%')
5361 break;
5362 if (i == __x_.size())
5363 break;
5364 ++i;
5365 if (__x_[i] == L'm')
5366 return time_base::ydm;
5367 break;
5368 }
5369 break;
5370 case L'm':
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'd')
5378 {
5379 for (++i; i < __x_.size(); ++i)
5380 if (__x_[i] == L'%')
5381 break;
5382 if (i == __x_.size())
5383 break;
5384 ++i;
5385 if (__x_[i] == L'y' || __x_[i] == L'Y')
5386 return time_base::mdy;
5387 break;
5388 }
5389 break;
5390 case L'd':
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'm')
5398 {
5399 for (++i; i < __x_.size(); ++i)
5400 if (__x_[i] == L'%')
5401 break;
5402 if (i == __x_.size())
5403 break;
5404 ++i;
5405 if (__x_[i] == L'y' || __x_[i] == L'Y')
5406 return time_base::dmy;
5407 break;
5408 }
5409 break;
5410 }
5411 return time_base::no_order;
5412}
5413
5414// time_put
5415
5416__time_put::__time_put(const char* nm)
5417 : __loc_(newlocale(LC_ALL_MASK, nm, 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 " + string(nm));
5422}
5423
5424__time_put::__time_put(const string& nm)
5425 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5426{
5427 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005428 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005429 " failed to construct for " + nm);
5430}
5431
5432__time_put::~__time_put()
5433{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005434 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005435 freelocale(__loc_);
5436}
5437
5438void
5439__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5440 char __fmt, char __mod) const
5441{
5442 char fmt[] = {'%', __fmt, __mod, 0};
5443 if (__mod != 0)
5444 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005445 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005446 __ne = __nb + n;
5447}
5448
5449void
5450__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5451 char __fmt, char __mod) const
5452{
5453 char __nar[100];
5454 char* __ne = __nar + 100;
5455 __do_put(__nar, __ne, __tm, __fmt, __mod);
5456 mbstate_t mb = {0};
5457 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005458 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005459 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005460 __throw_runtime_error("locale not supported");
5461 __we = __wb + j;
5462}
5463
5464// moneypunct_byname
5465
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005466template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005467static
5468void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005469__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5470 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5471 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005472{
5473 const char sign = static_cast<char>(money_base::sign);
5474 const char space = static_cast<char>(money_base::space);
5475 const char none = static_cast<char>(money_base::none);
5476 const char symbol = static_cast<char>(money_base::symbol);
5477 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005478 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5479
5480 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5481 // function'. "Space between sign and symbol or value" means that
5482 // if the sign is adjacent to the symbol, there's a space between
5483 // them, and otherwise there's a space between the sign and value.
5484 //
5485 // C11's localeconv specifies that the fourth character of an
5486 // international curr_symbol is used to separate the sign and
5487 // value when sep_by_space says to do so. C++ can't represent
5488 // that, so we just use a space. When sep_by_space says to
5489 // separate the symbol and value-or-sign with a space, we rearrange the
5490 // curr_symbol to put its spacing character on the correct side of
5491 // the symbol.
5492 //
5493 // We also need to avoid adding an extra space between the sign
5494 // and value when the currency symbol is suppressed (by not
5495 // setting showbase). We match glibc's strfmon by interpreting
5496 // sep_by_space==1 as "omit the space when the currency symbol is
5497 // absent".
5498 //
5499 // Users who want to get this right should use ICU instead.
5500
Howard Hinnantc51e1022010-05-11 19:42:16 +00005501 switch (cs_precedes)
5502 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005503 case 0: // value before curr_symbol
5504 if (symbol_contains_sep) {
5505 // Move the separator to before the symbol, to place it
5506 // between the value and symbol.
5507 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5508 __curr_symbol_.end());
5509 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005510 switch (sign_posn)
5511 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005512 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005513 pat.field[0] = sign;
5514 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005515 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005516 pat.field[3] = symbol;
5517 switch (sep_by_space)
5518 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005519 case 0: // No space separates the currency symbol and value.
5520 // This case may have changed between C99 and C11;
5521 // assume the currency symbol matches the intention.
5522 case 2: // Space between sign and currency or value.
5523 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005524 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005525 case 1: // Space between currency-and-sign or currency and value.
5526 if (!symbol_contains_sep) {
5527 // We insert the space into the symbol instead of
5528 // setting pat.field[2]=space so that when
5529 // showbase is not set, the space goes away too.
5530 __curr_symbol_.insert(0, 1, space_char);
5531 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005532 return;
5533 default:
5534 break;
5535 }
5536 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005537 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005538 pat.field[0] = sign;
5539 pat.field[3] = symbol;
5540 switch (sep_by_space)
5541 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005542 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005543 pat.field[1] = value;
5544 pat.field[2] = none;
5545 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005546 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005547 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005548 pat.field[2] = none;
5549 if (!symbol_contains_sep) {
5550 // We insert the space into the symbol instead of
5551 // setting pat.field[2]=space so that when
5552 // showbase is not set, the space goes away too.
5553 __curr_symbol_.insert(0, 1, space_char);
5554 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005555 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005556 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005557 pat.field[1] = space;
5558 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005559 if (symbol_contains_sep) {
5560 // Remove the separator from the symbol, since it
5561 // has already appeared after the sign.
5562 __curr_symbol_.erase(__curr_symbol_.begin());
5563 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005564 return;
5565 default:
5566 break;
5567 }
5568 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005569 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005570 pat.field[0] = value;
5571 pat.field[3] = sign;
5572 switch (sep_by_space)
5573 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005574 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005575 pat.field[1] = none;
5576 pat.field[2] = symbol;
5577 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005578 case 1: // Space between currency-and-sign or currency and value.
5579 if (!symbol_contains_sep) {
5580 // We insert the space into the symbol instead of
5581 // setting pat.field[1]=space so that when
5582 // showbase is not set, the space goes away too.
5583 __curr_symbol_.insert(0, 1, space_char);
5584 }
5585 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005586 pat.field[2] = symbol;
5587 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005588 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005589 pat.field[1] = symbol;
5590 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005591 if (symbol_contains_sep) {
5592 // Remove the separator from the symbol, since it
5593 // should not be removed if showbase is absent.
5594 __curr_symbol_.erase(__curr_symbol_.begin());
5595 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005596 return;
5597 default:
5598 break;
5599 }
5600 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005601 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602 pat.field[0] = value;
5603 pat.field[3] = symbol;
5604 switch (sep_by_space)
5605 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005606 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005607 pat.field[1] = none;
5608 pat.field[2] = sign;
5609 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005610 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005611 pat.field[1] = space;
5612 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005613 if (symbol_contains_sep) {
5614 // Remove the separator from the symbol, since it
5615 // has already appeared before the sign.
5616 __curr_symbol_.erase(__curr_symbol_.begin());
5617 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005618 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005619 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005620 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005621 pat.field[2] = none;
5622 if (!symbol_contains_sep) {
5623 // We insert the space into the symbol instead of
5624 // setting pat.field[2]=space so that when
5625 // showbase is not set, the space goes away too.
5626 __curr_symbol_.insert(0, 1, space_char);
5627 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005628 return;
5629 default:
5630 break;
5631 }
5632 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005633 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005634 pat.field[0] = value;
5635 pat.field[3] = sign;
5636 switch (sep_by_space)
5637 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005638 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005639 pat.field[1] = none;
5640 pat.field[2] = symbol;
5641 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005642 case 1: // Space between currency-and-sign or currency and value.
5643 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005644 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005645 if (!symbol_contains_sep) {
5646 // We insert the space into the symbol instead of
5647 // setting pat.field[1]=space so that when
5648 // showbase is not set, the space goes away too.
5649 __curr_symbol_.insert(0, 1, space_char);
5650 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005651 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005652 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005653 pat.field[1] = symbol;
5654 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005655 if (symbol_contains_sep) {
5656 // Remove the separator from the symbol, since it
5657 // should not disappear when showbase is absent.
5658 __curr_symbol_.erase(__curr_symbol_.begin());
5659 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005660 return;
5661 default:
5662 break;
5663 }
5664 break;
5665 default:
5666 break;
5667 }
5668 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005669 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005670 switch (sign_posn)
5671 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005672 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005673 pat.field[0] = sign;
5674 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005675 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005676 pat.field[3] = value;
5677 switch (sep_by_space)
5678 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005679 case 0: // No space separates the currency symbol and value.
5680 // This case may have changed between C99 and C11;
5681 // assume the currency symbol matches the intention.
5682 case 2: // Space between sign and currency or value.
5683 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005684 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005685 case 1: // Space between currency-and-sign or currency and value.
5686 if (!symbol_contains_sep) {
5687 // We insert the space into the symbol instead of
5688 // setting pat.field[2]=space so that when
5689 // showbase is not set, the space goes away too.
5690 __curr_symbol_.insert(0, 1, space_char);
5691 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005692 return;
5693 default:
5694 break;
5695 }
5696 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005697 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005698 pat.field[0] = sign;
5699 pat.field[3] = value;
5700 switch (sep_by_space)
5701 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005702 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005703 pat.field[1] = symbol;
5704 pat.field[2] = none;
5705 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005706 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005707 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005708 pat.field[2] = none;
5709 if (!symbol_contains_sep) {
5710 // We insert the space into the symbol instead of
5711 // setting pat.field[2]=space so that when
5712 // showbase is not set, the space goes away too.
5713 __curr_symbol_.push_back(space_char);
5714 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005715 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005716 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005717 pat.field[1] = space;
5718 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005719 if (symbol_contains_sep) {
5720 // Remove the separator from the symbol, since it
5721 // has already appeared after the sign.
5722 __curr_symbol_.pop_back();
5723 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005724 return;
5725 default:
5726 break;
5727 }
5728 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005729 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005730 pat.field[0] = symbol;
5731 pat.field[3] = sign;
5732 switch (sep_by_space)
5733 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005734 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005735 pat.field[1] = none;
5736 pat.field[2] = value;
5737 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005738 case 1: // Space between currency-and-sign or currency and value.
5739 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005740 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005741 if (!symbol_contains_sep) {
5742 // We insert the space into the symbol instead of
5743 // setting pat.field[1]=space so that when
5744 // showbase is not set, the space goes away too.
5745 __curr_symbol_.push_back(space_char);
5746 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005747 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005748 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005749 pat.field[1] = value;
5750 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005751 if (symbol_contains_sep) {
5752 // Remove the separator from the symbol, since it
5753 // will appear before the sign.
5754 __curr_symbol_.pop_back();
5755 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005756 return;
5757 default:
5758 break;
5759 }
5760 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005761 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005762 pat.field[0] = sign;
5763 pat.field[3] = value;
5764 switch (sep_by_space)
5765 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005766 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005767 pat.field[1] = symbol;
5768 pat.field[2] = none;
5769 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005770 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005771 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005772 pat.field[2] = none;
5773 if (!symbol_contains_sep) {
5774 // We insert the space into the symbol instead of
5775 // setting pat.field[2]=space so that when
5776 // showbase is not set, the space goes away too.
5777 __curr_symbol_.push_back(space_char);
5778 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005779 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005780 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005781 pat.field[1] = space;
5782 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005783 if (symbol_contains_sep) {
5784 // Remove the separator from the symbol, since it
5785 // has already appeared after the sign.
5786 __curr_symbol_.pop_back();
5787 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005788 return;
5789 default:
5790 break;
5791 }
5792 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005793 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005794 pat.field[0] = symbol;
5795 pat.field[3] = value;
5796 switch (sep_by_space)
5797 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005798 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005799 pat.field[1] = sign;
5800 pat.field[2] = none;
5801 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005802 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005803 pat.field[1] = sign;
5804 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005805 if (symbol_contains_sep) {
5806 // Remove the separator from the symbol, since it
5807 // should not disappear when showbase is absent.
5808 __curr_symbol_.pop_back();
5809 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005810 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005811 case 2: // Space between sign and currency or value.
5812 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005813 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005814 if (!symbol_contains_sep) {
5815 // We insert the space into the symbol instead of
5816 // setting pat.field[1]=space so that when
5817 // showbase is not set, the space goes away too.
5818 __curr_symbol_.push_back(space_char);
5819 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005820 return;
5821 default:
5822 break;
5823 }
5824 break;
5825 default:
5826 break;
5827 }
5828 break;
5829 default:
5830 break;
5831 }
5832 pat.field[0] = symbol;
5833 pat.field[1] = sign;
5834 pat.field[2] = none;
5835 pat.field[3] = value;
5836}
5837
5838template<>
5839void
5840moneypunct_byname<char, false>::init(const char* nm)
5841{
5842 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005843 __libcpp_unique_locale loc(nm);
5844 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005845 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005846 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005847
Ben Craig3756b922016-03-09 15:39:39 +00005848 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005849 if (!checked_string_to_char_convert(__decimal_point_,
5850 lc->mon_decimal_point,
5851 loc.get()))
5852 __decimal_point_ = base::do_decimal_point();
5853 if (!checked_string_to_char_convert(__thousands_sep_,
5854 lc->mon_thousands_sep,
5855 loc.get()))
5856 __thousands_sep_ = base::do_thousands_sep();
5857
Howard Hinnantc51e1022010-05-11 19:42:16 +00005858 __grouping_ = lc->mon_grouping;
5859 __curr_symbol_ = lc->currency_symbol;
5860 if (lc->frac_digits != CHAR_MAX)
5861 __frac_digits_ = lc->frac_digits;
5862 else
5863 __frac_digits_ = base::do_frac_digits();
5864 if (lc->p_sign_posn == 0)
5865 __positive_sign_ = "()";
5866 else
5867 __positive_sign_ = lc->positive_sign;
5868 if (lc->n_sign_posn == 0)
5869 __negative_sign_ = "()";
5870 else
5871 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005872 // Assume the positive and negative formats will want spaces in
5873 // the same places in curr_symbol since there's no way to
5874 // represent anything else.
5875 string_type __dummy_curr_symbol = __curr_symbol_;
5876 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5877 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5878 __init_pat(__neg_format_, __curr_symbol_, false,
5879 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005880}
5881
5882template<>
5883void
5884moneypunct_byname<char, true>::init(const char* nm)
5885{
5886 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005887 __libcpp_unique_locale loc(nm);
5888 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005889 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005890 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005891
Ben Craig3756b922016-03-09 15:39:39 +00005892 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005893 if (!checked_string_to_char_convert(__decimal_point_,
5894 lc->mon_decimal_point,
5895 loc.get()))
5896 __decimal_point_ = base::do_decimal_point();
5897 if (!checked_string_to_char_convert(__thousands_sep_,
5898 lc->mon_thousands_sep,
5899 loc.get()))
5900 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005901 __grouping_ = lc->mon_grouping;
5902 __curr_symbol_ = lc->int_curr_symbol;
5903 if (lc->int_frac_digits != CHAR_MAX)
5904 __frac_digits_ = lc->int_frac_digits;
5905 else
5906 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005907#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005908 if (lc->p_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_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005911#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005912 __positive_sign_ = "()";
5913 else
5914 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005915#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005916 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005917#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005918 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005919#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005920 __negative_sign_ = "()";
5921 else
5922 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005923 // Assume the positive and negative formats will want spaces in
5924 // the same places in curr_symbol since there's no way to
5925 // represent anything else.
5926 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005927#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005928 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5929 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5930 __init_pat(__neg_format_, __curr_symbol_, true,
5931 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005932#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005933 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5934 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5935 lc->int_p_sign_posn, ' ');
5936 __init_pat(__neg_format_, __curr_symbol_, true,
5937 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5938 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005939#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005940}
5941
5942template<>
5943void
5944moneypunct_byname<wchar_t, false>::init(const char* nm)
5945{
5946 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005947 __libcpp_unique_locale loc(nm);
5948 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005949 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005950 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005951 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005952 if (!checked_string_to_wchar_convert(__decimal_point_,
5953 lc->mon_decimal_point,
5954 loc.get()))
5955 __decimal_point_ = base::do_decimal_point();
5956 if (!checked_string_to_wchar_convert(__thousands_sep_,
5957 lc->mon_thousands_sep,
5958 loc.get()))
5959 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005960 __grouping_ = lc->mon_grouping;
5961 wchar_t wbuf[100];
5962 mbstate_t mb = {0};
5963 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005964 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005965 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005966 __throw_runtime_error("locale not supported");
5967 wchar_t* wbe = wbuf + j;
5968 __curr_symbol_.assign(wbuf, wbe);
5969 if (lc->frac_digits != CHAR_MAX)
5970 __frac_digits_ = lc->frac_digits;
5971 else
5972 __frac_digits_ = base::do_frac_digits();
5973 if (lc->p_sign_posn == 0)
5974 __positive_sign_ = L"()";
5975 else
5976 {
5977 mb = mbstate_t();
5978 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005979 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005980 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005981 __throw_runtime_error("locale not supported");
5982 wbe = wbuf + j;
5983 __positive_sign_.assign(wbuf, wbe);
5984 }
5985 if (lc->n_sign_posn == 0)
5986 __negative_sign_ = L"()";
5987 else
5988 {
5989 mb = mbstate_t();
5990 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005991 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005992 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005993 __throw_runtime_error("locale not supported");
5994 wbe = wbuf + j;
5995 __negative_sign_.assign(wbuf, wbe);
5996 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005997 // Assume the positive and negative formats will want spaces in
5998 // the same places in curr_symbol since there's no way to
5999 // represent anything else.
6000 string_type __dummy_curr_symbol = __curr_symbol_;
6001 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6002 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6003 __init_pat(__neg_format_, __curr_symbol_, false,
6004 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006005}
6006
6007template<>
6008void
6009moneypunct_byname<wchar_t, true>::init(const char* nm)
6010{
6011 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006012 __libcpp_unique_locale loc(nm);
6013 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006014 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006015 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006016
Ben Craig3756b922016-03-09 15:39:39 +00006017 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006018 if (!checked_string_to_wchar_convert(__decimal_point_,
6019 lc->mon_decimal_point,
6020 loc.get()))
6021 __decimal_point_ = base::do_decimal_point();
6022 if (!checked_string_to_wchar_convert(__thousands_sep_,
6023 lc->mon_thousands_sep,
6024 loc.get()))
6025 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006026 __grouping_ = lc->mon_grouping;
6027 wchar_t wbuf[100];
6028 mbstate_t mb = {0};
6029 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006030 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006031 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006032 __throw_runtime_error("locale not supported");
6033 wchar_t* wbe = wbuf + j;
6034 __curr_symbol_.assign(wbuf, wbe);
6035 if (lc->int_frac_digits != CHAR_MAX)
6036 __frac_digits_ = lc->int_frac_digits;
6037 else
6038 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006039#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006040 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006041#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006042 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006043#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006044 __positive_sign_ = L"()";
6045 else
6046 {
6047 mb = mbstate_t();
6048 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006049 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006050 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006051 __throw_runtime_error("locale not supported");
6052 wbe = wbuf + j;
6053 __positive_sign_.assign(wbuf, wbe);
6054 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006055#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006056 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006057#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006058 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006059#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006060 __negative_sign_ = L"()";
6061 else
6062 {
6063 mb = mbstate_t();
6064 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006065 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006066 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006067 __throw_runtime_error("locale not supported");
6068 wbe = wbuf + j;
6069 __negative_sign_.assign(wbuf, wbe);
6070 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006071 // Assume the positive and negative formats will want spaces in
6072 // the same places in curr_symbol since there's no way to
6073 // represent anything else.
6074 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006075#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006076 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6077 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6078 __init_pat(__neg_format_, __curr_symbol_, true,
6079 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006080#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006081 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6082 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6083 lc->int_p_sign_posn, L' ');
6084 __init_pat(__neg_format_, __curr_symbol_, true,
6085 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6086 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006087#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006088}
6089
6090void __do_nothing(void*) {}
6091
6092void __throw_runtime_error(const char* msg)
6093{
Howard Hinnant72f73582010-08-11 17:04:31 +00006094#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006095 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006096#else
6097 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006098 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006099#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006100}
6101
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006102template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6103template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006104
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006105template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6106template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006107
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006108template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6109template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006110
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006111template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6112template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006113
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006114template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6115template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006116
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006117template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6118template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006119
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006120template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6121template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006122
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006123template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6124template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006125
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006126template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6127template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006128
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006129template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6130template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6131template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6132template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006133
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006134template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6135template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6136template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6137template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006138
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006139template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6140template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006142template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6143template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006144
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006145template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6146template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006147
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006148template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6149template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006150
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006151template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6152template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006153
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006154template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6155template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006156
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006157template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6158template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6159template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6160template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006161
Howard Hinnantc51e1022010-05-11 19:42:16 +00006162_LIBCPP_END_NAMESPACE_STD