blob: b9c701137df2d7f86394dcedc7d3907e0db6dab4 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantc566dc32010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00004//
Howard Hinnantee11c312010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantc51e1022010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
David Chisnall8074c342012-02-29 13:05:08 +000010// On Solaris, we need to define something to make the C99 parts of localeconv
11// visible.
12#ifdef __sun__
13#define _LCONV_C99
14#endif
15
Howard Hinnantc51e1022010-05-11 19:42:16 +000016#include "string"
17#include "locale"
Howard Hinnant7282c5a2010-05-30 21:39:41 +000018#include "codecvt"
Howard Hinnantc51e1022010-05-11 19:42:16 +000019#include "vector"
20#include "algorithm"
Howard Hinnantc51e1022010-05-11 19:42:16 +000021#include "typeinfo"
Howard Hinnant718dae32013-07-28 18:20:00 +000022#ifndef _LIBCPP_NO_EXCEPTIONS
23# include "type_traits"
24#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000025#include "clocale"
26#include "cstring"
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +000027#if defined(_LIBCPP_MSVCRT)
28#define _CTYPE_DISABLE_MACROS
29#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000030#include "cwctype"
31#include "__sso_allocator"
Howard Hinnant8ad70912013-09-17 01:34:47 +000032#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Marshall Clowccb92572015-06-23 14:45:02 +000033#include "support/win32/locale_win32.h"
Dan Albert21800dc2016-09-19 18:00:45 +000034#elif !defined(__BIONIC__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000035#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000036#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000037#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000038#include <stdio.h>
Weiming Zhaob613db72017-09-19 23:18:03 +000039#include "include/atomic_support.h"
Eric Fiselierf4433a32017-05-31 22:07:49 +000040#include "__undef_macros"
Howard Hinnantc51e1022010-05-11 19:42:16 +000041
Marshall Clowab9c1772013-02-07 17:20:56 +000042// On Linux, wint_t and wchar_t have different signed-ness, and this causes
43// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000044#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000045#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000046#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000047
Howard Hinnantc51e1022010-05-11 19:42:16 +000048_LIBCPP_BEGIN_NAMESPACE_STD
49
Eric Fiselierebc2d2c2017-05-08 22:02:43 +000050struct __libcpp_unique_locale {
51 __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
52
53 ~__libcpp_unique_locale() {
54 if (__loc_)
55 freelocale(__loc_);
56 }
57
58 explicit operator bool() const { return __loc_; }
59
60 locale_t& get() { return __loc_; }
61
62 locale_t __loc_;
63private:
64 __libcpp_unique_locale(__libcpp_unique_locale const&);
65 __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
66};
67
Howard Hinnantf312e3e2011-09-28 23:39:33 +000068#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000069locale_t __cloc() {
70 // In theory this could create a race condition. In practice
71 // the race condition is non-fatal since it will just create
72 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000073 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
74 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000075}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000076#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000077
Howard Hinnantc51e1022010-05-11 19:42:16 +000078namespace {
79
80struct release
81{
82 void operator()(locale::facet* p) {p->__release_shared();}
83};
84
85template <class T, class A0>
86inline
87T&
88make(A0 a0)
89{
90 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +000091 auto *obj = ::new (&buf) T(a0);
92 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +000093}
94
95template <class T, class A0, class A1>
96inline
97T&
98make(A0 a0, A1 a1)
99{
100 static typename aligned_storage<sizeof(T)>::type buf;
101 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000102 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000103}
104
105template <class T, class A0, class A1, class A2>
106inline
107T&
108make(A0 a0, A1 a1, A2 a2)
109{
110 static typename aligned_storage<sizeof(T)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000111 auto *obj = ::new (&buf) T(a0, a1, a2);
112 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000113}
114
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000115template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000116inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000117_LIBCPP_CONSTEXPR
118size_t
119countof(const T (&)[N])
120{
121 return N;
122}
123
124template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000125inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000126_LIBCPP_CONSTEXPR
127size_t
128countof(const T * const begin, const T * const end)
129{
130 return static_cast<size_t>(end - begin);
131}
132
Marshall Clow8fea1612016-08-25 15:09:01 +0000133_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
134{
135#ifndef _LIBCPP_NO_EXCEPTIONS
136 throw runtime_error(msg);
137#else
138 (void)msg;
139 _VSTD::abort();
140#endif
141}
142
Howard Hinnantc51e1022010-05-11 19:42:16 +0000143}
144
Howard Hinnantdd099492013-08-29 23:37:50 +0000145#if defined(_AIX)
146// Set priority to INT_MIN + 256 + 150
147# pragma priority ( -2147483242 )
148#endif
149
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000150const locale::category locale::none;
151const locale::category locale::collate;
152const locale::category locale::ctype;
153const locale::category locale::monetary;
154const locale::category locale::numeric;
155const locale::category locale::time;
156const locale::category locale::messages;
157const locale::category locale::all;
158
Howard Hinnantc51e1022010-05-11 19:42:16 +0000159class _LIBCPP_HIDDEN locale::__imp
160 : public facet
161{
162 enum {N = 28};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000163#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000164// FIXME: MSVC doesn't support aligned parameters by value.
165// I can't get the __sso_allocator to work here
166// for MSVC I think for this reason.
167 vector<facet*> facets_;
168#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000169 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000170#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000171 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000172public:
173 explicit __imp(size_t refs = 0);
174 explicit __imp(const string& name, size_t refs = 0);
175 __imp(const __imp&);
176 __imp(const __imp&, const string&, locale::category c);
177 __imp(const __imp& other, const __imp& one, locale::category c);
178 __imp(const __imp&, facet* f, long id);
179 ~__imp();
180
181 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000182 bool has_facet(long id) const
183 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000184 const locale::facet* use_facet(long id) const;
185
186 static const locale& make_classic();
187 static locale& make_global();
188private:
189 void install(facet* f, long id);
190 template <class F> void install(F* f) {install(f, f->id.__get());}
191 template <class F> void install_from(const __imp& other);
192};
193
194locale::__imp::__imp(size_t refs)
195 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000196 facets_(N),
197 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000198{
199 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000200 install(&make<_VSTD::collate<char> >(1u));
201 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000202 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000203 install(&make<_VSTD::ctype<wchar_t> >(1u));
204 install(&make<codecvt<char, char, mbstate_t> >(1u));
205 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
206 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
207 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
208 install(&make<numpunct<char> >(1u));
209 install(&make<numpunct<wchar_t> >(1u));
210 install(&make<num_get<char> >(1u));
211 install(&make<num_get<wchar_t> >(1u));
212 install(&make<num_put<char> >(1u));
213 install(&make<num_put<wchar_t> >(1u));
214 install(&make<moneypunct<char, false> >(1u));
215 install(&make<moneypunct<char, true> >(1u));
216 install(&make<moneypunct<wchar_t, false> >(1u));
217 install(&make<moneypunct<wchar_t, true> >(1u));
218 install(&make<money_get<char> >(1u));
219 install(&make<money_get<wchar_t> >(1u));
220 install(&make<money_put<char> >(1u));
221 install(&make<money_put<wchar_t> >(1u));
222 install(&make<time_get<char> >(1u));
223 install(&make<time_get<wchar_t> >(1u));
224 install(&make<time_put<char> >(1u));
225 install(&make<time_put<wchar_t> >(1u));
226 install(&make<_VSTD::messages<char> >(1u));
227 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000228}
229
230locale::__imp::__imp(const string& name, size_t refs)
231 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000232 facets_(N),
233 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000234{
Howard Hinnant72f73582010-08-11 17:04:31 +0000235#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000236 try
237 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000238#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000239 facets_ = locale::classic().__locale_->facets_;
240 for (unsigned i = 0; i < facets_.size(); ++i)
241 if (facets_[i])
242 facets_[i]->__add_shared();
243 install(new collate_byname<char>(name_));
244 install(new collate_byname<wchar_t>(name_));
245 install(new ctype_byname<char>(name_));
246 install(new ctype_byname<wchar_t>(name_));
247 install(new codecvt_byname<char, char, mbstate_t>(name_));
248 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
249 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
250 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
251 install(new numpunct_byname<char>(name_));
252 install(new numpunct_byname<wchar_t>(name_));
253 install(new moneypunct_byname<char, false>(name_));
254 install(new moneypunct_byname<char, true>(name_));
255 install(new moneypunct_byname<wchar_t, false>(name_));
256 install(new moneypunct_byname<wchar_t, true>(name_));
257 install(new time_get_byname<char>(name_));
258 install(new time_get_byname<wchar_t>(name_));
259 install(new time_put_byname<char>(name_));
260 install(new time_put_byname<wchar_t>(name_));
261 install(new messages_byname<char>(name_));
262 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000263#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000264 }
265 catch (...)
266 {
267 for (unsigned i = 0; i < facets_.size(); ++i)
268 if (facets_[i])
269 facets_[i]->__release_shared();
270 throw;
271 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000272#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000273}
274
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000275// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000276// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000277#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000278#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000279#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000280#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000281
Howard Hinnantc51e1022010-05-11 19:42:16 +0000282locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000283 : facets_(max<size_t>(N, other.facets_.size())),
284 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000285{
286 facets_ = other.facets_;
287 for (unsigned i = 0; i < facets_.size(); ++i)
288 if (facets_[i])
289 facets_[i]->__add_shared();
290}
291
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000292#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000293#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000294#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000295
Howard Hinnantc51e1022010-05-11 19:42:16 +0000296locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000297 : facets_(N),
298 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000299{
300 facets_ = other.facets_;
301 for (unsigned i = 0; i < facets_.size(); ++i)
302 if (facets_[i])
303 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000304#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000305 try
306 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000307#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000308 if (c & locale::collate)
309 {
310 install(new collate_byname<char>(name));
311 install(new collate_byname<wchar_t>(name));
312 }
313 if (c & locale::ctype)
314 {
315 install(new ctype_byname<char>(name));
316 install(new ctype_byname<wchar_t>(name));
317 install(new codecvt_byname<char, char, mbstate_t>(name));
318 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
319 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
320 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
321 }
322 if (c & locale::monetary)
323 {
324 install(new moneypunct_byname<char, false>(name));
325 install(new moneypunct_byname<char, true>(name));
326 install(new moneypunct_byname<wchar_t, false>(name));
327 install(new moneypunct_byname<wchar_t, true>(name));
328 }
329 if (c & locale::numeric)
330 {
331 install(new numpunct_byname<char>(name));
332 install(new numpunct_byname<wchar_t>(name));
333 }
334 if (c & locale::time)
335 {
336 install(new time_get_byname<char>(name));
337 install(new time_get_byname<wchar_t>(name));
338 install(new time_put_byname<char>(name));
339 install(new time_put_byname<wchar_t>(name));
340 }
341 if (c & locale::messages)
342 {
343 install(new messages_byname<char>(name));
344 install(new messages_byname<wchar_t>(name));
345 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000346#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000347 }
348 catch (...)
349 {
350 for (unsigned i = 0; i < facets_.size(); ++i)
351 if (facets_[i])
352 facets_[i]->__release_shared();
353 throw;
354 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000355#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000356}
357
358template<class F>
359inline
360void
361locale::__imp::install_from(const locale::__imp& one)
362{
363 long id = F::id.__get();
364 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
365}
366
367locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000368 : facets_(N),
369 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000370{
371 facets_ = other.facets_;
372 for (unsigned i = 0; i < facets_.size(); ++i)
373 if (facets_[i])
374 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000375#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000376 try
377 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000378#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000379 if (c & locale::collate)
380 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000381 install_from<_VSTD::collate<char> >(one);
382 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000383 }
384 if (c & locale::ctype)
385 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000386 install_from<_VSTD::ctype<char> >(one);
387 install_from<_VSTD::ctype<wchar_t> >(one);
388 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
389 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
390 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
391 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000392 }
393 if (c & locale::monetary)
394 {
395 install_from<moneypunct<char, false> >(one);
396 install_from<moneypunct<char, true> >(one);
397 install_from<moneypunct<wchar_t, false> >(one);
398 install_from<moneypunct<wchar_t, true> >(one);
399 install_from<money_get<char> >(one);
400 install_from<money_get<wchar_t> >(one);
401 install_from<money_put<char> >(one);
402 install_from<money_put<wchar_t> >(one);
403 }
404 if (c & locale::numeric)
405 {
406 install_from<numpunct<char> >(one);
407 install_from<numpunct<wchar_t> >(one);
408 install_from<num_get<char> >(one);
409 install_from<num_get<wchar_t> >(one);
410 install_from<num_put<char> >(one);
411 install_from<num_put<wchar_t> >(one);
412 }
413 if (c & locale::time)
414 {
415 install_from<time_get<char> >(one);
416 install_from<time_get<wchar_t> >(one);
417 install_from<time_put<char> >(one);
418 install_from<time_put<wchar_t> >(one);
419 }
420 if (c & locale::messages)
421 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000422 install_from<_VSTD::messages<char> >(one);
423 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000424 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000425#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000426 }
427 catch (...)
428 {
429 for (unsigned i = 0; i < facets_.size(); ++i)
430 if (facets_[i])
431 facets_[i]->__release_shared();
432 throw;
433 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000434#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000435}
436
437locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000438 : facets_(max<size_t>(N, other.facets_.size()+1)),
439 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000440{
441 f->__add_shared();
442 unique_ptr<facet, release> hold(f);
443 facets_ = other.facets_;
444 for (unsigned i = 0; i < other.facets_.size(); ++i)
445 if (facets_[i])
446 facets_[i]->__add_shared();
447 install(hold.get(), id);
448}
449
450locale::__imp::~__imp()
451{
452 for (unsigned i = 0; i < facets_.size(); ++i)
453 if (facets_[i])
454 facets_[i]->__release_shared();
455}
456
457void
458locale::__imp::install(facet* f, long id)
459{
460 f->__add_shared();
461 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000462 if (static_cast<size_t>(id) >= facets_.size())
463 facets_.resize(static_cast<size_t>(id+1));
464 if (facets_[static_cast<size_t>(id)])
465 facets_[static_cast<size_t>(id)]->__release_shared();
466 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000467}
468
469const locale::facet*
470locale::__imp::use_facet(long id) const
471{
Howard Hinnant72f73582010-08-11 17:04:31 +0000472#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000473 if (!has_facet(id))
474 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000475#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000476 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000477}
478
479// locale
480
481const locale&
482locale::__imp::make_classic()
483{
484 // only one thread can get in here and it only gets in once
485 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000486 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000487 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000488 return *c;
489}
490
491const locale&
492locale::classic()
493{
494 static const locale& c = __imp::make_classic();
495 return c;
496}
497
498locale&
499locale::__imp::make_global()
500{
501 // only one thread can get in here and it only gets in once
502 static aligned_storage<sizeof(locale)>::type buf;
Eric Fiselier4db80032017-05-05 20:32:26 +0000503 auto *obj = ::new (&buf) locale(locale::classic());
504 return *obj;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000505}
506
507locale&
508locale::__global()
509{
510 static locale& g = __imp::make_global();
511 return g;
512}
513
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000514locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000515 : __locale_(__global().__locale_)
516{
517 __locale_->__add_shared();
518}
519
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000520locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000521 : __locale_(l.__locale_)
522{
523 __locale_->__add_shared();
524}
525
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000526locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000527{
528 __locale_->__release_shared();
529}
530
531const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000532locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000533{
534 other.__locale_->__add_shared();
535 __locale_->__release_shared();
536 __locale_ = other.__locale_;
537 return *this;
538}
539
540locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000541#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000542 : __locale_(name ? new __imp(name)
543 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000544#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000545 : __locale_(new __imp(name))
546#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000547{
548 __locale_->__add_shared();
549}
550
551locale::locale(const string& name)
552 : __locale_(new __imp(name))
553{
554 __locale_->__add_shared();
555}
556
557locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000558#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000559 : __locale_(name ? new __imp(*other.__locale_, name, c)
560 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000561#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000562 : __locale_(new __imp(*other.__locale_, name, c))
563#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000564{
565 __locale_->__add_shared();
566}
567
568locale::locale(const locale& other, const string& name, category c)
569 : __locale_(new __imp(*other.__locale_, name, c))
570{
571 __locale_->__add_shared();
572}
573
574locale::locale(const locale& other, const locale& one, category c)
575 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
576{
577 __locale_->__add_shared();
578}
579
580string
581locale::name() const
582{
583 return __locale_->name();
584}
585
586void
587locale::__install_ctor(const locale& other, facet* f, long id)
588{
589 if (f)
590 __locale_ = new __imp(*other.__locale_, f, id);
591 else
592 __locale_ = other.__locale_;
593 __locale_->__add_shared();
594}
595
596locale
597locale::global(const locale& loc)
598{
599 locale& g = __global();
600 locale r = g;
601 g = loc;
602 if (g.name() != "*")
603 setlocale(LC_ALL, g.name().c_str());
604 return r;
605}
606
607bool
608locale::has_facet(id& x) const
609{
610 return __locale_->has_facet(x.__get());
611}
612
613const locale::facet*
614locale::use_facet(id& x) const
615{
616 return __locale_->use_facet(x.__get());
617}
618
619bool
620locale::operator==(const locale& y) const
621{
622 return (__locale_ == y.__locale_)
623 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
624}
625
626// locale::facet
627
628locale::facet::~facet()
629{
630}
631
632void
Howard Hinnant719bda32011-05-28 14:41:13 +0000633locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000634{
635 delete this;
636}
637
638// locale::id
639
640int32_t locale::id::__next_id = 0;
641
642namespace
643{
644
645class __fake_bind
646{
647 locale::id* id_;
648 void (locale::id::* pmf_)();
649public:
650 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
651 : id_(id), pmf_(pmf) {}
652
653 void operator()() const
654 {
655 (id_->*pmf_)();
656 }
657};
658
659}
660
661long
662locale::id::__get()
663{
664 call_once(__flag_, __fake_bind(&locale::id::__init, this));
665 return __id_ - 1;
666}
667
668void
669locale::id::__init()
670{
Weiming Zhaob613db72017-09-19 23:18:03 +0000671 __id_ = __libcpp_atomic_add(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000672}
673
674// template <> class collate_byname<char>
675
676collate_byname<char>::collate_byname(const char* n, size_t refs)
677 : collate<char>(refs),
678 __l(newlocale(LC_ALL_MASK, n, 0))
679{
680 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000681 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000682 " failed to construct for " + string(n));
683}
684
685collate_byname<char>::collate_byname(const string& name, size_t refs)
686 : collate<char>(refs),
687 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
688{
689 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000690 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000691 " failed to construct for " + name);
692}
693
694collate_byname<char>::~collate_byname()
695{
696 freelocale(__l);
697}
698
699int
700collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
701 const char_type* __lo2, const char_type* __hi2) const
702{
703 string_type lhs(__lo1, __hi1);
704 string_type rhs(__lo2, __hi2);
705 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
706 if (r < 0)
707 return -1;
708 if (r > 0)
709 return 1;
710 return r;
711}
712
713collate_byname<char>::string_type
714collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
715{
716 const string_type in(lo, hi);
717 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
718 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
719 return out;
720}
721
722// template <> class collate_byname<wchar_t>
723
724collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
725 : collate<wchar_t>(refs),
726 __l(newlocale(LC_ALL_MASK, n, 0))
727{
728 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000729 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000730 " failed to construct for " + string(n));
731}
732
733collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
734 : collate<wchar_t>(refs),
735 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
736{
737 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000738 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000739 " failed to construct for " + name);
740}
741
742collate_byname<wchar_t>::~collate_byname()
743{
744 freelocale(__l);
745}
746
747int
748collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
749 const char_type* __lo2, const char_type* __hi2) const
750{
751 string_type lhs(__lo1, __hi1);
752 string_type rhs(__lo2, __hi2);
753 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
754 if (r < 0)
755 return -1;
756 if (r > 0)
757 return 1;
758 return r;
759}
760
761collate_byname<wchar_t>::string_type
762collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
763{
764 const string_type in(lo, hi);
765 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
766 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
767 return out;
768}
769
770// template <> class ctype<wchar_t>;
771
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000772const ctype_base::mask ctype_base::space;
773const ctype_base::mask ctype_base::print;
774const ctype_base::mask ctype_base::cntrl;
775const ctype_base::mask ctype_base::upper;
776const ctype_base::mask ctype_base::lower;
777const ctype_base::mask ctype_base::alpha;
778const ctype_base::mask ctype_base::digit;
779const ctype_base::mask ctype_base::punct;
780const ctype_base::mask ctype_base::xdigit;
781const ctype_base::mask ctype_base::blank;
782const ctype_base::mask ctype_base::alnum;
783const ctype_base::mask ctype_base::graph;
784
Howard Hinnantc51e1022010-05-11 19:42:16 +0000785locale::id ctype<wchar_t>::id;
786
787ctype<wchar_t>::~ctype()
788{
789}
790
791bool
792ctype<wchar_t>::do_is(mask m, char_type c) const
793{
Marshall Clowd920eea2013-10-21 15:07:28 +0000794 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000795}
796
797const wchar_t*
798ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
799{
800 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000801 *vec = static_cast<mask>(isascii(*low) ?
802 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000803 return low;
804}
805
806const wchar_t*
807ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
808{
809 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000810 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000811 break;
812 return low;
813}
814
815const wchar_t*
816ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
817{
818 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000819 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000820 break;
821 return low;
822}
823
824wchar_t
825ctype<wchar_t>::do_toupper(char_type c) const
826{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000827#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
828 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000829#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000830 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000831 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000832#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000833 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000834#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000835}
836
837const wchar_t*
838ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
839{
840 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000841#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
842 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000843#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000844 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000845 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
846 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000847#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000848 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000849#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000850 return low;
851}
852
853wchar_t
854ctype<wchar_t>::do_tolower(char_type c) const
855{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000856#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
857 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000858#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000859 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000860 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000861#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000862 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000863#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000864}
865
866const wchar_t*
867ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
868{
869 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000870#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
871 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000872#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000873 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000874 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
875 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000876#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000877 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000878#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000879 return low;
880}
881
882wchar_t
883ctype<wchar_t>::do_widen(char c) const
884{
885 return c;
886}
887
888const char*
889ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
890{
891 for (; low != high; ++low, ++dest)
892 *dest = *low;
893 return low;
894}
895
896char
897ctype<wchar_t>::do_narrow(char_type c, char dfault) const
898{
899 if (isascii(c))
900 return static_cast<char>(c);
901 return dfault;
902}
903
904const wchar_t*
905ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
906{
907 for (; low != high; ++low, ++dest)
908 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000909 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000910 else
911 *dest = dfault;
912 return low;
913}
914
915// template <> class ctype<char>;
916
917locale::id ctype<char>::id;
918
919ctype<char>::ctype(const mask* tab, bool del, size_t refs)
920 : locale::facet(refs),
921 __tab_(tab),
922 __del_(del)
923{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000924 if (__tab_ == 0)
925 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000926}
927
928ctype<char>::~ctype()
929{
930 if (__tab_ && __del_)
931 delete [] __tab_;
932}
933
934char
935ctype<char>::do_toupper(char_type c) const
936{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000937#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000938 return isascii(c) ?
939 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000940#elif defined(__NetBSD__)
941 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000942#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000943 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000944 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000945#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000946 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000947#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000948}
949
950const char*
951ctype<char>::do_toupper(char_type* low, const char_type* high) const
952{
953 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000954#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000955 *low = isascii(*low) ?
956 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000957#elif defined(__NetBSD__)
958 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000959#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000960 *low = isascii(*low) ?
961 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000962#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000963 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000964#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000965 return low;
966}
967
968char
969ctype<char>::do_tolower(char_type c) const
970{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000971#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000972 return isascii(c) ?
973 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000974#elif defined(__NetBSD__)
975 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000976#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000977 return isascii(c) ?
978 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000979#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000980 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000981#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000982}
983
984const char*
985ctype<char>::do_tolower(char_type* low, const char_type* high) const
986{
987 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000988#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000989 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000990#elif defined(__NetBSD__)
991 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000992#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000993 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000994#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000995 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000996#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000997 return low;
998}
999
1000char
1001ctype<char>::do_widen(char c) const
1002{
1003 return c;
1004}
1005
1006const char*
1007ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
1008{
1009 for (; low != high; ++low, ++dest)
1010 *dest = *low;
1011 return low;
1012}
1013
1014char
1015ctype<char>::do_narrow(char_type c, char dfault) const
1016{
1017 if (isascii(c))
1018 return static_cast<char>(c);
1019 return dfault;
1020}
1021
1022const char*
1023ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1024{
1025 for (; low != high; ++low, ++dest)
1026 if (isascii(*low))
1027 *dest = *low;
1028 else
1029 *dest = dfault;
1030 return low;
1031}
1032
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001033#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001034extern "C" const unsigned short ** __ctype_b_loc();
1035extern "C" const int ** __ctype_tolower_loc();
1036extern "C" const int ** __ctype_toupper_loc();
1037#endif
1038
Marshall Clow8f870232015-03-04 16:50:02 +00001039#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001040const ctype<char>::mask*
1041ctype<char>::classic_table() _NOEXCEPT
1042{
1043 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1044 cntrl, cntrl,
1045 cntrl, cntrl,
1046 cntrl, cntrl,
1047 cntrl, cntrl,
1048 cntrl, cntrl | space | blank,
1049 cntrl | space, cntrl | space,
1050 cntrl | space, cntrl | space,
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 cntrl, cntrl,
1060 space | blank | 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 punct | print, punct | print,
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 digit | print | xdigit, digit | print | xdigit,
1073 punct | print, punct | print,
1074 punct | print, punct | print,
1075 punct | print, punct | print,
1076 punct | print, upper | xdigit | print | alpha,
1077 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1078 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1079 upper | xdigit | 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, upper | print | alpha,
1089 upper | print | alpha, punct | print,
1090 punct | print, punct | print,
1091 punct | print, punct | print,
1092 punct | print, lower | xdigit | print | alpha,
1093 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1094 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1095 lower | xdigit | 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, lower | print | alpha,
1105 lower | print | alpha, punct | print,
1106 punct | print, punct | print,
1107 punct | print, cntrl,
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1116 };
1117 return builtin_table;
1118}
1119#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001120const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001121ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001122{
David Chisnall1d581062011-09-21 08:39:44 +00001123#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001124 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001125#elif defined(__NetBSD__)
1126 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001127#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001128 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001129#elif __sun__
1130 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001131#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001132 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001133#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001134 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001135#elif defined(_NEWLIB_VERSION)
1136 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1137 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001138#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001139 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001140#else
David Chisnall8074c342012-02-29 13:05:08 +00001141 // Platform not supported: abort so the person doing the port knows what to
1142 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001143# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001144 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001145 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001146 return NULL;
1147#endif
1148}
Marshall Clowb3f62842015-03-04 16:10:14 +00001149#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001150
Howard Hinnantd7a78632011-09-29 13:33:15 +00001151#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001152const int*
1153ctype<char>::__classic_lower_table() _NOEXCEPT
1154{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001155 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001156}
1157
1158const int*
1159ctype<char>::__classic_upper_table() _NOEXCEPT
1160{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001161 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001162}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001163#elif __NetBSD__
1164const short*
1165ctype<char>::__classic_lower_table() _NOEXCEPT
1166{
1167 return _C_tolower_tab_ + 1;
1168}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001169
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001170const short*
1171ctype<char>::__classic_upper_table() _NOEXCEPT
1172{
1173 return _C_toupper_tab_ + 1;
1174}
1175
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001176#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001177const int*
1178ctype<char>::__classic_lower_table() _NOEXCEPT
1179{
1180 return *__ctype_tolower_loc();
1181}
1182
1183const int*
1184ctype<char>::__classic_upper_table() _NOEXCEPT
1185{
1186 return *__ctype_toupper_loc();
1187}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001188#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001189
Howard Hinnantc51e1022010-05-11 19:42:16 +00001190// template <> class ctype_byname<char>
1191
1192ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1193 : ctype<char>(0, false, refs),
1194 __l(newlocale(LC_ALL_MASK, name, 0))
1195{
1196 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001197 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001198 " failed to construct for " + string(name));
1199}
1200
1201ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1202 : ctype<char>(0, false, refs),
1203 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1204{
1205 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001206 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207 " failed to construct for " + name);
1208}
1209
1210ctype_byname<char>::~ctype_byname()
1211{
1212 freelocale(__l);
1213}
1214
1215char
1216ctype_byname<char>::do_toupper(char_type c) const
1217{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001218 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001219}
1220
1221const char*
1222ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1223{
1224 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001225 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001226 return low;
1227}
1228
1229char
1230ctype_byname<char>::do_tolower(char_type c) const
1231{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001232 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001233}
1234
1235const char*
1236ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1237{
1238 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001239 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001240 return low;
1241}
1242
1243// template <> class ctype_byname<wchar_t>
1244
1245ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1246 : ctype<wchar_t>(refs),
1247 __l(newlocale(LC_ALL_MASK, name, 0))
1248{
1249 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001250 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001251 " failed to construct for " + string(name));
1252}
1253
1254ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1255 : ctype<wchar_t>(refs),
1256 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1257{
1258 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001259 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001260 " failed to construct for " + name);
1261}
1262
1263ctype_byname<wchar_t>::~ctype_byname()
1264{
1265 freelocale(__l);
1266}
1267
1268bool
1269ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1270{
Alexis Huntc2017f12011-07-09 03:40:04 +00001271#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001272 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001273#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001274 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001275 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001276 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1277 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1278 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1279 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1280 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1281 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1282 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1283 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1284 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1285 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001286 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001287#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001288}
1289
1290const wchar_t*
1291ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1292{
1293 for (; low != high; ++low, ++vec)
1294 {
1295 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001296 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001297 else
1298 {
1299 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001300 wint_t ch = static_cast<wint_t>(*low);
1301 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001302 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001303#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001304 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001305 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001306#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001307 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001308 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001309 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001310 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001311 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001312 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001313#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001314 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001315 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001316#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001317 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001318 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001319 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001320 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001321#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001322 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001323 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001324#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001325#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001326 if (iswblank_l(ch, __l))
1327 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001328#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001329 }
1330 }
1331 return low;
1332}
1333
1334const wchar_t*
1335ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1336{
1337 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001338 {
1339#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001340 if (iswctype_l(*low, m, __l))
1341 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001342#else
Marshall Clowada0f732013-02-07 14:22:51 +00001343 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001344 if ((m & space) == space && iswspace_l(ch, __l)) break;
1345 if ((m & print) == print && iswprint_l(ch, __l)) break;
1346 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1347 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1348 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1349 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1350 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1351 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1352 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1353 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001354#endif
1355 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001356 return low;
1357}
1358
1359const wchar_t*
1360ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1361{
1362 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001363 {
1364#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001365 if (!iswctype_l(*low, m, __l))
1366 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001367#else
Marshall Clowada0f732013-02-07 14:22:51 +00001368 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001369 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1370 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1371 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1372 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1373 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1374 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1375 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1376 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1377 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1378 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001379 break;
1380#endif
1381 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001382 return low;
1383}
1384
1385wchar_t
1386ctype_byname<wchar_t>::do_toupper(char_type c) const
1387{
1388 return towupper_l(c, __l);
1389}
1390
1391const wchar_t*
1392ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1393{
1394 for (; low != high; ++low)
1395 *low = towupper_l(*low, __l);
1396 return low;
1397}
1398
1399wchar_t
1400ctype_byname<wchar_t>::do_tolower(char_type c) const
1401{
1402 return towlower_l(c, __l);
1403}
1404
1405const wchar_t*
1406ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1407{
1408 for (; low != high; ++low)
1409 *low = towlower_l(*low, __l);
1410 return low;
1411}
1412
1413wchar_t
1414ctype_byname<wchar_t>::do_widen(char c) const
1415{
Ben Craig3756b922016-03-09 15:39:39 +00001416 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001417}
1418
1419const char*
1420ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1421{
1422 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001423 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001424 return low;
1425}
1426
1427char
1428ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1429{
Ben Craig3756b922016-03-09 15:39:39 +00001430 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001431 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001432}
1433
1434const wchar_t*
1435ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1436{
1437 for (; low != high; ++low, ++dest)
1438 {
Ben Craig3756b922016-03-09 15:39:39 +00001439 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001440 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001441 }
1442 return low;
1443}
1444
1445// template <> class codecvt<char, char, mbstate_t>
1446
Howard Hinnantffb308e2010-08-22 00:03:27 +00001447locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001448
1449codecvt<char, char, mbstate_t>::~codecvt()
1450{
1451}
1452
1453codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001454codecvt<char, char, mbstate_t>::do_out(state_type&,
1455 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001456 extern_type* to, extern_type*, extern_type*& to_nxt) const
1457{
1458 frm_nxt = frm;
1459 to_nxt = to;
1460 return noconv;
1461}
1462
1463codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001464codecvt<char, char, mbstate_t>::do_in(state_type&,
1465 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001466 intern_type* to, intern_type*, intern_type*& to_nxt) const
1467{
1468 frm_nxt = frm;
1469 to_nxt = to;
1470 return noconv;
1471}
1472
1473codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001474codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001475 extern_type* to, extern_type*, extern_type*& to_nxt) const
1476{
1477 to_nxt = to;
1478 return noconv;
1479}
1480
1481int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001482codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001483{
1484 return 1;
1485}
1486
1487bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001488codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001489{
1490 return true;
1491}
1492
1493int
1494codecvt<char, char, mbstate_t>::do_length(state_type&,
1495 const extern_type* frm, const extern_type* end, size_t mx) const
1496{
Howard Hinnant28b24882011-12-01 20:21:04 +00001497 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001498}
1499
1500int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001501codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001502{
1503 return 1;
1504}
1505
1506// template <> class codecvt<wchar_t, char, mbstate_t>
1507
Howard Hinnantffb308e2010-08-22 00:03:27 +00001508locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001509
1510codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1511 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001512 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001513{
1514}
1515
1516codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1517 : locale::facet(refs),
1518 __l(newlocale(LC_ALL_MASK, nm, 0))
1519{
1520 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001521 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001522 " failed to construct for " + string(nm));
1523}
1524
1525codecvt<wchar_t, char, mbstate_t>::~codecvt()
1526{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001527 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001528 freelocale(__l);
1529}
1530
1531codecvt<wchar_t, char, mbstate_t>::result
1532codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001533 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001534 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1535{
1536 // look for first internal null in frm
1537 const intern_type* fend = frm;
1538 for (; fend != frm_end; ++fend)
1539 if (*fend == 0)
1540 break;
1541 // loop over all null-terminated sequences in frm
1542 to_nxt = to;
1543 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1544 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001545 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001546 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001547 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1548 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001549 if (n == size_t(-1))
1550 {
1551 // need to recover to_nxt
1552 for (to_nxt = to; frm != frm_nxt; ++frm)
1553 {
Ben Craig3756b922016-03-09 15:39:39 +00001554 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001555 if (n == size_t(-1))
1556 break;
1557 to_nxt += n;
1558 }
1559 frm_nxt = frm;
1560 return error;
1561 }
1562 if (n == 0)
1563 return partial;
1564 to_nxt += n;
1565 if (to_nxt == to_end)
1566 break;
1567 if (fend != frm_end) // set up next null terminated sequence
1568 {
1569 // Try to write the terminating null
1570 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001571 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001572 if (n == size_t(-1)) // on error
1573 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001574 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001575 return partial;
1576 for (extern_type* p = tmp; n; --n) // write it
1577 *to_nxt++ = *p++;
1578 ++frm_nxt;
1579 // look for next null in frm
1580 for (fend = frm_nxt; fend != frm_end; ++fend)
1581 if (*fend == 0)
1582 break;
1583 }
1584 }
1585 return frm_nxt == frm_end ? ok : partial;
1586}
1587
1588codecvt<wchar_t, char, mbstate_t>::result
1589codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001590 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001591 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1592{
1593 // look for first internal null in frm
1594 const extern_type* fend = frm;
1595 for (; fend != frm_end; ++fend)
1596 if (*fend == 0)
1597 break;
1598 // loop over all null-terminated sequences in frm
1599 to_nxt = to;
1600 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1601 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001602 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001603 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001604 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1605 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001606 if (n == size_t(-1))
1607 {
1608 // need to recover to_nxt
1609 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1610 {
Ben Craig3756b922016-03-09 15:39:39 +00001611 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1612 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001613 switch (n)
1614 {
1615 case 0:
1616 ++frm;
1617 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001618 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001619 frm_nxt = frm;
1620 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001621 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 frm_nxt = frm;
1623 return partial;
1624 default:
1625 frm += n;
1626 break;
1627 }
1628 }
1629 frm_nxt = frm;
1630 return frm_nxt == frm_end ? ok : partial;
1631 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001632 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001633 return error;
1634 to_nxt += n;
1635 if (to_nxt == to_end)
1636 break;
1637 if (fend != frm_end) // set up next null terminated sequence
1638 {
1639 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001640 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001641 if (n != 0) // on error
1642 return error;
1643 ++to_nxt;
1644 ++frm_nxt;
1645 // look for next null in frm
1646 for (fend = frm_nxt; fend != frm_end; ++fend)
1647 if (*fend == 0)
1648 break;
1649 }
1650 }
1651 return frm_nxt == frm_end ? ok : partial;
1652}
1653
1654codecvt<wchar_t, char, mbstate_t>::result
1655codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1656 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1657{
1658 to_nxt = to;
1659 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001660 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001661 if (n == size_t(-1) || n == 0) // on error
1662 return error;
1663 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001664 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001665 return partial;
1666 for (extern_type* p = tmp; n; --n) // write it
1667 *to_nxt++ = *p++;
1668 return ok;
1669}
1670
1671int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001672codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001673{
Ben Craig3756b922016-03-09 15:39:39 +00001674 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001675 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001676
1677 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001678 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001679 return 1; // which take more than 1 char to form a wchar_t
1680 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001681}
1682
1683bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001684codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001685{
1686 return false;
1687}
1688
1689int
1690codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1691 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1692{
1693 int nbytes = 0;
1694 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1695 {
Ben Craig3756b922016-03-09 15:39:39 +00001696 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001697 switch (n)
1698 {
1699 case 0:
1700 ++nbytes;
1701 ++frm;
1702 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001703 case size_t(-1):
1704 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001705 return nbytes;
1706 default:
1707 nbytes += n;
1708 frm += n;
1709 break;
1710 }
1711 }
1712 return nbytes;
1713}
1714
1715int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001716codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001717{
Ben Craig3756b922016-03-09 15:39:39 +00001718 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001719}
1720
1721// Valid UTF ranges
1722// UTF-32 UTF-16 UTF-8 # of code points
1723// first second first second third fourth
1724// 000000 - 00007F 0000 - 007F 00 - 7F 127
1725// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1726// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1727// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1728// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1729// 00D800 - 00DFFF invalid
1730// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1731// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1732// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1733// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1734
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001735static
1736codecvt_base::result
1737utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1738 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1739 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1740{
1741 frm_nxt = frm;
1742 to_nxt = to;
1743 if (mode & generate_header)
1744 {
1745 if (to_end-to_nxt < 3)
1746 return codecvt_base::partial;
1747 *to_nxt++ = static_cast<uint8_t>(0xEF);
1748 *to_nxt++ = static_cast<uint8_t>(0xBB);
1749 *to_nxt++ = static_cast<uint8_t>(0xBF);
1750 }
1751 for (; frm_nxt < frm_end; ++frm_nxt)
1752 {
1753 uint16_t wc1 = *frm_nxt;
1754 if (wc1 > Maxcode)
1755 return codecvt_base::error;
1756 if (wc1 < 0x0080)
1757 {
1758 if (to_end-to_nxt < 1)
1759 return codecvt_base::partial;
1760 *to_nxt++ = static_cast<uint8_t>(wc1);
1761 }
1762 else if (wc1 < 0x0800)
1763 {
1764 if (to_end-to_nxt < 2)
1765 return codecvt_base::partial;
1766 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1767 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1768 }
1769 else if (wc1 < 0xD800)
1770 {
1771 if (to_end-to_nxt < 3)
1772 return codecvt_base::partial;
1773 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1774 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1775 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1776 }
1777 else if (wc1 < 0xDC00)
1778 {
1779 if (frm_end-frm_nxt < 2)
1780 return codecvt_base::partial;
1781 uint16_t wc2 = frm_nxt[1];
1782 if ((wc2 & 0xFC00) != 0xDC00)
1783 return codecvt_base::error;
1784 if (to_end-to_nxt < 4)
1785 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001786 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1787 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001788 return codecvt_base::error;
1789 ++frm_nxt;
1790 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1791 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1792 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1793 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1794 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1795 }
1796 else if (wc1 < 0xE000)
1797 {
1798 return codecvt_base::error;
1799 }
1800 else
1801 {
1802 if (to_end-to_nxt < 3)
1803 return codecvt_base::partial;
1804 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1805 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1806 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1807 }
1808 }
1809 return codecvt_base::ok;
1810}
1811
1812static
1813codecvt_base::result
1814utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1815 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1816 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1817{
1818 frm_nxt = frm;
1819 to_nxt = to;
1820 if (mode & generate_header)
1821 {
1822 if (to_end-to_nxt < 3)
1823 return codecvt_base::partial;
1824 *to_nxt++ = static_cast<uint8_t>(0xEF);
1825 *to_nxt++ = static_cast<uint8_t>(0xBB);
1826 *to_nxt++ = static_cast<uint8_t>(0xBF);
1827 }
1828 for (; frm_nxt < frm_end; ++frm_nxt)
1829 {
1830 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1831 if (wc1 > Maxcode)
1832 return codecvt_base::error;
1833 if (wc1 < 0x0080)
1834 {
1835 if (to_end-to_nxt < 1)
1836 return codecvt_base::partial;
1837 *to_nxt++ = static_cast<uint8_t>(wc1);
1838 }
1839 else if (wc1 < 0x0800)
1840 {
1841 if (to_end-to_nxt < 2)
1842 return codecvt_base::partial;
1843 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1844 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1845 }
1846 else if (wc1 < 0xD800)
1847 {
1848 if (to_end-to_nxt < 3)
1849 return codecvt_base::partial;
1850 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1852 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1853 }
1854 else if (wc1 < 0xDC00)
1855 {
1856 if (frm_end-frm_nxt < 2)
1857 return codecvt_base::partial;
1858 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1859 if ((wc2 & 0xFC00) != 0xDC00)
1860 return codecvt_base::error;
1861 if (to_end-to_nxt < 4)
1862 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001863 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1864 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001865 return codecvt_base::error;
1866 ++frm_nxt;
1867 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1868 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1869 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1870 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1871 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1872 }
1873 else if (wc1 < 0xE000)
1874 {
1875 return codecvt_base::error;
1876 }
1877 else
1878 {
1879 if (to_end-to_nxt < 3)
1880 return codecvt_base::partial;
1881 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1882 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1883 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1884 }
1885 }
1886 return codecvt_base::ok;
1887}
1888
1889static
1890codecvt_base::result
1891utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1892 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1893 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1894{
1895 frm_nxt = frm;
1896 to_nxt = to;
1897 if (mode & consume_header)
1898 {
1899 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1900 frm_nxt[2] == 0xBF)
1901 frm_nxt += 3;
1902 }
1903 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1904 {
1905 uint8_t c1 = *frm_nxt;
1906 if (c1 > Maxcode)
1907 return codecvt_base::error;
1908 if (c1 < 0x80)
1909 {
1910 *to_nxt = static_cast<uint16_t>(c1);
1911 ++frm_nxt;
1912 }
1913 else if (c1 < 0xC2)
1914 {
1915 return codecvt_base::error;
1916 }
1917 else if (c1 < 0xE0)
1918 {
1919 if (frm_end-frm_nxt < 2)
1920 return codecvt_base::partial;
1921 uint8_t c2 = frm_nxt[1];
1922 if ((c2 & 0xC0) != 0x80)
1923 return codecvt_base::error;
1924 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1925 if (t > Maxcode)
1926 return codecvt_base::error;
1927 *to_nxt = t;
1928 frm_nxt += 2;
1929 }
1930 else if (c1 < 0xF0)
1931 {
1932 if (frm_end-frm_nxt < 3)
1933 return codecvt_base::partial;
1934 uint8_t c2 = frm_nxt[1];
1935 uint8_t c3 = frm_nxt[2];
1936 switch (c1)
1937 {
1938 case 0xE0:
1939 if ((c2 & 0xE0) != 0xA0)
1940 return codecvt_base::error;
1941 break;
1942 case 0xED:
1943 if ((c2 & 0xE0) != 0x80)
1944 return codecvt_base::error;
1945 break;
1946 default:
1947 if ((c2 & 0xC0) != 0x80)
1948 return codecvt_base::error;
1949 break;
1950 }
1951 if ((c3 & 0xC0) != 0x80)
1952 return codecvt_base::error;
1953 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1954 | ((c2 & 0x3F) << 6)
1955 | (c3 & 0x3F));
1956 if (t > Maxcode)
1957 return codecvt_base::error;
1958 *to_nxt = t;
1959 frm_nxt += 3;
1960 }
1961 else if (c1 < 0xF5)
1962 {
1963 if (frm_end-frm_nxt < 4)
1964 return codecvt_base::partial;
1965 uint8_t c2 = frm_nxt[1];
1966 uint8_t c3 = frm_nxt[2];
1967 uint8_t c4 = frm_nxt[3];
1968 switch (c1)
1969 {
1970 case 0xF0:
1971 if (!(0x90 <= c2 && c2 <= 0xBF))
1972 return codecvt_base::error;
1973 break;
1974 case 0xF4:
1975 if ((c2 & 0xF0) != 0x80)
1976 return codecvt_base::error;
1977 break;
1978 default:
1979 if ((c2 & 0xC0) != 0x80)
1980 return codecvt_base::error;
1981 break;
1982 }
1983 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1984 return codecvt_base::error;
1985 if (to_end-to_nxt < 2)
1986 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001987 if ((((c1 & 7UL) << 18) +
1988 ((c2 & 0x3FUL) << 12) +
1989 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001990 return codecvt_base::error;
1991 *to_nxt = static_cast<uint16_t>(
1992 0xD800
1993 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1994 | ((c2 & 0x0F) << 2)
1995 | ((c3 & 0x30) >> 4));
1996 *++to_nxt = static_cast<uint16_t>(
1997 0xDC00
1998 | ((c3 & 0x0F) << 6)
1999 | (c4 & 0x3F));
2000 frm_nxt += 4;
2001 }
2002 else
2003 {
2004 return codecvt_base::error;
2005 }
2006 }
2007 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2008}
2009
2010static
2011codecvt_base::result
2012utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2013 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2014 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2015{
2016 frm_nxt = frm;
2017 to_nxt = to;
2018 if (mode & consume_header)
2019 {
2020 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2021 frm_nxt[2] == 0xBF)
2022 frm_nxt += 3;
2023 }
2024 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2025 {
2026 uint8_t c1 = *frm_nxt;
2027 if (c1 > Maxcode)
2028 return codecvt_base::error;
2029 if (c1 < 0x80)
2030 {
2031 *to_nxt = static_cast<uint32_t>(c1);
2032 ++frm_nxt;
2033 }
2034 else if (c1 < 0xC2)
2035 {
2036 return codecvt_base::error;
2037 }
2038 else if (c1 < 0xE0)
2039 {
2040 if (frm_end-frm_nxt < 2)
2041 return codecvt_base::partial;
2042 uint8_t c2 = frm_nxt[1];
2043 if ((c2 & 0xC0) != 0x80)
2044 return codecvt_base::error;
2045 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2046 if (t > Maxcode)
2047 return codecvt_base::error;
2048 *to_nxt = static_cast<uint32_t>(t);
2049 frm_nxt += 2;
2050 }
2051 else if (c1 < 0xF0)
2052 {
2053 if (frm_end-frm_nxt < 3)
2054 return codecvt_base::partial;
2055 uint8_t c2 = frm_nxt[1];
2056 uint8_t c3 = frm_nxt[2];
2057 switch (c1)
2058 {
2059 case 0xE0:
2060 if ((c2 & 0xE0) != 0xA0)
2061 return codecvt_base::error;
2062 break;
2063 case 0xED:
2064 if ((c2 & 0xE0) != 0x80)
2065 return codecvt_base::error;
2066 break;
2067 default:
2068 if ((c2 & 0xC0) != 0x80)
2069 return codecvt_base::error;
2070 break;
2071 }
2072 if ((c3 & 0xC0) != 0x80)
2073 return codecvt_base::error;
2074 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2075 | ((c2 & 0x3F) << 6)
2076 | (c3 & 0x3F));
2077 if (t > Maxcode)
2078 return codecvt_base::error;
2079 *to_nxt = static_cast<uint32_t>(t);
2080 frm_nxt += 3;
2081 }
2082 else if (c1 < 0xF5)
2083 {
2084 if (frm_end-frm_nxt < 4)
2085 return codecvt_base::partial;
2086 uint8_t c2 = frm_nxt[1];
2087 uint8_t c3 = frm_nxt[2];
2088 uint8_t c4 = frm_nxt[3];
2089 switch (c1)
2090 {
2091 case 0xF0:
2092 if (!(0x90 <= c2 && c2 <= 0xBF))
2093 return codecvt_base::error;
2094 break;
2095 case 0xF4:
2096 if ((c2 & 0xF0) != 0x80)
2097 return codecvt_base::error;
2098 break;
2099 default:
2100 if ((c2 & 0xC0) != 0x80)
2101 return codecvt_base::error;
2102 break;
2103 }
2104 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2105 return codecvt_base::error;
2106 if (to_end-to_nxt < 2)
2107 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002108 if ((((c1 & 7UL) << 18) +
2109 ((c2 & 0x3FUL) << 12) +
2110 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002111 return codecvt_base::error;
2112 *to_nxt = static_cast<uint32_t>(
2113 0xD800
2114 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2115 | ((c2 & 0x0F) << 2)
2116 | ((c3 & 0x30) >> 4));
2117 *++to_nxt = static_cast<uint32_t>(
2118 0xDC00
2119 | ((c3 & 0x0F) << 6)
2120 | (c4 & 0x3F));
2121 frm_nxt += 4;
2122 }
2123 else
2124 {
2125 return codecvt_base::error;
2126 }
2127 }
2128 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2129}
2130
2131static
2132int
2133utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2134 size_t mx, unsigned long Maxcode = 0x10FFFF,
2135 codecvt_mode mode = codecvt_mode(0))
2136{
2137 const uint8_t* frm_nxt = frm;
2138 if (mode & consume_header)
2139 {
2140 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2141 frm_nxt[2] == 0xBF)
2142 frm_nxt += 3;
2143 }
2144 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2145 {
2146 uint8_t c1 = *frm_nxt;
2147 if (c1 > Maxcode)
2148 break;
2149 if (c1 < 0x80)
2150 {
2151 ++frm_nxt;
2152 }
2153 else if (c1 < 0xC2)
2154 {
2155 break;
2156 }
2157 else if (c1 < 0xE0)
2158 {
2159 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2160 break;
2161 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2162 if (t > Maxcode)
2163 break;
2164 frm_nxt += 2;
2165 }
2166 else if (c1 < 0xF0)
2167 {
2168 if (frm_end-frm_nxt < 3)
2169 break;
2170 uint8_t c2 = frm_nxt[1];
2171 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002172 switch (c1)
2173 {
2174 case 0xE0:
2175 if ((c2 & 0xE0) != 0xA0)
2176 return static_cast<int>(frm_nxt - frm);
2177 break;
2178 case 0xED:
2179 if ((c2 & 0xE0) != 0x80)
2180 return static_cast<int>(frm_nxt - frm);
2181 break;
2182 default:
2183 if ((c2 & 0xC0) != 0x80)
2184 return static_cast<int>(frm_nxt - frm);
2185 break;
2186 }
2187 if ((c3 & 0xC0) != 0x80)
2188 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002189 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002190 break;
2191 frm_nxt += 3;
2192 }
2193 else if (c1 < 0xF5)
2194 {
2195 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2196 break;
2197 uint8_t c2 = frm_nxt[1];
2198 uint8_t c3 = frm_nxt[2];
2199 uint8_t c4 = frm_nxt[3];
2200 switch (c1)
2201 {
2202 case 0xF0:
2203 if (!(0x90 <= c2 && c2 <= 0xBF))
2204 return static_cast<int>(frm_nxt - frm);
2205 break;
2206 case 0xF4:
2207 if ((c2 & 0xF0) != 0x80)
2208 return static_cast<int>(frm_nxt - frm);
2209 break;
2210 default:
2211 if ((c2 & 0xC0) != 0x80)
2212 return static_cast<int>(frm_nxt - frm);
2213 break;
2214 }
2215 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2216 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002217 if ((((c1 & 7UL) << 18) +
2218 ((c2 & 0x3FUL) << 12) +
2219 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002220 break;
2221 ++nchar16_t;
2222 frm_nxt += 4;
2223 }
2224 else
2225 {
2226 break;
2227 }
2228 }
2229 return static_cast<int>(frm_nxt - frm);
2230}
2231
2232static
2233codecvt_base::result
2234ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2235 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2236 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2237{
2238 frm_nxt = frm;
2239 to_nxt = to;
2240 if (mode & generate_header)
2241 {
2242 if (to_end-to_nxt < 3)
2243 return codecvt_base::partial;
2244 *to_nxt++ = static_cast<uint8_t>(0xEF);
2245 *to_nxt++ = static_cast<uint8_t>(0xBB);
2246 *to_nxt++ = static_cast<uint8_t>(0xBF);
2247 }
2248 for (; frm_nxt < frm_end; ++frm_nxt)
2249 {
2250 uint32_t wc = *frm_nxt;
2251 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2252 return codecvt_base::error;
2253 if (wc < 0x000080)
2254 {
2255 if (to_end-to_nxt < 1)
2256 return codecvt_base::partial;
2257 *to_nxt++ = static_cast<uint8_t>(wc);
2258 }
2259 else if (wc < 0x000800)
2260 {
2261 if (to_end-to_nxt < 2)
2262 return codecvt_base::partial;
2263 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2264 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2265 }
2266 else if (wc < 0x010000)
2267 {
2268 if (to_end-to_nxt < 3)
2269 return codecvt_base::partial;
2270 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2271 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2272 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2273 }
2274 else // if (wc < 0x110000)
2275 {
2276 if (to_end-to_nxt < 4)
2277 return codecvt_base::partial;
2278 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2279 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2280 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2281 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2282 }
2283 }
2284 return codecvt_base::ok;
2285}
2286
2287static
2288codecvt_base::result
2289utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2290 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2291 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2292{
2293 frm_nxt = frm;
2294 to_nxt = to;
2295 if (mode & consume_header)
2296 {
2297 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2298 frm_nxt[2] == 0xBF)
2299 frm_nxt += 3;
2300 }
2301 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2302 {
2303 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2304 if (c1 < 0x80)
2305 {
2306 if (c1 > Maxcode)
2307 return codecvt_base::error;
2308 *to_nxt = static_cast<uint32_t>(c1);
2309 ++frm_nxt;
2310 }
2311 else if (c1 < 0xC2)
2312 {
2313 return codecvt_base::error;
2314 }
2315 else if (c1 < 0xE0)
2316 {
2317 if (frm_end-frm_nxt < 2)
2318 return codecvt_base::partial;
2319 uint8_t c2 = frm_nxt[1];
2320 if ((c2 & 0xC0) != 0x80)
2321 return codecvt_base::error;
2322 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2323 | (c2 & 0x3F));
2324 if (t > Maxcode)
2325 return codecvt_base::error;
2326 *to_nxt = t;
2327 frm_nxt += 2;
2328 }
2329 else if (c1 < 0xF0)
2330 {
2331 if (frm_end-frm_nxt < 3)
2332 return codecvt_base::partial;
2333 uint8_t c2 = frm_nxt[1];
2334 uint8_t c3 = frm_nxt[2];
2335 switch (c1)
2336 {
2337 case 0xE0:
2338 if ((c2 & 0xE0) != 0xA0)
2339 return codecvt_base::error;
2340 break;
2341 case 0xED:
2342 if ((c2 & 0xE0) != 0x80)
2343 return codecvt_base::error;
2344 break;
2345 default:
2346 if ((c2 & 0xC0) != 0x80)
2347 return codecvt_base::error;
2348 break;
2349 }
2350 if ((c3 & 0xC0) != 0x80)
2351 return codecvt_base::error;
2352 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2353 | ((c2 & 0x3F) << 6)
2354 | (c3 & 0x3F));
2355 if (t > Maxcode)
2356 return codecvt_base::error;
2357 *to_nxt = t;
2358 frm_nxt += 3;
2359 }
2360 else if (c1 < 0xF5)
2361 {
2362 if (frm_end-frm_nxt < 4)
2363 return codecvt_base::partial;
2364 uint8_t c2 = frm_nxt[1];
2365 uint8_t c3 = frm_nxt[2];
2366 uint8_t c4 = frm_nxt[3];
2367 switch (c1)
2368 {
2369 case 0xF0:
2370 if (!(0x90 <= c2 && c2 <= 0xBF))
2371 return codecvt_base::error;
2372 break;
2373 case 0xF4:
2374 if ((c2 & 0xF0) != 0x80)
2375 return codecvt_base::error;
2376 break;
2377 default:
2378 if ((c2 & 0xC0) != 0x80)
2379 return codecvt_base::error;
2380 break;
2381 }
2382 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2383 return codecvt_base::error;
2384 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2385 | ((c2 & 0x3F) << 12)
2386 | ((c3 & 0x3F) << 6)
2387 | (c4 & 0x3F));
2388 if (t > Maxcode)
2389 return codecvt_base::error;
2390 *to_nxt = t;
2391 frm_nxt += 4;
2392 }
2393 else
2394 {
2395 return codecvt_base::error;
2396 }
2397 }
2398 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2399}
2400
2401static
2402int
2403utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2404 size_t mx, unsigned long Maxcode = 0x10FFFF,
2405 codecvt_mode mode = codecvt_mode(0))
2406{
2407 const uint8_t* frm_nxt = frm;
2408 if (mode & consume_header)
2409 {
2410 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2411 frm_nxt[2] == 0xBF)
2412 frm_nxt += 3;
2413 }
2414 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2415 {
2416 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2417 if (c1 < 0x80)
2418 {
2419 if (c1 > Maxcode)
2420 break;
2421 ++frm_nxt;
2422 }
2423 else if (c1 < 0xC2)
2424 {
2425 break;
2426 }
2427 else if (c1 < 0xE0)
2428 {
2429 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2430 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002431 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002432 break;
2433 frm_nxt += 2;
2434 }
2435 else if (c1 < 0xF0)
2436 {
2437 if (frm_end-frm_nxt < 3)
2438 break;
2439 uint8_t c2 = frm_nxt[1];
2440 uint8_t c3 = frm_nxt[2];
2441 switch (c1)
2442 {
2443 case 0xE0:
2444 if ((c2 & 0xE0) != 0xA0)
2445 return static_cast<int>(frm_nxt - frm);
2446 break;
2447 case 0xED:
2448 if ((c2 & 0xE0) != 0x80)
2449 return static_cast<int>(frm_nxt - frm);
2450 break;
2451 default:
2452 if ((c2 & 0xC0) != 0x80)
2453 return static_cast<int>(frm_nxt - frm);
2454 break;
2455 }
2456 if ((c3 & 0xC0) != 0x80)
2457 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002458 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002459 break;
2460 frm_nxt += 3;
2461 }
2462 else if (c1 < 0xF5)
2463 {
2464 if (frm_end-frm_nxt < 4)
2465 break;
2466 uint8_t c2 = frm_nxt[1];
2467 uint8_t c3 = frm_nxt[2];
2468 uint8_t c4 = frm_nxt[3];
2469 switch (c1)
2470 {
2471 case 0xF0:
2472 if (!(0x90 <= c2 && c2 <= 0xBF))
2473 return static_cast<int>(frm_nxt - frm);
2474 break;
2475 case 0xF4:
2476 if ((c2 & 0xF0) != 0x80)
2477 return static_cast<int>(frm_nxt - frm);
2478 break;
2479 default:
2480 if ((c2 & 0xC0) != 0x80)
2481 return static_cast<int>(frm_nxt - frm);
2482 break;
2483 }
2484 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2485 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002486 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2487 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002488 break;
2489 frm_nxt += 4;
2490 }
2491 else
2492 {
2493 break;
2494 }
2495 }
2496 return static_cast<int>(frm_nxt - frm);
2497}
2498
2499static
2500codecvt_base::result
2501ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2502 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2503 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2504{
2505 frm_nxt = frm;
2506 to_nxt = to;
2507 if (mode & generate_header)
2508 {
2509 if (to_end-to_nxt < 3)
2510 return codecvt_base::partial;
2511 *to_nxt++ = static_cast<uint8_t>(0xEF);
2512 *to_nxt++ = static_cast<uint8_t>(0xBB);
2513 *to_nxt++ = static_cast<uint8_t>(0xBF);
2514 }
2515 for (; frm_nxt < frm_end; ++frm_nxt)
2516 {
2517 uint16_t wc = *frm_nxt;
2518 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2519 return codecvt_base::error;
2520 if (wc < 0x0080)
2521 {
2522 if (to_end-to_nxt < 1)
2523 return codecvt_base::partial;
2524 *to_nxt++ = static_cast<uint8_t>(wc);
2525 }
2526 else if (wc < 0x0800)
2527 {
2528 if (to_end-to_nxt < 2)
2529 return codecvt_base::partial;
2530 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2531 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2532 }
2533 else // if (wc <= 0xFFFF)
2534 {
2535 if (to_end-to_nxt < 3)
2536 return codecvt_base::partial;
2537 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2538 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2539 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2540 }
2541 }
2542 return codecvt_base::ok;
2543}
2544
2545static
2546codecvt_base::result
2547utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2548 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2549 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2550{
2551 frm_nxt = frm;
2552 to_nxt = to;
2553 if (mode & consume_header)
2554 {
2555 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2556 frm_nxt[2] == 0xBF)
2557 frm_nxt += 3;
2558 }
2559 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2560 {
2561 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2562 if (c1 < 0x80)
2563 {
2564 if (c1 > Maxcode)
2565 return codecvt_base::error;
2566 *to_nxt = static_cast<uint16_t>(c1);
2567 ++frm_nxt;
2568 }
2569 else if (c1 < 0xC2)
2570 {
2571 return codecvt_base::error;
2572 }
2573 else if (c1 < 0xE0)
2574 {
2575 if (frm_end-frm_nxt < 2)
2576 return codecvt_base::partial;
2577 uint8_t c2 = frm_nxt[1];
2578 if ((c2 & 0xC0) != 0x80)
2579 return codecvt_base::error;
2580 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2581 | (c2 & 0x3F));
2582 if (t > Maxcode)
2583 return codecvt_base::error;
2584 *to_nxt = t;
2585 frm_nxt += 2;
2586 }
2587 else if (c1 < 0xF0)
2588 {
2589 if (frm_end-frm_nxt < 3)
2590 return codecvt_base::partial;
2591 uint8_t c2 = frm_nxt[1];
2592 uint8_t c3 = frm_nxt[2];
2593 switch (c1)
2594 {
2595 case 0xE0:
2596 if ((c2 & 0xE0) != 0xA0)
2597 return codecvt_base::error;
2598 break;
2599 case 0xED:
2600 if ((c2 & 0xE0) != 0x80)
2601 return codecvt_base::error;
2602 break;
2603 default:
2604 if ((c2 & 0xC0) != 0x80)
2605 return codecvt_base::error;
2606 break;
2607 }
2608 if ((c3 & 0xC0) != 0x80)
2609 return codecvt_base::error;
2610 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2611 | ((c2 & 0x3F) << 6)
2612 | (c3 & 0x3F));
2613 if (t > Maxcode)
2614 return codecvt_base::error;
2615 *to_nxt = t;
2616 frm_nxt += 3;
2617 }
2618 else
2619 {
2620 return codecvt_base::error;
2621 }
2622 }
2623 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2624}
2625
2626static
2627int
2628utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2629 size_t mx, unsigned long Maxcode = 0x10FFFF,
2630 codecvt_mode mode = codecvt_mode(0))
2631{
2632 const uint8_t* frm_nxt = frm;
2633 if (mode & consume_header)
2634 {
2635 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2636 frm_nxt[2] == 0xBF)
2637 frm_nxt += 3;
2638 }
2639 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2640 {
2641 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2642 if (c1 < 0x80)
2643 {
2644 if (c1 > Maxcode)
2645 break;
2646 ++frm_nxt;
2647 }
2648 else if (c1 < 0xC2)
2649 {
2650 break;
2651 }
2652 else if (c1 < 0xE0)
2653 {
2654 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2655 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002656 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002657 break;
2658 frm_nxt += 2;
2659 }
2660 else if (c1 < 0xF0)
2661 {
2662 if (frm_end-frm_nxt < 3)
2663 break;
2664 uint8_t c2 = frm_nxt[1];
2665 uint8_t c3 = frm_nxt[2];
2666 switch (c1)
2667 {
2668 case 0xE0:
2669 if ((c2 & 0xE0) != 0xA0)
2670 return static_cast<int>(frm_nxt - frm);
2671 break;
2672 case 0xED:
2673 if ((c2 & 0xE0) != 0x80)
2674 return static_cast<int>(frm_nxt - frm);
2675 break;
2676 default:
2677 if ((c2 & 0xC0) != 0x80)
2678 return static_cast<int>(frm_nxt - frm);
2679 break;
2680 }
2681 if ((c3 & 0xC0) != 0x80)
2682 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002683 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002684 break;
2685 frm_nxt += 3;
2686 }
2687 else
2688 {
2689 break;
2690 }
2691 }
2692 return static_cast<int>(frm_nxt - frm);
2693}
2694
2695static
2696codecvt_base::result
2697ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2698 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2699 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2700{
2701 frm_nxt = frm;
2702 to_nxt = to;
2703 if (mode & generate_header)
2704 {
2705 if (to_end-to_nxt < 2)
2706 return codecvt_base::partial;
2707 *to_nxt++ = static_cast<uint8_t>(0xFE);
2708 *to_nxt++ = static_cast<uint8_t>(0xFF);
2709 }
2710 for (; frm_nxt < frm_end; ++frm_nxt)
2711 {
2712 uint32_t wc = *frm_nxt;
2713 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2714 return codecvt_base::error;
2715 if (wc < 0x010000)
2716 {
2717 if (to_end-to_nxt < 2)
2718 return codecvt_base::partial;
2719 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2720 *to_nxt++ = static_cast<uint8_t>(wc);
2721 }
2722 else
2723 {
2724 if (to_end-to_nxt < 4)
2725 return codecvt_base::partial;
2726 uint16_t t = static_cast<uint16_t>(
2727 0xD800
2728 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2729 | ((wc & 0x00FC00) >> 10));
2730 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2731 *to_nxt++ = static_cast<uint8_t>(t);
2732 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2733 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2734 *to_nxt++ = static_cast<uint8_t>(t);
2735 }
2736 }
2737 return codecvt_base::ok;
2738}
2739
2740static
2741codecvt_base::result
2742utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2743 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2744 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2745{
2746 frm_nxt = frm;
2747 to_nxt = to;
2748 if (mode & consume_header)
2749 {
2750 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2751 frm_nxt += 2;
2752 }
2753 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2754 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002755 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002756 if ((c1 & 0xFC00) == 0xDC00)
2757 return codecvt_base::error;
2758 if ((c1 & 0xFC00) != 0xD800)
2759 {
2760 if (c1 > Maxcode)
2761 return codecvt_base::error;
2762 *to_nxt = static_cast<uint32_t>(c1);
2763 frm_nxt += 2;
2764 }
2765 else
2766 {
2767 if (frm_end-frm_nxt < 4)
2768 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002769 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002770 if ((c2 & 0xFC00) != 0xDC00)
2771 return codecvt_base::error;
2772 uint32_t t = static_cast<uint32_t>(
2773 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2774 | ((c1 & 0x003F) << 10)
2775 | (c2 & 0x03FF));
2776 if (t > Maxcode)
2777 return codecvt_base::error;
2778 *to_nxt = t;
2779 frm_nxt += 4;
2780 }
2781 }
2782 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2783}
2784
2785static
2786int
2787utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2788 size_t mx, unsigned long Maxcode = 0x10FFFF,
2789 codecvt_mode mode = codecvt_mode(0))
2790{
2791 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002792 if (mode & consume_header)
2793 {
2794 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2795 frm_nxt += 2;
2796 }
2797 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2798 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002799 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002800 if ((c1 & 0xFC00) == 0xDC00)
2801 break;
2802 if ((c1 & 0xFC00) != 0xD800)
2803 {
2804 if (c1 > Maxcode)
2805 break;
2806 frm_nxt += 2;
2807 }
2808 else
2809 {
2810 if (frm_end-frm_nxt < 4)
2811 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002812 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002813 if ((c2 & 0xFC00) != 0xDC00)
2814 break;
2815 uint32_t t = static_cast<uint32_t>(
2816 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2817 | ((c1 & 0x003F) << 10)
2818 | (c2 & 0x03FF));
2819 if (t > Maxcode)
2820 break;
2821 frm_nxt += 4;
2822 }
2823 }
2824 return static_cast<int>(frm_nxt - frm);
2825}
2826
2827static
2828codecvt_base::result
2829ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2830 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2831 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2832{
2833 frm_nxt = frm;
2834 to_nxt = to;
2835 if (mode & generate_header)
2836 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002837 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002838 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002839 *to_nxt++ = static_cast<uint8_t>(0xFF);
2840 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002841 }
2842 for (; frm_nxt < frm_end; ++frm_nxt)
2843 {
2844 uint32_t wc = *frm_nxt;
2845 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2846 return codecvt_base::error;
2847 if (wc < 0x010000)
2848 {
2849 if (to_end-to_nxt < 2)
2850 return codecvt_base::partial;
2851 *to_nxt++ = static_cast<uint8_t>(wc);
2852 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2853 }
2854 else
2855 {
2856 if (to_end-to_nxt < 4)
2857 return codecvt_base::partial;
2858 uint16_t t = static_cast<uint16_t>(
2859 0xD800
2860 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2861 | ((wc & 0x00FC00) >> 10));
2862 *to_nxt++ = static_cast<uint8_t>(t);
2863 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2864 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2865 *to_nxt++ = static_cast<uint8_t>(t);
2866 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2867 }
2868 }
2869 return codecvt_base::ok;
2870}
2871
2872static
2873codecvt_base::result
2874utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2875 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2876 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2877{
2878 frm_nxt = frm;
2879 to_nxt = to;
2880 if (mode & consume_header)
2881 {
2882 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2883 frm_nxt += 2;
2884 }
2885 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2886 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002887 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002888 if ((c1 & 0xFC00) == 0xDC00)
2889 return codecvt_base::error;
2890 if ((c1 & 0xFC00) != 0xD800)
2891 {
2892 if (c1 > Maxcode)
2893 return codecvt_base::error;
2894 *to_nxt = static_cast<uint32_t>(c1);
2895 frm_nxt += 2;
2896 }
2897 else
2898 {
2899 if (frm_end-frm_nxt < 4)
2900 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002901 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002902 if ((c2 & 0xFC00) != 0xDC00)
2903 return codecvt_base::error;
2904 uint32_t t = static_cast<uint32_t>(
2905 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2906 | ((c1 & 0x003F) << 10)
2907 | (c2 & 0x03FF));
2908 if (t > Maxcode)
2909 return codecvt_base::error;
2910 *to_nxt = t;
2911 frm_nxt += 4;
2912 }
2913 }
2914 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2915}
2916
2917static
2918int
2919utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2920 size_t mx, unsigned long Maxcode = 0x10FFFF,
2921 codecvt_mode mode = codecvt_mode(0))
2922{
2923 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002924 if (mode & consume_header)
2925 {
2926 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2927 frm_nxt += 2;
2928 }
2929 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2930 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002931 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002932 if ((c1 & 0xFC00) == 0xDC00)
2933 break;
2934 if ((c1 & 0xFC00) != 0xD800)
2935 {
2936 if (c1 > Maxcode)
2937 break;
2938 frm_nxt += 2;
2939 }
2940 else
2941 {
2942 if (frm_end-frm_nxt < 4)
2943 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002944 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002945 if ((c2 & 0xFC00) != 0xDC00)
2946 break;
2947 uint32_t t = static_cast<uint32_t>(
2948 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2949 | ((c1 & 0x003F) << 10)
2950 | (c2 & 0x03FF));
2951 if (t > Maxcode)
2952 break;
2953 frm_nxt += 4;
2954 }
2955 }
2956 return static_cast<int>(frm_nxt - frm);
2957}
2958
2959static
2960codecvt_base::result
2961ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2962 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2963 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2964{
2965 frm_nxt = frm;
2966 to_nxt = to;
2967 if (mode & generate_header)
2968 {
2969 if (to_end-to_nxt < 2)
2970 return codecvt_base::partial;
2971 *to_nxt++ = static_cast<uint8_t>(0xFE);
2972 *to_nxt++ = static_cast<uint8_t>(0xFF);
2973 }
2974 for (; frm_nxt < frm_end; ++frm_nxt)
2975 {
2976 uint16_t wc = *frm_nxt;
2977 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2978 return codecvt_base::error;
2979 if (to_end-to_nxt < 2)
2980 return codecvt_base::partial;
2981 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2982 *to_nxt++ = static_cast<uint8_t>(wc);
2983 }
2984 return codecvt_base::ok;
2985}
2986
2987static
2988codecvt_base::result
2989utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2990 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2991 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2992{
2993 frm_nxt = frm;
2994 to_nxt = to;
2995 if (mode & consume_header)
2996 {
2997 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2998 frm_nxt += 2;
2999 }
3000 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3001 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003002 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003003 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3004 return codecvt_base::error;
3005 *to_nxt = c1;
3006 frm_nxt += 2;
3007 }
3008 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3009}
3010
3011static
3012int
3013utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3014 size_t mx, unsigned long Maxcode = 0x10FFFF,
3015 codecvt_mode mode = codecvt_mode(0))
3016{
3017 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003018 if (mode & consume_header)
3019 {
3020 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3021 frm_nxt += 2;
3022 }
3023 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3024 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003025 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003026 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3027 break;
3028 frm_nxt += 2;
3029 }
3030 return static_cast<int>(frm_nxt - frm);
3031}
3032
3033static
3034codecvt_base::result
3035ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3036 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3037 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3038{
3039 frm_nxt = frm;
3040 to_nxt = to;
3041 if (mode & generate_header)
3042 {
3043 if (to_end-to_nxt < 2)
3044 return codecvt_base::partial;
3045 *to_nxt++ = static_cast<uint8_t>(0xFF);
3046 *to_nxt++ = static_cast<uint8_t>(0xFE);
3047 }
3048 for (; frm_nxt < frm_end; ++frm_nxt)
3049 {
3050 uint16_t wc = *frm_nxt;
3051 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3052 return codecvt_base::error;
3053 if (to_end-to_nxt < 2)
3054 return codecvt_base::partial;
3055 *to_nxt++ = static_cast<uint8_t>(wc);
3056 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3057 }
3058 return codecvt_base::ok;
3059}
3060
3061static
3062codecvt_base::result
3063utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3064 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3065 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3066{
3067 frm_nxt = frm;
3068 to_nxt = to;
3069 if (mode & consume_header)
3070 {
3071 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3072 frm_nxt += 2;
3073 }
3074 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3075 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003076 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003077 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3078 return codecvt_base::error;
3079 *to_nxt = c1;
3080 frm_nxt += 2;
3081 }
3082 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3083}
3084
3085static
3086int
3087utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3088 size_t mx, unsigned long Maxcode = 0x10FFFF,
3089 codecvt_mode mode = codecvt_mode(0))
3090{
3091 const uint8_t* frm_nxt = frm;
3092 frm_nxt = frm;
3093 if (mode & consume_header)
3094 {
3095 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3096 frm_nxt += 2;
3097 }
3098 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3099 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003100 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003101 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3102 break;
3103 frm_nxt += 2;
3104 }
3105 return static_cast<int>(frm_nxt - frm);
3106}
3107
Howard Hinnantc51e1022010-05-11 19:42:16 +00003108// template <> class codecvt<char16_t, char, mbstate_t>
3109
Howard Hinnantffb308e2010-08-22 00:03:27 +00003110locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003111
3112codecvt<char16_t, char, mbstate_t>::~codecvt()
3113{
3114}
3115
3116codecvt<char16_t, char, mbstate_t>::result
3117codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003118 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003119 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3120{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003121 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3122 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3123 const uint16_t* _frm_nxt = _frm;
3124 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3125 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3126 uint8_t* _to_nxt = _to;
3127 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3128 frm_nxt = frm + (_frm_nxt - _frm);
3129 to_nxt = to + (_to_nxt - _to);
3130 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003131}
3132
3133codecvt<char16_t, char, mbstate_t>::result
3134codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003135 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003136 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3137{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003138 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3139 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3140 const uint8_t* _frm_nxt = _frm;
3141 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3142 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3143 uint16_t* _to_nxt = _to;
3144 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3145 frm_nxt = frm + (_frm_nxt - _frm);
3146 to_nxt = to + (_to_nxt - _to);
3147 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003148}
3149
3150codecvt<char16_t, char, mbstate_t>::result
3151codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3152 extern_type* to, extern_type*, extern_type*& to_nxt) const
3153{
3154 to_nxt = to;
3155 return noconv;
3156}
3157
3158int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003159codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003160{
3161 return 0;
3162}
3163
3164bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003165codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003166{
3167 return false;
3168}
3169
3170int
3171codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3172 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3173{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003174 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3175 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3176 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003177}
3178
3179int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003180codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003181{
3182 return 4;
3183}
3184
3185// template <> class codecvt<char32_t, char, mbstate_t>
3186
Howard Hinnantffb308e2010-08-22 00:03:27 +00003187locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003188
3189codecvt<char32_t, char, mbstate_t>::~codecvt()
3190{
3191}
3192
3193codecvt<char32_t, char, mbstate_t>::result
3194codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003195 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003196 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3197{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003198 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3199 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3200 const uint32_t* _frm_nxt = _frm;
3201 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3202 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3203 uint8_t* _to_nxt = _to;
3204 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3205 frm_nxt = frm + (_frm_nxt - _frm);
3206 to_nxt = to + (_to_nxt - _to);
3207 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003208}
3209
3210codecvt<char32_t, char, mbstate_t>::result
3211codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003212 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003213 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3214{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003215 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3216 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3217 const uint8_t* _frm_nxt = _frm;
3218 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3219 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3220 uint32_t* _to_nxt = _to;
3221 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3222 frm_nxt = frm + (_frm_nxt - _frm);
3223 to_nxt = to + (_to_nxt - _to);
3224 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003225}
3226
3227codecvt<char32_t, char, mbstate_t>::result
3228codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3229 extern_type* to, extern_type*, extern_type*& to_nxt) const
3230{
3231 to_nxt = to;
3232 return noconv;
3233}
3234
3235int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003236codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003237{
3238 return 0;
3239}
3240
3241bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003242codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003243{
3244 return false;
3245}
3246
3247int
3248codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3249 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3250{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003251 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3252 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3253 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003254}
3255
3256int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003257codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003258{
3259 return 4;
3260}
3261
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003262// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003263
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003264__codecvt_utf8<wchar_t>::result
3265__codecvt_utf8<wchar_t>::do_out(state_type&,
3266 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003267 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3268{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003269#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003270 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3271 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3272 const uint16_t* _frm_nxt = _frm;
3273#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003274 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3275 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3276 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003277#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003278 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3279 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3280 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003281#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003282 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3283 _Maxcode_, _Mode_);
3284#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003285 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3286 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003287#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003288 frm_nxt = frm + (_frm_nxt - _frm);
3289 to_nxt = to + (_to_nxt - _to);
3290 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003291}
3292
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003293__codecvt_utf8<wchar_t>::result
3294__codecvt_utf8<wchar_t>::do_in(state_type&,
3295 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003296 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3297{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003298 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3299 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3300 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003301#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003302 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3303 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3304 uint16_t* _to_nxt = _to;
3305 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3306 _Maxcode_, _Mode_);
3307#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003308 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3309 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3310 uint32_t* _to_nxt = _to;
3311 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3312 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003313#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003314 frm_nxt = frm + (_frm_nxt - _frm);
3315 to_nxt = to + (_to_nxt - _to);
3316 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003317}
3318
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003319__codecvt_utf8<wchar_t>::result
3320__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003321 extern_type* to, extern_type*, extern_type*& to_nxt) const
3322{
3323 to_nxt = to;
3324 return noconv;
3325}
3326
3327int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003328__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003329{
3330 return 0;
3331}
3332
3333bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003334__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003335{
3336 return false;
3337}
3338
3339int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003340__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003341 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3342{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003343 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3344 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3345 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003346}
3347
3348int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003349__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003350{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003351 if (_Mode_ & consume_header)
3352 return 7;
3353 return 4;
3354}
3355
3356// __codecvt_utf8<char16_t>
3357
3358__codecvt_utf8<char16_t>::result
3359__codecvt_utf8<char16_t>::do_out(state_type&,
3360 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3361 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3362{
3363 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3364 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3365 const uint16_t* _frm_nxt = _frm;
3366 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3367 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3368 uint8_t* _to_nxt = _to;
3369 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3370 _Maxcode_, _Mode_);
3371 frm_nxt = frm + (_frm_nxt - _frm);
3372 to_nxt = to + (_to_nxt - _to);
3373 return r;
3374}
3375
3376__codecvt_utf8<char16_t>::result
3377__codecvt_utf8<char16_t>::do_in(state_type&,
3378 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3379 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3380{
3381 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3382 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3383 const uint8_t* _frm_nxt = _frm;
3384 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3385 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3386 uint16_t* _to_nxt = _to;
3387 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3388 _Maxcode_, _Mode_);
3389 frm_nxt = frm + (_frm_nxt - _frm);
3390 to_nxt = to + (_to_nxt - _to);
3391 return r;
3392}
3393
3394__codecvt_utf8<char16_t>::result
3395__codecvt_utf8<char16_t>::do_unshift(state_type&,
3396 extern_type* to, extern_type*, extern_type*& to_nxt) const
3397{
3398 to_nxt = to;
3399 return noconv;
3400}
3401
3402int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003403__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003404{
3405 return 0;
3406}
3407
3408bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003409__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003410{
3411 return false;
3412}
3413
3414int
3415__codecvt_utf8<char16_t>::do_length(state_type&,
3416 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3417{
3418 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3419 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3420 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3421}
3422
3423int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003424__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003425{
3426 if (_Mode_ & consume_header)
3427 return 6;
3428 return 3;
3429}
3430
3431// __codecvt_utf8<char32_t>
3432
3433__codecvt_utf8<char32_t>::result
3434__codecvt_utf8<char32_t>::do_out(state_type&,
3435 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3436 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3437{
3438 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3439 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3440 const uint32_t* _frm_nxt = _frm;
3441 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3442 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3443 uint8_t* _to_nxt = _to;
3444 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3445 _Maxcode_, _Mode_);
3446 frm_nxt = frm + (_frm_nxt - _frm);
3447 to_nxt = to + (_to_nxt - _to);
3448 return r;
3449}
3450
3451__codecvt_utf8<char32_t>::result
3452__codecvt_utf8<char32_t>::do_in(state_type&,
3453 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3454 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3455{
3456 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3457 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3458 const uint8_t* _frm_nxt = _frm;
3459 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3460 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3461 uint32_t* _to_nxt = _to;
3462 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3463 _Maxcode_, _Mode_);
3464 frm_nxt = frm + (_frm_nxt - _frm);
3465 to_nxt = to + (_to_nxt - _to);
3466 return r;
3467}
3468
3469__codecvt_utf8<char32_t>::result
3470__codecvt_utf8<char32_t>::do_unshift(state_type&,
3471 extern_type* to, extern_type*, extern_type*& to_nxt) const
3472{
3473 to_nxt = to;
3474 return noconv;
3475}
3476
3477int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003478__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003479{
3480 return 0;
3481}
3482
3483bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003484__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003485{
3486 return false;
3487}
3488
3489int
3490__codecvt_utf8<char32_t>::do_length(state_type&,
3491 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3492{
3493 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3494 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3495 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3496}
3497
3498int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003499__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003500{
3501 if (_Mode_ & consume_header)
3502 return 7;
3503 return 4;
3504}
3505
3506// __codecvt_utf16<wchar_t, false>
3507
3508__codecvt_utf16<wchar_t, false>::result
3509__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3510 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3511 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3512{
3513 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3514 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3515 const uint32_t* _frm_nxt = _frm;
3516 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3517 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3518 uint8_t* _to_nxt = _to;
3519 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3520 _Maxcode_, _Mode_);
3521 frm_nxt = frm + (_frm_nxt - _frm);
3522 to_nxt = to + (_to_nxt - _to);
3523 return r;
3524}
3525
3526__codecvt_utf16<wchar_t, false>::result
3527__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3528 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3529 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3530{
3531 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3532 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3533 const uint8_t* _frm_nxt = _frm;
3534 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3535 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3536 uint32_t* _to_nxt = _to;
3537 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3538 _Maxcode_, _Mode_);
3539 frm_nxt = frm + (_frm_nxt - _frm);
3540 to_nxt = to + (_to_nxt - _to);
3541 return r;
3542}
3543
3544__codecvt_utf16<wchar_t, false>::result
3545__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3546 extern_type* to, extern_type*, extern_type*& to_nxt) const
3547{
3548 to_nxt = to;
3549 return noconv;
3550}
3551
3552int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003553__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003554{
3555 return 0;
3556}
3557
3558bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003559__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003560{
3561 return false;
3562}
3563
3564int
3565__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3566 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3567{
3568 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3569 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3570 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3571}
3572
3573int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003574__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003575{
3576 if (_Mode_ & consume_header)
3577 return 6;
3578 return 4;
3579}
3580
3581// __codecvt_utf16<wchar_t, true>
3582
3583__codecvt_utf16<wchar_t, true>::result
3584__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3585 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3586 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3587{
3588 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3589 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3590 const uint32_t* _frm_nxt = _frm;
3591 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3592 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3593 uint8_t* _to_nxt = _to;
3594 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3595 _Maxcode_, _Mode_);
3596 frm_nxt = frm + (_frm_nxt - _frm);
3597 to_nxt = to + (_to_nxt - _to);
3598 return r;
3599}
3600
3601__codecvt_utf16<wchar_t, true>::result
3602__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3603 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3604 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3605{
3606 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3607 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3608 const uint8_t* _frm_nxt = _frm;
3609 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3610 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3611 uint32_t* _to_nxt = _to;
3612 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3613 _Maxcode_, _Mode_);
3614 frm_nxt = frm + (_frm_nxt - _frm);
3615 to_nxt = to + (_to_nxt - _to);
3616 return r;
3617}
3618
3619__codecvt_utf16<wchar_t, true>::result
3620__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3621 extern_type* to, extern_type*, extern_type*& to_nxt) const
3622{
3623 to_nxt = to;
3624 return noconv;
3625}
3626
3627int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003628__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003629{
3630 return 0;
3631}
3632
3633bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003634__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003635{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003636 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003637}
3638
3639int
3640__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3641 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3642{
3643 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3644 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3645 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3646}
3647
3648int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003649__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003650{
3651 if (_Mode_ & consume_header)
3652 return 6;
3653 return 4;
3654}
3655
3656// __codecvt_utf16<char16_t, false>
3657
3658__codecvt_utf16<char16_t, false>::result
3659__codecvt_utf16<char16_t, false>::do_out(state_type&,
3660 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3661 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3662{
3663 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3664 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3665 const uint16_t* _frm_nxt = _frm;
3666 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3667 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3668 uint8_t* _to_nxt = _to;
3669 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3670 _Maxcode_, _Mode_);
3671 frm_nxt = frm + (_frm_nxt - _frm);
3672 to_nxt = to + (_to_nxt - _to);
3673 return r;
3674}
3675
3676__codecvt_utf16<char16_t, false>::result
3677__codecvt_utf16<char16_t, false>::do_in(state_type&,
3678 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3679 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3680{
3681 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3682 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3683 const uint8_t* _frm_nxt = _frm;
3684 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3685 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3686 uint16_t* _to_nxt = _to;
3687 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3688 _Maxcode_, _Mode_);
3689 frm_nxt = frm + (_frm_nxt - _frm);
3690 to_nxt = to + (_to_nxt - _to);
3691 return r;
3692}
3693
3694__codecvt_utf16<char16_t, false>::result
3695__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3696 extern_type* to, extern_type*, extern_type*& to_nxt) const
3697{
3698 to_nxt = to;
3699 return noconv;
3700}
3701
3702int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003703__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003704{
3705 return 0;
3706}
3707
3708bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003709__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003710{
3711 return false;
3712}
3713
3714int
3715__codecvt_utf16<char16_t, false>::do_length(state_type&,
3716 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3717{
3718 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3719 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3720 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3721}
3722
3723int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003724__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003725{
3726 if (_Mode_ & consume_header)
3727 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003728 return 2;
3729}
3730
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003731// __codecvt_utf16<char16_t, true>
3732
3733__codecvt_utf16<char16_t, true>::result
3734__codecvt_utf16<char16_t, true>::do_out(state_type&,
3735 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3736 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3737{
3738 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3739 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3740 const uint16_t* _frm_nxt = _frm;
3741 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3742 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3743 uint8_t* _to_nxt = _to;
3744 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3745 _Maxcode_, _Mode_);
3746 frm_nxt = frm + (_frm_nxt - _frm);
3747 to_nxt = to + (_to_nxt - _to);
3748 return r;
3749}
3750
3751__codecvt_utf16<char16_t, true>::result
3752__codecvt_utf16<char16_t, true>::do_in(state_type&,
3753 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3754 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3755{
3756 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3757 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3758 const uint8_t* _frm_nxt = _frm;
3759 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3760 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3761 uint16_t* _to_nxt = _to;
3762 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3763 _Maxcode_, _Mode_);
3764 frm_nxt = frm + (_frm_nxt - _frm);
3765 to_nxt = to + (_to_nxt - _to);
3766 return r;
3767}
3768
3769__codecvt_utf16<char16_t, true>::result
3770__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3771 extern_type* to, extern_type*, extern_type*& to_nxt) const
3772{
3773 to_nxt = to;
3774 return noconv;
3775}
3776
3777int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003778__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003779{
3780 return 0;
3781}
3782
3783bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003784__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003785{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003786 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003787}
3788
3789int
3790__codecvt_utf16<char16_t, true>::do_length(state_type&,
3791 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3792{
3793 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3794 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3795 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3796}
3797
3798int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003799__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003800{
3801 if (_Mode_ & consume_header)
3802 return 4;
3803 return 2;
3804}
3805
3806// __codecvt_utf16<char32_t, false>
3807
3808__codecvt_utf16<char32_t, false>::result
3809__codecvt_utf16<char32_t, false>::do_out(state_type&,
3810 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3811 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3812{
3813 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3814 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3815 const uint32_t* _frm_nxt = _frm;
3816 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3817 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3818 uint8_t* _to_nxt = _to;
3819 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3820 _Maxcode_, _Mode_);
3821 frm_nxt = frm + (_frm_nxt - _frm);
3822 to_nxt = to + (_to_nxt - _to);
3823 return r;
3824}
3825
3826__codecvt_utf16<char32_t, false>::result
3827__codecvt_utf16<char32_t, false>::do_in(state_type&,
3828 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3829 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3830{
3831 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3832 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3833 const uint8_t* _frm_nxt = _frm;
3834 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3835 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3836 uint32_t* _to_nxt = _to;
3837 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3838 _Maxcode_, _Mode_);
3839 frm_nxt = frm + (_frm_nxt - _frm);
3840 to_nxt = to + (_to_nxt - _to);
3841 return r;
3842}
3843
3844__codecvt_utf16<char32_t, false>::result
3845__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3846 extern_type* to, extern_type*, extern_type*& to_nxt) const
3847{
3848 to_nxt = to;
3849 return noconv;
3850}
3851
3852int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003853__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003854{
3855 return 0;
3856}
3857
3858bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003859__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003860{
3861 return false;
3862}
3863
3864int
3865__codecvt_utf16<char32_t, false>::do_length(state_type&,
3866 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3867{
3868 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3869 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3870 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3871}
3872
3873int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003874__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003875{
3876 if (_Mode_ & consume_header)
3877 return 6;
3878 return 4;
3879}
3880
3881// __codecvt_utf16<char32_t, true>
3882
3883__codecvt_utf16<char32_t, true>::result
3884__codecvt_utf16<char32_t, true>::do_out(state_type&,
3885 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3886 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3887{
3888 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3889 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3890 const uint32_t* _frm_nxt = _frm;
3891 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3892 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3893 uint8_t* _to_nxt = _to;
3894 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3895 _Maxcode_, _Mode_);
3896 frm_nxt = frm + (_frm_nxt - _frm);
3897 to_nxt = to + (_to_nxt - _to);
3898 return r;
3899}
3900
3901__codecvt_utf16<char32_t, true>::result
3902__codecvt_utf16<char32_t, true>::do_in(state_type&,
3903 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3904 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3905{
3906 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3907 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3908 const uint8_t* _frm_nxt = _frm;
3909 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3910 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3911 uint32_t* _to_nxt = _to;
3912 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3913 _Maxcode_, _Mode_);
3914 frm_nxt = frm + (_frm_nxt - _frm);
3915 to_nxt = to + (_to_nxt - _to);
3916 return r;
3917}
3918
3919__codecvt_utf16<char32_t, true>::result
3920__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3921 extern_type* to, extern_type*, extern_type*& to_nxt) const
3922{
3923 to_nxt = to;
3924 return noconv;
3925}
3926
3927int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003928__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003929{
3930 return 0;
3931}
3932
3933bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003934__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003935{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003936 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003937}
3938
3939int
3940__codecvt_utf16<char32_t, true>::do_length(state_type&,
3941 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3942{
3943 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3944 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3945 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3946}
3947
3948int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003949__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003950{
3951 if (_Mode_ & consume_header)
3952 return 6;
3953 return 4;
3954}
3955
3956// __codecvt_utf8_utf16<wchar_t>
3957
3958__codecvt_utf8_utf16<wchar_t>::result
3959__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3960 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3961 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3962{
3963 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3964 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3965 const uint32_t* _frm_nxt = _frm;
3966 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3967 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3968 uint8_t* _to_nxt = _to;
3969 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3970 _Maxcode_, _Mode_);
3971 frm_nxt = frm + (_frm_nxt - _frm);
3972 to_nxt = to + (_to_nxt - _to);
3973 return r;
3974}
3975
3976__codecvt_utf8_utf16<wchar_t>::result
3977__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3978 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3979 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3980{
3981 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3982 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3983 const uint8_t* _frm_nxt = _frm;
3984 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3985 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3986 uint32_t* _to_nxt = _to;
3987 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3988 _Maxcode_, _Mode_);
3989 frm_nxt = frm + (_frm_nxt - _frm);
3990 to_nxt = to + (_to_nxt - _to);
3991 return r;
3992}
3993
3994__codecvt_utf8_utf16<wchar_t>::result
3995__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3996 extern_type* to, extern_type*, extern_type*& to_nxt) const
3997{
3998 to_nxt = to;
3999 return noconv;
4000}
4001
4002int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004003__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004004{
4005 return 0;
4006}
4007
4008bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004009__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004010{
4011 return false;
4012}
4013
4014int
4015__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4016 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4017{
4018 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4019 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4020 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4021}
4022
4023int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004024__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004025{
4026 if (_Mode_ & consume_header)
4027 return 7;
4028 return 4;
4029}
4030
4031// __codecvt_utf8_utf16<char16_t>
4032
4033__codecvt_utf8_utf16<char16_t>::result
4034__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4035 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4036 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4037{
4038 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4039 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4040 const uint16_t* _frm_nxt = _frm;
4041 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4042 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4043 uint8_t* _to_nxt = _to;
4044 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4045 _Maxcode_, _Mode_);
4046 frm_nxt = frm + (_frm_nxt - _frm);
4047 to_nxt = to + (_to_nxt - _to);
4048 return r;
4049}
4050
4051__codecvt_utf8_utf16<char16_t>::result
4052__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4053 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4054 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4055{
4056 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4057 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4058 const uint8_t* _frm_nxt = _frm;
4059 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4060 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4061 uint16_t* _to_nxt = _to;
4062 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4063 _Maxcode_, _Mode_);
4064 frm_nxt = frm + (_frm_nxt - _frm);
4065 to_nxt = to + (_to_nxt - _to);
4066 return r;
4067}
4068
4069__codecvt_utf8_utf16<char16_t>::result
4070__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4071 extern_type* to, extern_type*, extern_type*& to_nxt) const
4072{
4073 to_nxt = to;
4074 return noconv;
4075}
4076
4077int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004078__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004079{
4080 return 0;
4081}
4082
4083bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004084__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004085{
4086 return false;
4087}
4088
4089int
4090__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4091 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4092{
4093 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4094 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4095 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4096}
4097
4098int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004099__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004100{
4101 if (_Mode_ & consume_header)
4102 return 7;
4103 return 4;
4104}
4105
4106// __codecvt_utf8_utf16<char32_t>
4107
4108__codecvt_utf8_utf16<char32_t>::result
4109__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4110 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4111 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4112{
4113 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4114 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4115 const uint32_t* _frm_nxt = _frm;
4116 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4117 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4118 uint8_t* _to_nxt = _to;
4119 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4120 _Maxcode_, _Mode_);
4121 frm_nxt = frm + (_frm_nxt - _frm);
4122 to_nxt = to + (_to_nxt - _to);
4123 return r;
4124}
4125
4126__codecvt_utf8_utf16<char32_t>::result
4127__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4128 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4129 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4130{
4131 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4132 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4133 const uint8_t* _frm_nxt = _frm;
4134 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4135 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4136 uint32_t* _to_nxt = _to;
4137 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4138 _Maxcode_, _Mode_);
4139 frm_nxt = frm + (_frm_nxt - _frm);
4140 to_nxt = to + (_to_nxt - _to);
4141 return r;
4142}
4143
4144__codecvt_utf8_utf16<char32_t>::result
4145__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4146 extern_type* to, extern_type*, extern_type*& to_nxt) const
4147{
4148 to_nxt = to;
4149 return noconv;
4150}
4151
4152int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004153__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004154{
4155 return 0;
4156}
4157
4158bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004159__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004160{
4161 return false;
4162}
4163
4164int
4165__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4166 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4167{
4168 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4169 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4170 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4171}
4172
4173int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004174__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004175{
4176 if (_Mode_ & consume_header)
4177 return 7;
4178 return 4;
4179}
4180
Howard Hinnantc51e1022010-05-11 19:42:16 +00004181// __narrow_to_utf8<16>
4182
4183__narrow_to_utf8<16>::~__narrow_to_utf8()
4184{
4185}
4186
4187// __narrow_to_utf8<32>
4188
4189__narrow_to_utf8<32>::~__narrow_to_utf8()
4190{
4191}
4192
4193// __widen_from_utf8<16>
4194
4195__widen_from_utf8<16>::~__widen_from_utf8()
4196{
4197}
4198
4199// __widen_from_utf8<32>
4200
4201__widen_from_utf8<32>::~__widen_from_utf8()
4202{
4203}
4204
Eric Fiselierbf945a22016-12-11 00:20:59 +00004205
4206static bool checked_string_to_wchar_convert(wchar_t& dest,
4207 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004208 locale_t loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004209 if (*ptr == '\0')
4210 return false;
4211 mbstate_t mb = {};
4212 wchar_t out;
4213 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4214 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4215 return false;
4216 }
4217 dest = out;
4218 return true;
4219}
4220
4221static bool checked_string_to_char_convert(char& dest,
4222 const char* ptr,
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004223 locale_t __loc) {
Eric Fiselierbf945a22016-12-11 00:20:59 +00004224 if (*ptr == '\0')
4225 return false;
4226 if (!ptr[1]) {
4227 dest = *ptr;
4228 return true;
4229 }
4230 // First convert the MBS into a wide char then attempt to narrow it using
4231 // wctob_l.
4232 wchar_t wout;
4233 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4234 return false;
4235 int res;
4236 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4237 dest = res;
4238 return true;
4239 }
4240 // FIXME: Work around specific multibyte sequences that we can reasonable
4241 // translate into a different single byte.
4242 switch (wout) {
Eric Fiseliercc85b762018-04-04 04:00:14 +00004243 case L'\u202F': // narrow non-breaking space
Eric Fiselierbf945a22016-12-11 00:20:59 +00004244 case L'\u00A0': // non-breaking space
4245 dest = ' ';
4246 return true;
4247 default:
4248 return false;
4249 }
4250 _LIBCPP_UNREACHABLE();
4251}
4252
4253
Howard Hinnantc51e1022010-05-11 19:42:16 +00004254// numpunct<char> && numpunct<wchar_t>
4255
4256locale::id numpunct< char >::id;
4257locale::id numpunct<wchar_t>::id;
4258
4259numpunct<char>::numpunct(size_t refs)
4260 : locale::facet(refs),
4261 __decimal_point_('.'),
4262 __thousands_sep_(',')
4263{
4264}
4265
4266numpunct<wchar_t>::numpunct(size_t refs)
4267 : locale::facet(refs),
4268 __decimal_point_(L'.'),
4269 __thousands_sep_(L',')
4270{
4271}
4272
4273numpunct<char>::~numpunct()
4274{
4275}
4276
4277numpunct<wchar_t>::~numpunct()
4278{
4279}
4280
4281 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4282wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4283
4284 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4285wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4286
4287string numpunct< char >::do_grouping() const {return __grouping_;}
4288string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4289
4290 string numpunct< char >::do_truename() const {return "true";}
4291wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4292
4293 string numpunct< char >::do_falsename() const {return "false";}
4294wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4295
4296// numpunct_byname<char>
4297
4298numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4299 : numpunct<char>(refs)
4300{
4301 __init(nm);
4302}
4303
4304numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4305 : numpunct<char>(refs)
4306{
4307 __init(nm.c_str());
4308}
4309
4310numpunct_byname<char>::~numpunct_byname()
4311{
4312}
4313
4314void
4315numpunct_byname<char>::__init(const char* nm)
4316{
4317 if (strcmp(nm, "C") != 0)
4318 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004319 __libcpp_unique_locale loc(nm);
4320 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00004321 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004322 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004323
Ben Craig3756b922016-03-09 15:39:39 +00004324 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004325 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4326 loc.get());
4327 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4328 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004329 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004330 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004331 }
4332}
4333
4334// numpunct_byname<wchar_t>
4335
4336numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4337 : numpunct<wchar_t>(refs)
4338{
4339 __init(nm);
4340}
4341
4342numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4343 : numpunct<wchar_t>(refs)
4344{
4345 __init(nm.c_str());
4346}
4347
4348numpunct_byname<wchar_t>::~numpunct_byname()
4349{
4350}
4351
4352void
4353numpunct_byname<wchar_t>::__init(const char* nm)
4354{
4355 if (strcmp(nm, "C") != 0)
4356 {
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00004357 __libcpp_unique_locale loc(nm);
4358 if (!loc)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004359 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004360 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004361
Ben Craig3756b922016-03-09 15:39:39 +00004362 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004363 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4364 loc.get());
4365 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4366 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004367 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004368 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004369 }
4370}
4371
4372// num_get helpers
4373
4374int
4375__num_get_base::__get_base(ios_base& iob)
4376{
4377 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4378 if (__basefield == ios_base::oct)
4379 return 8;
4380 else if (__basefield == ios_base::hex)
4381 return 16;
4382 else if (__basefield == 0)
4383 return 0;
4384 return 10;
4385}
4386
4387const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4388
4389void
4390__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4391 ios_base::iostate& __err)
4392{
4393 if (__grouping.size() != 0)
4394 {
4395 reverse(__g, __g_end);
4396 const char* __ig = __grouping.data();
4397 const char* __eg = __ig + __grouping.size();
4398 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4399 {
4400 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4401 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004402 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004403 {
4404 __err = ios_base::failbit;
4405 return;
4406 }
4407 }
4408 if (__eg - __ig > 1)
4409 ++__ig;
4410 }
4411 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4412 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004413 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004414 __err = ios_base::failbit;
4415 }
4416 }
4417}
4418
4419void
4420__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4421 ios_base::fmtflags __flags)
4422{
4423 if (__flags & ios_base::showpos)
4424 *__fmtp++ = '+';
4425 if (__flags & ios_base::showbase)
4426 *__fmtp++ = '#';
4427 while(*__len)
4428 *__fmtp++ = *__len++;
4429 if ((__flags & ios_base::basefield) == ios_base::oct)
4430 *__fmtp = 'o';
4431 else if ((__flags & ios_base::basefield) == ios_base::hex)
4432 {
4433 if (__flags & ios_base::uppercase)
4434 *__fmtp = 'X';
4435 else
4436 *__fmtp = 'x';
4437 }
4438 else if (__signd)
4439 *__fmtp = 'd';
4440 else
4441 *__fmtp = 'u';
4442}
4443
4444bool
4445__num_put_base::__format_float(char* __fmtp, const char* __len,
4446 ios_base::fmtflags __flags)
4447{
4448 bool specify_precision = true;
4449 if (__flags & ios_base::showpos)
4450 *__fmtp++ = '+';
4451 if (__flags & ios_base::showpoint)
4452 *__fmtp++ = '#';
4453 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004454 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004455 if (floatfield == (ios_base::fixed | ios_base::scientific))
4456 specify_precision = false;
4457 else
4458 {
4459 *__fmtp++ = '.';
4460 *__fmtp++ = '*';
4461 }
4462 while(*__len)
4463 *__fmtp++ = *__len++;
4464 if (floatfield == ios_base::fixed)
4465 {
4466 if (uppercase)
4467 *__fmtp = 'F';
4468 else
4469 *__fmtp = 'f';
4470 }
4471 else if (floatfield == ios_base::scientific)
4472 {
4473 if (uppercase)
4474 *__fmtp = 'E';
4475 else
4476 *__fmtp = 'e';
4477 }
4478 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4479 {
4480 if (uppercase)
4481 *__fmtp = 'A';
4482 else
4483 *__fmtp = 'a';
4484 }
4485 else
4486 {
4487 if (uppercase)
4488 *__fmtp = 'G';
4489 else
4490 *__fmtp = 'g';
4491 }
4492 return specify_precision;
4493}
4494
4495char*
4496__num_put_base::__identify_padding(char* __nb, char* __ne,
4497 const ios_base& __iob)
4498{
4499 switch (__iob.flags() & ios_base::adjustfield)
4500 {
4501 case ios_base::internal:
4502 if (__nb[0] == '-' || __nb[0] == '+')
4503 return __nb+1;
4504 if (__ne - __nb >= 2 && __nb[0] == '0'
4505 && (__nb[1] == 'x' || __nb[1] == 'X'))
4506 return __nb+2;
4507 break;
4508 case ios_base::left:
4509 return __ne;
4510 case ios_base::right:
4511 default:
4512 break;
4513 }
4514 return __nb;
4515}
4516
4517// time_get
4518
4519static
4520string*
4521init_weeks()
4522{
4523 static string weeks[14];
4524 weeks[0] = "Sunday";
4525 weeks[1] = "Monday";
4526 weeks[2] = "Tuesday";
4527 weeks[3] = "Wednesday";
4528 weeks[4] = "Thursday";
4529 weeks[5] = "Friday";
4530 weeks[6] = "Saturday";
4531 weeks[7] = "Sun";
4532 weeks[8] = "Mon";
4533 weeks[9] = "Tue";
4534 weeks[10] = "Wed";
4535 weeks[11] = "Thu";
4536 weeks[12] = "Fri";
4537 weeks[13] = "Sat";
4538 return weeks;
4539}
4540
4541static
4542wstring*
4543init_wweeks()
4544{
4545 static wstring weeks[14];
4546 weeks[0] = L"Sunday";
4547 weeks[1] = L"Monday";
4548 weeks[2] = L"Tuesday";
4549 weeks[3] = L"Wednesday";
4550 weeks[4] = L"Thursday";
4551 weeks[5] = L"Friday";
4552 weeks[6] = L"Saturday";
4553 weeks[7] = L"Sun";
4554 weeks[8] = L"Mon";
4555 weeks[9] = L"Tue";
4556 weeks[10] = L"Wed";
4557 weeks[11] = L"Thu";
4558 weeks[12] = L"Fri";
4559 weeks[13] = L"Sat";
4560 return weeks;
4561}
4562
4563template <>
4564const string*
4565__time_get_c_storage<char>::__weeks() const
4566{
4567 static const string* weeks = init_weeks();
4568 return weeks;
4569}
4570
4571template <>
4572const wstring*
4573__time_get_c_storage<wchar_t>::__weeks() const
4574{
4575 static const wstring* weeks = init_wweeks();
4576 return weeks;
4577}
4578
4579static
4580string*
4581init_months()
4582{
4583 static string months[24];
4584 months[0] = "January";
4585 months[1] = "February";
4586 months[2] = "March";
4587 months[3] = "April";
4588 months[4] = "May";
4589 months[5] = "June";
4590 months[6] = "July";
4591 months[7] = "August";
4592 months[8] = "September";
4593 months[9] = "October";
4594 months[10] = "November";
4595 months[11] = "December";
4596 months[12] = "Jan";
4597 months[13] = "Feb";
4598 months[14] = "Mar";
4599 months[15] = "Apr";
4600 months[16] = "May";
4601 months[17] = "Jun";
4602 months[18] = "Jul";
4603 months[19] = "Aug";
4604 months[20] = "Sep";
4605 months[21] = "Oct";
4606 months[22] = "Nov";
4607 months[23] = "Dec";
4608 return months;
4609}
4610
4611static
4612wstring*
4613init_wmonths()
4614{
4615 static wstring months[24];
4616 months[0] = L"January";
4617 months[1] = L"February";
4618 months[2] = L"March";
4619 months[3] = L"April";
4620 months[4] = L"May";
4621 months[5] = L"June";
4622 months[6] = L"July";
4623 months[7] = L"August";
4624 months[8] = L"September";
4625 months[9] = L"October";
4626 months[10] = L"November";
4627 months[11] = L"December";
4628 months[12] = L"Jan";
4629 months[13] = L"Feb";
4630 months[14] = L"Mar";
4631 months[15] = L"Apr";
4632 months[16] = L"May";
4633 months[17] = L"Jun";
4634 months[18] = L"Jul";
4635 months[19] = L"Aug";
4636 months[20] = L"Sep";
4637 months[21] = L"Oct";
4638 months[22] = L"Nov";
4639 months[23] = L"Dec";
4640 return months;
4641}
4642
4643template <>
4644const string*
4645__time_get_c_storage<char>::__months() const
4646{
4647 static const string* months = init_months();
4648 return months;
4649}
4650
4651template <>
4652const wstring*
4653__time_get_c_storage<wchar_t>::__months() const
4654{
4655 static const wstring* months = init_wmonths();
4656 return months;
4657}
4658
4659static
4660string*
4661init_am_pm()
4662{
Marshall Clow5cc04922018-01-11 17:16:52 +00004663 static string am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004664 am_pm[0] = "AM";
4665 am_pm[1] = "PM";
4666 return am_pm;
4667}
4668
4669static
4670wstring*
4671init_wam_pm()
4672{
Marshall Clow5cc04922018-01-11 17:16:52 +00004673 static wstring am_pm[2];
Howard Hinnantc51e1022010-05-11 19:42:16 +00004674 am_pm[0] = L"AM";
4675 am_pm[1] = L"PM";
4676 return am_pm;
4677}
4678
4679template <>
4680const string*
4681__time_get_c_storage<char>::__am_pm() const
4682{
4683 static const string* am_pm = init_am_pm();
4684 return am_pm;
4685}
4686
4687template <>
4688const wstring*
4689__time_get_c_storage<wchar_t>::__am_pm() const
4690{
4691 static const wstring* am_pm = init_wam_pm();
4692 return am_pm;
4693}
4694
4695template <>
4696const string&
4697__time_get_c_storage<char>::__x() const
4698{
4699 static string s("%m/%d/%y");
4700 return s;
4701}
4702
4703template <>
4704const wstring&
4705__time_get_c_storage<wchar_t>::__x() const
4706{
4707 static wstring s(L"%m/%d/%y");
4708 return s;
4709}
4710
4711template <>
4712const string&
4713__time_get_c_storage<char>::__X() const
4714{
4715 static string s("%H:%M:%S");
4716 return s;
4717}
4718
4719template <>
4720const wstring&
4721__time_get_c_storage<wchar_t>::__X() const
4722{
4723 static wstring s(L"%H:%M:%S");
4724 return s;
4725}
4726
4727template <>
4728const string&
4729__time_get_c_storage<char>::__c() const
4730{
4731 static string s("%a %b %d %H:%M:%S %Y");
4732 return s;
4733}
4734
4735template <>
4736const wstring&
4737__time_get_c_storage<wchar_t>::__c() const
4738{
4739 static wstring s(L"%a %b %d %H:%M:%S %Y");
4740 return s;
4741}
4742
4743template <>
4744const string&
4745__time_get_c_storage<char>::__r() const
4746{
4747 static string s("%I:%M:%S %p");
4748 return s;
4749}
4750
4751template <>
4752const wstring&
4753__time_get_c_storage<wchar_t>::__r() const
4754{
4755 static wstring s(L"%I:%M:%S %p");
4756 return s;
4757}
4758
4759// time_get_byname
4760
4761__time_get::__time_get(const char* nm)
4762 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4763{
4764 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004765 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004766 " failed to construct for " + string(nm));
4767}
4768
4769__time_get::__time_get(const string& nm)
4770 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4771{
4772 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004773 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004774 " failed to construct for " + nm);
4775}
4776
4777__time_get::~__time_get()
4778{
4779 freelocale(__loc_);
4780}
Marshall Clowd920eea2013-10-21 15:07:28 +00004781#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004782#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004783#endif
4784#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004785#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004786#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004787
Howard Hinnantc51e1022010-05-11 19:42:16 +00004788template <>
4789string
4790__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4791{
Howard Hinnant990207c2012-02-19 14:55:32 +00004792 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004793 t.tm_sec = 59;
4794 t.tm_min = 55;
4795 t.tm_hour = 23;
4796 t.tm_mday = 31;
4797 t.tm_mon = 11;
4798 t.tm_year = 161;
4799 t.tm_wday = 6;
4800 t.tm_yday = 364;
4801 t.tm_isdst = -1;
4802 char buf[100];
4803 char f[3] = {0};
4804 f[0] = '%';
4805 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004806 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004807 char* bb = buf;
4808 char* be = buf + n;
4809 string result;
4810 while (bb != be)
4811 {
4812 if (ct.is(ctype_base::space, *bb))
4813 {
4814 result.push_back(' ');
4815 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4816 ;
4817 continue;
4818 }
4819 char* w = bb;
4820 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004821 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004822 ct, err, false)
4823 - this->__weeks_;
4824 if (i < 14)
4825 {
4826 result.push_back('%');
4827 if (i < 7)
4828 result.push_back('A');
4829 else
4830 result.push_back('a');
4831 bb = w;
4832 continue;
4833 }
4834 w = bb;
4835 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4836 ct, err, false)
4837 - this->__months_;
4838 if (i < 24)
4839 {
4840 result.push_back('%');
4841 if (i < 12)
4842 result.push_back('B');
4843 else
4844 result.push_back('b');
4845 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4846 result.back() = 'm';
4847 bb = w;
4848 continue;
4849 }
4850 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4851 {
4852 w = bb;
4853 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4854 ct, err, false) - this->__am_pm_;
4855 if (i < 2)
4856 {
4857 result.push_back('%');
4858 result.push_back('p');
4859 bb = w;
4860 continue;
4861 }
4862 }
4863 w = bb;
4864 if (ct.is(ctype_base::digit, *bb))
4865 {
4866 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4867 {
4868 case 6:
4869 result.push_back('%');
4870 result.push_back('w');
4871 break;
4872 case 7:
4873 result.push_back('%');
4874 result.push_back('u');
4875 break;
4876 case 11:
4877 result.push_back('%');
4878 result.push_back('I');
4879 break;
4880 case 12:
4881 result.push_back('%');
4882 result.push_back('m');
4883 break;
4884 case 23:
4885 result.push_back('%');
4886 result.push_back('H');
4887 break;
4888 case 31:
4889 result.push_back('%');
4890 result.push_back('d');
4891 break;
4892 case 55:
4893 result.push_back('%');
4894 result.push_back('M');
4895 break;
4896 case 59:
4897 result.push_back('%');
4898 result.push_back('S');
4899 break;
4900 case 61:
4901 result.push_back('%');
4902 result.push_back('y');
4903 break;
4904 case 364:
4905 result.push_back('%');
4906 result.push_back('j');
4907 break;
4908 case 2061:
4909 result.push_back('%');
4910 result.push_back('Y');
4911 break;
4912 default:
4913 for (; w != bb; ++w)
4914 result.push_back(*w);
4915 break;
4916 }
4917 continue;
4918 }
4919 if (*bb == '%')
4920 {
4921 result.push_back('%');
4922 result.push_back('%');
4923 ++bb;
4924 continue;
4925 }
4926 result.push_back(*bb);
4927 ++bb;
4928 }
4929 return result;
4930}
4931
Marshall Clowd920eea2013-10-21 15:07:28 +00004932#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004933#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004934#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004935
Howard Hinnantc51e1022010-05-11 19:42:16 +00004936template <>
4937wstring
4938__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4939{
Howard Hinnant990207c2012-02-19 14:55:32 +00004940 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004941 t.tm_sec = 59;
4942 t.tm_min = 55;
4943 t.tm_hour = 23;
4944 t.tm_mday = 31;
4945 t.tm_mon = 11;
4946 t.tm_year = 161;
4947 t.tm_wday = 6;
4948 t.tm_yday = 364;
4949 t.tm_isdst = -1;
4950 char buf[100];
4951 char f[3] = {0};
4952 f[0] = '%';
4953 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004954 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004955 wchar_t wbuf[100];
4956 wchar_t* wbb = wbuf;
4957 mbstate_t mb = {0};
4958 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004959 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004960 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004961 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004962 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004963 wstring result;
4964 while (wbb != wbe)
4965 {
4966 if (ct.is(ctype_base::space, *wbb))
4967 {
4968 result.push_back(L' ');
4969 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4970 ;
4971 continue;
4972 }
4973 wchar_t* w = wbb;
4974 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004975 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004976 ct, err, false)
4977 - this->__weeks_;
4978 if (i < 14)
4979 {
4980 result.push_back(L'%');
4981 if (i < 7)
4982 result.push_back(L'A');
4983 else
4984 result.push_back(L'a');
4985 wbb = w;
4986 continue;
4987 }
4988 w = wbb;
4989 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4990 ct, err, false)
4991 - this->__months_;
4992 if (i < 24)
4993 {
4994 result.push_back(L'%');
4995 if (i < 12)
4996 result.push_back(L'B');
4997 else
4998 result.push_back(L'b');
4999 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5000 result.back() = L'm';
5001 wbb = w;
5002 continue;
5003 }
5004 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5005 {
5006 w = wbb;
5007 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5008 ct, err, false) - this->__am_pm_;
5009 if (i < 2)
5010 {
5011 result.push_back(L'%');
5012 result.push_back(L'p');
5013 wbb = w;
5014 continue;
5015 }
5016 }
5017 w = wbb;
5018 if (ct.is(ctype_base::digit, *wbb))
5019 {
5020 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5021 {
5022 case 6:
5023 result.push_back(L'%');
5024 result.push_back(L'w');
5025 break;
5026 case 7:
5027 result.push_back(L'%');
5028 result.push_back(L'u');
5029 break;
5030 case 11:
5031 result.push_back(L'%');
5032 result.push_back(L'I');
5033 break;
5034 case 12:
5035 result.push_back(L'%');
5036 result.push_back(L'm');
5037 break;
5038 case 23:
5039 result.push_back(L'%');
5040 result.push_back(L'H');
5041 break;
5042 case 31:
5043 result.push_back(L'%');
5044 result.push_back(L'd');
5045 break;
5046 case 55:
5047 result.push_back(L'%');
5048 result.push_back(L'M');
5049 break;
5050 case 59:
5051 result.push_back(L'%');
5052 result.push_back(L'S');
5053 break;
5054 case 61:
5055 result.push_back(L'%');
5056 result.push_back(L'y');
5057 break;
5058 case 364:
5059 result.push_back(L'%');
5060 result.push_back(L'j');
5061 break;
5062 case 2061:
5063 result.push_back(L'%');
5064 result.push_back(L'Y');
5065 break;
5066 default:
5067 for (; w != wbb; ++w)
5068 result.push_back(*w);
5069 break;
5070 }
5071 continue;
5072 }
5073 if (ct.narrow(*wbb, 0) == '%')
5074 {
5075 result.push_back(L'%');
5076 result.push_back(L'%');
5077 ++wbb;
5078 continue;
5079 }
5080 result.push_back(*wbb);
5081 ++wbb;
5082 }
5083 return result;
5084}
5085
5086template <>
5087void
5088__time_get_storage<char>::init(const ctype<char>& ct)
5089{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005090 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005091 char buf[100];
5092 // __weeks_
5093 for (int i = 0; i < 7; ++i)
5094 {
5095 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005096 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005097 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005098 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005099 __weeks_[i+7] = buf;
5100 }
5101 // __months_
5102 for (int i = 0; i < 12; ++i)
5103 {
5104 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005105 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005106 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005107 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005108 __months_[i+12] = buf;
5109 }
5110 // __am_pm_
5111 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005112 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005113 __am_pm_[0] = buf;
5114 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005115 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005116 __am_pm_[1] = buf;
5117 __c_ = __analyze('c', ct);
5118 __r_ = __analyze('r', ct);
5119 __x_ = __analyze('x', ct);
5120 __X_ = __analyze('X', ct);
5121}
5122
5123template <>
5124void
5125__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5126{
5127 tm t = {0};
5128 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005129 wchar_t wbuf[100];
5130 wchar_t* wbe;
5131 mbstate_t mb = {0};
5132 // __weeks_
5133 for (int i = 0; i < 7; ++i)
5134 {
5135 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005136 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005137 mb = mbstate_t();
5138 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005139 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005140 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005141 __throw_runtime_error("locale not supported");
5142 wbe = wbuf + j;
5143 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005144 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005145 mb = mbstate_t();
5146 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005147 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005148 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005149 __throw_runtime_error("locale not supported");
5150 wbe = wbuf + j;
5151 __weeks_[i+7].assign(wbuf, wbe);
5152 }
5153 // __months_
5154 for (int i = 0; i < 12; ++i)
5155 {
5156 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005157 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005158 mb = mbstate_t();
5159 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005160 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005161 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005162 __throw_runtime_error("locale not supported");
5163 wbe = wbuf + j;
5164 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005165 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005166 mb = mbstate_t();
5167 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005168 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005169 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005170 __throw_runtime_error("locale not supported");
5171 wbe = wbuf + j;
5172 __months_[i+12].assign(wbuf, wbe);
5173 }
5174 // __am_pm_
5175 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005176 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005177 mb = mbstate_t();
5178 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005179 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005180 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005181 __throw_runtime_error("locale not supported");
5182 wbe = wbuf + j;
5183 __am_pm_[0].assign(wbuf, wbe);
5184 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005185 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005186 mb = mbstate_t();
5187 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005188 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005189 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005190 __throw_runtime_error("locale not supported");
5191 wbe = wbuf + j;
5192 __am_pm_[1].assign(wbuf, wbe);
5193 __c_ = __analyze('c', ct);
5194 __r_ = __analyze('r', ct);
5195 __x_ = __analyze('x', ct);
5196 __X_ = __analyze('X', ct);
5197}
5198
5199template <class CharT>
5200struct _LIBCPP_HIDDEN __time_get_temp
5201 : public ctype_byname<CharT>
5202{
5203 explicit __time_get_temp(const char* nm)
5204 : ctype_byname<CharT>(nm, 1) {}
5205 explicit __time_get_temp(const string& nm)
5206 : ctype_byname<CharT>(nm, 1) {}
5207};
5208
5209template <>
5210__time_get_storage<char>::__time_get_storage(const char* __nm)
5211 : __time_get(__nm)
5212{
5213 const __time_get_temp<char> ct(__nm);
5214 init(ct);
5215}
5216
5217template <>
5218__time_get_storage<char>::__time_get_storage(const string& __nm)
5219 : __time_get(__nm)
5220{
5221 const __time_get_temp<char> ct(__nm);
5222 init(ct);
5223}
5224
5225template <>
5226__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5227 : __time_get(__nm)
5228{
5229 const __time_get_temp<wchar_t> ct(__nm);
5230 init(ct);
5231}
5232
5233template <>
5234__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5235 : __time_get(__nm)
5236{
5237 const __time_get_temp<wchar_t> ct(__nm);
5238 init(ct);
5239}
5240
5241template <>
5242time_base::dateorder
5243__time_get_storage<char>::__do_date_order() const
5244{
5245 unsigned i;
5246 for (i = 0; i < __x_.size(); ++i)
5247 if (__x_[i] == '%')
5248 break;
5249 ++i;
5250 switch (__x_[i])
5251 {
5252 case 'y':
5253 case 'Y':
5254 for (++i; i < __x_.size(); ++i)
5255 if (__x_[i] == '%')
5256 break;
5257 if (i == __x_.size())
5258 break;
5259 ++i;
5260 switch (__x_[i])
5261 {
5262 case 'm':
5263 for (++i; i < __x_.size(); ++i)
5264 if (__x_[i] == '%')
5265 break;
5266 if (i == __x_.size())
5267 break;
5268 ++i;
5269 if (__x_[i] == 'd')
5270 return time_base::ymd;
5271 break;
5272 case 'd':
5273 for (++i; i < __x_.size(); ++i)
5274 if (__x_[i] == '%')
5275 break;
5276 if (i == __x_.size())
5277 break;
5278 ++i;
5279 if (__x_[i] == 'm')
5280 return time_base::ydm;
5281 break;
5282 }
5283 break;
5284 case 'm':
5285 for (++i; i < __x_.size(); ++i)
5286 if (__x_[i] == '%')
5287 break;
5288 if (i == __x_.size())
5289 break;
5290 ++i;
5291 if (__x_[i] == 'd')
5292 {
5293 for (++i; i < __x_.size(); ++i)
5294 if (__x_[i] == '%')
5295 break;
5296 if (i == __x_.size())
5297 break;
5298 ++i;
5299 if (__x_[i] == 'y' || __x_[i] == 'Y')
5300 return time_base::mdy;
5301 break;
5302 }
5303 break;
5304 case 'd':
5305 for (++i; i < __x_.size(); ++i)
5306 if (__x_[i] == '%')
5307 break;
5308 if (i == __x_.size())
5309 break;
5310 ++i;
5311 if (__x_[i] == 'm')
5312 {
5313 for (++i; i < __x_.size(); ++i)
5314 if (__x_[i] == '%')
5315 break;
5316 if (i == __x_.size())
5317 break;
5318 ++i;
5319 if (__x_[i] == 'y' || __x_[i] == 'Y')
5320 return time_base::dmy;
5321 break;
5322 }
5323 break;
5324 }
5325 return time_base::no_order;
5326}
5327
5328template <>
5329time_base::dateorder
5330__time_get_storage<wchar_t>::__do_date_order() const
5331{
5332 unsigned i;
5333 for (i = 0; i < __x_.size(); ++i)
5334 if (__x_[i] == L'%')
5335 break;
5336 ++i;
5337 switch (__x_[i])
5338 {
5339 case L'y':
5340 case L'Y':
5341 for (++i; i < __x_.size(); ++i)
5342 if (__x_[i] == L'%')
5343 break;
5344 if (i == __x_.size())
5345 break;
5346 ++i;
5347 switch (__x_[i])
5348 {
5349 case L'm':
5350 for (++i; i < __x_.size(); ++i)
5351 if (__x_[i] == L'%')
5352 break;
5353 if (i == __x_.size())
5354 break;
5355 ++i;
5356 if (__x_[i] == L'd')
5357 return time_base::ymd;
5358 break;
5359 case L'd':
5360 for (++i; i < __x_.size(); ++i)
5361 if (__x_[i] == L'%')
5362 break;
5363 if (i == __x_.size())
5364 break;
5365 ++i;
5366 if (__x_[i] == L'm')
5367 return time_base::ydm;
5368 break;
5369 }
5370 break;
5371 case L'm':
5372 for (++i; i < __x_.size(); ++i)
5373 if (__x_[i] == L'%')
5374 break;
5375 if (i == __x_.size())
5376 break;
5377 ++i;
5378 if (__x_[i] == L'd')
5379 {
5380 for (++i; i < __x_.size(); ++i)
5381 if (__x_[i] == L'%')
5382 break;
5383 if (i == __x_.size())
5384 break;
5385 ++i;
5386 if (__x_[i] == L'y' || __x_[i] == L'Y')
5387 return time_base::mdy;
5388 break;
5389 }
5390 break;
5391 case L'd':
5392 for (++i; i < __x_.size(); ++i)
5393 if (__x_[i] == L'%')
5394 break;
5395 if (i == __x_.size())
5396 break;
5397 ++i;
5398 if (__x_[i] == L'm')
5399 {
5400 for (++i; i < __x_.size(); ++i)
5401 if (__x_[i] == L'%')
5402 break;
5403 if (i == __x_.size())
5404 break;
5405 ++i;
5406 if (__x_[i] == L'y' || __x_[i] == L'Y')
5407 return time_base::dmy;
5408 break;
5409 }
5410 break;
5411 }
5412 return time_base::no_order;
5413}
5414
5415// time_put
5416
5417__time_put::__time_put(const char* nm)
5418 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5419{
5420 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005421 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005422 " failed to construct for " + string(nm));
5423}
5424
5425__time_put::__time_put(const string& nm)
5426 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5427{
5428 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005429 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005430 " failed to construct for " + nm);
5431}
5432
5433__time_put::~__time_put()
5434{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005435 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005436 freelocale(__loc_);
5437}
5438
5439void
5440__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5441 char __fmt, char __mod) const
5442{
5443 char fmt[] = {'%', __fmt, __mod, 0};
5444 if (__mod != 0)
5445 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005446 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005447 __ne = __nb + n;
5448}
5449
5450void
5451__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5452 char __fmt, char __mod) const
5453{
5454 char __nar[100];
5455 char* __ne = __nar + 100;
5456 __do_put(__nar, __ne, __tm, __fmt, __mod);
5457 mbstate_t mb = {0};
5458 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005459 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005460 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005461 __throw_runtime_error("locale not supported");
5462 __we = __wb + j;
5463}
5464
5465// moneypunct_byname
5466
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005467template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005468static
5469void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005470__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5471 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5472 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005473{
5474 const char sign = static_cast<char>(money_base::sign);
5475 const char space = static_cast<char>(money_base::space);
5476 const char none = static_cast<char>(money_base::none);
5477 const char symbol = static_cast<char>(money_base::symbol);
5478 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005479 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5480
5481 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5482 // function'. "Space between sign and symbol or value" means that
5483 // if the sign is adjacent to the symbol, there's a space between
5484 // them, and otherwise there's a space between the sign and value.
5485 //
5486 // C11's localeconv specifies that the fourth character of an
5487 // international curr_symbol is used to separate the sign and
5488 // value when sep_by_space says to do so. C++ can't represent
5489 // that, so we just use a space. When sep_by_space says to
5490 // separate the symbol and value-or-sign with a space, we rearrange the
5491 // curr_symbol to put its spacing character on the correct side of
5492 // the symbol.
5493 //
5494 // We also need to avoid adding an extra space between the sign
5495 // and value when the currency symbol is suppressed (by not
5496 // setting showbase). We match glibc's strfmon by interpreting
5497 // sep_by_space==1 as "omit the space when the currency symbol is
5498 // absent".
5499 //
5500 // Users who want to get this right should use ICU instead.
5501
Howard Hinnantc51e1022010-05-11 19:42:16 +00005502 switch (cs_precedes)
5503 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005504 case 0: // value before curr_symbol
5505 if (symbol_contains_sep) {
5506 // Move the separator to before the symbol, to place it
5507 // between the value and symbol.
5508 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5509 __curr_symbol_.end());
5510 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005511 switch (sign_posn)
5512 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005513 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005514 pat.field[0] = sign;
5515 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005516 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005517 pat.field[3] = symbol;
5518 switch (sep_by_space)
5519 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005520 case 0: // No space separates the currency symbol and value.
5521 // This case may have changed between C99 and C11;
5522 // assume the currency symbol matches the intention.
5523 case 2: // Space between sign and currency or value.
5524 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005525 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005526 case 1: // Space between currency-and-sign or currency and value.
5527 if (!symbol_contains_sep) {
5528 // We insert the space into the symbol instead of
5529 // setting pat.field[2]=space so that when
5530 // showbase is not set, the space goes away too.
5531 __curr_symbol_.insert(0, 1, space_char);
5532 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005533 return;
5534 default:
5535 break;
5536 }
5537 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005538 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005539 pat.field[0] = sign;
5540 pat.field[3] = symbol;
5541 switch (sep_by_space)
5542 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005543 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005544 pat.field[1] = value;
5545 pat.field[2] = none;
5546 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005547 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005548 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005549 pat.field[2] = none;
5550 if (!symbol_contains_sep) {
5551 // We insert the space into the symbol instead of
5552 // setting pat.field[2]=space so that when
5553 // showbase is not set, the space goes away too.
5554 __curr_symbol_.insert(0, 1, space_char);
5555 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005556 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005557 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005558 pat.field[1] = space;
5559 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005560 if (symbol_contains_sep) {
5561 // Remove the separator from the symbol, since it
5562 // has already appeared after the sign.
5563 __curr_symbol_.erase(__curr_symbol_.begin());
5564 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005565 return;
5566 default:
5567 break;
5568 }
5569 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005570 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005571 pat.field[0] = value;
5572 pat.field[3] = sign;
5573 switch (sep_by_space)
5574 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005575 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005576 pat.field[1] = none;
5577 pat.field[2] = symbol;
5578 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005579 case 1: // Space between currency-and-sign or currency and value.
5580 if (!symbol_contains_sep) {
5581 // We insert the space into the symbol instead of
5582 // setting pat.field[1]=space so that when
5583 // showbase is not set, the space goes away too.
5584 __curr_symbol_.insert(0, 1, space_char);
5585 }
5586 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005587 pat.field[2] = symbol;
5588 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005589 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005590 pat.field[1] = symbol;
5591 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005592 if (symbol_contains_sep) {
5593 // Remove the separator from the symbol, since it
5594 // should not be removed if showbase is absent.
5595 __curr_symbol_.erase(__curr_symbol_.begin());
5596 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005597 return;
5598 default:
5599 break;
5600 }
5601 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005602 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005603 pat.field[0] = value;
5604 pat.field[3] = symbol;
5605 switch (sep_by_space)
5606 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005607 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005608 pat.field[1] = none;
5609 pat.field[2] = sign;
5610 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005611 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005612 pat.field[1] = space;
5613 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005614 if (symbol_contains_sep) {
5615 // Remove the separator from the symbol, since it
5616 // has already appeared before the sign.
5617 __curr_symbol_.erase(__curr_symbol_.begin());
5618 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005619 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005620 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005621 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005622 pat.field[2] = none;
5623 if (!symbol_contains_sep) {
5624 // We insert the space into the symbol instead of
5625 // setting pat.field[2]=space so that when
5626 // showbase is not set, the space goes away too.
5627 __curr_symbol_.insert(0, 1, space_char);
5628 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005629 return;
5630 default:
5631 break;
5632 }
5633 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005634 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005635 pat.field[0] = value;
5636 pat.field[3] = sign;
5637 switch (sep_by_space)
5638 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005639 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005640 pat.field[1] = none;
5641 pat.field[2] = symbol;
5642 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005643 case 1: // Space between currency-and-sign or currency and value.
5644 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005645 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005646 if (!symbol_contains_sep) {
5647 // We insert the space into the symbol instead of
5648 // setting pat.field[1]=space so that when
5649 // showbase is not set, the space goes away too.
5650 __curr_symbol_.insert(0, 1, space_char);
5651 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005652 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005653 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005654 pat.field[1] = symbol;
5655 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005656 if (symbol_contains_sep) {
5657 // Remove the separator from the symbol, since it
5658 // should not disappear when showbase is absent.
5659 __curr_symbol_.erase(__curr_symbol_.begin());
5660 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005661 return;
5662 default:
5663 break;
5664 }
5665 break;
5666 default:
5667 break;
5668 }
5669 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005670 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005671 switch (sign_posn)
5672 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005673 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005674 pat.field[0] = sign;
5675 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005676 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005677 pat.field[3] = value;
5678 switch (sep_by_space)
5679 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005680 case 0: // No space separates the currency symbol and value.
5681 // This case may have changed between C99 and C11;
5682 // assume the currency symbol matches the intention.
5683 case 2: // Space between sign and currency or value.
5684 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005685 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005686 case 1: // Space between currency-and-sign or currency and value.
5687 if (!symbol_contains_sep) {
5688 // We insert the space into the symbol instead of
5689 // setting pat.field[2]=space so that when
5690 // showbase is not set, the space goes away too.
5691 __curr_symbol_.insert(0, 1, space_char);
5692 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005693 return;
5694 default:
5695 break;
5696 }
5697 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005698 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005699 pat.field[0] = sign;
5700 pat.field[3] = value;
5701 switch (sep_by_space)
5702 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005703 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005704 pat.field[1] = symbol;
5705 pat.field[2] = none;
5706 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005707 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005708 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005709 pat.field[2] = none;
5710 if (!symbol_contains_sep) {
5711 // We insert the space into the symbol instead of
5712 // setting pat.field[2]=space so that when
5713 // showbase is not set, the space goes away too.
5714 __curr_symbol_.push_back(space_char);
5715 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005716 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005717 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005718 pat.field[1] = space;
5719 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005720 if (symbol_contains_sep) {
5721 // Remove the separator from the symbol, since it
5722 // has already appeared after the sign.
5723 __curr_symbol_.pop_back();
5724 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005725 return;
5726 default:
5727 break;
5728 }
5729 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005730 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005731 pat.field[0] = symbol;
5732 pat.field[3] = sign;
5733 switch (sep_by_space)
5734 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005735 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005736 pat.field[1] = none;
5737 pat.field[2] = value;
5738 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005739 case 1: // Space between currency-and-sign or currency and value.
5740 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005741 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005742 if (!symbol_contains_sep) {
5743 // We insert the space into the symbol instead of
5744 // setting pat.field[1]=space so that when
5745 // showbase is not set, the space goes away too.
5746 __curr_symbol_.push_back(space_char);
5747 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005748 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005749 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005750 pat.field[1] = value;
5751 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005752 if (symbol_contains_sep) {
5753 // Remove the separator from the symbol, since it
5754 // will appear before the sign.
5755 __curr_symbol_.pop_back();
5756 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005757 return;
5758 default:
5759 break;
5760 }
5761 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005762 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005763 pat.field[0] = sign;
5764 pat.field[3] = value;
5765 switch (sep_by_space)
5766 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005767 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005768 pat.field[1] = symbol;
5769 pat.field[2] = none;
5770 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005771 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005772 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005773 pat.field[2] = none;
5774 if (!symbol_contains_sep) {
5775 // We insert the space into the symbol instead of
5776 // setting pat.field[2]=space so that when
5777 // showbase is not set, the space goes away too.
5778 __curr_symbol_.push_back(space_char);
5779 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005780 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005781 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005782 pat.field[1] = space;
5783 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005784 if (symbol_contains_sep) {
5785 // Remove the separator from the symbol, since it
5786 // has already appeared after the sign.
5787 __curr_symbol_.pop_back();
5788 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005789 return;
5790 default:
5791 break;
5792 }
5793 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005794 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005795 pat.field[0] = symbol;
5796 pat.field[3] = value;
5797 switch (sep_by_space)
5798 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005799 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005800 pat.field[1] = sign;
5801 pat.field[2] = none;
5802 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005803 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005804 pat.field[1] = sign;
5805 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005806 if (symbol_contains_sep) {
5807 // Remove the separator from the symbol, since it
5808 // should not disappear when showbase is absent.
5809 __curr_symbol_.pop_back();
5810 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005811 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005812 case 2: // Space between sign and currency or value.
5813 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005814 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005815 if (!symbol_contains_sep) {
5816 // We insert the space into the symbol instead of
5817 // setting pat.field[1]=space so that when
5818 // showbase is not set, the space goes away too.
5819 __curr_symbol_.push_back(space_char);
5820 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005821 return;
5822 default:
5823 break;
5824 }
5825 break;
5826 default:
5827 break;
5828 }
5829 break;
5830 default:
5831 break;
5832 }
5833 pat.field[0] = symbol;
5834 pat.field[1] = sign;
5835 pat.field[2] = none;
5836 pat.field[3] = value;
5837}
5838
5839template<>
5840void
5841moneypunct_byname<char, false>::init(const char* nm)
5842{
5843 typedef moneypunct<char, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005844 __libcpp_unique_locale loc(nm);
5845 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005846 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005847 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005848
Ben Craig3756b922016-03-09 15:39:39 +00005849 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005850 if (!checked_string_to_char_convert(__decimal_point_,
5851 lc->mon_decimal_point,
5852 loc.get()))
5853 __decimal_point_ = base::do_decimal_point();
5854 if (!checked_string_to_char_convert(__thousands_sep_,
5855 lc->mon_thousands_sep,
5856 loc.get()))
5857 __thousands_sep_ = base::do_thousands_sep();
5858
Howard Hinnantc51e1022010-05-11 19:42:16 +00005859 __grouping_ = lc->mon_grouping;
5860 __curr_symbol_ = lc->currency_symbol;
5861 if (lc->frac_digits != CHAR_MAX)
5862 __frac_digits_ = lc->frac_digits;
5863 else
5864 __frac_digits_ = base::do_frac_digits();
5865 if (lc->p_sign_posn == 0)
5866 __positive_sign_ = "()";
5867 else
5868 __positive_sign_ = lc->positive_sign;
5869 if (lc->n_sign_posn == 0)
5870 __negative_sign_ = "()";
5871 else
5872 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005873 // Assume the positive and negative formats will want spaces in
5874 // the same places in curr_symbol since there's no way to
5875 // represent anything else.
5876 string_type __dummy_curr_symbol = __curr_symbol_;
5877 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5878 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5879 __init_pat(__neg_format_, __curr_symbol_, false,
5880 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005881}
5882
5883template<>
5884void
5885moneypunct_byname<char, true>::init(const char* nm)
5886{
5887 typedef moneypunct<char, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005888 __libcpp_unique_locale loc(nm);
5889 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005890 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005891 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005892
Ben Craig3756b922016-03-09 15:39:39 +00005893 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005894 if (!checked_string_to_char_convert(__decimal_point_,
5895 lc->mon_decimal_point,
5896 loc.get()))
5897 __decimal_point_ = base::do_decimal_point();
5898 if (!checked_string_to_char_convert(__thousands_sep_,
5899 lc->mon_thousands_sep,
5900 loc.get()))
5901 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005902 __grouping_ = lc->mon_grouping;
5903 __curr_symbol_ = lc->int_curr_symbol;
5904 if (lc->int_frac_digits != CHAR_MAX)
5905 __frac_digits_ = lc->int_frac_digits;
5906 else
5907 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005908#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005909 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005910#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005911 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005912#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005913 __positive_sign_ = "()";
5914 else
5915 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005916#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005917 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005918#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005919 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005920#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005921 __negative_sign_ = "()";
5922 else
5923 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005924 // Assume the positive and negative formats will want spaces in
5925 // the same places in curr_symbol since there's no way to
5926 // represent anything else.
5927 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005928#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5930 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5931 __init_pat(__neg_format_, __curr_symbol_, true,
5932 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005933#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005934 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5935 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5936 lc->int_p_sign_posn, ' ');
5937 __init_pat(__neg_format_, __curr_symbol_, true,
5938 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5939 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005940#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005941}
5942
5943template<>
5944void
5945moneypunct_byname<wchar_t, false>::init(const char* nm)
5946{
5947 typedef moneypunct<wchar_t, false> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00005948 __libcpp_unique_locale loc(nm);
5949 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00005950 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005951 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005952 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005953 if (!checked_string_to_wchar_convert(__decimal_point_,
5954 lc->mon_decimal_point,
5955 loc.get()))
5956 __decimal_point_ = base::do_decimal_point();
5957 if (!checked_string_to_wchar_convert(__thousands_sep_,
5958 lc->mon_thousands_sep,
5959 loc.get()))
5960 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005961 __grouping_ = lc->mon_grouping;
5962 wchar_t wbuf[100];
5963 mbstate_t mb = {0};
5964 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005965 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005966 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005967 __throw_runtime_error("locale not supported");
5968 wchar_t* wbe = wbuf + j;
5969 __curr_symbol_.assign(wbuf, wbe);
5970 if (lc->frac_digits != CHAR_MAX)
5971 __frac_digits_ = lc->frac_digits;
5972 else
5973 __frac_digits_ = base::do_frac_digits();
5974 if (lc->p_sign_posn == 0)
5975 __positive_sign_ = L"()";
5976 else
5977 {
5978 mb = mbstate_t();
5979 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005980 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005981 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005982 __throw_runtime_error("locale not supported");
5983 wbe = wbuf + j;
5984 __positive_sign_.assign(wbuf, wbe);
5985 }
5986 if (lc->n_sign_posn == 0)
5987 __negative_sign_ = L"()";
5988 else
5989 {
5990 mb = mbstate_t();
5991 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005992 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005993 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005994 __throw_runtime_error("locale not supported");
5995 wbe = wbuf + j;
5996 __negative_sign_.assign(wbuf, wbe);
5997 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005998 // Assume the positive and negative formats will want spaces in
5999 // the same places in curr_symbol since there's no way to
6000 // represent anything else.
6001 string_type __dummy_curr_symbol = __curr_symbol_;
6002 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6003 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6004 __init_pat(__neg_format_, __curr_symbol_, false,
6005 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006006}
6007
6008template<>
6009void
6010moneypunct_byname<wchar_t, true>::init(const char* nm)
6011{
6012 typedef moneypunct<wchar_t, true> base;
Eric Fiselierebc2d2c2017-05-08 22:02:43 +00006013 __libcpp_unique_locale loc(nm);
6014 if (!loc)
Marshall Clow8fea1612016-08-25 15:09:01 +00006015 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006016 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006017
Ben Craig3756b922016-03-09 15:39:39 +00006018 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006019 if (!checked_string_to_wchar_convert(__decimal_point_,
6020 lc->mon_decimal_point,
6021 loc.get()))
6022 __decimal_point_ = base::do_decimal_point();
6023 if (!checked_string_to_wchar_convert(__thousands_sep_,
6024 lc->mon_thousands_sep,
6025 loc.get()))
6026 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006027 __grouping_ = lc->mon_grouping;
6028 wchar_t wbuf[100];
6029 mbstate_t mb = {0};
6030 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006031 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006032 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006033 __throw_runtime_error("locale not supported");
6034 wchar_t* wbe = wbuf + j;
6035 __curr_symbol_.assign(wbuf, wbe);
6036 if (lc->int_frac_digits != CHAR_MAX)
6037 __frac_digits_ = lc->int_frac_digits;
6038 else
6039 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006040#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006041 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006042#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006043 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006044#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006045 __positive_sign_ = L"()";
6046 else
6047 {
6048 mb = mbstate_t();
6049 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006050 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006051 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006052 __throw_runtime_error("locale not supported");
6053 wbe = wbuf + j;
6054 __positive_sign_.assign(wbuf, wbe);
6055 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006056#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006057 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006058#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006059 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006060#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006061 __negative_sign_ = L"()";
6062 else
6063 {
6064 mb = mbstate_t();
6065 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006066 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006067 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006068 __throw_runtime_error("locale not supported");
6069 wbe = wbuf + j;
6070 __negative_sign_.assign(wbuf, wbe);
6071 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006072 // Assume the positive and negative formats will want spaces in
6073 // the same places in curr_symbol since there's no way to
6074 // represent anything else.
6075 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006076#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006077 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6078 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6079 __init_pat(__neg_format_, __curr_symbol_, true,
6080 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006081#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006082 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6083 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6084 lc->int_p_sign_posn, L' ');
6085 __init_pat(__neg_format_, __curr_symbol_, true,
6086 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6087 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006088#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006089}
6090
6091void __do_nothing(void*) {}
6092
6093void __throw_runtime_error(const char* msg)
6094{
Howard Hinnant72f73582010-08-11 17:04:31 +00006095#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006096 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006097#else
6098 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006099 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006100#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006101}
6102
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006103template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6104template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006105
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006106template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6107template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006108
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006109template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6110template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006111
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006112template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6113template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006114
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006115template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6116template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006117
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006118template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6119template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006120
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006121template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6122template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006123
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006124template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6125template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006126
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006127template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6128template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006129
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006130template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6131template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6132template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6133template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006134
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006135template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6136template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6137template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6138template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006139
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006140template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6141template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006142
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006143template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6144template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006145
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006146template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6147template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006148
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006149template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6150template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006151
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006152template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6153template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006154
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006155template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6156template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006157
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006158template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6159template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6160template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6161template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006162
Howard Hinnantc51e1022010-05-11 19:42:16 +00006163_LIBCPP_END_NAMESPACE_STD