blob: 4b462664a60c3ecdfd034dc808740d2d7f59fa54 [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>
Howard Hinnantc51e1022010-05-11 19:42:16 +000039
Marshall Clowab9c1772013-02-07 17:20:56 +000040// On Linux, wint_t and wchar_t have different signed-ness, and this causes
41// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000042#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000043#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000044#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000045
Howard Hinnantc51e1022010-05-11 19:42:16 +000046_LIBCPP_BEGIN_NAMESPACE_STD
47
Howard Hinnantf312e3e2011-09-28 23:39:33 +000048#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000049locale_t __cloc() {
50 // In theory this could create a race condition. In practice
51 // the race condition is non-fatal since it will just create
52 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000053 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
54 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000055}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000056#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000057
Howard Hinnantc51e1022010-05-11 19:42:16 +000058namespace {
59
60struct release
61{
62 void operator()(locale::facet* p) {p->__release_shared();}
63};
64
65template <class T, class A0>
66inline
67T&
68make(A0 a0)
69{
70 static typename aligned_storage<sizeof(T)>::type buf;
71 ::new (&buf) T(a0);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000072 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000073}
74
75template <class T, class A0, class A1>
76inline
77T&
78make(A0 a0, A1 a1)
79{
80 static typename aligned_storage<sizeof(T)>::type buf;
81 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000082 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000083}
84
85template <class T, class A0, class A1, class A2>
86inline
87T&
88make(A0 a0, A1 a1, A2 a2)
89{
90 static typename aligned_storage<sizeof(T)>::type buf;
91 ::new (&buf) T(a0, a1, a2);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000092 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000093}
94
Howard Hinnant3d2417c2012-12-27 21:17:53 +000095template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +000096inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +000097_LIBCPP_CONSTEXPR
98size_t
99countof(const T (&)[N])
100{
101 return N;
102}
103
104template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000105inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000106_LIBCPP_CONSTEXPR
107size_t
108countof(const T * const begin, const T * const end)
109{
110 return static_cast<size_t>(end - begin);
111}
112
Marshall Clow8fea1612016-08-25 15:09:01 +0000113_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg)
114{
115#ifndef _LIBCPP_NO_EXCEPTIONS
116 throw runtime_error(msg);
117#else
118 (void)msg;
119 _VSTD::abort();
120#endif
121}
122
Howard Hinnantc51e1022010-05-11 19:42:16 +0000123}
124
Howard Hinnantdd099492013-08-29 23:37:50 +0000125#if defined(_AIX)
126// Set priority to INT_MIN + 256 + 150
127# pragma priority ( -2147483242 )
128#endif
129
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000130const locale::category locale::none;
131const locale::category locale::collate;
132const locale::category locale::ctype;
133const locale::category locale::monetary;
134const locale::category locale::numeric;
135const locale::category locale::time;
136const locale::category locale::messages;
137const locale::category locale::all;
138
Howard Hinnantc51e1022010-05-11 19:42:16 +0000139class _LIBCPP_HIDDEN locale::__imp
140 : public facet
141{
142 enum {N = 28};
Marshall Clowd920eea2013-10-21 15:07:28 +0000143#if defined(_LIBCPP_MSVC)
144// FIXME: MSVC doesn't support aligned parameters by value.
145// I can't get the __sso_allocator to work here
146// for MSVC I think for this reason.
147 vector<facet*> facets_;
148#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000149 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000150#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000151 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000152public:
153 explicit __imp(size_t refs = 0);
154 explicit __imp(const string& name, size_t refs = 0);
155 __imp(const __imp&);
156 __imp(const __imp&, const string&, locale::category c);
157 __imp(const __imp& other, const __imp& one, locale::category c);
158 __imp(const __imp&, facet* f, long id);
159 ~__imp();
160
161 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000162 bool has_facet(long id) const
163 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000164 const locale::facet* use_facet(long id) const;
165
166 static const locale& make_classic();
167 static locale& make_global();
168private:
169 void install(facet* f, long id);
170 template <class F> void install(F* f) {install(f, f->id.__get());}
171 template <class F> void install_from(const __imp& other);
172};
173
174locale::__imp::__imp(size_t refs)
175 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000176 facets_(N),
177 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000178{
179 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000180 install(&make<_VSTD::collate<char> >(1u));
181 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000182 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000183 install(&make<_VSTD::ctype<wchar_t> >(1u));
184 install(&make<codecvt<char, char, mbstate_t> >(1u));
185 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
186 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
187 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
188 install(&make<numpunct<char> >(1u));
189 install(&make<numpunct<wchar_t> >(1u));
190 install(&make<num_get<char> >(1u));
191 install(&make<num_get<wchar_t> >(1u));
192 install(&make<num_put<char> >(1u));
193 install(&make<num_put<wchar_t> >(1u));
194 install(&make<moneypunct<char, false> >(1u));
195 install(&make<moneypunct<char, true> >(1u));
196 install(&make<moneypunct<wchar_t, false> >(1u));
197 install(&make<moneypunct<wchar_t, true> >(1u));
198 install(&make<money_get<char> >(1u));
199 install(&make<money_get<wchar_t> >(1u));
200 install(&make<money_put<char> >(1u));
201 install(&make<money_put<wchar_t> >(1u));
202 install(&make<time_get<char> >(1u));
203 install(&make<time_get<wchar_t> >(1u));
204 install(&make<time_put<char> >(1u));
205 install(&make<time_put<wchar_t> >(1u));
206 install(&make<_VSTD::messages<char> >(1u));
207 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000208}
209
210locale::__imp::__imp(const string& name, size_t refs)
211 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000212 facets_(N),
213 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000214{
Howard Hinnant72f73582010-08-11 17:04:31 +0000215#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000216 try
217 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000218#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000219 facets_ = locale::classic().__locale_->facets_;
220 for (unsigned i = 0; i < facets_.size(); ++i)
221 if (facets_[i])
222 facets_[i]->__add_shared();
223 install(new collate_byname<char>(name_));
224 install(new collate_byname<wchar_t>(name_));
225 install(new ctype_byname<char>(name_));
226 install(new ctype_byname<wchar_t>(name_));
227 install(new codecvt_byname<char, char, mbstate_t>(name_));
228 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
229 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
230 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
231 install(new numpunct_byname<char>(name_));
232 install(new numpunct_byname<wchar_t>(name_));
233 install(new moneypunct_byname<char, false>(name_));
234 install(new moneypunct_byname<char, true>(name_));
235 install(new moneypunct_byname<wchar_t, false>(name_));
236 install(new moneypunct_byname<wchar_t, true>(name_));
237 install(new time_get_byname<char>(name_));
238 install(new time_get_byname<wchar_t>(name_));
239 install(new time_put_byname<char>(name_));
240 install(new time_put_byname<wchar_t>(name_));
241 install(new messages_byname<char>(name_));
242 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000243#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000244 }
245 catch (...)
246 {
247 for (unsigned i = 0; i < facets_.size(); ++i)
248 if (facets_[i])
249 facets_[i]->__release_shared();
250 throw;
251 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000252#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000253}
254
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000255// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000256// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000257#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000258#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000259#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000260#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000261
Howard Hinnantc51e1022010-05-11 19:42:16 +0000262locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000263 : facets_(max<size_t>(N, other.facets_.size())),
264 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000265{
266 facets_ = other.facets_;
267 for (unsigned i = 0; i < facets_.size(); ++i)
268 if (facets_[i])
269 facets_[i]->__add_shared();
270}
271
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000272#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000273#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000274#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000275
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000277 : facets_(N),
278 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000279{
280 facets_ = other.facets_;
281 for (unsigned i = 0; i < facets_.size(); ++i)
282 if (facets_[i])
283 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000284#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000285 try
286 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000287#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288 if (c & locale::collate)
289 {
290 install(new collate_byname<char>(name));
291 install(new collate_byname<wchar_t>(name));
292 }
293 if (c & locale::ctype)
294 {
295 install(new ctype_byname<char>(name));
296 install(new ctype_byname<wchar_t>(name));
297 install(new codecvt_byname<char, char, mbstate_t>(name));
298 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
299 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
300 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
301 }
302 if (c & locale::monetary)
303 {
304 install(new moneypunct_byname<char, false>(name));
305 install(new moneypunct_byname<char, true>(name));
306 install(new moneypunct_byname<wchar_t, false>(name));
307 install(new moneypunct_byname<wchar_t, true>(name));
308 }
309 if (c & locale::numeric)
310 {
311 install(new numpunct_byname<char>(name));
312 install(new numpunct_byname<wchar_t>(name));
313 }
314 if (c & locale::time)
315 {
316 install(new time_get_byname<char>(name));
317 install(new time_get_byname<wchar_t>(name));
318 install(new time_put_byname<char>(name));
319 install(new time_put_byname<wchar_t>(name));
320 }
321 if (c & locale::messages)
322 {
323 install(new messages_byname<char>(name));
324 install(new messages_byname<wchar_t>(name));
325 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000326#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000327 }
328 catch (...)
329 {
330 for (unsigned i = 0; i < facets_.size(); ++i)
331 if (facets_[i])
332 facets_[i]->__release_shared();
333 throw;
334 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000335#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000336}
337
338template<class F>
339inline
340void
341locale::__imp::install_from(const locale::__imp& one)
342{
343 long id = F::id.__get();
344 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
345}
346
347locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000348 : facets_(N),
349 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000350{
351 facets_ = other.facets_;
352 for (unsigned i = 0; i < facets_.size(); ++i)
353 if (facets_[i])
354 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000355#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000356 try
357 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000358#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000359 if (c & locale::collate)
360 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000361 install_from<_VSTD::collate<char> >(one);
362 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000363 }
364 if (c & locale::ctype)
365 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000366 install_from<_VSTD::ctype<char> >(one);
367 install_from<_VSTD::ctype<wchar_t> >(one);
368 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
369 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
370 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
371 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000372 }
373 if (c & locale::monetary)
374 {
375 install_from<moneypunct<char, false> >(one);
376 install_from<moneypunct<char, true> >(one);
377 install_from<moneypunct<wchar_t, false> >(one);
378 install_from<moneypunct<wchar_t, true> >(one);
379 install_from<money_get<char> >(one);
380 install_from<money_get<wchar_t> >(one);
381 install_from<money_put<char> >(one);
382 install_from<money_put<wchar_t> >(one);
383 }
384 if (c & locale::numeric)
385 {
386 install_from<numpunct<char> >(one);
387 install_from<numpunct<wchar_t> >(one);
388 install_from<num_get<char> >(one);
389 install_from<num_get<wchar_t> >(one);
390 install_from<num_put<char> >(one);
391 install_from<num_put<wchar_t> >(one);
392 }
393 if (c & locale::time)
394 {
395 install_from<time_get<char> >(one);
396 install_from<time_get<wchar_t> >(one);
397 install_from<time_put<char> >(one);
398 install_from<time_put<wchar_t> >(one);
399 }
400 if (c & locale::messages)
401 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000402 install_from<_VSTD::messages<char> >(one);
403 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000404 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000405#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000406 }
407 catch (...)
408 {
409 for (unsigned i = 0; i < facets_.size(); ++i)
410 if (facets_[i])
411 facets_[i]->__release_shared();
412 throw;
413 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000414#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000415}
416
417locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000418 : facets_(max<size_t>(N, other.facets_.size()+1)),
419 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000420{
421 f->__add_shared();
422 unique_ptr<facet, release> hold(f);
423 facets_ = other.facets_;
424 for (unsigned i = 0; i < other.facets_.size(); ++i)
425 if (facets_[i])
426 facets_[i]->__add_shared();
427 install(hold.get(), id);
428}
429
430locale::__imp::~__imp()
431{
432 for (unsigned i = 0; i < facets_.size(); ++i)
433 if (facets_[i])
434 facets_[i]->__release_shared();
435}
436
437void
438locale::__imp::install(facet* f, long id)
439{
440 f->__add_shared();
441 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000442 if (static_cast<size_t>(id) >= facets_.size())
443 facets_.resize(static_cast<size_t>(id+1));
444 if (facets_[static_cast<size_t>(id)])
445 facets_[static_cast<size_t>(id)]->__release_shared();
446 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000447}
448
449const locale::facet*
450locale::__imp::use_facet(long id) const
451{
Howard Hinnant72f73582010-08-11 17:04:31 +0000452#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000453 if (!has_facet(id))
454 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000455#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000456 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000457}
458
459// locale
460
461const locale&
462locale::__imp::make_classic()
463{
464 // only one thread can get in here and it only gets in once
465 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000466 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000467 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000468 return *c;
469}
470
471const locale&
472locale::classic()
473{
474 static const locale& c = __imp::make_classic();
475 return c;
476}
477
478locale&
479locale::__imp::make_global()
480{
481 // only one thread can get in here and it only gets in once
482 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000483 ::new (&buf) locale(locale::classic());
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000484 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000485}
486
487locale&
488locale::__global()
489{
490 static locale& g = __imp::make_global();
491 return g;
492}
493
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000494locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000495 : __locale_(__global().__locale_)
496{
497 __locale_->__add_shared();
498}
499
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000500locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000501 : __locale_(l.__locale_)
502{
503 __locale_->__add_shared();
504}
505
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000506locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000507{
508 __locale_->__release_shared();
509}
510
511const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000512locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000513{
514 other.__locale_->__add_shared();
515 __locale_->__release_shared();
516 __locale_ = other.__locale_;
517 return *this;
518}
519
520locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000521#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000522 : __locale_(name ? new __imp(name)
523 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000524#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000525 : __locale_(new __imp(name))
526#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000527{
528 __locale_->__add_shared();
529}
530
531locale::locale(const string& name)
532 : __locale_(new __imp(name))
533{
534 __locale_->__add_shared();
535}
536
537locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000538#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000539 : __locale_(name ? new __imp(*other.__locale_, name, c)
540 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000541#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000542 : __locale_(new __imp(*other.__locale_, name, c))
543#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000544{
545 __locale_->__add_shared();
546}
547
548locale::locale(const locale& other, const string& name, category c)
549 : __locale_(new __imp(*other.__locale_, name, c))
550{
551 __locale_->__add_shared();
552}
553
554locale::locale(const locale& other, const locale& one, category c)
555 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
556{
557 __locale_->__add_shared();
558}
559
560string
561locale::name() const
562{
563 return __locale_->name();
564}
565
566void
567locale::__install_ctor(const locale& other, facet* f, long id)
568{
569 if (f)
570 __locale_ = new __imp(*other.__locale_, f, id);
571 else
572 __locale_ = other.__locale_;
573 __locale_->__add_shared();
574}
575
576locale
577locale::global(const locale& loc)
578{
579 locale& g = __global();
580 locale r = g;
581 g = loc;
Ed Schouten3d3341e2015-07-06 15:39:36 +0000582#ifndef __CloudABI__
Howard Hinnantc51e1022010-05-11 19:42:16 +0000583 if (g.name() != "*")
584 setlocale(LC_ALL, g.name().c_str());
Ed Schouten3d3341e2015-07-06 15:39:36 +0000585#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000586 return r;
587}
588
589bool
590locale::has_facet(id& x) const
591{
592 return __locale_->has_facet(x.__get());
593}
594
595const locale::facet*
596locale::use_facet(id& x) const
597{
598 return __locale_->use_facet(x.__get());
599}
600
601bool
602locale::operator==(const locale& y) const
603{
604 return (__locale_ == y.__locale_)
605 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
606}
607
608// locale::facet
609
610locale::facet::~facet()
611{
612}
613
614void
Howard Hinnant719bda32011-05-28 14:41:13 +0000615locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000616{
617 delete this;
618}
619
620// locale::id
621
622int32_t locale::id::__next_id = 0;
623
624namespace
625{
626
627class __fake_bind
628{
629 locale::id* id_;
630 void (locale::id::* pmf_)();
631public:
632 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
633 : id_(id), pmf_(pmf) {}
634
635 void operator()() const
636 {
637 (id_->*pmf_)();
638 }
639};
640
641}
642
643long
644locale::id::__get()
645{
646 call_once(__flag_, __fake_bind(&locale::id::__init, this));
647 return __id_ - 1;
648}
649
650void
651locale::id::__init()
652{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000653 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000654}
655
656// template <> class collate_byname<char>
657
658collate_byname<char>::collate_byname(const char* n, size_t refs)
659 : collate<char>(refs),
660 __l(newlocale(LC_ALL_MASK, n, 0))
661{
662 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000663 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000664 " failed to construct for " + string(n));
665}
666
667collate_byname<char>::collate_byname(const string& name, size_t refs)
668 : collate<char>(refs),
669 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
670{
671 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000672 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000673 " failed to construct for " + name);
674}
675
676collate_byname<char>::~collate_byname()
677{
678 freelocale(__l);
679}
680
681int
682collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
683 const char_type* __lo2, const char_type* __hi2) const
684{
685 string_type lhs(__lo1, __hi1);
686 string_type rhs(__lo2, __hi2);
687 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
688 if (r < 0)
689 return -1;
690 if (r > 0)
691 return 1;
692 return r;
693}
694
695collate_byname<char>::string_type
696collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
697{
698 const string_type in(lo, hi);
699 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
700 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
701 return out;
702}
703
704// template <> class collate_byname<wchar_t>
705
706collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
707 : collate<wchar_t>(refs),
708 __l(newlocale(LC_ALL_MASK, n, 0))
709{
710 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000711 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000712 " failed to construct for " + string(n));
713}
714
715collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
716 : collate<wchar_t>(refs),
717 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
718{
719 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000720 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000721 " failed to construct for " + name);
722}
723
724collate_byname<wchar_t>::~collate_byname()
725{
726 freelocale(__l);
727}
728
729int
730collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
731 const char_type* __lo2, const char_type* __hi2) const
732{
733 string_type lhs(__lo1, __hi1);
734 string_type rhs(__lo2, __hi2);
735 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
736 if (r < 0)
737 return -1;
738 if (r > 0)
739 return 1;
740 return r;
741}
742
743collate_byname<wchar_t>::string_type
744collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
745{
746 const string_type in(lo, hi);
747 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
748 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
749 return out;
750}
751
752// template <> class ctype<wchar_t>;
753
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000754const ctype_base::mask ctype_base::space;
755const ctype_base::mask ctype_base::print;
756const ctype_base::mask ctype_base::cntrl;
757const ctype_base::mask ctype_base::upper;
758const ctype_base::mask ctype_base::lower;
759const ctype_base::mask ctype_base::alpha;
760const ctype_base::mask ctype_base::digit;
761const ctype_base::mask ctype_base::punct;
762const ctype_base::mask ctype_base::xdigit;
763const ctype_base::mask ctype_base::blank;
764const ctype_base::mask ctype_base::alnum;
765const ctype_base::mask ctype_base::graph;
766
Howard Hinnantc51e1022010-05-11 19:42:16 +0000767locale::id ctype<wchar_t>::id;
768
769ctype<wchar_t>::~ctype()
770{
771}
772
773bool
774ctype<wchar_t>::do_is(mask m, char_type c) const
775{
Marshall Clowd920eea2013-10-21 15:07:28 +0000776 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000777}
778
779const wchar_t*
780ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
781{
782 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000783 *vec = static_cast<mask>(isascii(*low) ?
784 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000785 return low;
786}
787
788const wchar_t*
789ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
790{
791 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000792 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000793 break;
794 return low;
795}
796
797const wchar_t*
798ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
799{
800 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000801 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000802 break;
803 return low;
804}
805
806wchar_t
807ctype<wchar_t>::do_toupper(char_type c) const
808{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000809#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
810 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000811#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000812 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000813 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000814#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000815 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000816#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000817}
818
819const wchar_t*
820ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
821{
822 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000823#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
824 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000825#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000826 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000827 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
828 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000829#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000830 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000831#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000832 return low;
833}
834
835wchar_t
836ctype<wchar_t>::do_tolower(char_type c) const
837{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000838#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
839 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000840#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000841 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000842 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000843#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000844 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000845#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000846}
847
848const wchar_t*
849ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
850{
851 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000852#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
853 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000854#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000855 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000856 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
857 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000858#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000859 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000860#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000861 return low;
862}
863
864wchar_t
865ctype<wchar_t>::do_widen(char c) const
866{
867 return c;
868}
869
870const char*
871ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
872{
873 for (; low != high; ++low, ++dest)
874 *dest = *low;
875 return low;
876}
877
878char
879ctype<wchar_t>::do_narrow(char_type c, char dfault) const
880{
881 if (isascii(c))
882 return static_cast<char>(c);
883 return dfault;
884}
885
886const wchar_t*
887ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
888{
889 for (; low != high; ++low, ++dest)
890 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000891 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000892 else
893 *dest = dfault;
894 return low;
895}
896
897// template <> class ctype<char>;
898
899locale::id ctype<char>::id;
900
901ctype<char>::ctype(const mask* tab, bool del, size_t refs)
902 : locale::facet(refs),
903 __tab_(tab),
904 __del_(del)
905{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000906 if (__tab_ == 0)
907 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000908}
909
910ctype<char>::~ctype()
911{
912 if (__tab_ && __del_)
913 delete [] __tab_;
914}
915
916char
917ctype<char>::do_toupper(char_type c) const
918{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000919#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000920 return isascii(c) ?
921 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000922#elif defined(__NetBSD__)
923 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000924#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000925 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000926 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000927#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000928 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000929#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000930}
931
932const char*
933ctype<char>::do_toupper(char_type* low, const char_type* high) const
934{
935 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000936#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000937 *low = isascii(*low) ?
938 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000939#elif defined(__NetBSD__)
940 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000941#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000942 *low = isascii(*low) ?
943 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000944#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000945 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000946#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000947 return low;
948}
949
950char
951ctype<char>::do_tolower(char_type c) const
952{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000953#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000954 return isascii(c) ?
955 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000956#elif defined(__NetBSD__)
957 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000958#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000959 return isascii(c) ?
960 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000961#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000962 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000963#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000964}
965
966const char*
967ctype<char>::do_tolower(char_type* low, const char_type* high) const
968{
969 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000970#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000971 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000972#elif defined(__NetBSD__)
973 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000974#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000975 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000976#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000977 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000978#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000979 return low;
980}
981
982char
983ctype<char>::do_widen(char c) const
984{
985 return c;
986}
987
988const char*
989ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
990{
991 for (; low != high; ++low, ++dest)
992 *dest = *low;
993 return low;
994}
995
996char
997ctype<char>::do_narrow(char_type c, char dfault) const
998{
999 if (isascii(c))
1000 return static_cast<char>(c);
1001 return dfault;
1002}
1003
1004const char*
1005ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1006{
1007 for (; low != high; ++low, ++dest)
1008 if (isascii(*low))
1009 *dest = *low;
1010 else
1011 *dest = dfault;
1012 return low;
1013}
1014
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001015#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001016extern "C" const unsigned short ** __ctype_b_loc();
1017extern "C" const int ** __ctype_tolower_loc();
1018extern "C" const int ** __ctype_toupper_loc();
1019#endif
1020
Marshall Clow8f870232015-03-04 16:50:02 +00001021#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001022const ctype<char>::mask*
1023ctype<char>::classic_table() _NOEXCEPT
1024{
1025 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1026 cntrl, cntrl,
1027 cntrl, cntrl,
1028 cntrl, cntrl,
1029 cntrl, cntrl,
1030 cntrl, cntrl | space | blank,
1031 cntrl | space, cntrl | space,
1032 cntrl | space, cntrl | space,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl,
1040 cntrl, cntrl,
1041 cntrl, cntrl,
1042 space | blank | print, punct | print,
1043 punct | print, punct | print,
1044 punct | print, punct | print,
1045 punct | print, punct | print,
1046 punct | print, punct | print,
1047 punct | print, punct | print,
1048 punct | print, punct | print,
1049 punct | print, punct | print,
1050 digit | print | xdigit, digit | print | xdigit,
1051 digit | print | xdigit, digit | print | xdigit,
1052 digit | print | xdigit, digit | print | xdigit,
1053 digit | print | xdigit, digit | print | xdigit,
1054 digit | print | xdigit, digit | print | xdigit,
1055 punct | print, punct | print,
1056 punct | print, punct | print,
1057 punct | print, punct | print,
1058 punct | print, upper | xdigit | print | alpha,
1059 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1060 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1061 upper | xdigit | print | alpha, upper | print | alpha,
1062 upper | print | alpha, upper | print | alpha,
1063 upper | print | alpha, upper | print | alpha,
1064 upper | print | alpha, upper | print | alpha,
1065 upper | print | alpha, upper | print | alpha,
1066 upper | print | alpha, upper | print | alpha,
1067 upper | print | alpha, upper | print | alpha,
1068 upper | print | alpha, upper | print | alpha,
1069 upper | print | alpha, upper | print | alpha,
1070 upper | print | alpha, upper | print | alpha,
1071 upper | print | alpha, punct | print,
1072 punct | print, punct | print,
1073 punct | print, punct | print,
1074 punct | print, lower | xdigit | print | alpha,
1075 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1076 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1077 lower | xdigit | print | alpha, lower | print | alpha,
1078 lower | print | alpha, lower | print | alpha,
1079 lower | print | alpha, lower | print | alpha,
1080 lower | print | alpha, lower | print | alpha,
1081 lower | print | alpha, lower | print | alpha,
1082 lower | print | alpha, lower | print | alpha,
1083 lower | print | alpha, lower | print | alpha,
1084 lower | print | alpha, lower | print | alpha,
1085 lower | print | alpha, lower | print | alpha,
1086 lower | print | alpha, lower | print | alpha,
1087 lower | print | alpha, punct | print,
1088 punct | print, punct | print,
1089 punct | print, cntrl,
1090 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1091 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1092 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1094 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1095 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1096 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1097 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1098 };
1099 return builtin_table;
1100}
1101#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001102const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001103ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001104{
David Chisnall1d581062011-09-21 08:39:44 +00001105#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001106 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001107#elif defined(__NetBSD__)
1108 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001109#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001110 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001111#elif __sun__
1112 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001113#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001114#if _VC_CRT_MAJOR_VERSION < 14
1115 // This is assumed to be safe, which is a nonsense assumption because we're
1116 // going to end up dereferencing it later...
Howard Hinnantd7a78632011-09-29 13:33:15 +00001117 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001118#else
1119 return __pctype_func();
1120#endif
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001121#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001122 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001123#elif defined(_NEWLIB_VERSION)
1124 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1125 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001126#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001127 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001128#else
David Chisnall8074c342012-02-29 13:05:08 +00001129 // Platform not supported: abort so the person doing the port knows what to
1130 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001131# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001132 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001133 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001134 return NULL;
1135#endif
1136}
Marshall Clowb3f62842015-03-04 16:10:14 +00001137#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001138
Howard Hinnantd7a78632011-09-29 13:33:15 +00001139#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001140const int*
1141ctype<char>::__classic_lower_table() _NOEXCEPT
1142{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001143 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001144}
1145
1146const int*
1147ctype<char>::__classic_upper_table() _NOEXCEPT
1148{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001149 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001150}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001151#elif __NetBSD__
1152const short*
1153ctype<char>::__classic_lower_table() _NOEXCEPT
1154{
1155 return _C_tolower_tab_ + 1;
1156}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001157
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001158const short*
1159ctype<char>::__classic_upper_table() _NOEXCEPT
1160{
1161 return _C_toupper_tab_ + 1;
1162}
1163
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001164#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001165const int*
1166ctype<char>::__classic_lower_table() _NOEXCEPT
1167{
1168 return *__ctype_tolower_loc();
1169}
1170
1171const int*
1172ctype<char>::__classic_upper_table() _NOEXCEPT
1173{
1174 return *__ctype_toupper_loc();
1175}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001176#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001177
Howard Hinnantc51e1022010-05-11 19:42:16 +00001178// template <> class ctype_byname<char>
1179
1180ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1181 : ctype<char>(0, false, refs),
1182 __l(newlocale(LC_ALL_MASK, name, 0))
1183{
1184 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001185 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001186 " failed to construct for " + string(name));
1187}
1188
1189ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1190 : ctype<char>(0, false, refs),
1191 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1192{
1193 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001194 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001195 " failed to construct for " + name);
1196}
1197
1198ctype_byname<char>::~ctype_byname()
1199{
1200 freelocale(__l);
1201}
1202
1203char
1204ctype_byname<char>::do_toupper(char_type c) const
1205{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001206 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207}
1208
1209const char*
1210ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1211{
1212 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001213 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001214 return low;
1215}
1216
1217char
1218ctype_byname<char>::do_tolower(char_type c) const
1219{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001220 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001221}
1222
1223const char*
1224ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1225{
1226 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001227 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001228 return low;
1229}
1230
1231// template <> class ctype_byname<wchar_t>
1232
1233ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1234 : ctype<wchar_t>(refs),
1235 __l(newlocale(LC_ALL_MASK, name, 0))
1236{
1237 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001238 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001239 " failed to construct for " + string(name));
1240}
1241
1242ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1243 : ctype<wchar_t>(refs),
1244 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1245{
1246 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001247 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001248 " failed to construct for " + name);
1249}
1250
1251ctype_byname<wchar_t>::~ctype_byname()
1252{
1253 freelocale(__l);
1254}
1255
1256bool
1257ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1258{
Alexis Huntc2017f12011-07-09 03:40:04 +00001259#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001260 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001261#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001262 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001263 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001264 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1265 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1266 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1267 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1268 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1269 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1270 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1271 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1272 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1273 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001274 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001275#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001276}
1277
1278const wchar_t*
1279ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1280{
1281 for (; low != high; ++low, ++vec)
1282 {
1283 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001284 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001285 else
1286 {
1287 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001288 wint_t ch = static_cast<wint_t>(*low);
1289 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001290 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001291#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001292 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001293 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001294#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001295 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001296 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001297 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001298 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001299 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001301#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001302 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001303 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001304#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001305 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001306 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001307 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001308 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001309#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001310 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001311 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001312#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001313#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001314 if (iswblank_l(ch, __l))
1315 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001316#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001317 }
1318 }
1319 return low;
1320}
1321
1322const wchar_t*
1323ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1324{
1325 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001326 {
1327#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001328 if (iswctype_l(*low, m, __l))
1329 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001330#else
Marshall Clowada0f732013-02-07 14:22:51 +00001331 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001332 if ((m & space) == space && iswspace_l(ch, __l)) break;
1333 if ((m & print) == print && iswprint_l(ch, __l)) break;
1334 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1335 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1336 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1337 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1338 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1339 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1340 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1341 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001342#endif
1343 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001344 return low;
1345}
1346
1347const wchar_t*
1348ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1349{
1350 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001351 {
1352#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001353 if (!iswctype_l(*low, m, __l))
1354 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001355#else
Marshall Clowada0f732013-02-07 14:22:51 +00001356 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001357 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1358 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1359 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1360 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1361 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1362 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1363 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1364 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1365 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1366 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001367 break;
1368#endif
1369 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001370 return low;
1371}
1372
1373wchar_t
1374ctype_byname<wchar_t>::do_toupper(char_type c) const
1375{
1376 return towupper_l(c, __l);
1377}
1378
1379const wchar_t*
1380ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1381{
1382 for (; low != high; ++low)
1383 *low = towupper_l(*low, __l);
1384 return low;
1385}
1386
1387wchar_t
1388ctype_byname<wchar_t>::do_tolower(char_type c) const
1389{
1390 return towlower_l(c, __l);
1391}
1392
1393const wchar_t*
1394ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1395{
1396 for (; low != high; ++low)
1397 *low = towlower_l(*low, __l);
1398 return low;
1399}
1400
1401wchar_t
1402ctype_byname<wchar_t>::do_widen(char c) const
1403{
Ben Craig3756b922016-03-09 15:39:39 +00001404 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001405}
1406
1407const char*
1408ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1409{
1410 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001411 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001412 return low;
1413}
1414
1415char
1416ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1417{
Ben Craig3756b922016-03-09 15:39:39 +00001418 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001419 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001420}
1421
1422const wchar_t*
1423ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1424{
1425 for (; low != high; ++low, ++dest)
1426 {
Ben Craig3756b922016-03-09 15:39:39 +00001427 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001428 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001429 }
1430 return low;
1431}
1432
1433// template <> class codecvt<char, char, mbstate_t>
1434
Howard Hinnantffb308e2010-08-22 00:03:27 +00001435locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001436
1437codecvt<char, char, mbstate_t>::~codecvt()
1438{
1439}
1440
1441codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001442codecvt<char, char, mbstate_t>::do_out(state_type&,
1443 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001444 extern_type* to, extern_type*, extern_type*& to_nxt) const
1445{
1446 frm_nxt = frm;
1447 to_nxt = to;
1448 return noconv;
1449}
1450
1451codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001452codecvt<char, char, mbstate_t>::do_in(state_type&,
1453 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001454 intern_type* to, intern_type*, intern_type*& to_nxt) const
1455{
1456 frm_nxt = frm;
1457 to_nxt = to;
1458 return noconv;
1459}
1460
1461codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001462codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001463 extern_type* to, extern_type*, extern_type*& to_nxt) const
1464{
1465 to_nxt = to;
1466 return noconv;
1467}
1468
1469int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001470codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001471{
1472 return 1;
1473}
1474
1475bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001476codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001477{
1478 return true;
1479}
1480
1481int
1482codecvt<char, char, mbstate_t>::do_length(state_type&,
1483 const extern_type* frm, const extern_type* end, size_t mx) const
1484{
Howard Hinnant28b24882011-12-01 20:21:04 +00001485 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001486}
1487
1488int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001489codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001490{
1491 return 1;
1492}
1493
1494// template <> class codecvt<wchar_t, char, mbstate_t>
1495
Howard Hinnantffb308e2010-08-22 00:03:27 +00001496locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001497
1498codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1499 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001500 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001501{
1502}
1503
1504codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1505 : locale::facet(refs),
1506 __l(newlocale(LC_ALL_MASK, nm, 0))
1507{
1508 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001509 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001510 " failed to construct for " + string(nm));
1511}
1512
1513codecvt<wchar_t, char, mbstate_t>::~codecvt()
1514{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001515 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001516 freelocale(__l);
1517}
1518
1519codecvt<wchar_t, char, mbstate_t>::result
1520codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001521 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001522 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1523{
1524 // look for first internal null in frm
1525 const intern_type* fend = frm;
1526 for (; fend != frm_end; ++fend)
1527 if (*fend == 0)
1528 break;
1529 // loop over all null-terminated sequences in frm
1530 to_nxt = to;
1531 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1532 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001533 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001534 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001535 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1536 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001537 if (n == size_t(-1))
1538 {
1539 // need to recover to_nxt
1540 for (to_nxt = to; frm != frm_nxt; ++frm)
1541 {
Ben Craig3756b922016-03-09 15:39:39 +00001542 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001543 if (n == size_t(-1))
1544 break;
1545 to_nxt += n;
1546 }
1547 frm_nxt = frm;
1548 return error;
1549 }
1550 if (n == 0)
1551 return partial;
1552 to_nxt += n;
1553 if (to_nxt == to_end)
1554 break;
1555 if (fend != frm_end) // set up next null terminated sequence
1556 {
1557 // Try to write the terminating null
1558 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001559 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001560 if (n == size_t(-1)) // on error
1561 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001562 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001563 return partial;
1564 for (extern_type* p = tmp; n; --n) // write it
1565 *to_nxt++ = *p++;
1566 ++frm_nxt;
1567 // look for next null in frm
1568 for (fend = frm_nxt; fend != frm_end; ++fend)
1569 if (*fend == 0)
1570 break;
1571 }
1572 }
1573 return frm_nxt == frm_end ? ok : partial;
1574}
1575
1576codecvt<wchar_t, char, mbstate_t>::result
1577codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001578 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001579 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1580{
1581 // look for first internal null in frm
1582 const extern_type* fend = frm;
1583 for (; fend != frm_end; ++fend)
1584 if (*fend == 0)
1585 break;
1586 // loop over all null-terminated sequences in frm
1587 to_nxt = to;
1588 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1589 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001590 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001591 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001592 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1593 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001594 if (n == size_t(-1))
1595 {
1596 // need to recover to_nxt
1597 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1598 {
Ben Craig3756b922016-03-09 15:39:39 +00001599 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1600 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001601 switch (n)
1602 {
1603 case 0:
1604 ++frm;
1605 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001606 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001607 frm_nxt = frm;
1608 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001609 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001610 frm_nxt = frm;
1611 return partial;
1612 default:
1613 frm += n;
1614 break;
1615 }
1616 }
1617 frm_nxt = frm;
1618 return frm_nxt == frm_end ? ok : partial;
1619 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001620 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001621 return error;
1622 to_nxt += n;
1623 if (to_nxt == to_end)
1624 break;
1625 if (fend != frm_end) // set up next null terminated sequence
1626 {
1627 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001628 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001629 if (n != 0) // on error
1630 return error;
1631 ++to_nxt;
1632 ++frm_nxt;
1633 // look for next null in frm
1634 for (fend = frm_nxt; fend != frm_end; ++fend)
1635 if (*fend == 0)
1636 break;
1637 }
1638 }
1639 return frm_nxt == frm_end ? ok : partial;
1640}
1641
1642codecvt<wchar_t, char, mbstate_t>::result
1643codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1644 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1645{
1646 to_nxt = to;
1647 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001648 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001649 if (n == size_t(-1) || n == 0) // on error
1650 return error;
1651 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001652 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001653 return partial;
1654 for (extern_type* p = tmp; n; --n) // write it
1655 *to_nxt++ = *p++;
1656 return ok;
1657}
1658
1659int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001660codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001661{
Ben Craig3756b922016-03-09 15:39:39 +00001662 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001663 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001664
1665 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001666 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001667 return 1; // which take more than 1 char to form a wchar_t
1668 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001669}
1670
1671bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001672codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001673{
1674 return false;
1675}
1676
1677int
1678codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1679 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1680{
1681 int nbytes = 0;
1682 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1683 {
Ben Craig3756b922016-03-09 15:39:39 +00001684 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001685 switch (n)
1686 {
1687 case 0:
1688 ++nbytes;
1689 ++frm;
1690 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001691 case size_t(-1):
1692 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001693 return nbytes;
1694 default:
1695 nbytes += n;
1696 frm += n;
1697 break;
1698 }
1699 }
1700 return nbytes;
1701}
1702
1703int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001704codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001705{
Ben Craig3756b922016-03-09 15:39:39 +00001706 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001707}
1708
1709// Valid UTF ranges
1710// UTF-32 UTF-16 UTF-8 # of code points
1711// first second first second third fourth
1712// 000000 - 00007F 0000 - 007F 00 - 7F 127
1713// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1714// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1715// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1716// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1717// 00D800 - 00DFFF invalid
1718// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1719// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1720// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1721// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1722
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001723static
1724codecvt_base::result
1725utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1726 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1727 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1728{
1729 frm_nxt = frm;
1730 to_nxt = to;
1731 if (mode & generate_header)
1732 {
1733 if (to_end-to_nxt < 3)
1734 return codecvt_base::partial;
1735 *to_nxt++ = static_cast<uint8_t>(0xEF);
1736 *to_nxt++ = static_cast<uint8_t>(0xBB);
1737 *to_nxt++ = static_cast<uint8_t>(0xBF);
1738 }
1739 for (; frm_nxt < frm_end; ++frm_nxt)
1740 {
1741 uint16_t wc1 = *frm_nxt;
1742 if (wc1 > Maxcode)
1743 return codecvt_base::error;
1744 if (wc1 < 0x0080)
1745 {
1746 if (to_end-to_nxt < 1)
1747 return codecvt_base::partial;
1748 *to_nxt++ = static_cast<uint8_t>(wc1);
1749 }
1750 else if (wc1 < 0x0800)
1751 {
1752 if (to_end-to_nxt < 2)
1753 return codecvt_base::partial;
1754 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1756 }
1757 else if (wc1 < 0xD800)
1758 {
1759 if (to_end-to_nxt < 3)
1760 return codecvt_base::partial;
1761 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1762 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1763 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1764 }
1765 else if (wc1 < 0xDC00)
1766 {
1767 if (frm_end-frm_nxt < 2)
1768 return codecvt_base::partial;
1769 uint16_t wc2 = frm_nxt[1];
1770 if ((wc2 & 0xFC00) != 0xDC00)
1771 return codecvt_base::error;
1772 if (to_end-to_nxt < 4)
1773 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001774 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1775 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001776 return codecvt_base::error;
1777 ++frm_nxt;
1778 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1779 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1780 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1781 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1782 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1783 }
1784 else if (wc1 < 0xE000)
1785 {
1786 return codecvt_base::error;
1787 }
1788 else
1789 {
1790 if (to_end-to_nxt < 3)
1791 return codecvt_base::partial;
1792 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1793 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1794 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1795 }
1796 }
1797 return codecvt_base::ok;
1798}
1799
1800static
1801codecvt_base::result
1802utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1803 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1804 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1805{
1806 frm_nxt = frm;
1807 to_nxt = to;
1808 if (mode & generate_header)
1809 {
1810 if (to_end-to_nxt < 3)
1811 return codecvt_base::partial;
1812 *to_nxt++ = static_cast<uint8_t>(0xEF);
1813 *to_nxt++ = static_cast<uint8_t>(0xBB);
1814 *to_nxt++ = static_cast<uint8_t>(0xBF);
1815 }
1816 for (; frm_nxt < frm_end; ++frm_nxt)
1817 {
1818 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1819 if (wc1 > Maxcode)
1820 return codecvt_base::error;
1821 if (wc1 < 0x0080)
1822 {
1823 if (to_end-to_nxt < 1)
1824 return codecvt_base::partial;
1825 *to_nxt++ = static_cast<uint8_t>(wc1);
1826 }
1827 else if (wc1 < 0x0800)
1828 {
1829 if (to_end-to_nxt < 2)
1830 return codecvt_base::partial;
1831 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1832 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1833 }
1834 else if (wc1 < 0xD800)
1835 {
1836 if (to_end-to_nxt < 3)
1837 return codecvt_base::partial;
1838 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1839 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1840 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1841 }
1842 else if (wc1 < 0xDC00)
1843 {
1844 if (frm_end-frm_nxt < 2)
1845 return codecvt_base::partial;
1846 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1847 if ((wc2 & 0xFC00) != 0xDC00)
1848 return codecvt_base::error;
1849 if (to_end-to_nxt < 4)
1850 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001851 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1852 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001853 return codecvt_base::error;
1854 ++frm_nxt;
1855 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1856 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1857 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1858 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1859 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1860 }
1861 else if (wc1 < 0xE000)
1862 {
1863 return codecvt_base::error;
1864 }
1865 else
1866 {
1867 if (to_end-to_nxt < 3)
1868 return codecvt_base::partial;
1869 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1870 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1871 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1872 }
1873 }
1874 return codecvt_base::ok;
1875}
1876
1877static
1878codecvt_base::result
1879utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1880 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1881 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1882{
1883 frm_nxt = frm;
1884 to_nxt = to;
1885 if (mode & consume_header)
1886 {
1887 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1888 frm_nxt[2] == 0xBF)
1889 frm_nxt += 3;
1890 }
1891 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1892 {
1893 uint8_t c1 = *frm_nxt;
1894 if (c1 > Maxcode)
1895 return codecvt_base::error;
1896 if (c1 < 0x80)
1897 {
1898 *to_nxt = static_cast<uint16_t>(c1);
1899 ++frm_nxt;
1900 }
1901 else if (c1 < 0xC2)
1902 {
1903 return codecvt_base::error;
1904 }
1905 else if (c1 < 0xE0)
1906 {
1907 if (frm_end-frm_nxt < 2)
1908 return codecvt_base::partial;
1909 uint8_t c2 = frm_nxt[1];
1910 if ((c2 & 0xC0) != 0x80)
1911 return codecvt_base::error;
1912 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1913 if (t > Maxcode)
1914 return codecvt_base::error;
1915 *to_nxt = t;
1916 frm_nxt += 2;
1917 }
1918 else if (c1 < 0xF0)
1919 {
1920 if (frm_end-frm_nxt < 3)
1921 return codecvt_base::partial;
1922 uint8_t c2 = frm_nxt[1];
1923 uint8_t c3 = frm_nxt[2];
1924 switch (c1)
1925 {
1926 case 0xE0:
1927 if ((c2 & 0xE0) != 0xA0)
1928 return codecvt_base::error;
1929 break;
1930 case 0xED:
1931 if ((c2 & 0xE0) != 0x80)
1932 return codecvt_base::error;
1933 break;
1934 default:
1935 if ((c2 & 0xC0) != 0x80)
1936 return codecvt_base::error;
1937 break;
1938 }
1939 if ((c3 & 0xC0) != 0x80)
1940 return codecvt_base::error;
1941 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1942 | ((c2 & 0x3F) << 6)
1943 | (c3 & 0x3F));
1944 if (t > Maxcode)
1945 return codecvt_base::error;
1946 *to_nxt = t;
1947 frm_nxt += 3;
1948 }
1949 else if (c1 < 0xF5)
1950 {
1951 if (frm_end-frm_nxt < 4)
1952 return codecvt_base::partial;
1953 uint8_t c2 = frm_nxt[1];
1954 uint8_t c3 = frm_nxt[2];
1955 uint8_t c4 = frm_nxt[3];
1956 switch (c1)
1957 {
1958 case 0xF0:
1959 if (!(0x90 <= c2 && c2 <= 0xBF))
1960 return codecvt_base::error;
1961 break;
1962 case 0xF4:
1963 if ((c2 & 0xF0) != 0x80)
1964 return codecvt_base::error;
1965 break;
1966 default:
1967 if ((c2 & 0xC0) != 0x80)
1968 return codecvt_base::error;
1969 break;
1970 }
1971 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1972 return codecvt_base::error;
1973 if (to_end-to_nxt < 2)
1974 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001975 if ((((c1 & 7UL) << 18) +
1976 ((c2 & 0x3FUL) << 12) +
1977 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001978 return codecvt_base::error;
1979 *to_nxt = static_cast<uint16_t>(
1980 0xD800
1981 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1982 | ((c2 & 0x0F) << 2)
1983 | ((c3 & 0x30) >> 4));
1984 *++to_nxt = static_cast<uint16_t>(
1985 0xDC00
1986 | ((c3 & 0x0F) << 6)
1987 | (c4 & 0x3F));
1988 frm_nxt += 4;
1989 }
1990 else
1991 {
1992 return codecvt_base::error;
1993 }
1994 }
1995 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1996}
1997
1998static
1999codecvt_base::result
2000utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2001 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2002 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2003{
2004 frm_nxt = frm;
2005 to_nxt = to;
2006 if (mode & consume_header)
2007 {
2008 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2009 frm_nxt[2] == 0xBF)
2010 frm_nxt += 3;
2011 }
2012 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2013 {
2014 uint8_t c1 = *frm_nxt;
2015 if (c1 > Maxcode)
2016 return codecvt_base::error;
2017 if (c1 < 0x80)
2018 {
2019 *to_nxt = static_cast<uint32_t>(c1);
2020 ++frm_nxt;
2021 }
2022 else if (c1 < 0xC2)
2023 {
2024 return codecvt_base::error;
2025 }
2026 else if (c1 < 0xE0)
2027 {
2028 if (frm_end-frm_nxt < 2)
2029 return codecvt_base::partial;
2030 uint8_t c2 = frm_nxt[1];
2031 if ((c2 & 0xC0) != 0x80)
2032 return codecvt_base::error;
2033 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2034 if (t > Maxcode)
2035 return codecvt_base::error;
2036 *to_nxt = static_cast<uint32_t>(t);
2037 frm_nxt += 2;
2038 }
2039 else if (c1 < 0xF0)
2040 {
2041 if (frm_end-frm_nxt < 3)
2042 return codecvt_base::partial;
2043 uint8_t c2 = frm_nxt[1];
2044 uint8_t c3 = frm_nxt[2];
2045 switch (c1)
2046 {
2047 case 0xE0:
2048 if ((c2 & 0xE0) != 0xA0)
2049 return codecvt_base::error;
2050 break;
2051 case 0xED:
2052 if ((c2 & 0xE0) != 0x80)
2053 return codecvt_base::error;
2054 break;
2055 default:
2056 if ((c2 & 0xC0) != 0x80)
2057 return codecvt_base::error;
2058 break;
2059 }
2060 if ((c3 & 0xC0) != 0x80)
2061 return codecvt_base::error;
2062 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2063 | ((c2 & 0x3F) << 6)
2064 | (c3 & 0x3F));
2065 if (t > Maxcode)
2066 return codecvt_base::error;
2067 *to_nxt = static_cast<uint32_t>(t);
2068 frm_nxt += 3;
2069 }
2070 else if (c1 < 0xF5)
2071 {
2072 if (frm_end-frm_nxt < 4)
2073 return codecvt_base::partial;
2074 uint8_t c2 = frm_nxt[1];
2075 uint8_t c3 = frm_nxt[2];
2076 uint8_t c4 = frm_nxt[3];
2077 switch (c1)
2078 {
2079 case 0xF0:
2080 if (!(0x90 <= c2 && c2 <= 0xBF))
2081 return codecvt_base::error;
2082 break;
2083 case 0xF4:
2084 if ((c2 & 0xF0) != 0x80)
2085 return codecvt_base::error;
2086 break;
2087 default:
2088 if ((c2 & 0xC0) != 0x80)
2089 return codecvt_base::error;
2090 break;
2091 }
2092 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2093 return codecvt_base::error;
2094 if (to_end-to_nxt < 2)
2095 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002096 if ((((c1 & 7UL) << 18) +
2097 ((c2 & 0x3FUL) << 12) +
2098 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002099 return codecvt_base::error;
2100 *to_nxt = static_cast<uint32_t>(
2101 0xD800
2102 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2103 | ((c2 & 0x0F) << 2)
2104 | ((c3 & 0x30) >> 4));
2105 *++to_nxt = static_cast<uint32_t>(
2106 0xDC00
2107 | ((c3 & 0x0F) << 6)
2108 | (c4 & 0x3F));
2109 frm_nxt += 4;
2110 }
2111 else
2112 {
2113 return codecvt_base::error;
2114 }
2115 }
2116 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2117}
2118
2119static
2120int
2121utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2122 size_t mx, unsigned long Maxcode = 0x10FFFF,
2123 codecvt_mode mode = codecvt_mode(0))
2124{
2125 const uint8_t* frm_nxt = frm;
2126 if (mode & consume_header)
2127 {
2128 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2129 frm_nxt[2] == 0xBF)
2130 frm_nxt += 3;
2131 }
2132 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2133 {
2134 uint8_t c1 = *frm_nxt;
2135 if (c1 > Maxcode)
2136 break;
2137 if (c1 < 0x80)
2138 {
2139 ++frm_nxt;
2140 }
2141 else if (c1 < 0xC2)
2142 {
2143 break;
2144 }
2145 else if (c1 < 0xE0)
2146 {
2147 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2148 break;
2149 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2150 if (t > Maxcode)
2151 break;
2152 frm_nxt += 2;
2153 }
2154 else if (c1 < 0xF0)
2155 {
2156 if (frm_end-frm_nxt < 3)
2157 break;
2158 uint8_t c2 = frm_nxt[1];
2159 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002160 switch (c1)
2161 {
2162 case 0xE0:
2163 if ((c2 & 0xE0) != 0xA0)
2164 return static_cast<int>(frm_nxt - frm);
2165 break;
2166 case 0xED:
2167 if ((c2 & 0xE0) != 0x80)
2168 return static_cast<int>(frm_nxt - frm);
2169 break;
2170 default:
2171 if ((c2 & 0xC0) != 0x80)
2172 return static_cast<int>(frm_nxt - frm);
2173 break;
2174 }
2175 if ((c3 & 0xC0) != 0x80)
2176 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002177 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002178 break;
2179 frm_nxt += 3;
2180 }
2181 else if (c1 < 0xF5)
2182 {
2183 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2184 break;
2185 uint8_t c2 = frm_nxt[1];
2186 uint8_t c3 = frm_nxt[2];
2187 uint8_t c4 = frm_nxt[3];
2188 switch (c1)
2189 {
2190 case 0xF0:
2191 if (!(0x90 <= c2 && c2 <= 0xBF))
2192 return static_cast<int>(frm_nxt - frm);
2193 break;
2194 case 0xF4:
2195 if ((c2 & 0xF0) != 0x80)
2196 return static_cast<int>(frm_nxt - frm);
2197 break;
2198 default:
2199 if ((c2 & 0xC0) != 0x80)
2200 return static_cast<int>(frm_nxt - frm);
2201 break;
2202 }
2203 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2204 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002205 if ((((c1 & 7UL) << 18) +
2206 ((c2 & 0x3FUL) << 12) +
2207 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002208 break;
2209 ++nchar16_t;
2210 frm_nxt += 4;
2211 }
2212 else
2213 {
2214 break;
2215 }
2216 }
2217 return static_cast<int>(frm_nxt - frm);
2218}
2219
2220static
2221codecvt_base::result
2222ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2223 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2224 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2225{
2226 frm_nxt = frm;
2227 to_nxt = to;
2228 if (mode & generate_header)
2229 {
2230 if (to_end-to_nxt < 3)
2231 return codecvt_base::partial;
2232 *to_nxt++ = static_cast<uint8_t>(0xEF);
2233 *to_nxt++ = static_cast<uint8_t>(0xBB);
2234 *to_nxt++ = static_cast<uint8_t>(0xBF);
2235 }
2236 for (; frm_nxt < frm_end; ++frm_nxt)
2237 {
2238 uint32_t wc = *frm_nxt;
2239 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2240 return codecvt_base::error;
2241 if (wc < 0x000080)
2242 {
2243 if (to_end-to_nxt < 1)
2244 return codecvt_base::partial;
2245 *to_nxt++ = static_cast<uint8_t>(wc);
2246 }
2247 else if (wc < 0x000800)
2248 {
2249 if (to_end-to_nxt < 2)
2250 return codecvt_base::partial;
2251 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2252 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2253 }
2254 else if (wc < 0x010000)
2255 {
2256 if (to_end-to_nxt < 3)
2257 return codecvt_base::partial;
2258 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2259 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2260 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2261 }
2262 else // if (wc < 0x110000)
2263 {
2264 if (to_end-to_nxt < 4)
2265 return codecvt_base::partial;
2266 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2267 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2268 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2269 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2270 }
2271 }
2272 return codecvt_base::ok;
2273}
2274
2275static
2276codecvt_base::result
2277utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2278 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2279 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2280{
2281 frm_nxt = frm;
2282 to_nxt = to;
2283 if (mode & consume_header)
2284 {
2285 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2286 frm_nxt[2] == 0xBF)
2287 frm_nxt += 3;
2288 }
2289 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2290 {
2291 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2292 if (c1 < 0x80)
2293 {
2294 if (c1 > Maxcode)
2295 return codecvt_base::error;
2296 *to_nxt = static_cast<uint32_t>(c1);
2297 ++frm_nxt;
2298 }
2299 else if (c1 < 0xC2)
2300 {
2301 return codecvt_base::error;
2302 }
2303 else if (c1 < 0xE0)
2304 {
2305 if (frm_end-frm_nxt < 2)
2306 return codecvt_base::partial;
2307 uint8_t c2 = frm_nxt[1];
2308 if ((c2 & 0xC0) != 0x80)
2309 return codecvt_base::error;
2310 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2311 | (c2 & 0x3F));
2312 if (t > Maxcode)
2313 return codecvt_base::error;
2314 *to_nxt = t;
2315 frm_nxt += 2;
2316 }
2317 else if (c1 < 0xF0)
2318 {
2319 if (frm_end-frm_nxt < 3)
2320 return codecvt_base::partial;
2321 uint8_t c2 = frm_nxt[1];
2322 uint8_t c3 = frm_nxt[2];
2323 switch (c1)
2324 {
2325 case 0xE0:
2326 if ((c2 & 0xE0) != 0xA0)
2327 return codecvt_base::error;
2328 break;
2329 case 0xED:
2330 if ((c2 & 0xE0) != 0x80)
2331 return codecvt_base::error;
2332 break;
2333 default:
2334 if ((c2 & 0xC0) != 0x80)
2335 return codecvt_base::error;
2336 break;
2337 }
2338 if ((c3 & 0xC0) != 0x80)
2339 return codecvt_base::error;
2340 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2341 | ((c2 & 0x3F) << 6)
2342 | (c3 & 0x3F));
2343 if (t > Maxcode)
2344 return codecvt_base::error;
2345 *to_nxt = t;
2346 frm_nxt += 3;
2347 }
2348 else if (c1 < 0xF5)
2349 {
2350 if (frm_end-frm_nxt < 4)
2351 return codecvt_base::partial;
2352 uint8_t c2 = frm_nxt[1];
2353 uint8_t c3 = frm_nxt[2];
2354 uint8_t c4 = frm_nxt[3];
2355 switch (c1)
2356 {
2357 case 0xF0:
2358 if (!(0x90 <= c2 && c2 <= 0xBF))
2359 return codecvt_base::error;
2360 break;
2361 case 0xF4:
2362 if ((c2 & 0xF0) != 0x80)
2363 return codecvt_base::error;
2364 break;
2365 default:
2366 if ((c2 & 0xC0) != 0x80)
2367 return codecvt_base::error;
2368 break;
2369 }
2370 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2371 return codecvt_base::error;
2372 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2373 | ((c2 & 0x3F) << 12)
2374 | ((c3 & 0x3F) << 6)
2375 | (c4 & 0x3F));
2376 if (t > Maxcode)
2377 return codecvt_base::error;
2378 *to_nxt = t;
2379 frm_nxt += 4;
2380 }
2381 else
2382 {
2383 return codecvt_base::error;
2384 }
2385 }
2386 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2387}
2388
2389static
2390int
2391utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2392 size_t mx, unsigned long Maxcode = 0x10FFFF,
2393 codecvt_mode mode = codecvt_mode(0))
2394{
2395 const uint8_t* frm_nxt = frm;
2396 if (mode & consume_header)
2397 {
2398 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2399 frm_nxt[2] == 0xBF)
2400 frm_nxt += 3;
2401 }
2402 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2403 {
2404 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2405 if (c1 < 0x80)
2406 {
2407 if (c1 > Maxcode)
2408 break;
2409 ++frm_nxt;
2410 }
2411 else if (c1 < 0xC2)
2412 {
2413 break;
2414 }
2415 else if (c1 < 0xE0)
2416 {
2417 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2418 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002419 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002420 break;
2421 frm_nxt += 2;
2422 }
2423 else if (c1 < 0xF0)
2424 {
2425 if (frm_end-frm_nxt < 3)
2426 break;
2427 uint8_t c2 = frm_nxt[1];
2428 uint8_t c3 = frm_nxt[2];
2429 switch (c1)
2430 {
2431 case 0xE0:
2432 if ((c2 & 0xE0) != 0xA0)
2433 return static_cast<int>(frm_nxt - frm);
2434 break;
2435 case 0xED:
2436 if ((c2 & 0xE0) != 0x80)
2437 return static_cast<int>(frm_nxt - frm);
2438 break;
2439 default:
2440 if ((c2 & 0xC0) != 0x80)
2441 return static_cast<int>(frm_nxt - frm);
2442 break;
2443 }
2444 if ((c3 & 0xC0) != 0x80)
2445 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002446 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002447 break;
2448 frm_nxt += 3;
2449 }
2450 else if (c1 < 0xF5)
2451 {
2452 if (frm_end-frm_nxt < 4)
2453 break;
2454 uint8_t c2 = frm_nxt[1];
2455 uint8_t c3 = frm_nxt[2];
2456 uint8_t c4 = frm_nxt[3];
2457 switch (c1)
2458 {
2459 case 0xF0:
2460 if (!(0x90 <= c2 && c2 <= 0xBF))
2461 return static_cast<int>(frm_nxt - frm);
2462 break;
2463 case 0xF4:
2464 if ((c2 & 0xF0) != 0x80)
2465 return static_cast<int>(frm_nxt - frm);
2466 break;
2467 default:
2468 if ((c2 & 0xC0) != 0x80)
2469 return static_cast<int>(frm_nxt - frm);
2470 break;
2471 }
2472 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2473 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002474 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2475 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002476 break;
2477 frm_nxt += 4;
2478 }
2479 else
2480 {
2481 break;
2482 }
2483 }
2484 return static_cast<int>(frm_nxt - frm);
2485}
2486
2487static
2488codecvt_base::result
2489ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2490 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2491 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2492{
2493 frm_nxt = frm;
2494 to_nxt = to;
2495 if (mode & generate_header)
2496 {
2497 if (to_end-to_nxt < 3)
2498 return codecvt_base::partial;
2499 *to_nxt++ = static_cast<uint8_t>(0xEF);
2500 *to_nxt++ = static_cast<uint8_t>(0xBB);
2501 *to_nxt++ = static_cast<uint8_t>(0xBF);
2502 }
2503 for (; frm_nxt < frm_end; ++frm_nxt)
2504 {
2505 uint16_t wc = *frm_nxt;
2506 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2507 return codecvt_base::error;
2508 if (wc < 0x0080)
2509 {
2510 if (to_end-to_nxt < 1)
2511 return codecvt_base::partial;
2512 *to_nxt++ = static_cast<uint8_t>(wc);
2513 }
2514 else if (wc < 0x0800)
2515 {
2516 if (to_end-to_nxt < 2)
2517 return codecvt_base::partial;
2518 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2519 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2520 }
2521 else // if (wc <= 0xFFFF)
2522 {
2523 if (to_end-to_nxt < 3)
2524 return codecvt_base::partial;
2525 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2526 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2527 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2528 }
2529 }
2530 return codecvt_base::ok;
2531}
2532
2533static
2534codecvt_base::result
2535utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2536 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2537 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2538{
2539 frm_nxt = frm;
2540 to_nxt = to;
2541 if (mode & consume_header)
2542 {
2543 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2544 frm_nxt[2] == 0xBF)
2545 frm_nxt += 3;
2546 }
2547 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2548 {
2549 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2550 if (c1 < 0x80)
2551 {
2552 if (c1 > Maxcode)
2553 return codecvt_base::error;
2554 *to_nxt = static_cast<uint16_t>(c1);
2555 ++frm_nxt;
2556 }
2557 else if (c1 < 0xC2)
2558 {
2559 return codecvt_base::error;
2560 }
2561 else if (c1 < 0xE0)
2562 {
2563 if (frm_end-frm_nxt < 2)
2564 return codecvt_base::partial;
2565 uint8_t c2 = frm_nxt[1];
2566 if ((c2 & 0xC0) != 0x80)
2567 return codecvt_base::error;
2568 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2569 | (c2 & 0x3F));
2570 if (t > Maxcode)
2571 return codecvt_base::error;
2572 *to_nxt = t;
2573 frm_nxt += 2;
2574 }
2575 else if (c1 < 0xF0)
2576 {
2577 if (frm_end-frm_nxt < 3)
2578 return codecvt_base::partial;
2579 uint8_t c2 = frm_nxt[1];
2580 uint8_t c3 = frm_nxt[2];
2581 switch (c1)
2582 {
2583 case 0xE0:
2584 if ((c2 & 0xE0) != 0xA0)
2585 return codecvt_base::error;
2586 break;
2587 case 0xED:
2588 if ((c2 & 0xE0) != 0x80)
2589 return codecvt_base::error;
2590 break;
2591 default:
2592 if ((c2 & 0xC0) != 0x80)
2593 return codecvt_base::error;
2594 break;
2595 }
2596 if ((c3 & 0xC0) != 0x80)
2597 return codecvt_base::error;
2598 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2599 | ((c2 & 0x3F) << 6)
2600 | (c3 & 0x3F));
2601 if (t > Maxcode)
2602 return codecvt_base::error;
2603 *to_nxt = t;
2604 frm_nxt += 3;
2605 }
2606 else
2607 {
2608 return codecvt_base::error;
2609 }
2610 }
2611 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2612}
2613
2614static
2615int
2616utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2617 size_t mx, unsigned long Maxcode = 0x10FFFF,
2618 codecvt_mode mode = codecvt_mode(0))
2619{
2620 const uint8_t* frm_nxt = frm;
2621 if (mode & consume_header)
2622 {
2623 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2624 frm_nxt[2] == 0xBF)
2625 frm_nxt += 3;
2626 }
2627 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2628 {
2629 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2630 if (c1 < 0x80)
2631 {
2632 if (c1 > Maxcode)
2633 break;
2634 ++frm_nxt;
2635 }
2636 else if (c1 < 0xC2)
2637 {
2638 break;
2639 }
2640 else if (c1 < 0xE0)
2641 {
2642 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2643 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002644 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002645 break;
2646 frm_nxt += 2;
2647 }
2648 else if (c1 < 0xF0)
2649 {
2650 if (frm_end-frm_nxt < 3)
2651 break;
2652 uint8_t c2 = frm_nxt[1];
2653 uint8_t c3 = frm_nxt[2];
2654 switch (c1)
2655 {
2656 case 0xE0:
2657 if ((c2 & 0xE0) != 0xA0)
2658 return static_cast<int>(frm_nxt - frm);
2659 break;
2660 case 0xED:
2661 if ((c2 & 0xE0) != 0x80)
2662 return static_cast<int>(frm_nxt - frm);
2663 break;
2664 default:
2665 if ((c2 & 0xC0) != 0x80)
2666 return static_cast<int>(frm_nxt - frm);
2667 break;
2668 }
2669 if ((c3 & 0xC0) != 0x80)
2670 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002671 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002672 break;
2673 frm_nxt += 3;
2674 }
2675 else
2676 {
2677 break;
2678 }
2679 }
2680 return static_cast<int>(frm_nxt - frm);
2681}
2682
2683static
2684codecvt_base::result
2685ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2686 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2687 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2688{
2689 frm_nxt = frm;
2690 to_nxt = to;
2691 if (mode & generate_header)
2692 {
2693 if (to_end-to_nxt < 2)
2694 return codecvt_base::partial;
2695 *to_nxt++ = static_cast<uint8_t>(0xFE);
2696 *to_nxt++ = static_cast<uint8_t>(0xFF);
2697 }
2698 for (; frm_nxt < frm_end; ++frm_nxt)
2699 {
2700 uint32_t wc = *frm_nxt;
2701 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2702 return codecvt_base::error;
2703 if (wc < 0x010000)
2704 {
2705 if (to_end-to_nxt < 2)
2706 return codecvt_base::partial;
2707 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2708 *to_nxt++ = static_cast<uint8_t>(wc);
2709 }
2710 else
2711 {
2712 if (to_end-to_nxt < 4)
2713 return codecvt_base::partial;
2714 uint16_t t = static_cast<uint16_t>(
2715 0xD800
2716 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2717 | ((wc & 0x00FC00) >> 10));
2718 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2719 *to_nxt++ = static_cast<uint8_t>(t);
2720 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2721 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2722 *to_nxt++ = static_cast<uint8_t>(t);
2723 }
2724 }
2725 return codecvt_base::ok;
2726}
2727
2728static
2729codecvt_base::result
2730utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2731 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2732 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2733{
2734 frm_nxt = frm;
2735 to_nxt = to;
2736 if (mode & consume_header)
2737 {
2738 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2739 frm_nxt += 2;
2740 }
2741 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2742 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002743 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002744 if ((c1 & 0xFC00) == 0xDC00)
2745 return codecvt_base::error;
2746 if ((c1 & 0xFC00) != 0xD800)
2747 {
2748 if (c1 > Maxcode)
2749 return codecvt_base::error;
2750 *to_nxt = static_cast<uint32_t>(c1);
2751 frm_nxt += 2;
2752 }
2753 else
2754 {
2755 if (frm_end-frm_nxt < 4)
2756 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002757 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002758 if ((c2 & 0xFC00) != 0xDC00)
2759 return codecvt_base::error;
2760 uint32_t t = static_cast<uint32_t>(
2761 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2762 | ((c1 & 0x003F) << 10)
2763 | (c2 & 0x03FF));
2764 if (t > Maxcode)
2765 return codecvt_base::error;
2766 *to_nxt = t;
2767 frm_nxt += 4;
2768 }
2769 }
2770 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2771}
2772
2773static
2774int
2775utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2776 size_t mx, unsigned long Maxcode = 0x10FFFF,
2777 codecvt_mode mode = codecvt_mode(0))
2778{
2779 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002780 if (mode & consume_header)
2781 {
2782 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2783 frm_nxt += 2;
2784 }
2785 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2786 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002787 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002788 if ((c1 & 0xFC00) == 0xDC00)
2789 break;
2790 if ((c1 & 0xFC00) != 0xD800)
2791 {
2792 if (c1 > Maxcode)
2793 break;
2794 frm_nxt += 2;
2795 }
2796 else
2797 {
2798 if (frm_end-frm_nxt < 4)
2799 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002800 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002801 if ((c2 & 0xFC00) != 0xDC00)
2802 break;
2803 uint32_t t = static_cast<uint32_t>(
2804 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2805 | ((c1 & 0x003F) << 10)
2806 | (c2 & 0x03FF));
2807 if (t > Maxcode)
2808 break;
2809 frm_nxt += 4;
2810 }
2811 }
2812 return static_cast<int>(frm_nxt - frm);
2813}
2814
2815static
2816codecvt_base::result
2817ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2818 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2819 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2820{
2821 frm_nxt = frm;
2822 to_nxt = to;
2823 if (mode & generate_header)
2824 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002825 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002826 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002827 *to_nxt++ = static_cast<uint8_t>(0xFF);
2828 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002829 }
2830 for (; frm_nxt < frm_end; ++frm_nxt)
2831 {
2832 uint32_t wc = *frm_nxt;
2833 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2834 return codecvt_base::error;
2835 if (wc < 0x010000)
2836 {
2837 if (to_end-to_nxt < 2)
2838 return codecvt_base::partial;
2839 *to_nxt++ = static_cast<uint8_t>(wc);
2840 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2841 }
2842 else
2843 {
2844 if (to_end-to_nxt < 4)
2845 return codecvt_base::partial;
2846 uint16_t t = static_cast<uint16_t>(
2847 0xD800
2848 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2849 | ((wc & 0x00FC00) >> 10));
2850 *to_nxt++ = static_cast<uint8_t>(t);
2851 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2852 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2853 *to_nxt++ = static_cast<uint8_t>(t);
2854 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2855 }
2856 }
2857 return codecvt_base::ok;
2858}
2859
2860static
2861codecvt_base::result
2862utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2863 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2864 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2865{
2866 frm_nxt = frm;
2867 to_nxt = to;
2868 if (mode & consume_header)
2869 {
2870 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2871 frm_nxt += 2;
2872 }
2873 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2874 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002875 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002876 if ((c1 & 0xFC00) == 0xDC00)
2877 return codecvt_base::error;
2878 if ((c1 & 0xFC00) != 0xD800)
2879 {
2880 if (c1 > Maxcode)
2881 return codecvt_base::error;
2882 *to_nxt = static_cast<uint32_t>(c1);
2883 frm_nxt += 2;
2884 }
2885 else
2886 {
2887 if (frm_end-frm_nxt < 4)
2888 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002889 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002890 if ((c2 & 0xFC00) != 0xDC00)
2891 return codecvt_base::error;
2892 uint32_t t = static_cast<uint32_t>(
2893 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2894 | ((c1 & 0x003F) << 10)
2895 | (c2 & 0x03FF));
2896 if (t > Maxcode)
2897 return codecvt_base::error;
2898 *to_nxt = t;
2899 frm_nxt += 4;
2900 }
2901 }
2902 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2903}
2904
2905static
2906int
2907utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2908 size_t mx, unsigned long Maxcode = 0x10FFFF,
2909 codecvt_mode mode = codecvt_mode(0))
2910{
2911 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002912 if (mode & consume_header)
2913 {
2914 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2915 frm_nxt += 2;
2916 }
2917 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2918 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002919 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002920 if ((c1 & 0xFC00) == 0xDC00)
2921 break;
2922 if ((c1 & 0xFC00) != 0xD800)
2923 {
2924 if (c1 > Maxcode)
2925 break;
2926 frm_nxt += 2;
2927 }
2928 else
2929 {
2930 if (frm_end-frm_nxt < 4)
2931 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002932 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002933 if ((c2 & 0xFC00) != 0xDC00)
2934 break;
2935 uint32_t t = static_cast<uint32_t>(
2936 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2937 | ((c1 & 0x003F) << 10)
2938 | (c2 & 0x03FF));
2939 if (t > Maxcode)
2940 break;
2941 frm_nxt += 4;
2942 }
2943 }
2944 return static_cast<int>(frm_nxt - frm);
2945}
2946
2947static
2948codecvt_base::result
2949ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2950 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2951 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2952{
2953 frm_nxt = frm;
2954 to_nxt = to;
2955 if (mode & generate_header)
2956 {
2957 if (to_end-to_nxt < 2)
2958 return codecvt_base::partial;
2959 *to_nxt++ = static_cast<uint8_t>(0xFE);
2960 *to_nxt++ = static_cast<uint8_t>(0xFF);
2961 }
2962 for (; frm_nxt < frm_end; ++frm_nxt)
2963 {
2964 uint16_t wc = *frm_nxt;
2965 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2966 return codecvt_base::error;
2967 if (to_end-to_nxt < 2)
2968 return codecvt_base::partial;
2969 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2970 *to_nxt++ = static_cast<uint8_t>(wc);
2971 }
2972 return codecvt_base::ok;
2973}
2974
2975static
2976codecvt_base::result
2977utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2978 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2979 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2980{
2981 frm_nxt = frm;
2982 to_nxt = to;
2983 if (mode & consume_header)
2984 {
2985 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2986 frm_nxt += 2;
2987 }
2988 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2989 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002990 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002991 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2992 return codecvt_base::error;
2993 *to_nxt = c1;
2994 frm_nxt += 2;
2995 }
2996 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2997}
2998
2999static
3000int
3001utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3002 size_t mx, unsigned long Maxcode = 0x10FFFF,
3003 codecvt_mode mode = codecvt_mode(0))
3004{
3005 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003006 if (mode & consume_header)
3007 {
3008 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3009 frm_nxt += 2;
3010 }
3011 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3012 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003013 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003014 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3015 break;
3016 frm_nxt += 2;
3017 }
3018 return static_cast<int>(frm_nxt - frm);
3019}
3020
3021static
3022codecvt_base::result
3023ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3024 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3025 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3026{
3027 frm_nxt = frm;
3028 to_nxt = to;
3029 if (mode & generate_header)
3030 {
3031 if (to_end-to_nxt < 2)
3032 return codecvt_base::partial;
3033 *to_nxt++ = static_cast<uint8_t>(0xFF);
3034 *to_nxt++ = static_cast<uint8_t>(0xFE);
3035 }
3036 for (; frm_nxt < frm_end; ++frm_nxt)
3037 {
3038 uint16_t wc = *frm_nxt;
3039 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3040 return codecvt_base::error;
3041 if (to_end-to_nxt < 2)
3042 return codecvt_base::partial;
3043 *to_nxt++ = static_cast<uint8_t>(wc);
3044 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3045 }
3046 return codecvt_base::ok;
3047}
3048
3049static
3050codecvt_base::result
3051utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3052 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3053 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3054{
3055 frm_nxt = frm;
3056 to_nxt = to;
3057 if (mode & consume_header)
3058 {
3059 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3060 frm_nxt += 2;
3061 }
3062 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3063 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003064 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003065 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3066 return codecvt_base::error;
3067 *to_nxt = c1;
3068 frm_nxt += 2;
3069 }
3070 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3071}
3072
3073static
3074int
3075utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3076 size_t mx, unsigned long Maxcode = 0x10FFFF,
3077 codecvt_mode mode = codecvt_mode(0))
3078{
3079 const uint8_t* frm_nxt = frm;
3080 frm_nxt = frm;
3081 if (mode & consume_header)
3082 {
3083 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3084 frm_nxt += 2;
3085 }
3086 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3087 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003088 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003089 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3090 break;
3091 frm_nxt += 2;
3092 }
3093 return static_cast<int>(frm_nxt - frm);
3094}
3095
Howard Hinnantc51e1022010-05-11 19:42:16 +00003096// template <> class codecvt<char16_t, char, mbstate_t>
3097
Howard Hinnantffb308e2010-08-22 00:03:27 +00003098locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003099
3100codecvt<char16_t, char, mbstate_t>::~codecvt()
3101{
3102}
3103
3104codecvt<char16_t, char, mbstate_t>::result
3105codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003106 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003107 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3108{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003109 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3110 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3111 const uint16_t* _frm_nxt = _frm;
3112 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3113 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3114 uint8_t* _to_nxt = _to;
3115 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3116 frm_nxt = frm + (_frm_nxt - _frm);
3117 to_nxt = to + (_to_nxt - _to);
3118 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003119}
3120
3121codecvt<char16_t, char, mbstate_t>::result
3122codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003123 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003124 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3125{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003126 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3127 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3128 const uint8_t* _frm_nxt = _frm;
3129 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3130 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3131 uint16_t* _to_nxt = _to;
3132 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3133 frm_nxt = frm + (_frm_nxt - _frm);
3134 to_nxt = to + (_to_nxt - _to);
3135 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003136}
3137
3138codecvt<char16_t, char, mbstate_t>::result
3139codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3140 extern_type* to, extern_type*, extern_type*& to_nxt) const
3141{
3142 to_nxt = to;
3143 return noconv;
3144}
3145
3146int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003147codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003148{
3149 return 0;
3150}
3151
3152bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003153codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003154{
3155 return false;
3156}
3157
3158int
3159codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3160 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3161{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003162 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3163 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3164 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003165}
3166
3167int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003168codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003169{
3170 return 4;
3171}
3172
3173// template <> class codecvt<char32_t, char, mbstate_t>
3174
Howard Hinnantffb308e2010-08-22 00:03:27 +00003175locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003176
3177codecvt<char32_t, char, mbstate_t>::~codecvt()
3178{
3179}
3180
3181codecvt<char32_t, char, mbstate_t>::result
3182codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003183 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003184 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3185{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003186 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3187 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3188 const uint32_t* _frm_nxt = _frm;
3189 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3190 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3191 uint8_t* _to_nxt = _to;
3192 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3193 frm_nxt = frm + (_frm_nxt - _frm);
3194 to_nxt = to + (_to_nxt - _to);
3195 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003196}
3197
3198codecvt<char32_t, char, mbstate_t>::result
3199codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003200 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003201 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3202{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003203 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3204 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3205 const uint8_t* _frm_nxt = _frm;
3206 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3207 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3208 uint32_t* _to_nxt = _to;
3209 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3210 frm_nxt = frm + (_frm_nxt - _frm);
3211 to_nxt = to + (_to_nxt - _to);
3212 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003213}
3214
3215codecvt<char32_t, char, mbstate_t>::result
3216codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3217 extern_type* to, extern_type*, extern_type*& to_nxt) const
3218{
3219 to_nxt = to;
3220 return noconv;
3221}
3222
3223int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003224codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003225{
3226 return 0;
3227}
3228
3229bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003230codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003231{
3232 return false;
3233}
3234
3235int
3236codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3237 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3238{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003239 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3240 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3241 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003242}
3243
3244int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003245codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003246{
3247 return 4;
3248}
3249
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003250// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003251
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003252__codecvt_utf8<wchar_t>::result
3253__codecvt_utf8<wchar_t>::do_out(state_type&,
3254 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003255 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3256{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003257#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003258 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3259 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3260 const uint16_t* _frm_nxt = _frm;
3261#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003262 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3263 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3264 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003265#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003266 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3267 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3268 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003269#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003270 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3271 _Maxcode_, _Mode_);
3272#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003273 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3274 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003275#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003276 frm_nxt = frm + (_frm_nxt - _frm);
3277 to_nxt = to + (_to_nxt - _to);
3278 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003279}
3280
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003281__codecvt_utf8<wchar_t>::result
3282__codecvt_utf8<wchar_t>::do_in(state_type&,
3283 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003284 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3285{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003286 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3287 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3288 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003289#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003290 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3291 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3292 uint16_t* _to_nxt = _to;
3293 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3294 _Maxcode_, _Mode_);
3295#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003296 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3297 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3298 uint32_t* _to_nxt = _to;
3299 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3300 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003301#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003302 frm_nxt = frm + (_frm_nxt - _frm);
3303 to_nxt = to + (_to_nxt - _to);
3304 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003305}
3306
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003307__codecvt_utf8<wchar_t>::result
3308__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003309 extern_type* to, extern_type*, extern_type*& to_nxt) const
3310{
3311 to_nxt = to;
3312 return noconv;
3313}
3314
3315int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003316__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003317{
3318 return 0;
3319}
3320
3321bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003322__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003323{
3324 return false;
3325}
3326
3327int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003328__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003329 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3330{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003331 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3332 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3333 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003334}
3335
3336int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003337__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003338{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003339 if (_Mode_ & consume_header)
3340 return 7;
3341 return 4;
3342}
3343
3344// __codecvt_utf8<char16_t>
3345
3346__codecvt_utf8<char16_t>::result
3347__codecvt_utf8<char16_t>::do_out(state_type&,
3348 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3349 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3350{
3351 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3352 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3353 const uint16_t* _frm_nxt = _frm;
3354 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3355 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3356 uint8_t* _to_nxt = _to;
3357 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3358 _Maxcode_, _Mode_);
3359 frm_nxt = frm + (_frm_nxt - _frm);
3360 to_nxt = to + (_to_nxt - _to);
3361 return r;
3362}
3363
3364__codecvt_utf8<char16_t>::result
3365__codecvt_utf8<char16_t>::do_in(state_type&,
3366 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3367 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3368{
3369 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3370 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3371 const uint8_t* _frm_nxt = _frm;
3372 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3373 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3374 uint16_t* _to_nxt = _to;
3375 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3376 _Maxcode_, _Mode_);
3377 frm_nxt = frm + (_frm_nxt - _frm);
3378 to_nxt = to + (_to_nxt - _to);
3379 return r;
3380}
3381
3382__codecvt_utf8<char16_t>::result
3383__codecvt_utf8<char16_t>::do_unshift(state_type&,
3384 extern_type* to, extern_type*, extern_type*& to_nxt) const
3385{
3386 to_nxt = to;
3387 return noconv;
3388}
3389
3390int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003391__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003392{
3393 return 0;
3394}
3395
3396bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003397__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003398{
3399 return false;
3400}
3401
3402int
3403__codecvt_utf8<char16_t>::do_length(state_type&,
3404 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3405{
3406 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3407 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3408 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3409}
3410
3411int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003412__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003413{
3414 if (_Mode_ & consume_header)
3415 return 6;
3416 return 3;
3417}
3418
3419// __codecvt_utf8<char32_t>
3420
3421__codecvt_utf8<char32_t>::result
3422__codecvt_utf8<char32_t>::do_out(state_type&,
3423 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3424 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3425{
3426 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3427 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3428 const uint32_t* _frm_nxt = _frm;
3429 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3430 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3431 uint8_t* _to_nxt = _to;
3432 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3433 _Maxcode_, _Mode_);
3434 frm_nxt = frm + (_frm_nxt - _frm);
3435 to_nxt = to + (_to_nxt - _to);
3436 return r;
3437}
3438
3439__codecvt_utf8<char32_t>::result
3440__codecvt_utf8<char32_t>::do_in(state_type&,
3441 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3442 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3443{
3444 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3445 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3446 const uint8_t* _frm_nxt = _frm;
3447 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3448 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3449 uint32_t* _to_nxt = _to;
3450 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3451 _Maxcode_, _Mode_);
3452 frm_nxt = frm + (_frm_nxt - _frm);
3453 to_nxt = to + (_to_nxt - _to);
3454 return r;
3455}
3456
3457__codecvt_utf8<char32_t>::result
3458__codecvt_utf8<char32_t>::do_unshift(state_type&,
3459 extern_type* to, extern_type*, extern_type*& to_nxt) const
3460{
3461 to_nxt = to;
3462 return noconv;
3463}
3464
3465int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003466__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003467{
3468 return 0;
3469}
3470
3471bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003472__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003473{
3474 return false;
3475}
3476
3477int
3478__codecvt_utf8<char32_t>::do_length(state_type&,
3479 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3480{
3481 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3482 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3483 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3484}
3485
3486int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003487__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003488{
3489 if (_Mode_ & consume_header)
3490 return 7;
3491 return 4;
3492}
3493
3494// __codecvt_utf16<wchar_t, false>
3495
3496__codecvt_utf16<wchar_t, false>::result
3497__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3498 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3499 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3500{
3501 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3502 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3503 const uint32_t* _frm_nxt = _frm;
3504 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3505 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3506 uint8_t* _to_nxt = _to;
3507 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3508 _Maxcode_, _Mode_);
3509 frm_nxt = frm + (_frm_nxt - _frm);
3510 to_nxt = to + (_to_nxt - _to);
3511 return r;
3512}
3513
3514__codecvt_utf16<wchar_t, false>::result
3515__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3516 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3517 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3518{
3519 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3520 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3521 const uint8_t* _frm_nxt = _frm;
3522 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3523 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3524 uint32_t* _to_nxt = _to;
3525 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3526 _Maxcode_, _Mode_);
3527 frm_nxt = frm + (_frm_nxt - _frm);
3528 to_nxt = to + (_to_nxt - _to);
3529 return r;
3530}
3531
3532__codecvt_utf16<wchar_t, false>::result
3533__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3534 extern_type* to, extern_type*, extern_type*& to_nxt) const
3535{
3536 to_nxt = to;
3537 return noconv;
3538}
3539
3540int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003541__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003542{
3543 return 0;
3544}
3545
3546bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003547__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003548{
3549 return false;
3550}
3551
3552int
3553__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3554 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3555{
3556 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3557 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3558 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3559}
3560
3561int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003562__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003563{
3564 if (_Mode_ & consume_header)
3565 return 6;
3566 return 4;
3567}
3568
3569// __codecvt_utf16<wchar_t, true>
3570
3571__codecvt_utf16<wchar_t, true>::result
3572__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3573 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3574 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3575{
3576 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3577 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3578 const uint32_t* _frm_nxt = _frm;
3579 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3580 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3581 uint8_t* _to_nxt = _to;
3582 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3583 _Maxcode_, _Mode_);
3584 frm_nxt = frm + (_frm_nxt - _frm);
3585 to_nxt = to + (_to_nxt - _to);
3586 return r;
3587}
3588
3589__codecvt_utf16<wchar_t, true>::result
3590__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3591 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3592 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3593{
3594 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3595 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3596 const uint8_t* _frm_nxt = _frm;
3597 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3598 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3599 uint32_t* _to_nxt = _to;
3600 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3601 _Maxcode_, _Mode_);
3602 frm_nxt = frm + (_frm_nxt - _frm);
3603 to_nxt = to + (_to_nxt - _to);
3604 return r;
3605}
3606
3607__codecvt_utf16<wchar_t, true>::result
3608__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3609 extern_type* to, extern_type*, extern_type*& to_nxt) const
3610{
3611 to_nxt = to;
3612 return noconv;
3613}
3614
3615int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003616__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003617{
3618 return 0;
3619}
3620
3621bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003622__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003623{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003624 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003625}
3626
3627int
3628__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3629 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3630{
3631 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3632 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3633 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3634}
3635
3636int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003637__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003638{
3639 if (_Mode_ & consume_header)
3640 return 6;
3641 return 4;
3642}
3643
3644// __codecvt_utf16<char16_t, false>
3645
3646__codecvt_utf16<char16_t, false>::result
3647__codecvt_utf16<char16_t, false>::do_out(state_type&,
3648 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3649 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3650{
3651 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3652 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3653 const uint16_t* _frm_nxt = _frm;
3654 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3655 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3656 uint8_t* _to_nxt = _to;
3657 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3658 _Maxcode_, _Mode_);
3659 frm_nxt = frm + (_frm_nxt - _frm);
3660 to_nxt = to + (_to_nxt - _to);
3661 return r;
3662}
3663
3664__codecvt_utf16<char16_t, false>::result
3665__codecvt_utf16<char16_t, false>::do_in(state_type&,
3666 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3667 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3668{
3669 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3670 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3671 const uint8_t* _frm_nxt = _frm;
3672 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3673 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3674 uint16_t* _to_nxt = _to;
3675 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3676 _Maxcode_, _Mode_);
3677 frm_nxt = frm + (_frm_nxt - _frm);
3678 to_nxt = to + (_to_nxt - _to);
3679 return r;
3680}
3681
3682__codecvt_utf16<char16_t, false>::result
3683__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3684 extern_type* to, extern_type*, extern_type*& to_nxt) const
3685{
3686 to_nxt = to;
3687 return noconv;
3688}
3689
3690int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003691__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003692{
3693 return 0;
3694}
3695
3696bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003697__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003698{
3699 return false;
3700}
3701
3702int
3703__codecvt_utf16<char16_t, false>::do_length(state_type&,
3704 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3705{
3706 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3707 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3708 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3709}
3710
3711int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003712__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003713{
3714 if (_Mode_ & consume_header)
3715 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003716 return 2;
3717}
3718
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003719// __codecvt_utf16<char16_t, true>
3720
3721__codecvt_utf16<char16_t, true>::result
3722__codecvt_utf16<char16_t, true>::do_out(state_type&,
3723 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3724 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3725{
3726 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3727 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3728 const uint16_t* _frm_nxt = _frm;
3729 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3730 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3731 uint8_t* _to_nxt = _to;
3732 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3733 _Maxcode_, _Mode_);
3734 frm_nxt = frm + (_frm_nxt - _frm);
3735 to_nxt = to + (_to_nxt - _to);
3736 return r;
3737}
3738
3739__codecvt_utf16<char16_t, true>::result
3740__codecvt_utf16<char16_t, true>::do_in(state_type&,
3741 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3742 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3743{
3744 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3745 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3746 const uint8_t* _frm_nxt = _frm;
3747 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3748 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3749 uint16_t* _to_nxt = _to;
3750 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3751 _Maxcode_, _Mode_);
3752 frm_nxt = frm + (_frm_nxt - _frm);
3753 to_nxt = to + (_to_nxt - _to);
3754 return r;
3755}
3756
3757__codecvt_utf16<char16_t, true>::result
3758__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3759 extern_type* to, extern_type*, extern_type*& to_nxt) const
3760{
3761 to_nxt = to;
3762 return noconv;
3763}
3764
3765int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003766__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003767{
3768 return 0;
3769}
3770
3771bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003772__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003773{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003774 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003775}
3776
3777int
3778__codecvt_utf16<char16_t, true>::do_length(state_type&,
3779 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3780{
3781 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3782 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3783 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3784}
3785
3786int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003787__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003788{
3789 if (_Mode_ & consume_header)
3790 return 4;
3791 return 2;
3792}
3793
3794// __codecvt_utf16<char32_t, false>
3795
3796__codecvt_utf16<char32_t, false>::result
3797__codecvt_utf16<char32_t, false>::do_out(state_type&,
3798 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3799 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3800{
3801 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3802 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3803 const uint32_t* _frm_nxt = _frm;
3804 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3805 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3806 uint8_t* _to_nxt = _to;
3807 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3808 _Maxcode_, _Mode_);
3809 frm_nxt = frm + (_frm_nxt - _frm);
3810 to_nxt = to + (_to_nxt - _to);
3811 return r;
3812}
3813
3814__codecvt_utf16<char32_t, false>::result
3815__codecvt_utf16<char32_t, false>::do_in(state_type&,
3816 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3817 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3818{
3819 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3820 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3821 const uint8_t* _frm_nxt = _frm;
3822 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3823 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3824 uint32_t* _to_nxt = _to;
3825 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3826 _Maxcode_, _Mode_);
3827 frm_nxt = frm + (_frm_nxt - _frm);
3828 to_nxt = to + (_to_nxt - _to);
3829 return r;
3830}
3831
3832__codecvt_utf16<char32_t, false>::result
3833__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3834 extern_type* to, extern_type*, extern_type*& to_nxt) const
3835{
3836 to_nxt = to;
3837 return noconv;
3838}
3839
3840int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003841__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003842{
3843 return 0;
3844}
3845
3846bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003847__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003848{
3849 return false;
3850}
3851
3852int
3853__codecvt_utf16<char32_t, false>::do_length(state_type&,
3854 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3855{
3856 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3857 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3858 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3859}
3860
3861int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003862__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003863{
3864 if (_Mode_ & consume_header)
3865 return 6;
3866 return 4;
3867}
3868
3869// __codecvt_utf16<char32_t, true>
3870
3871__codecvt_utf16<char32_t, true>::result
3872__codecvt_utf16<char32_t, true>::do_out(state_type&,
3873 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3874 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3875{
3876 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3877 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3878 const uint32_t* _frm_nxt = _frm;
3879 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3880 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3881 uint8_t* _to_nxt = _to;
3882 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3883 _Maxcode_, _Mode_);
3884 frm_nxt = frm + (_frm_nxt - _frm);
3885 to_nxt = to + (_to_nxt - _to);
3886 return r;
3887}
3888
3889__codecvt_utf16<char32_t, true>::result
3890__codecvt_utf16<char32_t, true>::do_in(state_type&,
3891 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3892 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3893{
3894 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3895 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3896 const uint8_t* _frm_nxt = _frm;
3897 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3898 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3899 uint32_t* _to_nxt = _to;
3900 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3901 _Maxcode_, _Mode_);
3902 frm_nxt = frm + (_frm_nxt - _frm);
3903 to_nxt = to + (_to_nxt - _to);
3904 return r;
3905}
3906
3907__codecvt_utf16<char32_t, true>::result
3908__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3909 extern_type* to, extern_type*, extern_type*& to_nxt) const
3910{
3911 to_nxt = to;
3912 return noconv;
3913}
3914
3915int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003916__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003917{
3918 return 0;
3919}
3920
3921bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003922__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003923{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003924 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003925}
3926
3927int
3928__codecvt_utf16<char32_t, true>::do_length(state_type&,
3929 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3930{
3931 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3932 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3933 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3934}
3935
3936int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003937__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003938{
3939 if (_Mode_ & consume_header)
3940 return 6;
3941 return 4;
3942}
3943
3944// __codecvt_utf8_utf16<wchar_t>
3945
3946__codecvt_utf8_utf16<wchar_t>::result
3947__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3948 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3949 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3950{
3951 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3952 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3953 const uint32_t* _frm_nxt = _frm;
3954 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3955 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3956 uint8_t* _to_nxt = _to;
3957 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3958 _Maxcode_, _Mode_);
3959 frm_nxt = frm + (_frm_nxt - _frm);
3960 to_nxt = to + (_to_nxt - _to);
3961 return r;
3962}
3963
3964__codecvt_utf8_utf16<wchar_t>::result
3965__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3966 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3967 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3968{
3969 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3970 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3971 const uint8_t* _frm_nxt = _frm;
3972 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3973 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3974 uint32_t* _to_nxt = _to;
3975 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3976 _Maxcode_, _Mode_);
3977 frm_nxt = frm + (_frm_nxt - _frm);
3978 to_nxt = to + (_to_nxt - _to);
3979 return r;
3980}
3981
3982__codecvt_utf8_utf16<wchar_t>::result
3983__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3984 extern_type* to, extern_type*, extern_type*& to_nxt) const
3985{
3986 to_nxt = to;
3987 return noconv;
3988}
3989
3990int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003991__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003992{
3993 return 0;
3994}
3995
3996bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003997__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003998{
3999 return false;
4000}
4001
4002int
4003__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4004 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4005{
4006 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4007 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4008 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4009}
4010
4011int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004012__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004013{
4014 if (_Mode_ & consume_header)
4015 return 7;
4016 return 4;
4017}
4018
4019// __codecvt_utf8_utf16<char16_t>
4020
4021__codecvt_utf8_utf16<char16_t>::result
4022__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4023 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4024 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4025{
4026 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4027 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4028 const uint16_t* _frm_nxt = _frm;
4029 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4030 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4031 uint8_t* _to_nxt = _to;
4032 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4033 _Maxcode_, _Mode_);
4034 frm_nxt = frm + (_frm_nxt - _frm);
4035 to_nxt = to + (_to_nxt - _to);
4036 return r;
4037}
4038
4039__codecvt_utf8_utf16<char16_t>::result
4040__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4041 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4042 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4043{
4044 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4045 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4046 const uint8_t* _frm_nxt = _frm;
4047 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4048 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4049 uint16_t* _to_nxt = _to;
4050 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4051 _Maxcode_, _Mode_);
4052 frm_nxt = frm + (_frm_nxt - _frm);
4053 to_nxt = to + (_to_nxt - _to);
4054 return r;
4055}
4056
4057__codecvt_utf8_utf16<char16_t>::result
4058__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4059 extern_type* to, extern_type*, extern_type*& to_nxt) const
4060{
4061 to_nxt = to;
4062 return noconv;
4063}
4064
4065int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004066__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004067{
4068 return 0;
4069}
4070
4071bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004072__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004073{
4074 return false;
4075}
4076
4077int
4078__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4079 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4080{
4081 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4082 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4083 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4084}
4085
4086int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004087__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004088{
4089 if (_Mode_ & consume_header)
4090 return 7;
4091 return 4;
4092}
4093
4094// __codecvt_utf8_utf16<char32_t>
4095
4096__codecvt_utf8_utf16<char32_t>::result
4097__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4098 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4099 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4100{
4101 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4102 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4103 const uint32_t* _frm_nxt = _frm;
4104 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4105 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4106 uint8_t* _to_nxt = _to;
4107 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4108 _Maxcode_, _Mode_);
4109 frm_nxt = frm + (_frm_nxt - _frm);
4110 to_nxt = to + (_to_nxt - _to);
4111 return r;
4112}
4113
4114__codecvt_utf8_utf16<char32_t>::result
4115__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4116 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4117 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4118{
4119 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4120 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4121 const uint8_t* _frm_nxt = _frm;
4122 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4123 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4124 uint32_t* _to_nxt = _to;
4125 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4126 _Maxcode_, _Mode_);
4127 frm_nxt = frm + (_frm_nxt - _frm);
4128 to_nxt = to + (_to_nxt - _to);
4129 return r;
4130}
4131
4132__codecvt_utf8_utf16<char32_t>::result
4133__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4134 extern_type* to, extern_type*, extern_type*& to_nxt) const
4135{
4136 to_nxt = to;
4137 return noconv;
4138}
4139
4140int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004141__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004142{
4143 return 0;
4144}
4145
4146bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004147__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004148{
4149 return false;
4150}
4151
4152int
4153__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4154 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4155{
4156 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4157 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4158 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4159}
4160
4161int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004162__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004163{
4164 if (_Mode_ & consume_header)
4165 return 7;
4166 return 4;
4167}
4168
Howard Hinnantc51e1022010-05-11 19:42:16 +00004169// __narrow_to_utf8<16>
4170
4171__narrow_to_utf8<16>::~__narrow_to_utf8()
4172{
4173}
4174
4175// __narrow_to_utf8<32>
4176
4177__narrow_to_utf8<32>::~__narrow_to_utf8()
4178{
4179}
4180
4181// __widen_from_utf8<16>
4182
4183__widen_from_utf8<16>::~__widen_from_utf8()
4184{
4185}
4186
4187// __widen_from_utf8<32>
4188
4189__widen_from_utf8<32>::~__widen_from_utf8()
4190{
4191}
4192
Eric Fiselierbf945a22016-12-11 00:20:59 +00004193
4194static bool checked_string_to_wchar_convert(wchar_t& dest,
4195 const char* ptr,
4196 __locale_struct* loc) {
4197 if (*ptr == '\0')
4198 return false;
4199 mbstate_t mb = {};
4200 wchar_t out;
4201 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4202 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4203 return false;
4204 }
4205 dest = out;
4206 return true;
4207}
4208
4209static bool checked_string_to_char_convert(char& dest,
4210 const char* ptr,
4211 __locale_struct* __loc) {
4212 if (*ptr == '\0')
4213 return false;
4214 if (!ptr[1]) {
4215 dest = *ptr;
4216 return true;
4217 }
4218 // First convert the MBS into a wide char then attempt to narrow it using
4219 // wctob_l.
4220 wchar_t wout;
4221 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4222 return false;
4223 int res;
4224 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4225 dest = res;
4226 return true;
4227 }
4228 // FIXME: Work around specific multibyte sequences that we can reasonable
4229 // translate into a different single byte.
4230 switch (wout) {
4231 case L'\u00A0': // non-breaking space
4232 dest = ' ';
4233 return true;
4234 default:
4235 return false;
4236 }
4237 _LIBCPP_UNREACHABLE();
4238}
4239
4240
Howard Hinnantc51e1022010-05-11 19:42:16 +00004241// numpunct<char> && numpunct<wchar_t>
4242
4243locale::id numpunct< char >::id;
4244locale::id numpunct<wchar_t>::id;
4245
4246numpunct<char>::numpunct(size_t refs)
4247 : locale::facet(refs),
4248 __decimal_point_('.'),
4249 __thousands_sep_(',')
4250{
4251}
4252
4253numpunct<wchar_t>::numpunct(size_t refs)
4254 : locale::facet(refs),
4255 __decimal_point_(L'.'),
4256 __thousands_sep_(L',')
4257{
4258}
4259
4260numpunct<char>::~numpunct()
4261{
4262}
4263
4264numpunct<wchar_t>::~numpunct()
4265{
4266}
4267
4268 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4269wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4270
4271 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4272wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4273
4274string numpunct< char >::do_grouping() const {return __grouping_;}
4275string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4276
4277 string numpunct< char >::do_truename() const {return "true";}
4278wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4279
4280 string numpunct< char >::do_falsename() const {return "false";}
4281wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4282
4283// numpunct_byname<char>
4284
4285numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4286 : numpunct<char>(refs)
4287{
4288 __init(nm);
4289}
4290
4291numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4292 : numpunct<char>(refs)
4293{
4294 __init(nm.c_str());
4295}
4296
4297numpunct_byname<char>::~numpunct_byname()
4298{
4299}
4300
4301void
4302numpunct_byname<char>::__init(const char* nm)
4303{
4304 if (strcmp(nm, "C") != 0)
4305 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004306 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004307 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00004308 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004309 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004310
Ben Craig3756b922016-03-09 15:39:39 +00004311 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004312 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4313 loc.get());
4314 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4315 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004316 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004317 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004318 }
4319}
4320
4321// numpunct_byname<wchar_t>
4322
4323numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4324 : numpunct<wchar_t>(refs)
4325{
4326 __init(nm);
4327}
4328
4329numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4330 : numpunct<wchar_t>(refs)
4331{
4332 __init(nm.c_str());
4333}
4334
4335numpunct_byname<wchar_t>::~numpunct_byname()
4336{
4337}
4338
4339void
4340numpunct_byname<wchar_t>::__init(const char* nm)
4341{
4342 if (strcmp(nm, "C") != 0)
4343 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004344 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004345 if (loc == nullptr)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004346 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004347 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004348
Ben Craig3756b922016-03-09 15:39:39 +00004349 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004350 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4351 loc.get());
4352 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4353 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004354 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004355 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004356 }
4357}
4358
4359// num_get helpers
4360
4361int
4362__num_get_base::__get_base(ios_base& iob)
4363{
4364 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4365 if (__basefield == ios_base::oct)
4366 return 8;
4367 else if (__basefield == ios_base::hex)
4368 return 16;
4369 else if (__basefield == 0)
4370 return 0;
4371 return 10;
4372}
4373
4374const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4375
4376void
4377__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4378 ios_base::iostate& __err)
4379{
4380 if (__grouping.size() != 0)
4381 {
4382 reverse(__g, __g_end);
4383 const char* __ig = __grouping.data();
4384 const char* __eg = __ig + __grouping.size();
4385 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4386 {
4387 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4388 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004389 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004390 {
4391 __err = ios_base::failbit;
4392 return;
4393 }
4394 }
4395 if (__eg - __ig > 1)
4396 ++__ig;
4397 }
4398 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4399 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004400 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004401 __err = ios_base::failbit;
4402 }
4403 }
4404}
4405
4406void
4407__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4408 ios_base::fmtflags __flags)
4409{
4410 if (__flags & ios_base::showpos)
4411 *__fmtp++ = '+';
4412 if (__flags & ios_base::showbase)
4413 *__fmtp++ = '#';
4414 while(*__len)
4415 *__fmtp++ = *__len++;
4416 if ((__flags & ios_base::basefield) == ios_base::oct)
4417 *__fmtp = 'o';
4418 else if ((__flags & ios_base::basefield) == ios_base::hex)
4419 {
4420 if (__flags & ios_base::uppercase)
4421 *__fmtp = 'X';
4422 else
4423 *__fmtp = 'x';
4424 }
4425 else if (__signd)
4426 *__fmtp = 'd';
4427 else
4428 *__fmtp = 'u';
4429}
4430
4431bool
4432__num_put_base::__format_float(char* __fmtp, const char* __len,
4433 ios_base::fmtflags __flags)
4434{
4435 bool specify_precision = true;
4436 if (__flags & ios_base::showpos)
4437 *__fmtp++ = '+';
4438 if (__flags & ios_base::showpoint)
4439 *__fmtp++ = '#';
4440 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004441 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004442 if (floatfield == (ios_base::fixed | ios_base::scientific))
4443 specify_precision = false;
4444 else
4445 {
4446 *__fmtp++ = '.';
4447 *__fmtp++ = '*';
4448 }
4449 while(*__len)
4450 *__fmtp++ = *__len++;
4451 if (floatfield == ios_base::fixed)
4452 {
4453 if (uppercase)
4454 *__fmtp = 'F';
4455 else
4456 *__fmtp = 'f';
4457 }
4458 else if (floatfield == ios_base::scientific)
4459 {
4460 if (uppercase)
4461 *__fmtp = 'E';
4462 else
4463 *__fmtp = 'e';
4464 }
4465 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4466 {
4467 if (uppercase)
4468 *__fmtp = 'A';
4469 else
4470 *__fmtp = 'a';
4471 }
4472 else
4473 {
4474 if (uppercase)
4475 *__fmtp = 'G';
4476 else
4477 *__fmtp = 'g';
4478 }
4479 return specify_precision;
4480}
4481
4482char*
4483__num_put_base::__identify_padding(char* __nb, char* __ne,
4484 const ios_base& __iob)
4485{
4486 switch (__iob.flags() & ios_base::adjustfield)
4487 {
4488 case ios_base::internal:
4489 if (__nb[0] == '-' || __nb[0] == '+')
4490 return __nb+1;
4491 if (__ne - __nb >= 2 && __nb[0] == '0'
4492 && (__nb[1] == 'x' || __nb[1] == 'X'))
4493 return __nb+2;
4494 break;
4495 case ios_base::left:
4496 return __ne;
4497 case ios_base::right:
4498 default:
4499 break;
4500 }
4501 return __nb;
4502}
4503
4504// time_get
4505
4506static
4507string*
4508init_weeks()
4509{
4510 static string weeks[14];
4511 weeks[0] = "Sunday";
4512 weeks[1] = "Monday";
4513 weeks[2] = "Tuesday";
4514 weeks[3] = "Wednesday";
4515 weeks[4] = "Thursday";
4516 weeks[5] = "Friday";
4517 weeks[6] = "Saturday";
4518 weeks[7] = "Sun";
4519 weeks[8] = "Mon";
4520 weeks[9] = "Tue";
4521 weeks[10] = "Wed";
4522 weeks[11] = "Thu";
4523 weeks[12] = "Fri";
4524 weeks[13] = "Sat";
4525 return weeks;
4526}
4527
4528static
4529wstring*
4530init_wweeks()
4531{
4532 static wstring weeks[14];
4533 weeks[0] = L"Sunday";
4534 weeks[1] = L"Monday";
4535 weeks[2] = L"Tuesday";
4536 weeks[3] = L"Wednesday";
4537 weeks[4] = L"Thursday";
4538 weeks[5] = L"Friday";
4539 weeks[6] = L"Saturday";
4540 weeks[7] = L"Sun";
4541 weeks[8] = L"Mon";
4542 weeks[9] = L"Tue";
4543 weeks[10] = L"Wed";
4544 weeks[11] = L"Thu";
4545 weeks[12] = L"Fri";
4546 weeks[13] = L"Sat";
4547 return weeks;
4548}
4549
4550template <>
4551const string*
4552__time_get_c_storage<char>::__weeks() const
4553{
4554 static const string* weeks = init_weeks();
4555 return weeks;
4556}
4557
4558template <>
4559const wstring*
4560__time_get_c_storage<wchar_t>::__weeks() const
4561{
4562 static const wstring* weeks = init_wweeks();
4563 return weeks;
4564}
4565
4566static
4567string*
4568init_months()
4569{
4570 static string months[24];
4571 months[0] = "January";
4572 months[1] = "February";
4573 months[2] = "March";
4574 months[3] = "April";
4575 months[4] = "May";
4576 months[5] = "June";
4577 months[6] = "July";
4578 months[7] = "August";
4579 months[8] = "September";
4580 months[9] = "October";
4581 months[10] = "November";
4582 months[11] = "December";
4583 months[12] = "Jan";
4584 months[13] = "Feb";
4585 months[14] = "Mar";
4586 months[15] = "Apr";
4587 months[16] = "May";
4588 months[17] = "Jun";
4589 months[18] = "Jul";
4590 months[19] = "Aug";
4591 months[20] = "Sep";
4592 months[21] = "Oct";
4593 months[22] = "Nov";
4594 months[23] = "Dec";
4595 return months;
4596}
4597
4598static
4599wstring*
4600init_wmonths()
4601{
4602 static wstring months[24];
4603 months[0] = L"January";
4604 months[1] = L"February";
4605 months[2] = L"March";
4606 months[3] = L"April";
4607 months[4] = L"May";
4608 months[5] = L"June";
4609 months[6] = L"July";
4610 months[7] = L"August";
4611 months[8] = L"September";
4612 months[9] = L"October";
4613 months[10] = L"November";
4614 months[11] = L"December";
4615 months[12] = L"Jan";
4616 months[13] = L"Feb";
4617 months[14] = L"Mar";
4618 months[15] = L"Apr";
4619 months[16] = L"May";
4620 months[17] = L"Jun";
4621 months[18] = L"Jul";
4622 months[19] = L"Aug";
4623 months[20] = L"Sep";
4624 months[21] = L"Oct";
4625 months[22] = L"Nov";
4626 months[23] = L"Dec";
4627 return months;
4628}
4629
4630template <>
4631const string*
4632__time_get_c_storage<char>::__months() const
4633{
4634 static const string* months = init_months();
4635 return months;
4636}
4637
4638template <>
4639const wstring*
4640__time_get_c_storage<wchar_t>::__months() const
4641{
4642 static const wstring* months = init_wmonths();
4643 return months;
4644}
4645
4646static
4647string*
4648init_am_pm()
4649{
4650 static string am_pm[24];
4651 am_pm[0] = "AM";
4652 am_pm[1] = "PM";
4653 return am_pm;
4654}
4655
4656static
4657wstring*
4658init_wam_pm()
4659{
4660 static wstring am_pm[24];
4661 am_pm[0] = L"AM";
4662 am_pm[1] = L"PM";
4663 return am_pm;
4664}
4665
4666template <>
4667const string*
4668__time_get_c_storage<char>::__am_pm() const
4669{
4670 static const string* am_pm = init_am_pm();
4671 return am_pm;
4672}
4673
4674template <>
4675const wstring*
4676__time_get_c_storage<wchar_t>::__am_pm() const
4677{
4678 static const wstring* am_pm = init_wam_pm();
4679 return am_pm;
4680}
4681
4682template <>
4683const string&
4684__time_get_c_storage<char>::__x() const
4685{
4686 static string s("%m/%d/%y");
4687 return s;
4688}
4689
4690template <>
4691const wstring&
4692__time_get_c_storage<wchar_t>::__x() const
4693{
4694 static wstring s(L"%m/%d/%y");
4695 return s;
4696}
4697
4698template <>
4699const string&
4700__time_get_c_storage<char>::__X() const
4701{
4702 static string s("%H:%M:%S");
4703 return s;
4704}
4705
4706template <>
4707const wstring&
4708__time_get_c_storage<wchar_t>::__X() const
4709{
4710 static wstring s(L"%H:%M:%S");
4711 return s;
4712}
4713
4714template <>
4715const string&
4716__time_get_c_storage<char>::__c() const
4717{
4718 static string s("%a %b %d %H:%M:%S %Y");
4719 return s;
4720}
4721
4722template <>
4723const wstring&
4724__time_get_c_storage<wchar_t>::__c() const
4725{
4726 static wstring s(L"%a %b %d %H:%M:%S %Y");
4727 return s;
4728}
4729
4730template <>
4731const string&
4732__time_get_c_storage<char>::__r() const
4733{
4734 static string s("%I:%M:%S %p");
4735 return s;
4736}
4737
4738template <>
4739const wstring&
4740__time_get_c_storage<wchar_t>::__r() const
4741{
4742 static wstring s(L"%I:%M:%S %p");
4743 return s;
4744}
4745
4746// time_get_byname
4747
4748__time_get::__time_get(const char* nm)
4749 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4750{
4751 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004752 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004753 " failed to construct for " + string(nm));
4754}
4755
4756__time_get::__time_get(const string& nm)
4757 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4758{
4759 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004760 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004761 " failed to construct for " + nm);
4762}
4763
4764__time_get::~__time_get()
4765{
4766 freelocale(__loc_);
4767}
Marshall Clowd920eea2013-10-21 15:07:28 +00004768#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004769#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004770#endif
4771#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004772#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004773#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004774
Howard Hinnantc51e1022010-05-11 19:42:16 +00004775template <>
4776string
4777__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4778{
Howard Hinnant990207c2012-02-19 14:55:32 +00004779 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004780 t.tm_sec = 59;
4781 t.tm_min = 55;
4782 t.tm_hour = 23;
4783 t.tm_mday = 31;
4784 t.tm_mon = 11;
4785 t.tm_year = 161;
4786 t.tm_wday = 6;
4787 t.tm_yday = 364;
4788 t.tm_isdst = -1;
4789 char buf[100];
4790 char f[3] = {0};
4791 f[0] = '%';
4792 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004793 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004794 char* bb = buf;
4795 char* be = buf + n;
4796 string result;
4797 while (bb != be)
4798 {
4799 if (ct.is(ctype_base::space, *bb))
4800 {
4801 result.push_back(' ');
4802 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4803 ;
4804 continue;
4805 }
4806 char* w = bb;
4807 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004808 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004809 ct, err, false)
4810 - this->__weeks_;
4811 if (i < 14)
4812 {
4813 result.push_back('%');
4814 if (i < 7)
4815 result.push_back('A');
4816 else
4817 result.push_back('a');
4818 bb = w;
4819 continue;
4820 }
4821 w = bb;
4822 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4823 ct, err, false)
4824 - this->__months_;
4825 if (i < 24)
4826 {
4827 result.push_back('%');
4828 if (i < 12)
4829 result.push_back('B');
4830 else
4831 result.push_back('b');
4832 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4833 result.back() = 'm';
4834 bb = w;
4835 continue;
4836 }
4837 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4838 {
4839 w = bb;
4840 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4841 ct, err, false) - this->__am_pm_;
4842 if (i < 2)
4843 {
4844 result.push_back('%');
4845 result.push_back('p');
4846 bb = w;
4847 continue;
4848 }
4849 }
4850 w = bb;
4851 if (ct.is(ctype_base::digit, *bb))
4852 {
4853 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4854 {
4855 case 6:
4856 result.push_back('%');
4857 result.push_back('w');
4858 break;
4859 case 7:
4860 result.push_back('%');
4861 result.push_back('u');
4862 break;
4863 case 11:
4864 result.push_back('%');
4865 result.push_back('I');
4866 break;
4867 case 12:
4868 result.push_back('%');
4869 result.push_back('m');
4870 break;
4871 case 23:
4872 result.push_back('%');
4873 result.push_back('H');
4874 break;
4875 case 31:
4876 result.push_back('%');
4877 result.push_back('d');
4878 break;
4879 case 55:
4880 result.push_back('%');
4881 result.push_back('M');
4882 break;
4883 case 59:
4884 result.push_back('%');
4885 result.push_back('S');
4886 break;
4887 case 61:
4888 result.push_back('%');
4889 result.push_back('y');
4890 break;
4891 case 364:
4892 result.push_back('%');
4893 result.push_back('j');
4894 break;
4895 case 2061:
4896 result.push_back('%');
4897 result.push_back('Y');
4898 break;
4899 default:
4900 for (; w != bb; ++w)
4901 result.push_back(*w);
4902 break;
4903 }
4904 continue;
4905 }
4906 if (*bb == '%')
4907 {
4908 result.push_back('%');
4909 result.push_back('%');
4910 ++bb;
4911 continue;
4912 }
4913 result.push_back(*bb);
4914 ++bb;
4915 }
4916 return result;
4917}
4918
Marshall Clowd920eea2013-10-21 15:07:28 +00004919#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004920#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004921#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004922
Howard Hinnantc51e1022010-05-11 19:42:16 +00004923template <>
4924wstring
4925__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4926{
Howard Hinnant990207c2012-02-19 14:55:32 +00004927 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004928 t.tm_sec = 59;
4929 t.tm_min = 55;
4930 t.tm_hour = 23;
4931 t.tm_mday = 31;
4932 t.tm_mon = 11;
4933 t.tm_year = 161;
4934 t.tm_wday = 6;
4935 t.tm_yday = 364;
4936 t.tm_isdst = -1;
4937 char buf[100];
4938 char f[3] = {0};
4939 f[0] = '%';
4940 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004941 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004942 wchar_t wbuf[100];
4943 wchar_t* wbb = wbuf;
4944 mbstate_t mb = {0};
4945 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004946 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004947 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004948 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004949 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004950 wstring result;
4951 while (wbb != wbe)
4952 {
4953 if (ct.is(ctype_base::space, *wbb))
4954 {
4955 result.push_back(L' ');
4956 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4957 ;
4958 continue;
4959 }
4960 wchar_t* w = wbb;
4961 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004962 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004963 ct, err, false)
4964 - this->__weeks_;
4965 if (i < 14)
4966 {
4967 result.push_back(L'%');
4968 if (i < 7)
4969 result.push_back(L'A');
4970 else
4971 result.push_back(L'a');
4972 wbb = w;
4973 continue;
4974 }
4975 w = wbb;
4976 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4977 ct, err, false)
4978 - this->__months_;
4979 if (i < 24)
4980 {
4981 result.push_back(L'%');
4982 if (i < 12)
4983 result.push_back(L'B');
4984 else
4985 result.push_back(L'b');
4986 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4987 result.back() = L'm';
4988 wbb = w;
4989 continue;
4990 }
4991 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4992 {
4993 w = wbb;
4994 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4995 ct, err, false) - this->__am_pm_;
4996 if (i < 2)
4997 {
4998 result.push_back(L'%');
4999 result.push_back(L'p');
5000 wbb = w;
5001 continue;
5002 }
5003 }
5004 w = wbb;
5005 if (ct.is(ctype_base::digit, *wbb))
5006 {
5007 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5008 {
5009 case 6:
5010 result.push_back(L'%');
5011 result.push_back(L'w');
5012 break;
5013 case 7:
5014 result.push_back(L'%');
5015 result.push_back(L'u');
5016 break;
5017 case 11:
5018 result.push_back(L'%');
5019 result.push_back(L'I');
5020 break;
5021 case 12:
5022 result.push_back(L'%');
5023 result.push_back(L'm');
5024 break;
5025 case 23:
5026 result.push_back(L'%');
5027 result.push_back(L'H');
5028 break;
5029 case 31:
5030 result.push_back(L'%');
5031 result.push_back(L'd');
5032 break;
5033 case 55:
5034 result.push_back(L'%');
5035 result.push_back(L'M');
5036 break;
5037 case 59:
5038 result.push_back(L'%');
5039 result.push_back(L'S');
5040 break;
5041 case 61:
5042 result.push_back(L'%');
5043 result.push_back(L'y');
5044 break;
5045 case 364:
5046 result.push_back(L'%');
5047 result.push_back(L'j');
5048 break;
5049 case 2061:
5050 result.push_back(L'%');
5051 result.push_back(L'Y');
5052 break;
5053 default:
5054 for (; w != wbb; ++w)
5055 result.push_back(*w);
5056 break;
5057 }
5058 continue;
5059 }
5060 if (ct.narrow(*wbb, 0) == '%')
5061 {
5062 result.push_back(L'%');
5063 result.push_back(L'%');
5064 ++wbb;
5065 continue;
5066 }
5067 result.push_back(*wbb);
5068 ++wbb;
5069 }
5070 return result;
5071}
5072
5073template <>
5074void
5075__time_get_storage<char>::init(const ctype<char>& ct)
5076{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005077 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005078 char buf[100];
5079 // __weeks_
5080 for (int i = 0; i < 7; ++i)
5081 {
5082 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005083 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005084 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005085 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005086 __weeks_[i+7] = buf;
5087 }
5088 // __months_
5089 for (int i = 0; i < 12; ++i)
5090 {
5091 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005092 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005093 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005094 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005095 __months_[i+12] = buf;
5096 }
5097 // __am_pm_
5098 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005099 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005100 __am_pm_[0] = buf;
5101 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005102 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005103 __am_pm_[1] = buf;
5104 __c_ = __analyze('c', ct);
5105 __r_ = __analyze('r', ct);
5106 __x_ = __analyze('x', ct);
5107 __X_ = __analyze('X', ct);
5108}
5109
5110template <>
5111void
5112__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5113{
5114 tm t = {0};
5115 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005116 wchar_t wbuf[100];
5117 wchar_t* wbe;
5118 mbstate_t mb = {0};
5119 // __weeks_
5120 for (int i = 0; i < 7; ++i)
5121 {
5122 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005123 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005124 mb = mbstate_t();
5125 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005126 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005127 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005128 __throw_runtime_error("locale not supported");
5129 wbe = wbuf + j;
5130 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005131 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005132 mb = mbstate_t();
5133 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005134 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005135 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005136 __throw_runtime_error("locale not supported");
5137 wbe = wbuf + j;
5138 __weeks_[i+7].assign(wbuf, wbe);
5139 }
5140 // __months_
5141 for (int i = 0; i < 12; ++i)
5142 {
5143 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005144 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005145 mb = mbstate_t();
5146 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005147 size_t 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 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005152 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005153 mb = mbstate_t();
5154 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005155 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005156 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005157 __throw_runtime_error("locale not supported");
5158 wbe = wbuf + j;
5159 __months_[i+12].assign(wbuf, wbe);
5160 }
5161 // __am_pm_
5162 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005163 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005164 mb = mbstate_t();
5165 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005166 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005167 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005168 __throw_runtime_error("locale not supported");
5169 wbe = wbuf + j;
5170 __am_pm_[0].assign(wbuf, wbe);
5171 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005172 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005173 mb = mbstate_t();
5174 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005175 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005176 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005177 __throw_runtime_error("locale not supported");
5178 wbe = wbuf + j;
5179 __am_pm_[1].assign(wbuf, wbe);
5180 __c_ = __analyze('c', ct);
5181 __r_ = __analyze('r', ct);
5182 __x_ = __analyze('x', ct);
5183 __X_ = __analyze('X', ct);
5184}
5185
5186template <class CharT>
5187struct _LIBCPP_HIDDEN __time_get_temp
5188 : public ctype_byname<CharT>
5189{
5190 explicit __time_get_temp(const char* nm)
5191 : ctype_byname<CharT>(nm, 1) {}
5192 explicit __time_get_temp(const string& nm)
5193 : ctype_byname<CharT>(nm, 1) {}
5194};
5195
5196template <>
5197__time_get_storage<char>::__time_get_storage(const char* __nm)
5198 : __time_get(__nm)
5199{
5200 const __time_get_temp<char> ct(__nm);
5201 init(ct);
5202}
5203
5204template <>
5205__time_get_storage<char>::__time_get_storage(const string& __nm)
5206 : __time_get(__nm)
5207{
5208 const __time_get_temp<char> ct(__nm);
5209 init(ct);
5210}
5211
5212template <>
5213__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5214 : __time_get(__nm)
5215{
5216 const __time_get_temp<wchar_t> ct(__nm);
5217 init(ct);
5218}
5219
5220template <>
5221__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5222 : __time_get(__nm)
5223{
5224 const __time_get_temp<wchar_t> ct(__nm);
5225 init(ct);
5226}
5227
5228template <>
5229time_base::dateorder
5230__time_get_storage<char>::__do_date_order() const
5231{
5232 unsigned i;
5233 for (i = 0; i < __x_.size(); ++i)
5234 if (__x_[i] == '%')
5235 break;
5236 ++i;
5237 switch (__x_[i])
5238 {
5239 case 'y':
5240 case 'Y':
5241 for (++i; i < __x_.size(); ++i)
5242 if (__x_[i] == '%')
5243 break;
5244 if (i == __x_.size())
5245 break;
5246 ++i;
5247 switch (__x_[i])
5248 {
5249 case 'm':
5250 for (++i; i < __x_.size(); ++i)
5251 if (__x_[i] == '%')
5252 break;
5253 if (i == __x_.size())
5254 break;
5255 ++i;
5256 if (__x_[i] == 'd')
5257 return time_base::ymd;
5258 break;
5259 case 'd':
5260 for (++i; i < __x_.size(); ++i)
5261 if (__x_[i] == '%')
5262 break;
5263 if (i == __x_.size())
5264 break;
5265 ++i;
5266 if (__x_[i] == 'm')
5267 return time_base::ydm;
5268 break;
5269 }
5270 break;
5271 case 'm':
5272 for (++i; i < __x_.size(); ++i)
5273 if (__x_[i] == '%')
5274 break;
5275 if (i == __x_.size())
5276 break;
5277 ++i;
5278 if (__x_[i] == 'd')
5279 {
5280 for (++i; i < __x_.size(); ++i)
5281 if (__x_[i] == '%')
5282 break;
5283 if (i == __x_.size())
5284 break;
5285 ++i;
5286 if (__x_[i] == 'y' || __x_[i] == 'Y')
5287 return time_base::mdy;
5288 break;
5289 }
5290 break;
5291 case 'd':
5292 for (++i; i < __x_.size(); ++i)
5293 if (__x_[i] == '%')
5294 break;
5295 if (i == __x_.size())
5296 break;
5297 ++i;
5298 if (__x_[i] == 'm')
5299 {
5300 for (++i; i < __x_.size(); ++i)
5301 if (__x_[i] == '%')
5302 break;
5303 if (i == __x_.size())
5304 break;
5305 ++i;
5306 if (__x_[i] == 'y' || __x_[i] == 'Y')
5307 return time_base::dmy;
5308 break;
5309 }
5310 break;
5311 }
5312 return time_base::no_order;
5313}
5314
5315template <>
5316time_base::dateorder
5317__time_get_storage<wchar_t>::__do_date_order() const
5318{
5319 unsigned i;
5320 for (i = 0; i < __x_.size(); ++i)
5321 if (__x_[i] == L'%')
5322 break;
5323 ++i;
5324 switch (__x_[i])
5325 {
5326 case L'y':
5327 case L'Y':
5328 for (++i; i < __x_.size(); ++i)
5329 if (__x_[i] == L'%')
5330 break;
5331 if (i == __x_.size())
5332 break;
5333 ++i;
5334 switch (__x_[i])
5335 {
5336 case L'm':
5337 for (++i; i < __x_.size(); ++i)
5338 if (__x_[i] == L'%')
5339 break;
5340 if (i == __x_.size())
5341 break;
5342 ++i;
5343 if (__x_[i] == L'd')
5344 return time_base::ymd;
5345 break;
5346 case L'd':
5347 for (++i; i < __x_.size(); ++i)
5348 if (__x_[i] == L'%')
5349 break;
5350 if (i == __x_.size())
5351 break;
5352 ++i;
5353 if (__x_[i] == L'm')
5354 return time_base::ydm;
5355 break;
5356 }
5357 break;
5358 case L'm':
5359 for (++i; i < __x_.size(); ++i)
5360 if (__x_[i] == L'%')
5361 break;
5362 if (i == __x_.size())
5363 break;
5364 ++i;
5365 if (__x_[i] == L'd')
5366 {
5367 for (++i; i < __x_.size(); ++i)
5368 if (__x_[i] == L'%')
5369 break;
5370 if (i == __x_.size())
5371 break;
5372 ++i;
5373 if (__x_[i] == L'y' || __x_[i] == L'Y')
5374 return time_base::mdy;
5375 break;
5376 }
5377 break;
5378 case L'd':
5379 for (++i; i < __x_.size(); ++i)
5380 if (__x_[i] == L'%')
5381 break;
5382 if (i == __x_.size())
5383 break;
5384 ++i;
5385 if (__x_[i] == L'm')
5386 {
5387 for (++i; i < __x_.size(); ++i)
5388 if (__x_[i] == L'%')
5389 break;
5390 if (i == __x_.size())
5391 break;
5392 ++i;
5393 if (__x_[i] == L'y' || __x_[i] == L'Y')
5394 return time_base::dmy;
5395 break;
5396 }
5397 break;
5398 }
5399 return time_base::no_order;
5400}
5401
5402// time_put
5403
5404__time_put::__time_put(const char* nm)
5405 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5406{
5407 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005408 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005409 " failed to construct for " + string(nm));
5410}
5411
5412__time_put::__time_put(const string& nm)
5413 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5414{
5415 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005416 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005417 " failed to construct for " + nm);
5418}
5419
5420__time_put::~__time_put()
5421{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005422 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005423 freelocale(__loc_);
5424}
5425
5426void
5427__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5428 char __fmt, char __mod) const
5429{
5430 char fmt[] = {'%', __fmt, __mod, 0};
5431 if (__mod != 0)
5432 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005433 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005434 __ne = __nb + n;
5435}
5436
5437void
5438__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5439 char __fmt, char __mod) const
5440{
5441 char __nar[100];
5442 char* __ne = __nar + 100;
5443 __do_put(__nar, __ne, __tm, __fmt, __mod);
5444 mbstate_t mb = {0};
5445 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005446 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005447 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005448 __throw_runtime_error("locale not supported");
5449 __we = __wb + j;
5450}
5451
5452// moneypunct_byname
5453
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005454template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005455static
5456void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005457__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5458 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5459 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005460{
5461 const char sign = static_cast<char>(money_base::sign);
5462 const char space = static_cast<char>(money_base::space);
5463 const char none = static_cast<char>(money_base::none);
5464 const char symbol = static_cast<char>(money_base::symbol);
5465 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005466 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5467
5468 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5469 // function'. "Space between sign and symbol or value" means that
5470 // if the sign is adjacent to the symbol, there's a space between
5471 // them, and otherwise there's a space between the sign and value.
5472 //
5473 // C11's localeconv specifies that the fourth character of an
5474 // international curr_symbol is used to separate the sign and
5475 // value when sep_by_space says to do so. C++ can't represent
5476 // that, so we just use a space. When sep_by_space says to
5477 // separate the symbol and value-or-sign with a space, we rearrange the
5478 // curr_symbol to put its spacing character on the correct side of
5479 // the symbol.
5480 //
5481 // We also need to avoid adding an extra space between the sign
5482 // and value when the currency symbol is suppressed (by not
5483 // setting showbase). We match glibc's strfmon by interpreting
5484 // sep_by_space==1 as "omit the space when the currency symbol is
5485 // absent".
5486 //
5487 // Users who want to get this right should use ICU instead.
5488
Howard Hinnantc51e1022010-05-11 19:42:16 +00005489 switch (cs_precedes)
5490 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005491 case 0: // value before curr_symbol
5492 if (symbol_contains_sep) {
5493 // Move the separator to before the symbol, to place it
5494 // between the value and symbol.
5495 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5496 __curr_symbol_.end());
5497 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005498 switch (sign_posn)
5499 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005500 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005501 pat.field[0] = sign;
5502 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005503 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005504 pat.field[3] = symbol;
5505 switch (sep_by_space)
5506 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005507 case 0: // No space separates the currency symbol and value.
5508 // This case may have changed between C99 and C11;
5509 // assume the currency symbol matches the intention.
5510 case 2: // Space between sign and currency or value.
5511 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005512 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005513 case 1: // Space between currency-and-sign or currency and value.
5514 if (!symbol_contains_sep) {
5515 // We insert the space into the symbol instead of
5516 // setting pat.field[2]=space so that when
5517 // showbase is not set, the space goes away too.
5518 __curr_symbol_.insert(0, 1, space_char);
5519 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005520 return;
5521 default:
5522 break;
5523 }
5524 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005525 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005526 pat.field[0] = sign;
5527 pat.field[3] = symbol;
5528 switch (sep_by_space)
5529 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005530 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005531 pat.field[1] = value;
5532 pat.field[2] = none;
5533 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005534 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005535 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005536 pat.field[2] = none;
5537 if (!symbol_contains_sep) {
5538 // We insert the space into the symbol instead of
5539 // setting pat.field[2]=space so that when
5540 // showbase is not set, the space goes away too.
5541 __curr_symbol_.insert(0, 1, space_char);
5542 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005543 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005544 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005545 pat.field[1] = space;
5546 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005547 if (symbol_contains_sep) {
5548 // Remove the separator from the symbol, since it
5549 // has already appeared after the sign.
5550 __curr_symbol_.erase(__curr_symbol_.begin());
5551 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005552 return;
5553 default:
5554 break;
5555 }
5556 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005557 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005558 pat.field[0] = value;
5559 pat.field[3] = sign;
5560 switch (sep_by_space)
5561 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005562 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005563 pat.field[1] = none;
5564 pat.field[2] = symbol;
5565 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005566 case 1: // Space between currency-and-sign or currency and value.
5567 if (!symbol_contains_sep) {
5568 // We insert the space into the symbol instead of
5569 // setting pat.field[1]=space so that when
5570 // showbase is not set, the space goes away too.
5571 __curr_symbol_.insert(0, 1, space_char);
5572 }
5573 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005574 pat.field[2] = symbol;
5575 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005576 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 pat.field[1] = symbol;
5578 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005579 if (symbol_contains_sep) {
5580 // Remove the separator from the symbol, since it
5581 // should not be removed if showbase is absent.
5582 __curr_symbol_.erase(__curr_symbol_.begin());
5583 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005584 return;
5585 default:
5586 break;
5587 }
5588 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005589 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005590 pat.field[0] = value;
5591 pat.field[3] = symbol;
5592 switch (sep_by_space)
5593 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005594 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005595 pat.field[1] = none;
5596 pat.field[2] = sign;
5597 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005598 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599 pat.field[1] = space;
5600 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005601 if (symbol_contains_sep) {
5602 // Remove the separator from the symbol, since it
5603 // has already appeared before the sign.
5604 __curr_symbol_.erase(__curr_symbol_.begin());
5605 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005606 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005607 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005608 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005609 pat.field[2] = none;
5610 if (!symbol_contains_sep) {
5611 // We insert the space into the symbol instead of
5612 // setting pat.field[2]=space so that when
5613 // showbase is not set, the space goes away too.
5614 __curr_symbol_.insert(0, 1, space_char);
5615 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005616 return;
5617 default:
5618 break;
5619 }
5620 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005621 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005622 pat.field[0] = value;
5623 pat.field[3] = sign;
5624 switch (sep_by_space)
5625 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005626 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005627 pat.field[1] = none;
5628 pat.field[2] = symbol;
5629 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005630 case 1: // Space between currency-and-sign or currency and value.
5631 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005632 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005633 if (!symbol_contains_sep) {
5634 // We insert the space into the symbol instead of
5635 // setting pat.field[1]=space so that when
5636 // showbase is not set, the space goes away too.
5637 __curr_symbol_.insert(0, 1, space_char);
5638 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005639 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005640 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005641 pat.field[1] = symbol;
5642 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005643 if (symbol_contains_sep) {
5644 // Remove the separator from the symbol, since it
5645 // should not disappear when showbase is absent.
5646 __curr_symbol_.erase(__curr_symbol_.begin());
5647 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005648 return;
5649 default:
5650 break;
5651 }
5652 break;
5653 default:
5654 break;
5655 }
5656 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005657 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005658 switch (sign_posn)
5659 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005660 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005661 pat.field[0] = sign;
5662 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005663 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005664 pat.field[3] = value;
5665 switch (sep_by_space)
5666 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005667 case 0: // No space separates the currency symbol and value.
5668 // This case may have changed between C99 and C11;
5669 // assume the currency symbol matches the intention.
5670 case 2: // Space between sign and currency or value.
5671 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005672 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005673 case 1: // Space between currency-and-sign or currency and value.
5674 if (!symbol_contains_sep) {
5675 // We insert the space into the symbol instead of
5676 // setting pat.field[2]=space so that when
5677 // showbase is not set, the space goes away too.
5678 __curr_symbol_.insert(0, 1, space_char);
5679 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005680 return;
5681 default:
5682 break;
5683 }
5684 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005685 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005686 pat.field[0] = sign;
5687 pat.field[3] = value;
5688 switch (sep_by_space)
5689 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005690 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005691 pat.field[1] = symbol;
5692 pat.field[2] = none;
5693 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005694 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005695 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005696 pat.field[2] = none;
5697 if (!symbol_contains_sep) {
5698 // We insert the space into the symbol instead of
5699 // setting pat.field[2]=space so that when
5700 // showbase is not set, the space goes away too.
5701 __curr_symbol_.push_back(space_char);
5702 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005703 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005704 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005705 pat.field[1] = space;
5706 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005707 if (symbol_contains_sep) {
5708 // Remove the separator from the symbol, since it
5709 // has already appeared after the sign.
5710 __curr_symbol_.pop_back();
5711 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005712 return;
5713 default:
5714 break;
5715 }
5716 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005717 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005718 pat.field[0] = symbol;
5719 pat.field[3] = sign;
5720 switch (sep_by_space)
5721 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005722 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005723 pat.field[1] = none;
5724 pat.field[2] = value;
5725 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005726 case 1: // Space between currency-and-sign or currency and value.
5727 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005728 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005729 if (!symbol_contains_sep) {
5730 // We insert the space into the symbol instead of
5731 // setting pat.field[1]=space so that when
5732 // showbase is not set, the space goes away too.
5733 __curr_symbol_.push_back(space_char);
5734 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005735 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005736 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005737 pat.field[1] = value;
5738 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005739 if (symbol_contains_sep) {
5740 // Remove the separator from the symbol, since it
5741 // will appear before the sign.
5742 __curr_symbol_.pop_back();
5743 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005744 return;
5745 default:
5746 break;
5747 }
5748 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005749 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005750 pat.field[0] = sign;
5751 pat.field[3] = value;
5752 switch (sep_by_space)
5753 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005754 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005755 pat.field[1] = symbol;
5756 pat.field[2] = none;
5757 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005758 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005759 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005760 pat.field[2] = none;
5761 if (!symbol_contains_sep) {
5762 // We insert the space into the symbol instead of
5763 // setting pat.field[2]=space so that when
5764 // showbase is not set, the space goes away too.
5765 __curr_symbol_.push_back(space_char);
5766 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005767 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005768 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005769 pat.field[1] = space;
5770 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005771 if (symbol_contains_sep) {
5772 // Remove the separator from the symbol, since it
5773 // has already appeared after the sign.
5774 __curr_symbol_.pop_back();
5775 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005776 return;
5777 default:
5778 break;
5779 }
5780 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005781 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005782 pat.field[0] = symbol;
5783 pat.field[3] = value;
5784 switch (sep_by_space)
5785 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005786 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005787 pat.field[1] = sign;
5788 pat.field[2] = none;
5789 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005790 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005791 pat.field[1] = sign;
5792 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005793 if (symbol_contains_sep) {
5794 // Remove the separator from the symbol, since it
5795 // should not disappear when showbase is absent.
5796 __curr_symbol_.pop_back();
5797 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005798 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005799 case 2: // Space between sign and currency or value.
5800 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005801 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005802 if (!symbol_contains_sep) {
5803 // We insert the space into the symbol instead of
5804 // setting pat.field[1]=space so that when
5805 // showbase is not set, the space goes away too.
5806 __curr_symbol_.push_back(space_char);
5807 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005808 return;
5809 default:
5810 break;
5811 }
5812 break;
5813 default:
5814 break;
5815 }
5816 break;
5817 default:
5818 break;
5819 }
5820 pat.field[0] = symbol;
5821 pat.field[1] = sign;
5822 pat.field[2] = none;
5823 pat.field[3] = value;
5824}
5825
5826template<>
5827void
5828moneypunct_byname<char, false>::init(const char* nm)
5829{
5830 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005831 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005832 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005833 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005834 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005835
Ben Craig3756b922016-03-09 15:39:39 +00005836 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005837 if (!checked_string_to_char_convert(__decimal_point_,
5838 lc->mon_decimal_point,
5839 loc.get()))
5840 __decimal_point_ = base::do_decimal_point();
5841 if (!checked_string_to_char_convert(__thousands_sep_,
5842 lc->mon_thousands_sep,
5843 loc.get()))
5844 __thousands_sep_ = base::do_thousands_sep();
5845
Howard Hinnantc51e1022010-05-11 19:42:16 +00005846 __grouping_ = lc->mon_grouping;
5847 __curr_symbol_ = lc->currency_symbol;
5848 if (lc->frac_digits != CHAR_MAX)
5849 __frac_digits_ = lc->frac_digits;
5850 else
5851 __frac_digits_ = base::do_frac_digits();
5852 if (lc->p_sign_posn == 0)
5853 __positive_sign_ = "()";
5854 else
5855 __positive_sign_ = lc->positive_sign;
5856 if (lc->n_sign_posn == 0)
5857 __negative_sign_ = "()";
5858 else
5859 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005860 // Assume the positive and negative formats will want spaces in
5861 // the same places in curr_symbol since there's no way to
5862 // represent anything else.
5863 string_type __dummy_curr_symbol = __curr_symbol_;
5864 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5865 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5866 __init_pat(__neg_format_, __curr_symbol_, false,
5867 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005868}
5869
5870template<>
5871void
5872moneypunct_byname<char, true>::init(const char* nm)
5873{
5874 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005875 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005876 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005877 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005878 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005879
Ben Craig3756b922016-03-09 15:39:39 +00005880 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005881 if (!checked_string_to_char_convert(__decimal_point_,
5882 lc->mon_decimal_point,
5883 loc.get()))
5884 __decimal_point_ = base::do_decimal_point();
5885 if (!checked_string_to_char_convert(__thousands_sep_,
5886 lc->mon_thousands_sep,
5887 loc.get()))
5888 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005889 __grouping_ = lc->mon_grouping;
5890 __curr_symbol_ = lc->int_curr_symbol;
5891 if (lc->int_frac_digits != CHAR_MAX)
5892 __frac_digits_ = lc->int_frac_digits;
5893 else
5894 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005895#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005896 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005897#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005898 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005899#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005900 __positive_sign_ = "()";
5901 else
5902 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005903#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005904 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005905#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005906 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005907#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005908 __negative_sign_ = "()";
5909 else
5910 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005911 // Assume the positive and negative formats will want spaces in
5912 // the same places in curr_symbol since there's no way to
5913 // represent anything else.
5914 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005915#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005916 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5917 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5918 __init_pat(__neg_format_, __curr_symbol_, true,
5919 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005920#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005921 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5922 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5923 lc->int_p_sign_posn, ' ');
5924 __init_pat(__neg_format_, __curr_symbol_, true,
5925 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5926 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005927#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005928}
5929
5930template<>
5931void
5932moneypunct_byname<wchar_t, false>::init(const char* nm)
5933{
5934 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005935 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005936 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005937 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005938 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005939 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005940 if (!checked_string_to_wchar_convert(__decimal_point_,
5941 lc->mon_decimal_point,
5942 loc.get()))
5943 __decimal_point_ = base::do_decimal_point();
5944 if (!checked_string_to_wchar_convert(__thousands_sep_,
5945 lc->mon_thousands_sep,
5946 loc.get()))
5947 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005948 __grouping_ = lc->mon_grouping;
5949 wchar_t wbuf[100];
5950 mbstate_t mb = {0};
5951 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005952 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005953 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005954 __throw_runtime_error("locale not supported");
5955 wchar_t* wbe = wbuf + j;
5956 __curr_symbol_.assign(wbuf, wbe);
5957 if (lc->frac_digits != CHAR_MAX)
5958 __frac_digits_ = lc->frac_digits;
5959 else
5960 __frac_digits_ = base::do_frac_digits();
5961 if (lc->p_sign_posn == 0)
5962 __positive_sign_ = L"()";
5963 else
5964 {
5965 mb = mbstate_t();
5966 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005967 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005968 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 __throw_runtime_error("locale not supported");
5970 wbe = wbuf + j;
5971 __positive_sign_.assign(wbuf, wbe);
5972 }
5973 if (lc->n_sign_posn == 0)
5974 __negative_sign_ = L"()";
5975 else
5976 {
5977 mb = mbstate_t();
5978 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005979 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005980 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005981 __throw_runtime_error("locale not supported");
5982 wbe = wbuf + j;
5983 __negative_sign_.assign(wbuf, wbe);
5984 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005985 // Assume the positive and negative formats will want spaces in
5986 // the same places in curr_symbol since there's no way to
5987 // represent anything else.
5988 string_type __dummy_curr_symbol = __curr_symbol_;
5989 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5990 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5991 __init_pat(__neg_format_, __curr_symbol_, false,
5992 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005993}
5994
5995template<>
5996void
5997moneypunct_byname<wchar_t, true>::init(const char* nm)
5998{
5999 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006000 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00006001 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00006002 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00006003 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00006004
Ben Craig3756b922016-03-09 15:39:39 +00006005 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00006006 if (!checked_string_to_wchar_convert(__decimal_point_,
6007 lc->mon_decimal_point,
6008 loc.get()))
6009 __decimal_point_ = base::do_decimal_point();
6010 if (!checked_string_to_wchar_convert(__thousands_sep_,
6011 lc->mon_thousands_sep,
6012 loc.get()))
6013 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006014 __grouping_ = lc->mon_grouping;
6015 wchar_t wbuf[100];
6016 mbstate_t mb = {0};
6017 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006018 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006019 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006020 __throw_runtime_error("locale not supported");
6021 wchar_t* wbe = wbuf + j;
6022 __curr_symbol_.assign(wbuf, wbe);
6023 if (lc->int_frac_digits != CHAR_MAX)
6024 __frac_digits_ = lc->int_frac_digits;
6025 else
6026 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006027#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006028 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006029#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006030 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006031#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006032 __positive_sign_ = L"()";
6033 else
6034 {
6035 mb = mbstate_t();
6036 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006037 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006038 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006039 __throw_runtime_error("locale not supported");
6040 wbe = wbuf + j;
6041 __positive_sign_.assign(wbuf, wbe);
6042 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006043#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006044 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006045#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006046 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006047#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006048 __negative_sign_ = L"()";
6049 else
6050 {
6051 mb = mbstate_t();
6052 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006053 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006054 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006055 __throw_runtime_error("locale not supported");
6056 wbe = wbuf + j;
6057 __negative_sign_.assign(wbuf, wbe);
6058 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006059 // Assume the positive and negative formats will want spaces in
6060 // the same places in curr_symbol since there's no way to
6061 // represent anything else.
6062 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006063#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006064 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6065 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6066 __init_pat(__neg_format_, __curr_symbol_, true,
6067 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006068#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006069 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6070 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6071 lc->int_p_sign_posn, L' ');
6072 __init_pat(__neg_format_, __curr_symbol_, true,
6073 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6074 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006075#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006076}
6077
6078void __do_nothing(void*) {}
6079
6080void __throw_runtime_error(const char* msg)
6081{
Howard Hinnant72f73582010-08-11 17:04:31 +00006082#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006083 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006084#else
6085 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006086 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006087#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006088}
6089
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006090template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6091template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006092
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006093template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6094template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006095
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006096template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6097template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006098
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006099template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6100template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006101
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006102template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6103template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006104
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006105template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6106template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006107
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006108template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6109template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006110
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006111template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6112template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006113
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006114template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6115template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006116
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006117template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6118template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6119template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6120template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006121
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006122template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6123template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6124template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6125template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006126
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006127template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6128template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006129
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006130template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6131template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006132
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006133template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6134template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006135
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006136template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6137template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006138
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006139template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6140template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006142template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6143template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006144
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006145template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6146template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6147template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6148template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006149
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006150template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006151
6152_LIBCPP_END_NAMESPACE_STD