blob: 1ed9b41fd4adb360a30a6e9fb6f9bc4ff4da3b4f [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;
Eric Fiselier4db80032017-05-05 20:32:26 +000071 auto *obj = ::new (&buf) T(a0);
72 return *obj;
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;
Eric Fiselier4db80032017-05-05 20:32:26 +000091 auto *obj = ::new (&buf) T(a0, a1, a2);
92 return *obj;
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};
Eric Fiselier8fbccea2017-01-06 21:42:58 +0000143#if defined(_LIBCPP_COMPILER_MSVC)
Marshall Clowd920eea2013-10-21 15:07:28 +0000144// 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;
Eric Fiselier4db80032017-05-05 20:32:26 +0000483 auto *obj = ::new (&buf) locale(locale::classic());
484 return *obj;
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;
582 if (g.name() != "*")
583 setlocale(LC_ALL, g.name().c_str());
584 return r;
585}
586
587bool
588locale::has_facet(id& x) const
589{
590 return __locale_->has_facet(x.__get());
591}
592
593const locale::facet*
594locale::use_facet(id& x) const
595{
596 return __locale_->use_facet(x.__get());
597}
598
599bool
600locale::operator==(const locale& y) const
601{
602 return (__locale_ == y.__locale_)
603 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
604}
605
606// locale::facet
607
608locale::facet::~facet()
609{
610}
611
612void
Howard Hinnant719bda32011-05-28 14:41:13 +0000613locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000614{
615 delete this;
616}
617
618// locale::id
619
620int32_t locale::id::__next_id = 0;
621
622namespace
623{
624
625class __fake_bind
626{
627 locale::id* id_;
628 void (locale::id::* pmf_)();
629public:
630 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
631 : id_(id), pmf_(pmf) {}
632
633 void operator()() const
634 {
635 (id_->*pmf_)();
636 }
637};
638
639}
640
641long
642locale::id::__get()
643{
644 call_once(__flag_, __fake_bind(&locale::id::__init, this));
645 return __id_ - 1;
646}
647
648void
649locale::id::__init()
650{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000651 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000652}
653
654// template <> class collate_byname<char>
655
656collate_byname<char>::collate_byname(const char* n, size_t refs)
657 : collate<char>(refs),
658 __l(newlocale(LC_ALL_MASK, n, 0))
659{
660 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000661 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000662 " failed to construct for " + string(n));
663}
664
665collate_byname<char>::collate_byname(const string& name, size_t refs)
666 : collate<char>(refs),
667 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
668{
669 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000670 __throw_runtime_error("collate_byname<char>::collate_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000671 " failed to construct for " + name);
672}
673
674collate_byname<char>::~collate_byname()
675{
676 freelocale(__l);
677}
678
679int
680collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
681 const char_type* __lo2, const char_type* __hi2) const
682{
683 string_type lhs(__lo1, __hi1);
684 string_type rhs(__lo2, __hi2);
685 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
686 if (r < 0)
687 return -1;
688 if (r > 0)
689 return 1;
690 return r;
691}
692
693collate_byname<char>::string_type
694collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
695{
696 const string_type in(lo, hi);
697 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
698 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
699 return out;
700}
701
702// template <> class collate_byname<wchar_t>
703
704collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
705 : collate<wchar_t>(refs),
706 __l(newlocale(LC_ALL_MASK, n, 0))
707{
708 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000709 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000710 " failed to construct for " + string(n));
711}
712
713collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
714 : collate<wchar_t>(refs),
715 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
716{
717 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +0000718 __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
Howard Hinnantc51e1022010-05-11 19:42:16 +0000719 " failed to construct for " + name);
720}
721
722collate_byname<wchar_t>::~collate_byname()
723{
724 freelocale(__l);
725}
726
727int
728collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
729 const char_type* __lo2, const char_type* __hi2) const
730{
731 string_type lhs(__lo1, __hi1);
732 string_type rhs(__lo2, __hi2);
733 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
734 if (r < 0)
735 return -1;
736 if (r > 0)
737 return 1;
738 return r;
739}
740
741collate_byname<wchar_t>::string_type
742collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
743{
744 const string_type in(lo, hi);
745 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
746 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
747 return out;
748}
749
750// template <> class ctype<wchar_t>;
751
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000752const ctype_base::mask ctype_base::space;
753const ctype_base::mask ctype_base::print;
754const ctype_base::mask ctype_base::cntrl;
755const ctype_base::mask ctype_base::upper;
756const ctype_base::mask ctype_base::lower;
757const ctype_base::mask ctype_base::alpha;
758const ctype_base::mask ctype_base::digit;
759const ctype_base::mask ctype_base::punct;
760const ctype_base::mask ctype_base::xdigit;
761const ctype_base::mask ctype_base::blank;
762const ctype_base::mask ctype_base::alnum;
763const ctype_base::mask ctype_base::graph;
764
Howard Hinnantc51e1022010-05-11 19:42:16 +0000765locale::id ctype<wchar_t>::id;
766
767ctype<wchar_t>::~ctype()
768{
769}
770
771bool
772ctype<wchar_t>::do_is(mask m, char_type c) const
773{
Marshall Clowd920eea2013-10-21 15:07:28 +0000774 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000775}
776
777const wchar_t*
778ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
779{
780 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000781 *vec = static_cast<mask>(isascii(*low) ?
782 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000783 return low;
784}
785
786const wchar_t*
787ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
788{
789 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000790 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000791 break;
792 return low;
793}
794
795const wchar_t*
796ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
797{
798 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000799 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000800 break;
801 return low;
802}
803
804wchar_t
805ctype<wchar_t>::do_toupper(char_type c) const
806{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000807#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
808 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000809#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000810 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000811 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000812#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000813 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000814#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000815}
816
817const wchar_t*
818ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
819{
820 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000821#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
822 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000823#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000824 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000825 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
826 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000827#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000828 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000829#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000830 return low;
831}
832
833wchar_t
834ctype<wchar_t>::do_tolower(char_type c) const
835{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000836#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
837 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000838#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000839 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000840 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000841#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000842 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000843#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000844}
845
846const wchar_t*
847ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
848{
849 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000850#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
851 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000852#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000853 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000854 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
855 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000856#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000857 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000858#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000859 return low;
860}
861
862wchar_t
863ctype<wchar_t>::do_widen(char c) const
864{
865 return c;
866}
867
868const char*
869ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
870{
871 for (; low != high; ++low, ++dest)
872 *dest = *low;
873 return low;
874}
875
876char
877ctype<wchar_t>::do_narrow(char_type c, char dfault) const
878{
879 if (isascii(c))
880 return static_cast<char>(c);
881 return dfault;
882}
883
884const wchar_t*
885ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
886{
887 for (; low != high; ++low, ++dest)
888 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000889 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890 else
891 *dest = dfault;
892 return low;
893}
894
895// template <> class ctype<char>;
896
897locale::id ctype<char>::id;
898
899ctype<char>::ctype(const mask* tab, bool del, size_t refs)
900 : locale::facet(refs),
901 __tab_(tab),
902 __del_(del)
903{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000904 if (__tab_ == 0)
905 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000906}
907
908ctype<char>::~ctype()
909{
910 if (__tab_ && __del_)
911 delete [] __tab_;
912}
913
914char
915ctype<char>::do_toupper(char_type c) const
916{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000917#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000918 return isascii(c) ?
919 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000920#elif defined(__NetBSD__)
921 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000922#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000923 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000924 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000925#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000926 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000927#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000928}
929
930const char*
931ctype<char>::do_toupper(char_type* low, const char_type* high) const
932{
933 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000934#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000935 *low = isascii(*low) ?
936 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000937#elif defined(__NetBSD__)
938 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000939#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000940 *low = isascii(*low) ?
941 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000942#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000943 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000944#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000945 return low;
946}
947
948char
949ctype<char>::do_tolower(char_type c) const
950{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000951#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000952 return isascii(c) ?
953 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000954#elif defined(__NetBSD__)
955 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000956#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000957 return isascii(c) ?
958 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000959#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000960 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000961#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000962}
963
964const char*
965ctype<char>::do_tolower(char_type* low, const char_type* high) const
966{
967 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000968#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000969 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000970#elif defined(__NetBSD__)
971 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000972#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000973 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000974#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000975 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000976#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000977 return low;
978}
979
980char
981ctype<char>::do_widen(char c) const
982{
983 return c;
984}
985
986const char*
987ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
988{
989 for (; low != high; ++low, ++dest)
990 *dest = *low;
991 return low;
992}
993
994char
995ctype<char>::do_narrow(char_type c, char dfault) const
996{
997 if (isascii(c))
998 return static_cast<char>(c);
999 return dfault;
1000}
1001
1002const char*
1003ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1004{
1005 for (; low != high; ++low, ++dest)
1006 if (isascii(*low))
1007 *dest = *low;
1008 else
1009 *dest = dfault;
1010 return low;
1011}
1012
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001013#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001014extern "C" const unsigned short ** __ctype_b_loc();
1015extern "C" const int ** __ctype_tolower_loc();
1016extern "C" const int ** __ctype_toupper_loc();
1017#endif
1018
Marshall Clow8f870232015-03-04 16:50:02 +00001019#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001020const ctype<char>::mask*
1021ctype<char>::classic_table() _NOEXCEPT
1022{
1023 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1024 cntrl, cntrl,
1025 cntrl, cntrl,
1026 cntrl, cntrl,
1027 cntrl, cntrl,
1028 cntrl, cntrl | space | blank,
1029 cntrl | space, cntrl | space,
1030 cntrl | space, cntrl | space,
1031 cntrl, cntrl,
1032 cntrl, cntrl,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl,
1040 space | blank | print, punct | print,
1041 punct | print, punct | print,
1042 punct | 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 digit | print | xdigit, digit | print | xdigit,
1049 digit | print | xdigit, digit | print | xdigit,
1050 digit | print | xdigit, digit | print | xdigit,
1051 digit | print | xdigit, digit | print | xdigit,
1052 digit | print | xdigit, digit | print | xdigit,
1053 punct | print, punct | print,
1054 punct | print, punct | print,
1055 punct | print, punct | print,
1056 punct | print, upper | xdigit | print | alpha,
1057 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1058 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1059 upper | xdigit | print | alpha, upper | print | alpha,
1060 upper | print | alpha, upper | print | alpha,
1061 upper | 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, punct | print,
1070 punct | print, punct | print,
1071 punct | print, punct | print,
1072 punct | print, lower | xdigit | print | alpha,
1073 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1074 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1075 lower | xdigit | print | alpha, lower | print | alpha,
1076 lower | print | alpha, lower | print | alpha,
1077 lower | 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, punct | print,
1086 punct | print, punct | print,
1087 punct | print, cntrl,
1088 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1089 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 };
1097 return builtin_table;
1098}
1099#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001100const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001101ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001102{
David Chisnall1d581062011-09-21 08:39:44 +00001103#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001104 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001105#elif defined(__NetBSD__)
1106 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001107#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001108 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001109#elif __sun__
1110 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001111#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Saleem Abdulrasooldc51b092017-01-02 18:41:48 +00001112 return __pctype_func();
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001113#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001114 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001115#elif defined(_NEWLIB_VERSION)
1116 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1117 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001118#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001119 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001120#else
David Chisnall8074c342012-02-29 13:05:08 +00001121 // Platform not supported: abort so the person doing the port knows what to
1122 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001123# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001124 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001125 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001126 return NULL;
1127#endif
1128}
Marshall Clowb3f62842015-03-04 16:10:14 +00001129#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001130
Howard Hinnantd7a78632011-09-29 13:33:15 +00001131#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001132const int*
1133ctype<char>::__classic_lower_table() _NOEXCEPT
1134{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001135 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001136}
1137
1138const int*
1139ctype<char>::__classic_upper_table() _NOEXCEPT
1140{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001141 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001142}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001143#elif __NetBSD__
1144const short*
1145ctype<char>::__classic_lower_table() _NOEXCEPT
1146{
1147 return _C_tolower_tab_ + 1;
1148}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001149
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001150const short*
1151ctype<char>::__classic_upper_table() _NOEXCEPT
1152{
1153 return _C_toupper_tab_ + 1;
1154}
1155
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001156#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001157const int*
1158ctype<char>::__classic_lower_table() _NOEXCEPT
1159{
1160 return *__ctype_tolower_loc();
1161}
1162
1163const int*
1164ctype<char>::__classic_upper_table() _NOEXCEPT
1165{
1166 return *__ctype_toupper_loc();
1167}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001168#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001169
Howard Hinnantc51e1022010-05-11 19:42:16 +00001170// template <> class ctype_byname<char>
1171
1172ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1173 : ctype<char>(0, false, refs),
1174 __l(newlocale(LC_ALL_MASK, name, 0))
1175{
1176 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001177 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001178 " failed to construct for " + string(name));
1179}
1180
1181ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1182 : ctype<char>(0, false, refs),
1183 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1184{
1185 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001186 __throw_runtime_error("ctype_byname<char>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001187 " failed to construct for " + name);
1188}
1189
1190ctype_byname<char>::~ctype_byname()
1191{
1192 freelocale(__l);
1193}
1194
1195char
1196ctype_byname<char>::do_toupper(char_type c) const
1197{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001198 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001199}
1200
1201const char*
1202ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1203{
1204 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001205 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001206 return low;
1207}
1208
1209char
1210ctype_byname<char>::do_tolower(char_type c) const
1211{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001212 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001213}
1214
1215const char*
1216ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1217{
1218 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001219 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001220 return low;
1221}
1222
1223// template <> class ctype_byname<wchar_t>
1224
1225ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1226 : ctype<wchar_t>(refs),
1227 __l(newlocale(LC_ALL_MASK, name, 0))
1228{
1229 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001230 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001231 " failed to construct for " + string(name));
1232}
1233
1234ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1235 : ctype<wchar_t>(refs),
1236 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1237{
1238 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001239 __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001240 " failed to construct for " + name);
1241}
1242
1243ctype_byname<wchar_t>::~ctype_byname()
1244{
1245 freelocale(__l);
1246}
1247
1248bool
1249ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1250{
Alexis Huntc2017f12011-07-09 03:40:04 +00001251#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001252 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001253#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001254 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001255 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001256 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1257 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1258 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1259 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1260 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1261 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1262 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1263 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1264 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1265 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001266 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001267#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001268}
1269
1270const wchar_t*
1271ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1272{
1273 for (; low != high; ++low, ++vec)
1274 {
1275 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001276 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001277 else
1278 {
1279 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001280 wint_t ch = static_cast<wint_t>(*low);
1281 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001282 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001283#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001284 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001285 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001286#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001287 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001288 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001289 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001290 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001291 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001292 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001293#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001294 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001295 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001296#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001297 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001298 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001299 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001301#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001302 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001303 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001304#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001305#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001306 if (iswblank_l(ch, __l))
1307 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001308#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001309 }
1310 }
1311 return low;
1312}
1313
1314const wchar_t*
1315ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1316{
1317 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001318 {
1319#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001320 if (iswctype_l(*low, m, __l))
1321 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001322#else
Marshall Clowada0f732013-02-07 14:22:51 +00001323 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001324 if ((m & space) == space && iswspace_l(ch, __l)) break;
1325 if ((m & print) == print && iswprint_l(ch, __l)) break;
1326 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1327 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1328 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1329 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1330 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1331 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1332 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1333 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001334#endif
1335 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001336 return low;
1337}
1338
1339const wchar_t*
1340ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1341{
1342 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001343 {
1344#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345 if (!iswctype_l(*low, m, __l))
1346 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001347#else
Marshall Clowada0f732013-02-07 14:22:51 +00001348 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001349 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1350 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1351 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1352 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1353 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1354 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1355 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1356 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1357 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1358 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001359 break;
1360#endif
1361 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001362 return low;
1363}
1364
1365wchar_t
1366ctype_byname<wchar_t>::do_toupper(char_type c) const
1367{
1368 return towupper_l(c, __l);
1369}
1370
1371const wchar_t*
1372ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1373{
1374 for (; low != high; ++low)
1375 *low = towupper_l(*low, __l);
1376 return low;
1377}
1378
1379wchar_t
1380ctype_byname<wchar_t>::do_tolower(char_type c) const
1381{
1382 return towlower_l(c, __l);
1383}
1384
1385const wchar_t*
1386ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1387{
1388 for (; low != high; ++low)
1389 *low = towlower_l(*low, __l);
1390 return low;
1391}
1392
1393wchar_t
1394ctype_byname<wchar_t>::do_widen(char c) const
1395{
Ben Craig3756b922016-03-09 15:39:39 +00001396 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001397}
1398
1399const char*
1400ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1401{
1402 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001403 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404 return low;
1405}
1406
1407char
1408ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1409{
Ben Craig3756b922016-03-09 15:39:39 +00001410 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001411 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001412}
1413
1414const wchar_t*
1415ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1416{
1417 for (; low != high; ++low, ++dest)
1418 {
Ben Craig3756b922016-03-09 15:39:39 +00001419 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001420 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001421 }
1422 return low;
1423}
1424
1425// template <> class codecvt<char, char, mbstate_t>
1426
Howard Hinnantffb308e2010-08-22 00:03:27 +00001427locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001428
1429codecvt<char, char, mbstate_t>::~codecvt()
1430{
1431}
1432
1433codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001434codecvt<char, char, mbstate_t>::do_out(state_type&,
1435 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001436 extern_type* to, extern_type*, extern_type*& to_nxt) const
1437{
1438 frm_nxt = frm;
1439 to_nxt = to;
1440 return noconv;
1441}
1442
1443codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001444codecvt<char, char, mbstate_t>::do_in(state_type&,
1445 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001446 intern_type* to, intern_type*, intern_type*& to_nxt) const
1447{
1448 frm_nxt = frm;
1449 to_nxt = to;
1450 return noconv;
1451}
1452
1453codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001454codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001455 extern_type* to, extern_type*, extern_type*& to_nxt) const
1456{
1457 to_nxt = to;
1458 return noconv;
1459}
1460
1461int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001462codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001463{
1464 return 1;
1465}
1466
1467bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001468codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001469{
1470 return true;
1471}
1472
1473int
1474codecvt<char, char, mbstate_t>::do_length(state_type&,
1475 const extern_type* frm, const extern_type* end, size_t mx) const
1476{
Howard Hinnant28b24882011-12-01 20:21:04 +00001477 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001478}
1479
1480int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001481codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001482{
1483 return 1;
1484}
1485
1486// template <> class codecvt<wchar_t, char, mbstate_t>
1487
Howard Hinnantffb308e2010-08-22 00:03:27 +00001488locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001489
1490codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1491 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001492 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001493{
1494}
1495
1496codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1497 : locale::facet(refs),
1498 __l(newlocale(LC_ALL_MASK, nm, 0))
1499{
1500 if (__l == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00001501 __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00001502 " failed to construct for " + string(nm));
1503}
1504
1505codecvt<wchar_t, char, mbstate_t>::~codecvt()
1506{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001507 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001508 freelocale(__l);
1509}
1510
1511codecvt<wchar_t, char, mbstate_t>::result
1512codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001513 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001514 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1515{
1516 // look for first internal null in frm
1517 const intern_type* fend = frm;
1518 for (; fend != frm_end; ++fend)
1519 if (*fend == 0)
1520 break;
1521 // loop over all null-terminated sequences in frm
1522 to_nxt = to;
1523 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1524 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001525 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001527 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1528 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001529 if (n == size_t(-1))
1530 {
1531 // need to recover to_nxt
1532 for (to_nxt = to; frm != frm_nxt; ++frm)
1533 {
Ben Craig3756b922016-03-09 15:39:39 +00001534 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001535 if (n == size_t(-1))
1536 break;
1537 to_nxt += n;
1538 }
1539 frm_nxt = frm;
1540 return error;
1541 }
1542 if (n == 0)
1543 return partial;
1544 to_nxt += n;
1545 if (to_nxt == to_end)
1546 break;
1547 if (fend != frm_end) // set up next null terminated sequence
1548 {
1549 // Try to write the terminating null
1550 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001551 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001552 if (n == size_t(-1)) // on error
1553 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001554 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001555 return partial;
1556 for (extern_type* p = tmp; n; --n) // write it
1557 *to_nxt++ = *p++;
1558 ++frm_nxt;
1559 // look for next null in frm
1560 for (fend = frm_nxt; fend != frm_end; ++fend)
1561 if (*fend == 0)
1562 break;
1563 }
1564 }
1565 return frm_nxt == frm_end ? ok : partial;
1566}
1567
1568codecvt<wchar_t, char, mbstate_t>::result
1569codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001570 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001571 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1572{
1573 // look for first internal null in frm
1574 const extern_type* fend = frm;
1575 for (; fend != frm_end; ++fend)
1576 if (*fend == 0)
1577 break;
1578 // loop over all null-terminated sequences in frm
1579 to_nxt = to;
1580 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1581 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001582 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001583 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001584 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1585 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001586 if (n == size_t(-1))
1587 {
1588 // need to recover to_nxt
1589 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1590 {
Ben Craig3756b922016-03-09 15:39:39 +00001591 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1592 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001593 switch (n)
1594 {
1595 case 0:
1596 ++frm;
1597 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001598 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001599 frm_nxt = frm;
1600 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001601 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001602 frm_nxt = frm;
1603 return partial;
1604 default:
1605 frm += n;
1606 break;
1607 }
1608 }
1609 frm_nxt = frm;
1610 return frm_nxt == frm_end ? ok : partial;
1611 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001612 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001613 return error;
1614 to_nxt += n;
1615 if (to_nxt == to_end)
1616 break;
1617 if (fend != frm_end) // set up next null terminated sequence
1618 {
1619 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001620 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001621 if (n != 0) // on error
1622 return error;
1623 ++to_nxt;
1624 ++frm_nxt;
1625 // look for next null in frm
1626 for (fend = frm_nxt; fend != frm_end; ++fend)
1627 if (*fend == 0)
1628 break;
1629 }
1630 }
1631 return frm_nxt == frm_end ? ok : partial;
1632}
1633
1634codecvt<wchar_t, char, mbstate_t>::result
1635codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1636 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1637{
1638 to_nxt = to;
1639 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001640 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001641 if (n == size_t(-1) || n == 0) // on error
1642 return error;
1643 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001644 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001645 return partial;
1646 for (extern_type* p = tmp; n; --n) // write it
1647 *to_nxt++ = *p++;
1648 return ok;
1649}
1650
1651int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001652codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001653{
Ben Craig3756b922016-03-09 15:39:39 +00001654 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001655 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001656
1657 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001658 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001659 return 1; // which take more than 1 char to form a wchar_t
1660 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001661}
1662
1663bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001664codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001665{
1666 return false;
1667}
1668
1669int
1670codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1671 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1672{
1673 int nbytes = 0;
1674 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1675 {
Ben Craig3756b922016-03-09 15:39:39 +00001676 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001677 switch (n)
1678 {
1679 case 0:
1680 ++nbytes;
1681 ++frm;
1682 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001683 case size_t(-1):
1684 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001685 return nbytes;
1686 default:
1687 nbytes += n;
1688 frm += n;
1689 break;
1690 }
1691 }
1692 return nbytes;
1693}
1694
1695int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001696codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001697{
Ben Craig3756b922016-03-09 15:39:39 +00001698 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001699}
1700
1701// Valid UTF ranges
1702// UTF-32 UTF-16 UTF-8 # of code points
1703// first second first second third fourth
1704// 000000 - 00007F 0000 - 007F 00 - 7F 127
1705// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1706// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1707// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1708// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1709// 00D800 - 00DFFF invalid
1710// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1711// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1712// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1713// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1714
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001715static
1716codecvt_base::result
1717utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1718 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1719 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1720{
1721 frm_nxt = frm;
1722 to_nxt = to;
1723 if (mode & generate_header)
1724 {
1725 if (to_end-to_nxt < 3)
1726 return codecvt_base::partial;
1727 *to_nxt++ = static_cast<uint8_t>(0xEF);
1728 *to_nxt++ = static_cast<uint8_t>(0xBB);
1729 *to_nxt++ = static_cast<uint8_t>(0xBF);
1730 }
1731 for (; frm_nxt < frm_end; ++frm_nxt)
1732 {
1733 uint16_t wc1 = *frm_nxt;
1734 if (wc1 > Maxcode)
1735 return codecvt_base::error;
1736 if (wc1 < 0x0080)
1737 {
1738 if (to_end-to_nxt < 1)
1739 return codecvt_base::partial;
1740 *to_nxt++ = static_cast<uint8_t>(wc1);
1741 }
1742 else if (wc1 < 0x0800)
1743 {
1744 if (to_end-to_nxt < 2)
1745 return codecvt_base::partial;
1746 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1747 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1748 }
1749 else if (wc1 < 0xD800)
1750 {
1751 if (to_end-to_nxt < 3)
1752 return codecvt_base::partial;
1753 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1754 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1756 }
1757 else if (wc1 < 0xDC00)
1758 {
1759 if (frm_end-frm_nxt < 2)
1760 return codecvt_base::partial;
1761 uint16_t wc2 = frm_nxt[1];
1762 if ((wc2 & 0xFC00) != 0xDC00)
1763 return codecvt_base::error;
1764 if (to_end-to_nxt < 4)
1765 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001766 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1767 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001768 return codecvt_base::error;
1769 ++frm_nxt;
1770 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1771 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1772 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1773 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1774 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1775 }
1776 else if (wc1 < 0xE000)
1777 {
1778 return codecvt_base::error;
1779 }
1780 else
1781 {
1782 if (to_end-to_nxt < 3)
1783 return codecvt_base::partial;
1784 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1785 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1786 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1787 }
1788 }
1789 return codecvt_base::ok;
1790}
1791
1792static
1793codecvt_base::result
1794utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1795 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1796 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1797{
1798 frm_nxt = frm;
1799 to_nxt = to;
1800 if (mode & generate_header)
1801 {
1802 if (to_end-to_nxt < 3)
1803 return codecvt_base::partial;
1804 *to_nxt++ = static_cast<uint8_t>(0xEF);
1805 *to_nxt++ = static_cast<uint8_t>(0xBB);
1806 *to_nxt++ = static_cast<uint8_t>(0xBF);
1807 }
1808 for (; frm_nxt < frm_end; ++frm_nxt)
1809 {
1810 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1811 if (wc1 > Maxcode)
1812 return codecvt_base::error;
1813 if (wc1 < 0x0080)
1814 {
1815 if (to_end-to_nxt < 1)
1816 return codecvt_base::partial;
1817 *to_nxt++ = static_cast<uint8_t>(wc1);
1818 }
1819 else if (wc1 < 0x0800)
1820 {
1821 if (to_end-to_nxt < 2)
1822 return codecvt_base::partial;
1823 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1824 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1825 }
1826 else if (wc1 < 0xD800)
1827 {
1828 if (to_end-to_nxt < 3)
1829 return codecvt_base::partial;
1830 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1831 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1832 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1833 }
1834 else if (wc1 < 0xDC00)
1835 {
1836 if (frm_end-frm_nxt < 2)
1837 return codecvt_base::partial;
1838 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1839 if ((wc2 & 0xFC00) != 0xDC00)
1840 return codecvt_base::error;
1841 if (to_end-to_nxt < 4)
1842 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001843 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1844 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001845 return codecvt_base::error;
1846 ++frm_nxt;
1847 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1848 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1849 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1851 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1852 }
1853 else if (wc1 < 0xE000)
1854 {
1855 return codecvt_base::error;
1856 }
1857 else
1858 {
1859 if (to_end-to_nxt < 3)
1860 return codecvt_base::partial;
1861 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1862 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1863 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1864 }
1865 }
1866 return codecvt_base::ok;
1867}
1868
1869static
1870codecvt_base::result
1871utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1872 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1873 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1874{
1875 frm_nxt = frm;
1876 to_nxt = to;
1877 if (mode & consume_header)
1878 {
1879 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1880 frm_nxt[2] == 0xBF)
1881 frm_nxt += 3;
1882 }
1883 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1884 {
1885 uint8_t c1 = *frm_nxt;
1886 if (c1 > Maxcode)
1887 return codecvt_base::error;
1888 if (c1 < 0x80)
1889 {
1890 *to_nxt = static_cast<uint16_t>(c1);
1891 ++frm_nxt;
1892 }
1893 else if (c1 < 0xC2)
1894 {
1895 return codecvt_base::error;
1896 }
1897 else if (c1 < 0xE0)
1898 {
1899 if (frm_end-frm_nxt < 2)
1900 return codecvt_base::partial;
1901 uint8_t c2 = frm_nxt[1];
1902 if ((c2 & 0xC0) != 0x80)
1903 return codecvt_base::error;
1904 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1905 if (t > Maxcode)
1906 return codecvt_base::error;
1907 *to_nxt = t;
1908 frm_nxt += 2;
1909 }
1910 else if (c1 < 0xF0)
1911 {
1912 if (frm_end-frm_nxt < 3)
1913 return codecvt_base::partial;
1914 uint8_t c2 = frm_nxt[1];
1915 uint8_t c3 = frm_nxt[2];
1916 switch (c1)
1917 {
1918 case 0xE0:
1919 if ((c2 & 0xE0) != 0xA0)
1920 return codecvt_base::error;
1921 break;
1922 case 0xED:
1923 if ((c2 & 0xE0) != 0x80)
1924 return codecvt_base::error;
1925 break;
1926 default:
1927 if ((c2 & 0xC0) != 0x80)
1928 return codecvt_base::error;
1929 break;
1930 }
1931 if ((c3 & 0xC0) != 0x80)
1932 return codecvt_base::error;
1933 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1934 | ((c2 & 0x3F) << 6)
1935 | (c3 & 0x3F));
1936 if (t > Maxcode)
1937 return codecvt_base::error;
1938 *to_nxt = t;
1939 frm_nxt += 3;
1940 }
1941 else if (c1 < 0xF5)
1942 {
1943 if (frm_end-frm_nxt < 4)
1944 return codecvt_base::partial;
1945 uint8_t c2 = frm_nxt[1];
1946 uint8_t c3 = frm_nxt[2];
1947 uint8_t c4 = frm_nxt[3];
1948 switch (c1)
1949 {
1950 case 0xF0:
1951 if (!(0x90 <= c2 && c2 <= 0xBF))
1952 return codecvt_base::error;
1953 break;
1954 case 0xF4:
1955 if ((c2 & 0xF0) != 0x80)
1956 return codecvt_base::error;
1957 break;
1958 default:
1959 if ((c2 & 0xC0) != 0x80)
1960 return codecvt_base::error;
1961 break;
1962 }
1963 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1964 return codecvt_base::error;
1965 if (to_end-to_nxt < 2)
1966 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001967 if ((((c1 & 7UL) << 18) +
1968 ((c2 & 0x3FUL) << 12) +
1969 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001970 return codecvt_base::error;
1971 *to_nxt = static_cast<uint16_t>(
1972 0xD800
1973 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1974 | ((c2 & 0x0F) << 2)
1975 | ((c3 & 0x30) >> 4));
1976 *++to_nxt = static_cast<uint16_t>(
1977 0xDC00
1978 | ((c3 & 0x0F) << 6)
1979 | (c4 & 0x3F));
1980 frm_nxt += 4;
1981 }
1982 else
1983 {
1984 return codecvt_base::error;
1985 }
1986 }
1987 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1988}
1989
1990static
1991codecvt_base::result
1992utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1993 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1994 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1995{
1996 frm_nxt = frm;
1997 to_nxt = to;
1998 if (mode & consume_header)
1999 {
2000 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2001 frm_nxt[2] == 0xBF)
2002 frm_nxt += 3;
2003 }
2004 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2005 {
2006 uint8_t c1 = *frm_nxt;
2007 if (c1 > Maxcode)
2008 return codecvt_base::error;
2009 if (c1 < 0x80)
2010 {
2011 *to_nxt = static_cast<uint32_t>(c1);
2012 ++frm_nxt;
2013 }
2014 else if (c1 < 0xC2)
2015 {
2016 return codecvt_base::error;
2017 }
2018 else if (c1 < 0xE0)
2019 {
2020 if (frm_end-frm_nxt < 2)
2021 return codecvt_base::partial;
2022 uint8_t c2 = frm_nxt[1];
2023 if ((c2 & 0xC0) != 0x80)
2024 return codecvt_base::error;
2025 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2026 if (t > Maxcode)
2027 return codecvt_base::error;
2028 *to_nxt = static_cast<uint32_t>(t);
2029 frm_nxt += 2;
2030 }
2031 else if (c1 < 0xF0)
2032 {
2033 if (frm_end-frm_nxt < 3)
2034 return codecvt_base::partial;
2035 uint8_t c2 = frm_nxt[1];
2036 uint8_t c3 = frm_nxt[2];
2037 switch (c1)
2038 {
2039 case 0xE0:
2040 if ((c2 & 0xE0) != 0xA0)
2041 return codecvt_base::error;
2042 break;
2043 case 0xED:
2044 if ((c2 & 0xE0) != 0x80)
2045 return codecvt_base::error;
2046 break;
2047 default:
2048 if ((c2 & 0xC0) != 0x80)
2049 return codecvt_base::error;
2050 break;
2051 }
2052 if ((c3 & 0xC0) != 0x80)
2053 return codecvt_base::error;
2054 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2055 | ((c2 & 0x3F) << 6)
2056 | (c3 & 0x3F));
2057 if (t > Maxcode)
2058 return codecvt_base::error;
2059 *to_nxt = static_cast<uint32_t>(t);
2060 frm_nxt += 3;
2061 }
2062 else if (c1 < 0xF5)
2063 {
2064 if (frm_end-frm_nxt < 4)
2065 return codecvt_base::partial;
2066 uint8_t c2 = frm_nxt[1];
2067 uint8_t c3 = frm_nxt[2];
2068 uint8_t c4 = frm_nxt[3];
2069 switch (c1)
2070 {
2071 case 0xF0:
2072 if (!(0x90 <= c2 && c2 <= 0xBF))
2073 return codecvt_base::error;
2074 break;
2075 case 0xF4:
2076 if ((c2 & 0xF0) != 0x80)
2077 return codecvt_base::error;
2078 break;
2079 default:
2080 if ((c2 & 0xC0) != 0x80)
2081 return codecvt_base::error;
2082 break;
2083 }
2084 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2085 return codecvt_base::error;
2086 if (to_end-to_nxt < 2)
2087 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002088 if ((((c1 & 7UL) << 18) +
2089 ((c2 & 0x3FUL) << 12) +
2090 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002091 return codecvt_base::error;
2092 *to_nxt = static_cast<uint32_t>(
2093 0xD800
2094 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2095 | ((c2 & 0x0F) << 2)
2096 | ((c3 & 0x30) >> 4));
2097 *++to_nxt = static_cast<uint32_t>(
2098 0xDC00
2099 | ((c3 & 0x0F) << 6)
2100 | (c4 & 0x3F));
2101 frm_nxt += 4;
2102 }
2103 else
2104 {
2105 return codecvt_base::error;
2106 }
2107 }
2108 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2109}
2110
2111static
2112int
2113utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2114 size_t mx, unsigned long Maxcode = 0x10FFFF,
2115 codecvt_mode mode = codecvt_mode(0))
2116{
2117 const uint8_t* frm_nxt = frm;
2118 if (mode & consume_header)
2119 {
2120 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2121 frm_nxt[2] == 0xBF)
2122 frm_nxt += 3;
2123 }
2124 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2125 {
2126 uint8_t c1 = *frm_nxt;
2127 if (c1 > Maxcode)
2128 break;
2129 if (c1 < 0x80)
2130 {
2131 ++frm_nxt;
2132 }
2133 else if (c1 < 0xC2)
2134 {
2135 break;
2136 }
2137 else if (c1 < 0xE0)
2138 {
2139 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2140 break;
2141 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2142 if (t > Maxcode)
2143 break;
2144 frm_nxt += 2;
2145 }
2146 else if (c1 < 0xF0)
2147 {
2148 if (frm_end-frm_nxt < 3)
2149 break;
2150 uint8_t c2 = frm_nxt[1];
2151 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002152 switch (c1)
2153 {
2154 case 0xE0:
2155 if ((c2 & 0xE0) != 0xA0)
2156 return static_cast<int>(frm_nxt - frm);
2157 break;
2158 case 0xED:
2159 if ((c2 & 0xE0) != 0x80)
2160 return static_cast<int>(frm_nxt - frm);
2161 break;
2162 default:
2163 if ((c2 & 0xC0) != 0x80)
2164 return static_cast<int>(frm_nxt - frm);
2165 break;
2166 }
2167 if ((c3 & 0xC0) != 0x80)
2168 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002169 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002170 break;
2171 frm_nxt += 3;
2172 }
2173 else if (c1 < 0xF5)
2174 {
2175 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2176 break;
2177 uint8_t c2 = frm_nxt[1];
2178 uint8_t c3 = frm_nxt[2];
2179 uint8_t c4 = frm_nxt[3];
2180 switch (c1)
2181 {
2182 case 0xF0:
2183 if (!(0x90 <= c2 && c2 <= 0xBF))
2184 return static_cast<int>(frm_nxt - frm);
2185 break;
2186 case 0xF4:
2187 if ((c2 & 0xF0) != 0x80)
2188 return static_cast<int>(frm_nxt - frm);
2189 break;
2190 default:
2191 if ((c2 & 0xC0) != 0x80)
2192 return static_cast<int>(frm_nxt - frm);
2193 break;
2194 }
2195 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2196 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002197 if ((((c1 & 7UL) << 18) +
2198 ((c2 & 0x3FUL) << 12) +
2199 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002200 break;
2201 ++nchar16_t;
2202 frm_nxt += 4;
2203 }
2204 else
2205 {
2206 break;
2207 }
2208 }
2209 return static_cast<int>(frm_nxt - frm);
2210}
2211
2212static
2213codecvt_base::result
2214ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2215 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2216 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2217{
2218 frm_nxt = frm;
2219 to_nxt = to;
2220 if (mode & generate_header)
2221 {
2222 if (to_end-to_nxt < 3)
2223 return codecvt_base::partial;
2224 *to_nxt++ = static_cast<uint8_t>(0xEF);
2225 *to_nxt++ = static_cast<uint8_t>(0xBB);
2226 *to_nxt++ = static_cast<uint8_t>(0xBF);
2227 }
2228 for (; frm_nxt < frm_end; ++frm_nxt)
2229 {
2230 uint32_t wc = *frm_nxt;
2231 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2232 return codecvt_base::error;
2233 if (wc < 0x000080)
2234 {
2235 if (to_end-to_nxt < 1)
2236 return codecvt_base::partial;
2237 *to_nxt++ = static_cast<uint8_t>(wc);
2238 }
2239 else if (wc < 0x000800)
2240 {
2241 if (to_end-to_nxt < 2)
2242 return codecvt_base::partial;
2243 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2244 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2245 }
2246 else if (wc < 0x010000)
2247 {
2248 if (to_end-to_nxt < 3)
2249 return codecvt_base::partial;
2250 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2251 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2252 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2253 }
2254 else // if (wc < 0x110000)
2255 {
2256 if (to_end-to_nxt < 4)
2257 return codecvt_base::partial;
2258 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2259 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2260 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2261 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2262 }
2263 }
2264 return codecvt_base::ok;
2265}
2266
2267static
2268codecvt_base::result
2269utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2270 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2271 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2272{
2273 frm_nxt = frm;
2274 to_nxt = to;
2275 if (mode & consume_header)
2276 {
2277 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2278 frm_nxt[2] == 0xBF)
2279 frm_nxt += 3;
2280 }
2281 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2282 {
2283 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2284 if (c1 < 0x80)
2285 {
2286 if (c1 > Maxcode)
2287 return codecvt_base::error;
2288 *to_nxt = static_cast<uint32_t>(c1);
2289 ++frm_nxt;
2290 }
2291 else if (c1 < 0xC2)
2292 {
2293 return codecvt_base::error;
2294 }
2295 else if (c1 < 0xE0)
2296 {
2297 if (frm_end-frm_nxt < 2)
2298 return codecvt_base::partial;
2299 uint8_t c2 = frm_nxt[1];
2300 if ((c2 & 0xC0) != 0x80)
2301 return codecvt_base::error;
2302 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2303 | (c2 & 0x3F));
2304 if (t > Maxcode)
2305 return codecvt_base::error;
2306 *to_nxt = t;
2307 frm_nxt += 2;
2308 }
2309 else if (c1 < 0xF0)
2310 {
2311 if (frm_end-frm_nxt < 3)
2312 return codecvt_base::partial;
2313 uint8_t c2 = frm_nxt[1];
2314 uint8_t c3 = frm_nxt[2];
2315 switch (c1)
2316 {
2317 case 0xE0:
2318 if ((c2 & 0xE0) != 0xA0)
2319 return codecvt_base::error;
2320 break;
2321 case 0xED:
2322 if ((c2 & 0xE0) != 0x80)
2323 return codecvt_base::error;
2324 break;
2325 default:
2326 if ((c2 & 0xC0) != 0x80)
2327 return codecvt_base::error;
2328 break;
2329 }
2330 if ((c3 & 0xC0) != 0x80)
2331 return codecvt_base::error;
2332 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2333 | ((c2 & 0x3F) << 6)
2334 | (c3 & 0x3F));
2335 if (t > Maxcode)
2336 return codecvt_base::error;
2337 *to_nxt = t;
2338 frm_nxt += 3;
2339 }
2340 else if (c1 < 0xF5)
2341 {
2342 if (frm_end-frm_nxt < 4)
2343 return codecvt_base::partial;
2344 uint8_t c2 = frm_nxt[1];
2345 uint8_t c3 = frm_nxt[2];
2346 uint8_t c4 = frm_nxt[3];
2347 switch (c1)
2348 {
2349 case 0xF0:
2350 if (!(0x90 <= c2 && c2 <= 0xBF))
2351 return codecvt_base::error;
2352 break;
2353 case 0xF4:
2354 if ((c2 & 0xF0) != 0x80)
2355 return codecvt_base::error;
2356 break;
2357 default:
2358 if ((c2 & 0xC0) != 0x80)
2359 return codecvt_base::error;
2360 break;
2361 }
2362 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2363 return codecvt_base::error;
2364 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2365 | ((c2 & 0x3F) << 12)
2366 | ((c3 & 0x3F) << 6)
2367 | (c4 & 0x3F));
2368 if (t > Maxcode)
2369 return codecvt_base::error;
2370 *to_nxt = t;
2371 frm_nxt += 4;
2372 }
2373 else
2374 {
2375 return codecvt_base::error;
2376 }
2377 }
2378 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2379}
2380
2381static
2382int
2383utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2384 size_t mx, unsigned long Maxcode = 0x10FFFF,
2385 codecvt_mode mode = codecvt_mode(0))
2386{
2387 const uint8_t* frm_nxt = frm;
2388 if (mode & consume_header)
2389 {
2390 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2391 frm_nxt[2] == 0xBF)
2392 frm_nxt += 3;
2393 }
2394 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2395 {
2396 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2397 if (c1 < 0x80)
2398 {
2399 if (c1 > Maxcode)
2400 break;
2401 ++frm_nxt;
2402 }
2403 else if (c1 < 0xC2)
2404 {
2405 break;
2406 }
2407 else if (c1 < 0xE0)
2408 {
2409 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2410 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002411 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002412 break;
2413 frm_nxt += 2;
2414 }
2415 else if (c1 < 0xF0)
2416 {
2417 if (frm_end-frm_nxt < 3)
2418 break;
2419 uint8_t c2 = frm_nxt[1];
2420 uint8_t c3 = frm_nxt[2];
2421 switch (c1)
2422 {
2423 case 0xE0:
2424 if ((c2 & 0xE0) != 0xA0)
2425 return static_cast<int>(frm_nxt - frm);
2426 break;
2427 case 0xED:
2428 if ((c2 & 0xE0) != 0x80)
2429 return static_cast<int>(frm_nxt - frm);
2430 break;
2431 default:
2432 if ((c2 & 0xC0) != 0x80)
2433 return static_cast<int>(frm_nxt - frm);
2434 break;
2435 }
2436 if ((c3 & 0xC0) != 0x80)
2437 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002438 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002439 break;
2440 frm_nxt += 3;
2441 }
2442 else if (c1 < 0xF5)
2443 {
2444 if (frm_end-frm_nxt < 4)
2445 break;
2446 uint8_t c2 = frm_nxt[1];
2447 uint8_t c3 = frm_nxt[2];
2448 uint8_t c4 = frm_nxt[3];
2449 switch (c1)
2450 {
2451 case 0xF0:
2452 if (!(0x90 <= c2 && c2 <= 0xBF))
2453 return static_cast<int>(frm_nxt - frm);
2454 break;
2455 case 0xF4:
2456 if ((c2 & 0xF0) != 0x80)
2457 return static_cast<int>(frm_nxt - frm);
2458 break;
2459 default:
2460 if ((c2 & 0xC0) != 0x80)
2461 return static_cast<int>(frm_nxt - frm);
2462 break;
2463 }
2464 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2465 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002466 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2467 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002468 break;
2469 frm_nxt += 4;
2470 }
2471 else
2472 {
2473 break;
2474 }
2475 }
2476 return static_cast<int>(frm_nxt - frm);
2477}
2478
2479static
2480codecvt_base::result
2481ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2482 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2483 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2484{
2485 frm_nxt = frm;
2486 to_nxt = to;
2487 if (mode & generate_header)
2488 {
2489 if (to_end-to_nxt < 3)
2490 return codecvt_base::partial;
2491 *to_nxt++ = static_cast<uint8_t>(0xEF);
2492 *to_nxt++ = static_cast<uint8_t>(0xBB);
2493 *to_nxt++ = static_cast<uint8_t>(0xBF);
2494 }
2495 for (; frm_nxt < frm_end; ++frm_nxt)
2496 {
2497 uint16_t wc = *frm_nxt;
2498 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2499 return codecvt_base::error;
2500 if (wc < 0x0080)
2501 {
2502 if (to_end-to_nxt < 1)
2503 return codecvt_base::partial;
2504 *to_nxt++ = static_cast<uint8_t>(wc);
2505 }
2506 else if (wc < 0x0800)
2507 {
2508 if (to_end-to_nxt < 2)
2509 return codecvt_base::partial;
2510 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2511 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2512 }
2513 else // if (wc <= 0xFFFF)
2514 {
2515 if (to_end-to_nxt < 3)
2516 return codecvt_base::partial;
2517 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2518 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2519 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2520 }
2521 }
2522 return codecvt_base::ok;
2523}
2524
2525static
2526codecvt_base::result
2527utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2528 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2529 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2530{
2531 frm_nxt = frm;
2532 to_nxt = to;
2533 if (mode & consume_header)
2534 {
2535 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2536 frm_nxt[2] == 0xBF)
2537 frm_nxt += 3;
2538 }
2539 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2540 {
2541 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2542 if (c1 < 0x80)
2543 {
2544 if (c1 > Maxcode)
2545 return codecvt_base::error;
2546 *to_nxt = static_cast<uint16_t>(c1);
2547 ++frm_nxt;
2548 }
2549 else if (c1 < 0xC2)
2550 {
2551 return codecvt_base::error;
2552 }
2553 else if (c1 < 0xE0)
2554 {
2555 if (frm_end-frm_nxt < 2)
2556 return codecvt_base::partial;
2557 uint8_t c2 = frm_nxt[1];
2558 if ((c2 & 0xC0) != 0x80)
2559 return codecvt_base::error;
2560 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2561 | (c2 & 0x3F));
2562 if (t > Maxcode)
2563 return codecvt_base::error;
2564 *to_nxt = t;
2565 frm_nxt += 2;
2566 }
2567 else if (c1 < 0xF0)
2568 {
2569 if (frm_end-frm_nxt < 3)
2570 return codecvt_base::partial;
2571 uint8_t c2 = frm_nxt[1];
2572 uint8_t c3 = frm_nxt[2];
2573 switch (c1)
2574 {
2575 case 0xE0:
2576 if ((c2 & 0xE0) != 0xA0)
2577 return codecvt_base::error;
2578 break;
2579 case 0xED:
2580 if ((c2 & 0xE0) != 0x80)
2581 return codecvt_base::error;
2582 break;
2583 default:
2584 if ((c2 & 0xC0) != 0x80)
2585 return codecvt_base::error;
2586 break;
2587 }
2588 if ((c3 & 0xC0) != 0x80)
2589 return codecvt_base::error;
2590 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2591 | ((c2 & 0x3F) << 6)
2592 | (c3 & 0x3F));
2593 if (t > Maxcode)
2594 return codecvt_base::error;
2595 *to_nxt = t;
2596 frm_nxt += 3;
2597 }
2598 else
2599 {
2600 return codecvt_base::error;
2601 }
2602 }
2603 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2604}
2605
2606static
2607int
2608utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2609 size_t mx, unsigned long Maxcode = 0x10FFFF,
2610 codecvt_mode mode = codecvt_mode(0))
2611{
2612 const uint8_t* frm_nxt = frm;
2613 if (mode & consume_header)
2614 {
2615 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2616 frm_nxt[2] == 0xBF)
2617 frm_nxt += 3;
2618 }
2619 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2620 {
2621 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2622 if (c1 < 0x80)
2623 {
2624 if (c1 > Maxcode)
2625 break;
2626 ++frm_nxt;
2627 }
2628 else if (c1 < 0xC2)
2629 {
2630 break;
2631 }
2632 else if (c1 < 0xE0)
2633 {
2634 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2635 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002636 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002637 break;
2638 frm_nxt += 2;
2639 }
2640 else if (c1 < 0xF0)
2641 {
2642 if (frm_end-frm_nxt < 3)
2643 break;
2644 uint8_t c2 = frm_nxt[1];
2645 uint8_t c3 = frm_nxt[2];
2646 switch (c1)
2647 {
2648 case 0xE0:
2649 if ((c2 & 0xE0) != 0xA0)
2650 return static_cast<int>(frm_nxt - frm);
2651 break;
2652 case 0xED:
2653 if ((c2 & 0xE0) != 0x80)
2654 return static_cast<int>(frm_nxt - frm);
2655 break;
2656 default:
2657 if ((c2 & 0xC0) != 0x80)
2658 return static_cast<int>(frm_nxt - frm);
2659 break;
2660 }
2661 if ((c3 & 0xC0) != 0x80)
2662 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002663 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002664 break;
2665 frm_nxt += 3;
2666 }
2667 else
2668 {
2669 break;
2670 }
2671 }
2672 return static_cast<int>(frm_nxt - frm);
2673}
2674
2675static
2676codecvt_base::result
2677ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2678 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2679 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2680{
2681 frm_nxt = frm;
2682 to_nxt = to;
2683 if (mode & generate_header)
2684 {
2685 if (to_end-to_nxt < 2)
2686 return codecvt_base::partial;
2687 *to_nxt++ = static_cast<uint8_t>(0xFE);
2688 *to_nxt++ = static_cast<uint8_t>(0xFF);
2689 }
2690 for (; frm_nxt < frm_end; ++frm_nxt)
2691 {
2692 uint32_t wc = *frm_nxt;
2693 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2694 return codecvt_base::error;
2695 if (wc < 0x010000)
2696 {
2697 if (to_end-to_nxt < 2)
2698 return codecvt_base::partial;
2699 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2700 *to_nxt++ = static_cast<uint8_t>(wc);
2701 }
2702 else
2703 {
2704 if (to_end-to_nxt < 4)
2705 return codecvt_base::partial;
2706 uint16_t t = static_cast<uint16_t>(
2707 0xD800
2708 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2709 | ((wc & 0x00FC00) >> 10));
2710 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2711 *to_nxt++ = static_cast<uint8_t>(t);
2712 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2713 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2714 *to_nxt++ = static_cast<uint8_t>(t);
2715 }
2716 }
2717 return codecvt_base::ok;
2718}
2719
2720static
2721codecvt_base::result
2722utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2723 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2724 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2725{
2726 frm_nxt = frm;
2727 to_nxt = to;
2728 if (mode & consume_header)
2729 {
2730 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2731 frm_nxt += 2;
2732 }
2733 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2734 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002735 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002736 if ((c1 & 0xFC00) == 0xDC00)
2737 return codecvt_base::error;
2738 if ((c1 & 0xFC00) != 0xD800)
2739 {
2740 if (c1 > Maxcode)
2741 return codecvt_base::error;
2742 *to_nxt = static_cast<uint32_t>(c1);
2743 frm_nxt += 2;
2744 }
2745 else
2746 {
2747 if (frm_end-frm_nxt < 4)
2748 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002749 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002750 if ((c2 & 0xFC00) != 0xDC00)
2751 return codecvt_base::error;
2752 uint32_t t = static_cast<uint32_t>(
2753 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2754 | ((c1 & 0x003F) << 10)
2755 | (c2 & 0x03FF));
2756 if (t > Maxcode)
2757 return codecvt_base::error;
2758 *to_nxt = t;
2759 frm_nxt += 4;
2760 }
2761 }
2762 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2763}
2764
2765static
2766int
2767utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2768 size_t mx, unsigned long Maxcode = 0x10FFFF,
2769 codecvt_mode mode = codecvt_mode(0))
2770{
2771 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002772 if (mode & consume_header)
2773 {
2774 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2775 frm_nxt += 2;
2776 }
2777 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2778 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002779 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002780 if ((c1 & 0xFC00) == 0xDC00)
2781 break;
2782 if ((c1 & 0xFC00) != 0xD800)
2783 {
2784 if (c1 > Maxcode)
2785 break;
2786 frm_nxt += 2;
2787 }
2788 else
2789 {
2790 if (frm_end-frm_nxt < 4)
2791 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002792 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002793 if ((c2 & 0xFC00) != 0xDC00)
2794 break;
2795 uint32_t t = static_cast<uint32_t>(
2796 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2797 | ((c1 & 0x003F) << 10)
2798 | (c2 & 0x03FF));
2799 if (t > Maxcode)
2800 break;
2801 frm_nxt += 4;
2802 }
2803 }
2804 return static_cast<int>(frm_nxt - frm);
2805}
2806
2807static
2808codecvt_base::result
2809ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2810 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2811 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2812{
2813 frm_nxt = frm;
2814 to_nxt = to;
2815 if (mode & generate_header)
2816 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002817 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002818 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002819 *to_nxt++ = static_cast<uint8_t>(0xFF);
2820 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002821 }
2822 for (; frm_nxt < frm_end; ++frm_nxt)
2823 {
2824 uint32_t wc = *frm_nxt;
2825 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2826 return codecvt_base::error;
2827 if (wc < 0x010000)
2828 {
2829 if (to_end-to_nxt < 2)
2830 return codecvt_base::partial;
2831 *to_nxt++ = static_cast<uint8_t>(wc);
2832 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2833 }
2834 else
2835 {
2836 if (to_end-to_nxt < 4)
2837 return codecvt_base::partial;
2838 uint16_t t = static_cast<uint16_t>(
2839 0xD800
2840 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2841 | ((wc & 0x00FC00) >> 10));
2842 *to_nxt++ = static_cast<uint8_t>(t);
2843 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2844 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2845 *to_nxt++ = static_cast<uint8_t>(t);
2846 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2847 }
2848 }
2849 return codecvt_base::ok;
2850}
2851
2852static
2853codecvt_base::result
2854utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2855 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2856 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2857{
2858 frm_nxt = frm;
2859 to_nxt = to;
2860 if (mode & consume_header)
2861 {
2862 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2863 frm_nxt += 2;
2864 }
2865 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2866 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002867 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002868 if ((c1 & 0xFC00) == 0xDC00)
2869 return codecvt_base::error;
2870 if ((c1 & 0xFC00) != 0xD800)
2871 {
2872 if (c1 > Maxcode)
2873 return codecvt_base::error;
2874 *to_nxt = static_cast<uint32_t>(c1);
2875 frm_nxt += 2;
2876 }
2877 else
2878 {
2879 if (frm_end-frm_nxt < 4)
2880 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002881 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002882 if ((c2 & 0xFC00) != 0xDC00)
2883 return codecvt_base::error;
2884 uint32_t t = static_cast<uint32_t>(
2885 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2886 | ((c1 & 0x003F) << 10)
2887 | (c2 & 0x03FF));
2888 if (t > Maxcode)
2889 return codecvt_base::error;
2890 *to_nxt = t;
2891 frm_nxt += 4;
2892 }
2893 }
2894 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2895}
2896
2897static
2898int
2899utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2900 size_t mx, unsigned long Maxcode = 0x10FFFF,
2901 codecvt_mode mode = codecvt_mode(0))
2902{
2903 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002904 if (mode & consume_header)
2905 {
2906 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2907 frm_nxt += 2;
2908 }
2909 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2910 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002911 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002912 if ((c1 & 0xFC00) == 0xDC00)
2913 break;
2914 if ((c1 & 0xFC00) != 0xD800)
2915 {
2916 if (c1 > Maxcode)
2917 break;
2918 frm_nxt += 2;
2919 }
2920 else
2921 {
2922 if (frm_end-frm_nxt < 4)
2923 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002924 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002925 if ((c2 & 0xFC00) != 0xDC00)
2926 break;
2927 uint32_t t = static_cast<uint32_t>(
2928 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2929 | ((c1 & 0x003F) << 10)
2930 | (c2 & 0x03FF));
2931 if (t > Maxcode)
2932 break;
2933 frm_nxt += 4;
2934 }
2935 }
2936 return static_cast<int>(frm_nxt - frm);
2937}
2938
2939static
2940codecvt_base::result
2941ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2942 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2943 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2944{
2945 frm_nxt = frm;
2946 to_nxt = to;
2947 if (mode & generate_header)
2948 {
2949 if (to_end-to_nxt < 2)
2950 return codecvt_base::partial;
2951 *to_nxt++ = static_cast<uint8_t>(0xFE);
2952 *to_nxt++ = static_cast<uint8_t>(0xFF);
2953 }
2954 for (; frm_nxt < frm_end; ++frm_nxt)
2955 {
2956 uint16_t wc = *frm_nxt;
2957 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2958 return codecvt_base::error;
2959 if (to_end-to_nxt < 2)
2960 return codecvt_base::partial;
2961 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2962 *to_nxt++ = static_cast<uint8_t>(wc);
2963 }
2964 return codecvt_base::ok;
2965}
2966
2967static
2968codecvt_base::result
2969utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2970 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2971 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2972{
2973 frm_nxt = frm;
2974 to_nxt = to;
2975 if (mode & consume_header)
2976 {
2977 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2978 frm_nxt += 2;
2979 }
2980 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2981 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002982 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002983 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2984 return codecvt_base::error;
2985 *to_nxt = c1;
2986 frm_nxt += 2;
2987 }
2988 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2989}
2990
2991static
2992int
2993utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2994 size_t mx, unsigned long Maxcode = 0x10FFFF,
2995 codecvt_mode mode = codecvt_mode(0))
2996{
2997 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002998 if (mode & consume_header)
2999 {
3000 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3001 frm_nxt += 2;
3002 }
3003 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3004 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003005 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003006 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3007 break;
3008 frm_nxt += 2;
3009 }
3010 return static_cast<int>(frm_nxt - frm);
3011}
3012
3013static
3014codecvt_base::result
3015ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3016 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3017 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3018{
3019 frm_nxt = frm;
3020 to_nxt = to;
3021 if (mode & generate_header)
3022 {
3023 if (to_end-to_nxt < 2)
3024 return codecvt_base::partial;
3025 *to_nxt++ = static_cast<uint8_t>(0xFF);
3026 *to_nxt++ = static_cast<uint8_t>(0xFE);
3027 }
3028 for (; frm_nxt < frm_end; ++frm_nxt)
3029 {
3030 uint16_t wc = *frm_nxt;
3031 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3032 return codecvt_base::error;
3033 if (to_end-to_nxt < 2)
3034 return codecvt_base::partial;
3035 *to_nxt++ = static_cast<uint8_t>(wc);
3036 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3037 }
3038 return codecvt_base::ok;
3039}
3040
3041static
3042codecvt_base::result
3043utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3044 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3045 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3046{
3047 frm_nxt = frm;
3048 to_nxt = to;
3049 if (mode & consume_header)
3050 {
3051 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3052 frm_nxt += 2;
3053 }
3054 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3055 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003056 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003057 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3058 return codecvt_base::error;
3059 *to_nxt = c1;
3060 frm_nxt += 2;
3061 }
3062 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3063}
3064
3065static
3066int
3067utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3068 size_t mx, unsigned long Maxcode = 0x10FFFF,
3069 codecvt_mode mode = codecvt_mode(0))
3070{
3071 const uint8_t* frm_nxt = frm;
3072 frm_nxt = frm;
3073 if (mode & consume_header)
3074 {
3075 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3076 frm_nxt += 2;
3077 }
3078 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3079 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003080 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003081 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3082 break;
3083 frm_nxt += 2;
3084 }
3085 return static_cast<int>(frm_nxt - frm);
3086}
3087
Howard Hinnantc51e1022010-05-11 19:42:16 +00003088// template <> class codecvt<char16_t, char, mbstate_t>
3089
Howard Hinnantffb308e2010-08-22 00:03:27 +00003090locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003091
3092codecvt<char16_t, char, mbstate_t>::~codecvt()
3093{
3094}
3095
3096codecvt<char16_t, char, mbstate_t>::result
3097codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003098 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003099 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3100{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003101 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3102 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3103 const uint16_t* _frm_nxt = _frm;
3104 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3105 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3106 uint8_t* _to_nxt = _to;
3107 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3108 frm_nxt = frm + (_frm_nxt - _frm);
3109 to_nxt = to + (_to_nxt - _to);
3110 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003111}
3112
3113codecvt<char16_t, char, mbstate_t>::result
3114codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003115 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003116 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3117{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003118 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3119 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3120 const uint8_t* _frm_nxt = _frm;
3121 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3122 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3123 uint16_t* _to_nxt = _to;
3124 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3125 frm_nxt = frm + (_frm_nxt - _frm);
3126 to_nxt = to + (_to_nxt - _to);
3127 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003128}
3129
3130codecvt<char16_t, char, mbstate_t>::result
3131codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3132 extern_type* to, extern_type*, extern_type*& to_nxt) const
3133{
3134 to_nxt = to;
3135 return noconv;
3136}
3137
3138int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003139codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003140{
3141 return 0;
3142}
3143
3144bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003145codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003146{
3147 return false;
3148}
3149
3150int
3151codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3152 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3153{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003154 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3155 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3156 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003157}
3158
3159int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003160codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003161{
3162 return 4;
3163}
3164
3165// template <> class codecvt<char32_t, char, mbstate_t>
3166
Howard Hinnantffb308e2010-08-22 00:03:27 +00003167locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003168
3169codecvt<char32_t, char, mbstate_t>::~codecvt()
3170{
3171}
3172
3173codecvt<char32_t, char, mbstate_t>::result
3174codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003175 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003176 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3177{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003178 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3179 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3180 const uint32_t* _frm_nxt = _frm;
3181 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3182 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3183 uint8_t* _to_nxt = _to;
3184 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3185 frm_nxt = frm + (_frm_nxt - _frm);
3186 to_nxt = to + (_to_nxt - _to);
3187 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003188}
3189
3190codecvt<char32_t, char, mbstate_t>::result
3191codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003192 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003193 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3194{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003195 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3196 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3197 const uint8_t* _frm_nxt = _frm;
3198 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3199 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3200 uint32_t* _to_nxt = _to;
3201 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3202 frm_nxt = frm + (_frm_nxt - _frm);
3203 to_nxt = to + (_to_nxt - _to);
3204 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003205}
3206
3207codecvt<char32_t, char, mbstate_t>::result
3208codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3209 extern_type* to, extern_type*, extern_type*& to_nxt) const
3210{
3211 to_nxt = to;
3212 return noconv;
3213}
3214
3215int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003216codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003217{
3218 return 0;
3219}
3220
3221bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003222codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003223{
3224 return false;
3225}
3226
3227int
3228codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3229 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3230{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003231 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3232 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3233 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003234}
3235
3236int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003237codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003238{
3239 return 4;
3240}
3241
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003242// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003243
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003244__codecvt_utf8<wchar_t>::result
3245__codecvt_utf8<wchar_t>::do_out(state_type&,
3246 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003247 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3248{
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003249#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003250 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3251 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3252 const uint16_t* _frm_nxt = _frm;
3253#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003254 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3255 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3256 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003257#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003258 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3259 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3260 uint8_t* _to_nxt = _to;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003261#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003262 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3263 _Maxcode_, _Mode_);
3264#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003265 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3266 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003267#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003268 frm_nxt = frm + (_frm_nxt - _frm);
3269 to_nxt = to + (_to_nxt - _to);
3270 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003271}
3272
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003273__codecvt_utf8<wchar_t>::result
3274__codecvt_utf8<wchar_t>::do_in(state_type&,
3275 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003276 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3277{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003278 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3279 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3280 const uint8_t* _frm_nxt = _frm;
Saleem Abdulrasoolee302e42017-01-03 21:53:51 +00003281#if defined(_LIBCPP_SHORT_WCHAR)
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003282 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3283 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3284 uint16_t* _to_nxt = _to;
3285 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3286 _Maxcode_, _Mode_);
3287#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003288 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3289 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3290 uint32_t* _to_nxt = _to;
3291 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3292 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003293#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003294 frm_nxt = frm + (_frm_nxt - _frm);
3295 to_nxt = to + (_to_nxt - _to);
3296 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003297}
3298
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003299__codecvt_utf8<wchar_t>::result
3300__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003301 extern_type* to, extern_type*, extern_type*& to_nxt) const
3302{
3303 to_nxt = to;
3304 return noconv;
3305}
3306
3307int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003308__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003309{
3310 return 0;
3311}
3312
3313bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003314__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003315{
3316 return false;
3317}
3318
3319int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003320__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003321 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3322{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003323 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3324 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3325 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003326}
3327
3328int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003329__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003330{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003331 if (_Mode_ & consume_header)
3332 return 7;
3333 return 4;
3334}
3335
3336// __codecvt_utf8<char16_t>
3337
3338__codecvt_utf8<char16_t>::result
3339__codecvt_utf8<char16_t>::do_out(state_type&,
3340 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3341 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3342{
3343 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3344 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3345 const uint16_t* _frm_nxt = _frm;
3346 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3347 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3348 uint8_t* _to_nxt = _to;
3349 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3350 _Maxcode_, _Mode_);
3351 frm_nxt = frm + (_frm_nxt - _frm);
3352 to_nxt = to + (_to_nxt - _to);
3353 return r;
3354}
3355
3356__codecvt_utf8<char16_t>::result
3357__codecvt_utf8<char16_t>::do_in(state_type&,
3358 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3359 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3360{
3361 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3362 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3363 const uint8_t* _frm_nxt = _frm;
3364 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3365 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3366 uint16_t* _to_nxt = _to;
3367 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3368 _Maxcode_, _Mode_);
3369 frm_nxt = frm + (_frm_nxt - _frm);
3370 to_nxt = to + (_to_nxt - _to);
3371 return r;
3372}
3373
3374__codecvt_utf8<char16_t>::result
3375__codecvt_utf8<char16_t>::do_unshift(state_type&,
3376 extern_type* to, extern_type*, extern_type*& to_nxt) const
3377{
3378 to_nxt = to;
3379 return noconv;
3380}
3381
3382int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003383__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003384{
3385 return 0;
3386}
3387
3388bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003389__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003390{
3391 return false;
3392}
3393
3394int
3395__codecvt_utf8<char16_t>::do_length(state_type&,
3396 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3397{
3398 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3399 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3400 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3401}
3402
3403int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003404__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003405{
3406 if (_Mode_ & consume_header)
3407 return 6;
3408 return 3;
3409}
3410
3411// __codecvt_utf8<char32_t>
3412
3413__codecvt_utf8<char32_t>::result
3414__codecvt_utf8<char32_t>::do_out(state_type&,
3415 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3416 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3417{
3418 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3419 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3420 const uint32_t* _frm_nxt = _frm;
3421 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3422 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3423 uint8_t* _to_nxt = _to;
3424 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3425 _Maxcode_, _Mode_);
3426 frm_nxt = frm + (_frm_nxt - _frm);
3427 to_nxt = to + (_to_nxt - _to);
3428 return r;
3429}
3430
3431__codecvt_utf8<char32_t>::result
3432__codecvt_utf8<char32_t>::do_in(state_type&,
3433 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3434 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3435{
3436 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3437 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3438 const uint8_t* _frm_nxt = _frm;
3439 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3440 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3441 uint32_t* _to_nxt = _to;
3442 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3443 _Maxcode_, _Mode_);
3444 frm_nxt = frm + (_frm_nxt - _frm);
3445 to_nxt = to + (_to_nxt - _to);
3446 return r;
3447}
3448
3449__codecvt_utf8<char32_t>::result
3450__codecvt_utf8<char32_t>::do_unshift(state_type&,
3451 extern_type* to, extern_type*, extern_type*& to_nxt) const
3452{
3453 to_nxt = to;
3454 return noconv;
3455}
3456
3457int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003458__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003459{
3460 return 0;
3461}
3462
3463bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003464__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003465{
3466 return false;
3467}
3468
3469int
3470__codecvt_utf8<char32_t>::do_length(state_type&,
3471 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3472{
3473 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3474 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3475 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3476}
3477
3478int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003479__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003480{
3481 if (_Mode_ & consume_header)
3482 return 7;
3483 return 4;
3484}
3485
3486// __codecvt_utf16<wchar_t, false>
3487
3488__codecvt_utf16<wchar_t, false>::result
3489__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3490 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3491 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3492{
3493 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3494 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3495 const uint32_t* _frm_nxt = _frm;
3496 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3497 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3498 uint8_t* _to_nxt = _to;
3499 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3500 _Maxcode_, _Mode_);
3501 frm_nxt = frm + (_frm_nxt - _frm);
3502 to_nxt = to + (_to_nxt - _to);
3503 return r;
3504}
3505
3506__codecvt_utf16<wchar_t, false>::result
3507__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3508 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3509 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3510{
3511 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3512 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3513 const uint8_t* _frm_nxt = _frm;
3514 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3515 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3516 uint32_t* _to_nxt = _to;
3517 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3518 _Maxcode_, _Mode_);
3519 frm_nxt = frm + (_frm_nxt - _frm);
3520 to_nxt = to + (_to_nxt - _to);
3521 return r;
3522}
3523
3524__codecvt_utf16<wchar_t, false>::result
3525__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3526 extern_type* to, extern_type*, extern_type*& to_nxt) const
3527{
3528 to_nxt = to;
3529 return noconv;
3530}
3531
3532int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003533__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003534{
3535 return 0;
3536}
3537
3538bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003539__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003540{
3541 return false;
3542}
3543
3544int
3545__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3546 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3547{
3548 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3549 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3550 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3551}
3552
3553int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003554__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003555{
3556 if (_Mode_ & consume_header)
3557 return 6;
3558 return 4;
3559}
3560
3561// __codecvt_utf16<wchar_t, true>
3562
3563__codecvt_utf16<wchar_t, true>::result
3564__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3565 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3566 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3567{
3568 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3569 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3570 const uint32_t* _frm_nxt = _frm;
3571 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3572 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3573 uint8_t* _to_nxt = _to;
3574 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3575 _Maxcode_, _Mode_);
3576 frm_nxt = frm + (_frm_nxt - _frm);
3577 to_nxt = to + (_to_nxt - _to);
3578 return r;
3579}
3580
3581__codecvt_utf16<wchar_t, true>::result
3582__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3583 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3584 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3585{
3586 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3587 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3588 const uint8_t* _frm_nxt = _frm;
3589 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3590 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3591 uint32_t* _to_nxt = _to;
3592 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3593 _Maxcode_, _Mode_);
3594 frm_nxt = frm + (_frm_nxt - _frm);
3595 to_nxt = to + (_to_nxt - _to);
3596 return r;
3597}
3598
3599__codecvt_utf16<wchar_t, true>::result
3600__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3601 extern_type* to, extern_type*, extern_type*& to_nxt) const
3602{
3603 to_nxt = to;
3604 return noconv;
3605}
3606
3607int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003608__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003609{
3610 return 0;
3611}
3612
3613bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003614__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003615{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003616 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003617}
3618
3619int
3620__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3621 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3622{
3623 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3624 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3625 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3626}
3627
3628int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003629__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003630{
3631 if (_Mode_ & consume_header)
3632 return 6;
3633 return 4;
3634}
3635
3636// __codecvt_utf16<char16_t, false>
3637
3638__codecvt_utf16<char16_t, false>::result
3639__codecvt_utf16<char16_t, false>::do_out(state_type&,
3640 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3641 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3642{
3643 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3644 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3645 const uint16_t* _frm_nxt = _frm;
3646 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3647 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3648 uint8_t* _to_nxt = _to;
3649 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3650 _Maxcode_, _Mode_);
3651 frm_nxt = frm + (_frm_nxt - _frm);
3652 to_nxt = to + (_to_nxt - _to);
3653 return r;
3654}
3655
3656__codecvt_utf16<char16_t, false>::result
3657__codecvt_utf16<char16_t, false>::do_in(state_type&,
3658 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3659 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3660{
3661 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3662 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3663 const uint8_t* _frm_nxt = _frm;
3664 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3665 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3666 uint16_t* _to_nxt = _to;
3667 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3668 _Maxcode_, _Mode_);
3669 frm_nxt = frm + (_frm_nxt - _frm);
3670 to_nxt = to + (_to_nxt - _to);
3671 return r;
3672}
3673
3674__codecvt_utf16<char16_t, false>::result
3675__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3676 extern_type* to, extern_type*, extern_type*& to_nxt) const
3677{
3678 to_nxt = to;
3679 return noconv;
3680}
3681
3682int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003683__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003684{
3685 return 0;
3686}
3687
3688bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003689__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003690{
3691 return false;
3692}
3693
3694int
3695__codecvt_utf16<char16_t, false>::do_length(state_type&,
3696 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3697{
3698 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3699 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3700 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3701}
3702
3703int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003704__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003705{
3706 if (_Mode_ & consume_header)
3707 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003708 return 2;
3709}
3710
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003711// __codecvt_utf16<char16_t, true>
3712
3713__codecvt_utf16<char16_t, true>::result
3714__codecvt_utf16<char16_t, true>::do_out(state_type&,
3715 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3716 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3717{
3718 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3719 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3720 const uint16_t* _frm_nxt = _frm;
3721 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3722 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3723 uint8_t* _to_nxt = _to;
3724 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3725 _Maxcode_, _Mode_);
3726 frm_nxt = frm + (_frm_nxt - _frm);
3727 to_nxt = to + (_to_nxt - _to);
3728 return r;
3729}
3730
3731__codecvt_utf16<char16_t, true>::result
3732__codecvt_utf16<char16_t, true>::do_in(state_type&,
3733 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3734 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3735{
3736 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3737 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3738 const uint8_t* _frm_nxt = _frm;
3739 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3740 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3741 uint16_t* _to_nxt = _to;
3742 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3743 _Maxcode_, _Mode_);
3744 frm_nxt = frm + (_frm_nxt - _frm);
3745 to_nxt = to + (_to_nxt - _to);
3746 return r;
3747}
3748
3749__codecvt_utf16<char16_t, true>::result
3750__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3751 extern_type* to, extern_type*, extern_type*& to_nxt) const
3752{
3753 to_nxt = to;
3754 return noconv;
3755}
3756
3757int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003758__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003759{
3760 return 0;
3761}
3762
3763bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003764__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003765{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003766 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003767}
3768
3769int
3770__codecvt_utf16<char16_t, true>::do_length(state_type&,
3771 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3772{
3773 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3774 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3775 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3776}
3777
3778int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003779__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003780{
3781 if (_Mode_ & consume_header)
3782 return 4;
3783 return 2;
3784}
3785
3786// __codecvt_utf16<char32_t, false>
3787
3788__codecvt_utf16<char32_t, false>::result
3789__codecvt_utf16<char32_t, false>::do_out(state_type&,
3790 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3791 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3792{
3793 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3794 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3795 const uint32_t* _frm_nxt = _frm;
3796 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3797 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3798 uint8_t* _to_nxt = _to;
3799 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3800 _Maxcode_, _Mode_);
3801 frm_nxt = frm + (_frm_nxt - _frm);
3802 to_nxt = to + (_to_nxt - _to);
3803 return r;
3804}
3805
3806__codecvt_utf16<char32_t, false>::result
3807__codecvt_utf16<char32_t, false>::do_in(state_type&,
3808 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3809 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3810{
3811 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3812 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3813 const uint8_t* _frm_nxt = _frm;
3814 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3815 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3816 uint32_t* _to_nxt = _to;
3817 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3818 _Maxcode_, _Mode_);
3819 frm_nxt = frm + (_frm_nxt - _frm);
3820 to_nxt = to + (_to_nxt - _to);
3821 return r;
3822}
3823
3824__codecvt_utf16<char32_t, false>::result
3825__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3826 extern_type* to, extern_type*, extern_type*& to_nxt) const
3827{
3828 to_nxt = to;
3829 return noconv;
3830}
3831
3832int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003833__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003834{
3835 return 0;
3836}
3837
3838bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003839__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003840{
3841 return false;
3842}
3843
3844int
3845__codecvt_utf16<char32_t, false>::do_length(state_type&,
3846 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3847{
3848 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3849 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3850 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3851}
3852
3853int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003854__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003855{
3856 if (_Mode_ & consume_header)
3857 return 6;
3858 return 4;
3859}
3860
3861// __codecvt_utf16<char32_t, true>
3862
3863__codecvt_utf16<char32_t, true>::result
3864__codecvt_utf16<char32_t, true>::do_out(state_type&,
3865 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3866 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3867{
3868 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3869 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3870 const uint32_t* _frm_nxt = _frm;
3871 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3872 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3873 uint8_t* _to_nxt = _to;
3874 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3875 _Maxcode_, _Mode_);
3876 frm_nxt = frm + (_frm_nxt - _frm);
3877 to_nxt = to + (_to_nxt - _to);
3878 return r;
3879}
3880
3881__codecvt_utf16<char32_t, true>::result
3882__codecvt_utf16<char32_t, true>::do_in(state_type&,
3883 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3884 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3885{
3886 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3887 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3888 const uint8_t* _frm_nxt = _frm;
3889 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3890 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3891 uint32_t* _to_nxt = _to;
3892 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3893 _Maxcode_, _Mode_);
3894 frm_nxt = frm + (_frm_nxt - _frm);
3895 to_nxt = to + (_to_nxt - _to);
3896 return r;
3897}
3898
3899__codecvt_utf16<char32_t, true>::result
3900__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3901 extern_type* to, extern_type*, extern_type*& to_nxt) const
3902{
3903 to_nxt = to;
3904 return noconv;
3905}
3906
3907int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003908__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003909{
3910 return 0;
3911}
3912
3913bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003914__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003915{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003916 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003917}
3918
3919int
3920__codecvt_utf16<char32_t, true>::do_length(state_type&,
3921 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3922{
3923 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3924 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3925 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3926}
3927
3928int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003929__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003930{
3931 if (_Mode_ & consume_header)
3932 return 6;
3933 return 4;
3934}
3935
3936// __codecvt_utf8_utf16<wchar_t>
3937
3938__codecvt_utf8_utf16<wchar_t>::result
3939__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3940 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3941 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3942{
3943 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3944 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3945 const uint32_t* _frm_nxt = _frm;
3946 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3947 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3948 uint8_t* _to_nxt = _to;
3949 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3950 _Maxcode_, _Mode_);
3951 frm_nxt = frm + (_frm_nxt - _frm);
3952 to_nxt = to + (_to_nxt - _to);
3953 return r;
3954}
3955
3956__codecvt_utf8_utf16<wchar_t>::result
3957__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3958 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3959 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3960{
3961 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3962 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3963 const uint8_t* _frm_nxt = _frm;
3964 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3965 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3966 uint32_t* _to_nxt = _to;
3967 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3968 _Maxcode_, _Mode_);
3969 frm_nxt = frm + (_frm_nxt - _frm);
3970 to_nxt = to + (_to_nxt - _to);
3971 return r;
3972}
3973
3974__codecvt_utf8_utf16<wchar_t>::result
3975__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3976 extern_type* to, extern_type*, extern_type*& to_nxt) const
3977{
3978 to_nxt = to;
3979 return noconv;
3980}
3981
3982int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003983__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003984{
3985 return 0;
3986}
3987
3988bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003989__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003990{
3991 return false;
3992}
3993
3994int
3995__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3996 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3997{
3998 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3999 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4000 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4001}
4002
4003int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004004__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004005{
4006 if (_Mode_ & consume_header)
4007 return 7;
4008 return 4;
4009}
4010
4011// __codecvt_utf8_utf16<char16_t>
4012
4013__codecvt_utf8_utf16<char16_t>::result
4014__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4015 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4016 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4017{
4018 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4019 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4020 const uint16_t* _frm_nxt = _frm;
4021 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4022 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4023 uint8_t* _to_nxt = _to;
4024 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4025 _Maxcode_, _Mode_);
4026 frm_nxt = frm + (_frm_nxt - _frm);
4027 to_nxt = to + (_to_nxt - _to);
4028 return r;
4029}
4030
4031__codecvt_utf8_utf16<char16_t>::result
4032__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4033 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4034 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4035{
4036 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4037 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4038 const uint8_t* _frm_nxt = _frm;
4039 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4040 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4041 uint16_t* _to_nxt = _to;
4042 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4043 _Maxcode_, _Mode_);
4044 frm_nxt = frm + (_frm_nxt - _frm);
4045 to_nxt = to + (_to_nxt - _to);
4046 return r;
4047}
4048
4049__codecvt_utf8_utf16<char16_t>::result
4050__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4051 extern_type* to, extern_type*, extern_type*& to_nxt) const
4052{
4053 to_nxt = to;
4054 return noconv;
4055}
4056
4057int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004058__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004059{
4060 return 0;
4061}
4062
4063bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004064__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004065{
4066 return false;
4067}
4068
4069int
4070__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4071 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4072{
4073 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4074 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4075 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4076}
4077
4078int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004079__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004080{
4081 if (_Mode_ & consume_header)
4082 return 7;
4083 return 4;
4084}
4085
4086// __codecvt_utf8_utf16<char32_t>
4087
4088__codecvt_utf8_utf16<char32_t>::result
4089__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4090 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4091 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4092{
4093 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4094 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4095 const uint32_t* _frm_nxt = _frm;
4096 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4097 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4098 uint8_t* _to_nxt = _to;
4099 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4100 _Maxcode_, _Mode_);
4101 frm_nxt = frm + (_frm_nxt - _frm);
4102 to_nxt = to + (_to_nxt - _to);
4103 return r;
4104}
4105
4106__codecvt_utf8_utf16<char32_t>::result
4107__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4108 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4109 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4110{
4111 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4112 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4113 const uint8_t* _frm_nxt = _frm;
4114 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4115 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4116 uint32_t* _to_nxt = _to;
4117 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4118 _Maxcode_, _Mode_);
4119 frm_nxt = frm + (_frm_nxt - _frm);
4120 to_nxt = to + (_to_nxt - _to);
4121 return r;
4122}
4123
4124__codecvt_utf8_utf16<char32_t>::result
4125__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4126 extern_type* to, extern_type*, extern_type*& to_nxt) const
4127{
4128 to_nxt = to;
4129 return noconv;
4130}
4131
4132int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004133__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004134{
4135 return 0;
4136}
4137
4138bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004139__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004140{
4141 return false;
4142}
4143
4144int
4145__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4146 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4147{
4148 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4149 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4150 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4151}
4152
4153int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004154__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004155{
4156 if (_Mode_ & consume_header)
4157 return 7;
4158 return 4;
4159}
4160
Howard Hinnantc51e1022010-05-11 19:42:16 +00004161// __narrow_to_utf8<16>
4162
4163__narrow_to_utf8<16>::~__narrow_to_utf8()
4164{
4165}
4166
4167// __narrow_to_utf8<32>
4168
4169__narrow_to_utf8<32>::~__narrow_to_utf8()
4170{
4171}
4172
4173// __widen_from_utf8<16>
4174
4175__widen_from_utf8<16>::~__widen_from_utf8()
4176{
4177}
4178
4179// __widen_from_utf8<32>
4180
4181__widen_from_utf8<32>::~__widen_from_utf8()
4182{
4183}
4184
Eric Fiselierbf945a22016-12-11 00:20:59 +00004185
4186static bool checked_string_to_wchar_convert(wchar_t& dest,
4187 const char* ptr,
4188 __locale_struct* loc) {
4189 if (*ptr == '\0')
4190 return false;
4191 mbstate_t mb = {};
4192 wchar_t out;
4193 size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc);
4194 if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) {
4195 return false;
4196 }
4197 dest = out;
4198 return true;
4199}
4200
4201static bool checked_string_to_char_convert(char& dest,
4202 const char* ptr,
4203 __locale_struct* __loc) {
4204 if (*ptr == '\0')
4205 return false;
4206 if (!ptr[1]) {
4207 dest = *ptr;
4208 return true;
4209 }
4210 // First convert the MBS into a wide char then attempt to narrow it using
4211 // wctob_l.
4212 wchar_t wout;
4213 if (!checked_string_to_wchar_convert(wout, ptr, __loc))
4214 return false;
4215 int res;
4216 if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) {
4217 dest = res;
4218 return true;
4219 }
4220 // FIXME: Work around specific multibyte sequences that we can reasonable
4221 // translate into a different single byte.
4222 switch (wout) {
4223 case L'\u00A0': // non-breaking space
4224 dest = ' ';
4225 return true;
4226 default:
4227 return false;
4228 }
4229 _LIBCPP_UNREACHABLE();
4230}
4231
4232
Howard Hinnantc51e1022010-05-11 19:42:16 +00004233// numpunct<char> && numpunct<wchar_t>
4234
4235locale::id numpunct< char >::id;
4236locale::id numpunct<wchar_t>::id;
4237
4238numpunct<char>::numpunct(size_t refs)
4239 : locale::facet(refs),
4240 __decimal_point_('.'),
4241 __thousands_sep_(',')
4242{
4243}
4244
4245numpunct<wchar_t>::numpunct(size_t refs)
4246 : locale::facet(refs),
4247 __decimal_point_(L'.'),
4248 __thousands_sep_(L',')
4249{
4250}
4251
4252numpunct<char>::~numpunct()
4253{
4254}
4255
4256numpunct<wchar_t>::~numpunct()
4257{
4258}
4259
4260 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4261wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4262
4263 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4264wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4265
4266string numpunct< char >::do_grouping() const {return __grouping_;}
4267string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4268
4269 string numpunct< char >::do_truename() const {return "true";}
4270wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4271
4272 string numpunct< char >::do_falsename() const {return "false";}
4273wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4274
4275// numpunct_byname<char>
4276
4277numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4278 : numpunct<char>(refs)
4279{
4280 __init(nm);
4281}
4282
4283numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4284 : numpunct<char>(refs)
4285{
4286 __init(nm.c_str());
4287}
4288
4289numpunct_byname<char>::~numpunct_byname()
4290{
4291}
4292
4293void
4294numpunct_byname<char>::__init(const char* nm)
4295{
4296 if (strcmp(nm, "C") != 0)
4297 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004298 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004299 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00004300 __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004301 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004302
Ben Craig3756b922016-03-09 15:39:39 +00004303 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004304 checked_string_to_char_convert(__decimal_point_, lc->decimal_point,
4305 loc.get());
4306 checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep,
4307 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004308 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004309 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004310 }
4311}
4312
4313// numpunct_byname<wchar_t>
4314
4315numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4316 : numpunct<wchar_t>(refs)
4317{
4318 __init(nm);
4319}
4320
4321numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4322 : numpunct<wchar_t>(refs)
4323{
4324 __init(nm.c_str());
4325}
4326
4327numpunct_byname<wchar_t>::~numpunct_byname()
4328{
4329}
4330
4331void
4332numpunct_byname<wchar_t>::__init(const char* nm)
4333{
4334 if (strcmp(nm, "C") != 0)
4335 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004336 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00004337 if (loc == nullptr)
Eric Fiselierbf945a22016-12-11 00:20:59 +00004338 __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004339 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00004340
Ben Craig3756b922016-03-09 15:39:39 +00004341 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00004342 checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point,
4343 loc.get());
4344 checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep,
4345 loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004346 __grouping_ = lc->grouping;
Eric Fiselierbf945a22016-12-11 00:20:59 +00004347 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004348 }
4349}
4350
4351// num_get helpers
4352
4353int
4354__num_get_base::__get_base(ios_base& iob)
4355{
4356 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4357 if (__basefield == ios_base::oct)
4358 return 8;
4359 else if (__basefield == ios_base::hex)
4360 return 16;
4361 else if (__basefield == 0)
4362 return 0;
4363 return 10;
4364}
4365
4366const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4367
4368void
4369__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4370 ios_base::iostate& __err)
4371{
4372 if (__grouping.size() != 0)
4373 {
4374 reverse(__g, __g_end);
4375 const char* __ig = __grouping.data();
4376 const char* __eg = __ig + __grouping.size();
4377 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4378 {
4379 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4380 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004381 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004382 {
4383 __err = ios_base::failbit;
4384 return;
4385 }
4386 }
4387 if (__eg - __ig > 1)
4388 ++__ig;
4389 }
4390 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4391 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004392 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004393 __err = ios_base::failbit;
4394 }
4395 }
4396}
4397
4398void
4399__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4400 ios_base::fmtflags __flags)
4401{
4402 if (__flags & ios_base::showpos)
4403 *__fmtp++ = '+';
4404 if (__flags & ios_base::showbase)
4405 *__fmtp++ = '#';
4406 while(*__len)
4407 *__fmtp++ = *__len++;
4408 if ((__flags & ios_base::basefield) == ios_base::oct)
4409 *__fmtp = 'o';
4410 else if ((__flags & ios_base::basefield) == ios_base::hex)
4411 {
4412 if (__flags & ios_base::uppercase)
4413 *__fmtp = 'X';
4414 else
4415 *__fmtp = 'x';
4416 }
4417 else if (__signd)
4418 *__fmtp = 'd';
4419 else
4420 *__fmtp = 'u';
4421}
4422
4423bool
4424__num_put_base::__format_float(char* __fmtp, const char* __len,
4425 ios_base::fmtflags __flags)
4426{
4427 bool specify_precision = true;
4428 if (__flags & ios_base::showpos)
4429 *__fmtp++ = '+';
4430 if (__flags & ios_base::showpoint)
4431 *__fmtp++ = '#';
4432 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004433 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004434 if (floatfield == (ios_base::fixed | ios_base::scientific))
4435 specify_precision = false;
4436 else
4437 {
4438 *__fmtp++ = '.';
4439 *__fmtp++ = '*';
4440 }
4441 while(*__len)
4442 *__fmtp++ = *__len++;
4443 if (floatfield == ios_base::fixed)
4444 {
4445 if (uppercase)
4446 *__fmtp = 'F';
4447 else
4448 *__fmtp = 'f';
4449 }
4450 else if (floatfield == ios_base::scientific)
4451 {
4452 if (uppercase)
4453 *__fmtp = 'E';
4454 else
4455 *__fmtp = 'e';
4456 }
4457 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4458 {
4459 if (uppercase)
4460 *__fmtp = 'A';
4461 else
4462 *__fmtp = 'a';
4463 }
4464 else
4465 {
4466 if (uppercase)
4467 *__fmtp = 'G';
4468 else
4469 *__fmtp = 'g';
4470 }
4471 return specify_precision;
4472}
4473
4474char*
4475__num_put_base::__identify_padding(char* __nb, char* __ne,
4476 const ios_base& __iob)
4477{
4478 switch (__iob.flags() & ios_base::adjustfield)
4479 {
4480 case ios_base::internal:
4481 if (__nb[0] == '-' || __nb[0] == '+')
4482 return __nb+1;
4483 if (__ne - __nb >= 2 && __nb[0] == '0'
4484 && (__nb[1] == 'x' || __nb[1] == 'X'))
4485 return __nb+2;
4486 break;
4487 case ios_base::left:
4488 return __ne;
4489 case ios_base::right:
4490 default:
4491 break;
4492 }
4493 return __nb;
4494}
4495
4496// time_get
4497
4498static
4499string*
4500init_weeks()
4501{
4502 static string weeks[14];
4503 weeks[0] = "Sunday";
4504 weeks[1] = "Monday";
4505 weeks[2] = "Tuesday";
4506 weeks[3] = "Wednesday";
4507 weeks[4] = "Thursday";
4508 weeks[5] = "Friday";
4509 weeks[6] = "Saturday";
4510 weeks[7] = "Sun";
4511 weeks[8] = "Mon";
4512 weeks[9] = "Tue";
4513 weeks[10] = "Wed";
4514 weeks[11] = "Thu";
4515 weeks[12] = "Fri";
4516 weeks[13] = "Sat";
4517 return weeks;
4518}
4519
4520static
4521wstring*
4522init_wweeks()
4523{
4524 static wstring weeks[14];
4525 weeks[0] = L"Sunday";
4526 weeks[1] = L"Monday";
4527 weeks[2] = L"Tuesday";
4528 weeks[3] = L"Wednesday";
4529 weeks[4] = L"Thursday";
4530 weeks[5] = L"Friday";
4531 weeks[6] = L"Saturday";
4532 weeks[7] = L"Sun";
4533 weeks[8] = L"Mon";
4534 weeks[9] = L"Tue";
4535 weeks[10] = L"Wed";
4536 weeks[11] = L"Thu";
4537 weeks[12] = L"Fri";
4538 weeks[13] = L"Sat";
4539 return weeks;
4540}
4541
4542template <>
4543const string*
4544__time_get_c_storage<char>::__weeks() const
4545{
4546 static const string* weeks = init_weeks();
4547 return weeks;
4548}
4549
4550template <>
4551const wstring*
4552__time_get_c_storage<wchar_t>::__weeks() const
4553{
4554 static const wstring* weeks = init_wweeks();
4555 return weeks;
4556}
4557
4558static
4559string*
4560init_months()
4561{
4562 static string months[24];
4563 months[0] = "January";
4564 months[1] = "February";
4565 months[2] = "March";
4566 months[3] = "April";
4567 months[4] = "May";
4568 months[5] = "June";
4569 months[6] = "July";
4570 months[7] = "August";
4571 months[8] = "September";
4572 months[9] = "October";
4573 months[10] = "November";
4574 months[11] = "December";
4575 months[12] = "Jan";
4576 months[13] = "Feb";
4577 months[14] = "Mar";
4578 months[15] = "Apr";
4579 months[16] = "May";
4580 months[17] = "Jun";
4581 months[18] = "Jul";
4582 months[19] = "Aug";
4583 months[20] = "Sep";
4584 months[21] = "Oct";
4585 months[22] = "Nov";
4586 months[23] = "Dec";
4587 return months;
4588}
4589
4590static
4591wstring*
4592init_wmonths()
4593{
4594 static wstring months[24];
4595 months[0] = L"January";
4596 months[1] = L"February";
4597 months[2] = L"March";
4598 months[3] = L"April";
4599 months[4] = L"May";
4600 months[5] = L"June";
4601 months[6] = L"July";
4602 months[7] = L"August";
4603 months[8] = L"September";
4604 months[9] = L"October";
4605 months[10] = L"November";
4606 months[11] = L"December";
4607 months[12] = L"Jan";
4608 months[13] = L"Feb";
4609 months[14] = L"Mar";
4610 months[15] = L"Apr";
4611 months[16] = L"May";
4612 months[17] = L"Jun";
4613 months[18] = L"Jul";
4614 months[19] = L"Aug";
4615 months[20] = L"Sep";
4616 months[21] = L"Oct";
4617 months[22] = L"Nov";
4618 months[23] = L"Dec";
4619 return months;
4620}
4621
4622template <>
4623const string*
4624__time_get_c_storage<char>::__months() const
4625{
4626 static const string* months = init_months();
4627 return months;
4628}
4629
4630template <>
4631const wstring*
4632__time_get_c_storage<wchar_t>::__months() const
4633{
4634 static const wstring* months = init_wmonths();
4635 return months;
4636}
4637
4638static
4639string*
4640init_am_pm()
4641{
4642 static string am_pm[24];
4643 am_pm[0] = "AM";
4644 am_pm[1] = "PM";
4645 return am_pm;
4646}
4647
4648static
4649wstring*
4650init_wam_pm()
4651{
4652 static wstring am_pm[24];
4653 am_pm[0] = L"AM";
4654 am_pm[1] = L"PM";
4655 return am_pm;
4656}
4657
4658template <>
4659const string*
4660__time_get_c_storage<char>::__am_pm() const
4661{
4662 static const string* am_pm = init_am_pm();
4663 return am_pm;
4664}
4665
4666template <>
4667const wstring*
4668__time_get_c_storage<wchar_t>::__am_pm() const
4669{
4670 static const wstring* am_pm = init_wam_pm();
4671 return am_pm;
4672}
4673
4674template <>
4675const string&
4676__time_get_c_storage<char>::__x() const
4677{
4678 static string s("%m/%d/%y");
4679 return s;
4680}
4681
4682template <>
4683const wstring&
4684__time_get_c_storage<wchar_t>::__x() const
4685{
4686 static wstring s(L"%m/%d/%y");
4687 return s;
4688}
4689
4690template <>
4691const string&
4692__time_get_c_storage<char>::__X() const
4693{
4694 static string s("%H:%M:%S");
4695 return s;
4696}
4697
4698template <>
4699const wstring&
4700__time_get_c_storage<wchar_t>::__X() const
4701{
4702 static wstring s(L"%H:%M:%S");
4703 return s;
4704}
4705
4706template <>
4707const string&
4708__time_get_c_storage<char>::__c() const
4709{
4710 static string s("%a %b %d %H:%M:%S %Y");
4711 return s;
4712}
4713
4714template <>
4715const wstring&
4716__time_get_c_storage<wchar_t>::__c() const
4717{
4718 static wstring s(L"%a %b %d %H:%M:%S %Y");
4719 return s;
4720}
4721
4722template <>
4723const string&
4724__time_get_c_storage<char>::__r() const
4725{
4726 static string s("%I:%M:%S %p");
4727 return s;
4728}
4729
4730template <>
4731const wstring&
4732__time_get_c_storage<wchar_t>::__r() const
4733{
4734 static wstring s(L"%I:%M:%S %p");
4735 return s;
4736}
4737
4738// time_get_byname
4739
4740__time_get::__time_get(const char* nm)
4741 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4742{
4743 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00004744 __throw_runtime_error("time_get_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00004745 " failed to construct for " + string(nm));
4746}
4747
4748__time_get::__time_get(const string& nm)
4749 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 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 " + nm);
4754}
4755
4756__time_get::~__time_get()
4757{
4758 freelocale(__loc_);
4759}
Marshall Clowd920eea2013-10-21 15:07:28 +00004760#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004761#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004762#endif
4763#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004764#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004765#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004766
Howard Hinnantc51e1022010-05-11 19:42:16 +00004767template <>
4768string
4769__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4770{
Howard Hinnant990207c2012-02-19 14:55:32 +00004771 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004772 t.tm_sec = 59;
4773 t.tm_min = 55;
4774 t.tm_hour = 23;
4775 t.tm_mday = 31;
4776 t.tm_mon = 11;
4777 t.tm_year = 161;
4778 t.tm_wday = 6;
4779 t.tm_yday = 364;
4780 t.tm_isdst = -1;
4781 char buf[100];
4782 char f[3] = {0};
4783 f[0] = '%';
4784 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004785 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004786 char* bb = buf;
4787 char* be = buf + n;
4788 string result;
4789 while (bb != be)
4790 {
4791 if (ct.is(ctype_base::space, *bb))
4792 {
4793 result.push_back(' ');
4794 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4795 ;
4796 continue;
4797 }
4798 char* w = bb;
4799 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004800 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004801 ct, err, false)
4802 - this->__weeks_;
4803 if (i < 14)
4804 {
4805 result.push_back('%');
4806 if (i < 7)
4807 result.push_back('A');
4808 else
4809 result.push_back('a');
4810 bb = w;
4811 continue;
4812 }
4813 w = bb;
4814 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4815 ct, err, false)
4816 - this->__months_;
4817 if (i < 24)
4818 {
4819 result.push_back('%');
4820 if (i < 12)
4821 result.push_back('B');
4822 else
4823 result.push_back('b');
4824 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4825 result.back() = 'm';
4826 bb = w;
4827 continue;
4828 }
4829 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4830 {
4831 w = bb;
4832 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4833 ct, err, false) - this->__am_pm_;
4834 if (i < 2)
4835 {
4836 result.push_back('%');
4837 result.push_back('p');
4838 bb = w;
4839 continue;
4840 }
4841 }
4842 w = bb;
4843 if (ct.is(ctype_base::digit, *bb))
4844 {
4845 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4846 {
4847 case 6:
4848 result.push_back('%');
4849 result.push_back('w');
4850 break;
4851 case 7:
4852 result.push_back('%');
4853 result.push_back('u');
4854 break;
4855 case 11:
4856 result.push_back('%');
4857 result.push_back('I');
4858 break;
4859 case 12:
4860 result.push_back('%');
4861 result.push_back('m');
4862 break;
4863 case 23:
4864 result.push_back('%');
4865 result.push_back('H');
4866 break;
4867 case 31:
4868 result.push_back('%');
4869 result.push_back('d');
4870 break;
4871 case 55:
4872 result.push_back('%');
4873 result.push_back('M');
4874 break;
4875 case 59:
4876 result.push_back('%');
4877 result.push_back('S');
4878 break;
4879 case 61:
4880 result.push_back('%');
4881 result.push_back('y');
4882 break;
4883 case 364:
4884 result.push_back('%');
4885 result.push_back('j');
4886 break;
4887 case 2061:
4888 result.push_back('%');
4889 result.push_back('Y');
4890 break;
4891 default:
4892 for (; w != bb; ++w)
4893 result.push_back(*w);
4894 break;
4895 }
4896 continue;
4897 }
4898 if (*bb == '%')
4899 {
4900 result.push_back('%');
4901 result.push_back('%');
4902 ++bb;
4903 continue;
4904 }
4905 result.push_back(*bb);
4906 ++bb;
4907 }
4908 return result;
4909}
4910
Marshall Clowd920eea2013-10-21 15:07:28 +00004911#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004912#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004913#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004914
Howard Hinnantc51e1022010-05-11 19:42:16 +00004915template <>
4916wstring
4917__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4918{
Howard Hinnant990207c2012-02-19 14:55:32 +00004919 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004920 t.tm_sec = 59;
4921 t.tm_min = 55;
4922 t.tm_hour = 23;
4923 t.tm_mday = 31;
4924 t.tm_mon = 11;
4925 t.tm_year = 161;
4926 t.tm_wday = 6;
4927 t.tm_yday = 364;
4928 t.tm_isdst = -1;
4929 char buf[100];
4930 char f[3] = {0};
4931 f[0] = '%';
4932 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004933 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004934 wchar_t wbuf[100];
4935 wchar_t* wbb = wbuf;
4936 mbstate_t mb = {0};
4937 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004938 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004939 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004940 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004941 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004942 wstring result;
4943 while (wbb != wbe)
4944 {
4945 if (ct.is(ctype_base::space, *wbb))
4946 {
4947 result.push_back(L' ');
4948 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4949 ;
4950 continue;
4951 }
4952 wchar_t* w = wbb;
4953 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004954 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004955 ct, err, false)
4956 - this->__weeks_;
4957 if (i < 14)
4958 {
4959 result.push_back(L'%');
4960 if (i < 7)
4961 result.push_back(L'A');
4962 else
4963 result.push_back(L'a');
4964 wbb = w;
4965 continue;
4966 }
4967 w = wbb;
4968 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4969 ct, err, false)
4970 - this->__months_;
4971 if (i < 24)
4972 {
4973 result.push_back(L'%');
4974 if (i < 12)
4975 result.push_back(L'B');
4976 else
4977 result.push_back(L'b');
4978 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4979 result.back() = L'm';
4980 wbb = w;
4981 continue;
4982 }
4983 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4984 {
4985 w = wbb;
4986 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4987 ct, err, false) - this->__am_pm_;
4988 if (i < 2)
4989 {
4990 result.push_back(L'%');
4991 result.push_back(L'p');
4992 wbb = w;
4993 continue;
4994 }
4995 }
4996 w = wbb;
4997 if (ct.is(ctype_base::digit, *wbb))
4998 {
4999 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5000 {
5001 case 6:
5002 result.push_back(L'%');
5003 result.push_back(L'w');
5004 break;
5005 case 7:
5006 result.push_back(L'%');
5007 result.push_back(L'u');
5008 break;
5009 case 11:
5010 result.push_back(L'%');
5011 result.push_back(L'I');
5012 break;
5013 case 12:
5014 result.push_back(L'%');
5015 result.push_back(L'm');
5016 break;
5017 case 23:
5018 result.push_back(L'%');
5019 result.push_back(L'H');
5020 break;
5021 case 31:
5022 result.push_back(L'%');
5023 result.push_back(L'd');
5024 break;
5025 case 55:
5026 result.push_back(L'%');
5027 result.push_back(L'M');
5028 break;
5029 case 59:
5030 result.push_back(L'%');
5031 result.push_back(L'S');
5032 break;
5033 case 61:
5034 result.push_back(L'%');
5035 result.push_back(L'y');
5036 break;
5037 case 364:
5038 result.push_back(L'%');
5039 result.push_back(L'j');
5040 break;
5041 case 2061:
5042 result.push_back(L'%');
5043 result.push_back(L'Y');
5044 break;
5045 default:
5046 for (; w != wbb; ++w)
5047 result.push_back(*w);
5048 break;
5049 }
5050 continue;
5051 }
5052 if (ct.narrow(*wbb, 0) == '%')
5053 {
5054 result.push_back(L'%');
5055 result.push_back(L'%');
5056 ++wbb;
5057 continue;
5058 }
5059 result.push_back(*wbb);
5060 ++wbb;
5061 }
5062 return result;
5063}
5064
5065template <>
5066void
5067__time_get_storage<char>::init(const ctype<char>& ct)
5068{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005069 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005070 char buf[100];
5071 // __weeks_
5072 for (int i = 0; i < 7; ++i)
5073 {
5074 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005075 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005076 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005077 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005078 __weeks_[i+7] = buf;
5079 }
5080 // __months_
5081 for (int i = 0; i < 12; ++i)
5082 {
5083 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005084 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005085 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005086 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005087 __months_[i+12] = buf;
5088 }
5089 // __am_pm_
5090 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005091 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005092 __am_pm_[0] = buf;
5093 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005094 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005095 __am_pm_[1] = buf;
5096 __c_ = __analyze('c', ct);
5097 __r_ = __analyze('r', ct);
5098 __x_ = __analyze('x', ct);
5099 __X_ = __analyze('X', ct);
5100}
5101
5102template <>
5103void
5104__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5105{
5106 tm t = {0};
5107 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005108 wchar_t wbuf[100];
5109 wchar_t* wbe;
5110 mbstate_t mb = {0};
5111 // __weeks_
5112 for (int i = 0; i < 7; ++i)
5113 {
5114 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005115 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005116 mb = mbstate_t();
5117 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005118 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005119 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005120 __throw_runtime_error("locale not supported");
5121 wbe = wbuf + j;
5122 __weeks_[i].assign(wbuf, wbe);
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 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005126 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+7].assign(wbuf, wbe);
5131 }
5132 // __months_
5133 for (int i = 0; i < 12; ++i)
5134 {
5135 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005136 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005137 mb = mbstate_t();
5138 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005139 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005140 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005141 __throw_runtime_error("locale not supported");
5142 wbe = wbuf + j;
5143 __months_[i].assign(wbuf, wbe);
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 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005147 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005148 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005149 __throw_runtime_error("locale not supported");
5150 wbe = wbuf + j;
5151 __months_[i+12].assign(wbuf, wbe);
5152 }
5153 // __am_pm_
5154 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005155 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005156 mb = mbstate_t();
5157 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005158 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005159 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005160 __throw_runtime_error("locale not supported");
5161 wbe = wbuf + j;
5162 __am_pm_[0].assign(wbuf, wbe);
5163 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005164 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005165 mb = mbstate_t();
5166 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005167 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005168 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005169 __throw_runtime_error("locale not supported");
5170 wbe = wbuf + j;
5171 __am_pm_[1].assign(wbuf, wbe);
5172 __c_ = __analyze('c', ct);
5173 __r_ = __analyze('r', ct);
5174 __x_ = __analyze('x', ct);
5175 __X_ = __analyze('X', ct);
5176}
5177
5178template <class CharT>
5179struct _LIBCPP_HIDDEN __time_get_temp
5180 : public ctype_byname<CharT>
5181{
5182 explicit __time_get_temp(const char* nm)
5183 : ctype_byname<CharT>(nm, 1) {}
5184 explicit __time_get_temp(const string& nm)
5185 : ctype_byname<CharT>(nm, 1) {}
5186};
5187
5188template <>
5189__time_get_storage<char>::__time_get_storage(const char* __nm)
5190 : __time_get(__nm)
5191{
5192 const __time_get_temp<char> ct(__nm);
5193 init(ct);
5194}
5195
5196template <>
5197__time_get_storage<char>::__time_get_storage(const string& __nm)
5198 : __time_get(__nm)
5199{
5200 const __time_get_temp<char> ct(__nm);
5201 init(ct);
5202}
5203
5204template <>
5205__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5206 : __time_get(__nm)
5207{
5208 const __time_get_temp<wchar_t> ct(__nm);
5209 init(ct);
5210}
5211
5212template <>
5213__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5214 : __time_get(__nm)
5215{
5216 const __time_get_temp<wchar_t> ct(__nm);
5217 init(ct);
5218}
5219
5220template <>
5221time_base::dateorder
5222__time_get_storage<char>::__do_date_order() const
5223{
5224 unsigned i;
5225 for (i = 0; i < __x_.size(); ++i)
5226 if (__x_[i] == '%')
5227 break;
5228 ++i;
5229 switch (__x_[i])
5230 {
5231 case 'y':
5232 case 'Y':
5233 for (++i; i < __x_.size(); ++i)
5234 if (__x_[i] == '%')
5235 break;
5236 if (i == __x_.size())
5237 break;
5238 ++i;
5239 switch (__x_[i])
5240 {
5241 case 'm':
5242 for (++i; i < __x_.size(); ++i)
5243 if (__x_[i] == '%')
5244 break;
5245 if (i == __x_.size())
5246 break;
5247 ++i;
5248 if (__x_[i] == 'd')
5249 return time_base::ymd;
5250 break;
5251 case 'd':
5252 for (++i; i < __x_.size(); ++i)
5253 if (__x_[i] == '%')
5254 break;
5255 if (i == __x_.size())
5256 break;
5257 ++i;
5258 if (__x_[i] == 'm')
5259 return time_base::ydm;
5260 break;
5261 }
5262 break;
5263 case 'm':
5264 for (++i; i < __x_.size(); ++i)
5265 if (__x_[i] == '%')
5266 break;
5267 if (i == __x_.size())
5268 break;
5269 ++i;
5270 if (__x_[i] == 'd')
5271 {
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] == 'y' || __x_[i] == 'Y')
5279 return time_base::mdy;
5280 break;
5281 }
5282 break;
5283 case 'd':
5284 for (++i; i < __x_.size(); ++i)
5285 if (__x_[i] == '%')
5286 break;
5287 if (i == __x_.size())
5288 break;
5289 ++i;
5290 if (__x_[i] == 'm')
5291 {
5292 for (++i; i < __x_.size(); ++i)
5293 if (__x_[i] == '%')
5294 break;
5295 if (i == __x_.size())
5296 break;
5297 ++i;
5298 if (__x_[i] == 'y' || __x_[i] == 'Y')
5299 return time_base::dmy;
5300 break;
5301 }
5302 break;
5303 }
5304 return time_base::no_order;
5305}
5306
5307template <>
5308time_base::dateorder
5309__time_get_storage<wchar_t>::__do_date_order() const
5310{
5311 unsigned i;
5312 for (i = 0; i < __x_.size(); ++i)
5313 if (__x_[i] == L'%')
5314 break;
5315 ++i;
5316 switch (__x_[i])
5317 {
5318 case L'y':
5319 case L'Y':
5320 for (++i; i < __x_.size(); ++i)
5321 if (__x_[i] == L'%')
5322 break;
5323 if (i == __x_.size())
5324 break;
5325 ++i;
5326 switch (__x_[i])
5327 {
5328 case L'm':
5329 for (++i; i < __x_.size(); ++i)
5330 if (__x_[i] == L'%')
5331 break;
5332 if (i == __x_.size())
5333 break;
5334 ++i;
5335 if (__x_[i] == L'd')
5336 return time_base::ymd;
5337 break;
5338 case L'd':
5339 for (++i; i < __x_.size(); ++i)
5340 if (__x_[i] == L'%')
5341 break;
5342 if (i == __x_.size())
5343 break;
5344 ++i;
5345 if (__x_[i] == L'm')
5346 return time_base::ydm;
5347 break;
5348 }
5349 break;
5350 case L'm':
5351 for (++i; i < __x_.size(); ++i)
5352 if (__x_[i] == L'%')
5353 break;
5354 if (i == __x_.size())
5355 break;
5356 ++i;
5357 if (__x_[i] == L'd')
5358 {
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'y' || __x_[i] == L'Y')
5366 return time_base::mdy;
5367 break;
5368 }
5369 break;
5370 case L'd':
5371 for (++i; i < __x_.size(); ++i)
5372 if (__x_[i] == L'%')
5373 break;
5374 if (i == __x_.size())
5375 break;
5376 ++i;
5377 if (__x_[i] == L'm')
5378 {
5379 for (++i; i < __x_.size(); ++i)
5380 if (__x_[i] == L'%')
5381 break;
5382 if (i == __x_.size())
5383 break;
5384 ++i;
5385 if (__x_[i] == L'y' || __x_[i] == L'Y')
5386 return time_base::dmy;
5387 break;
5388 }
5389 break;
5390 }
5391 return time_base::no_order;
5392}
5393
5394// time_put
5395
5396__time_put::__time_put(const char* nm)
5397 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5398{
5399 if (__loc_ == 0)
Marshall Clow8fea1612016-08-25 15:09:01 +00005400 __throw_runtime_error("time_put_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005401 " failed to construct for " + string(nm));
5402}
5403
5404__time_put::__time_put(const string& nm)
5405 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 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 " + nm);
5410}
5411
5412__time_put::~__time_put()
5413{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005414 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005415 freelocale(__loc_);
5416}
5417
5418void
5419__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5420 char __fmt, char __mod) const
5421{
5422 char fmt[] = {'%', __fmt, __mod, 0};
5423 if (__mod != 0)
5424 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005425 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005426 __ne = __nb + n;
5427}
5428
5429void
5430__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5431 char __fmt, char __mod) const
5432{
5433 char __nar[100];
5434 char* __ne = __nar + 100;
5435 __do_put(__nar, __ne, __tm, __fmt, __mod);
5436 mbstate_t mb = {0};
5437 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005438 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005439 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005440 __throw_runtime_error("locale not supported");
5441 __we = __wb + j;
5442}
5443
5444// moneypunct_byname
5445
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005446template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005447static
5448void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005449__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5450 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5451 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005452{
5453 const char sign = static_cast<char>(money_base::sign);
5454 const char space = static_cast<char>(money_base::space);
5455 const char none = static_cast<char>(money_base::none);
5456 const char symbol = static_cast<char>(money_base::symbol);
5457 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005458 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5459
5460 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5461 // function'. "Space between sign and symbol or value" means that
5462 // if the sign is adjacent to the symbol, there's a space between
5463 // them, and otherwise there's a space between the sign and value.
5464 //
5465 // C11's localeconv specifies that the fourth character of an
5466 // international curr_symbol is used to separate the sign and
5467 // value when sep_by_space says to do so. C++ can't represent
5468 // that, so we just use a space. When sep_by_space says to
5469 // separate the symbol and value-or-sign with a space, we rearrange the
5470 // curr_symbol to put its spacing character on the correct side of
5471 // the symbol.
5472 //
5473 // We also need to avoid adding an extra space between the sign
5474 // and value when the currency symbol is suppressed (by not
5475 // setting showbase). We match glibc's strfmon by interpreting
5476 // sep_by_space==1 as "omit the space when the currency symbol is
5477 // absent".
5478 //
5479 // Users who want to get this right should use ICU instead.
5480
Howard Hinnantc51e1022010-05-11 19:42:16 +00005481 switch (cs_precedes)
5482 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005483 case 0: // value before curr_symbol
5484 if (symbol_contains_sep) {
5485 // Move the separator to before the symbol, to place it
5486 // between the value and symbol.
5487 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5488 __curr_symbol_.end());
5489 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005490 switch (sign_posn)
5491 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005492 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005493 pat.field[0] = sign;
5494 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005495 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005496 pat.field[3] = symbol;
5497 switch (sep_by_space)
5498 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005499 case 0: // No space separates the currency symbol and value.
5500 // This case may have changed between C99 and C11;
5501 // assume the currency symbol matches the intention.
5502 case 2: // Space between sign and currency or value.
5503 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005504 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005505 case 1: // Space between currency-and-sign or currency and value.
5506 if (!symbol_contains_sep) {
5507 // We insert the space into the symbol instead of
5508 // setting pat.field[2]=space so that when
5509 // showbase is not set, the space goes away too.
5510 __curr_symbol_.insert(0, 1, space_char);
5511 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005512 return;
5513 default:
5514 break;
5515 }
5516 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005517 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005518 pat.field[0] = sign;
5519 pat.field[3] = symbol;
5520 switch (sep_by_space)
5521 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005522 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005523 pat.field[1] = value;
5524 pat.field[2] = none;
5525 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005526 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005527 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005528 pat.field[2] = none;
5529 if (!symbol_contains_sep) {
5530 // We insert the space into the symbol instead of
5531 // setting pat.field[2]=space so that when
5532 // showbase is not set, the space goes away too.
5533 __curr_symbol_.insert(0, 1, space_char);
5534 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005535 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005536 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005537 pat.field[1] = space;
5538 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005539 if (symbol_contains_sep) {
5540 // Remove the separator from the symbol, since it
5541 // has already appeared after the sign.
5542 __curr_symbol_.erase(__curr_symbol_.begin());
5543 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005544 return;
5545 default:
5546 break;
5547 }
5548 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005549 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005550 pat.field[0] = value;
5551 pat.field[3] = sign;
5552 switch (sep_by_space)
5553 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005554 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005555 pat.field[1] = none;
5556 pat.field[2] = symbol;
5557 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005558 case 1: // Space between currency-and-sign or currency and value.
5559 if (!symbol_contains_sep) {
5560 // We insert the space into the symbol instead of
5561 // setting pat.field[1]=space so that when
5562 // showbase is not set, the space goes away too.
5563 __curr_symbol_.insert(0, 1, space_char);
5564 }
5565 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005566 pat.field[2] = symbol;
5567 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005568 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005569 pat.field[1] = symbol;
5570 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005571 if (symbol_contains_sep) {
5572 // Remove the separator from the symbol, since it
5573 // should not be removed if showbase is absent.
5574 __curr_symbol_.erase(__curr_symbol_.begin());
5575 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005576 return;
5577 default:
5578 break;
5579 }
5580 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005581 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005582 pat.field[0] = value;
5583 pat.field[3] = symbol;
5584 switch (sep_by_space)
5585 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005586 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005587 pat.field[1] = none;
5588 pat.field[2] = sign;
5589 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005590 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005591 pat.field[1] = space;
5592 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005593 if (symbol_contains_sep) {
5594 // Remove the separator from the symbol, since it
5595 // has already appeared before the sign.
5596 __curr_symbol_.erase(__curr_symbol_.begin());
5597 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005598 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005599 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005600 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005601 pat.field[2] = none;
5602 if (!symbol_contains_sep) {
5603 // We insert the space into the symbol instead of
5604 // setting pat.field[2]=space so that when
5605 // showbase is not set, the space goes away too.
5606 __curr_symbol_.insert(0, 1, space_char);
5607 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005608 return;
5609 default:
5610 break;
5611 }
5612 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005613 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005614 pat.field[0] = value;
5615 pat.field[3] = sign;
5616 switch (sep_by_space)
5617 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005618 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005619 pat.field[1] = none;
5620 pat.field[2] = symbol;
5621 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005622 case 1: // Space between currency-and-sign or currency and value.
5623 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005624 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005625 if (!symbol_contains_sep) {
5626 // We insert the space into the symbol instead of
5627 // setting pat.field[1]=space so that when
5628 // showbase is not set, the space goes away too.
5629 __curr_symbol_.insert(0, 1, space_char);
5630 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005631 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005632 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005633 pat.field[1] = symbol;
5634 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005635 if (symbol_contains_sep) {
5636 // Remove the separator from the symbol, since it
5637 // should not disappear when showbase is absent.
5638 __curr_symbol_.erase(__curr_symbol_.begin());
5639 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005640 return;
5641 default:
5642 break;
5643 }
5644 break;
5645 default:
5646 break;
5647 }
5648 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005649 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005650 switch (sign_posn)
5651 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005652 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005653 pat.field[0] = sign;
5654 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005655 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005656 pat.field[3] = value;
5657 switch (sep_by_space)
5658 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005659 case 0: // No space separates the currency symbol and value.
5660 // This case may have changed between C99 and C11;
5661 // assume the currency symbol matches the intention.
5662 case 2: // Space between sign and currency or value.
5663 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005664 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005665 case 1: // Space between currency-and-sign or currency and value.
5666 if (!symbol_contains_sep) {
5667 // We insert the space into the symbol instead of
5668 // setting pat.field[2]=space so that when
5669 // showbase is not set, the space goes away too.
5670 __curr_symbol_.insert(0, 1, space_char);
5671 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005672 return;
5673 default:
5674 break;
5675 }
5676 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005677 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005678 pat.field[0] = sign;
5679 pat.field[3] = value;
5680 switch (sep_by_space)
5681 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005682 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005683 pat.field[1] = symbol;
5684 pat.field[2] = none;
5685 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005686 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005687 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005688 pat.field[2] = none;
5689 if (!symbol_contains_sep) {
5690 // We insert the space into the symbol instead of
5691 // setting pat.field[2]=space so that when
5692 // showbase is not set, the space goes away too.
5693 __curr_symbol_.push_back(space_char);
5694 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005695 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005696 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005697 pat.field[1] = space;
5698 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005699 if (symbol_contains_sep) {
5700 // Remove the separator from the symbol, since it
5701 // has already appeared after the sign.
5702 __curr_symbol_.pop_back();
5703 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005704 return;
5705 default:
5706 break;
5707 }
5708 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005709 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005710 pat.field[0] = symbol;
5711 pat.field[3] = sign;
5712 switch (sep_by_space)
5713 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005714 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005715 pat.field[1] = none;
5716 pat.field[2] = value;
5717 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005718 case 1: // Space between currency-and-sign or currency and value.
5719 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005720 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005721 if (!symbol_contains_sep) {
5722 // We insert the space into the symbol instead of
5723 // setting pat.field[1]=space so that when
5724 // showbase is not set, the space goes away too.
5725 __curr_symbol_.push_back(space_char);
5726 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005727 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005728 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005729 pat.field[1] = value;
5730 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005731 if (symbol_contains_sep) {
5732 // Remove the separator from the symbol, since it
5733 // will appear before the sign.
5734 __curr_symbol_.pop_back();
5735 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005736 return;
5737 default:
5738 break;
5739 }
5740 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005741 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005742 pat.field[0] = sign;
5743 pat.field[3] = value;
5744 switch (sep_by_space)
5745 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005746 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005747 pat.field[1] = symbol;
5748 pat.field[2] = none;
5749 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005750 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005751 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005752 pat.field[2] = none;
5753 if (!symbol_contains_sep) {
5754 // We insert the space into the symbol instead of
5755 // setting pat.field[2]=space so that when
5756 // showbase is not set, the space goes away too.
5757 __curr_symbol_.push_back(space_char);
5758 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005759 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005760 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005761 pat.field[1] = space;
5762 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005763 if (symbol_contains_sep) {
5764 // Remove the separator from the symbol, since it
5765 // has already appeared after the sign.
5766 __curr_symbol_.pop_back();
5767 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005768 return;
5769 default:
5770 break;
5771 }
5772 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005773 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005774 pat.field[0] = symbol;
5775 pat.field[3] = value;
5776 switch (sep_by_space)
5777 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005778 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005779 pat.field[1] = sign;
5780 pat.field[2] = none;
5781 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005782 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005783 pat.field[1] = sign;
5784 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005785 if (symbol_contains_sep) {
5786 // Remove the separator from the symbol, since it
5787 // should not disappear when showbase is absent.
5788 __curr_symbol_.pop_back();
5789 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005790 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005791 case 2: // Space between sign and currency or value.
5792 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005793 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005794 if (!symbol_contains_sep) {
5795 // We insert the space into the symbol instead of
5796 // setting pat.field[1]=space so that when
5797 // showbase is not set, the space goes away too.
5798 __curr_symbol_.push_back(space_char);
5799 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005800 return;
5801 default:
5802 break;
5803 }
5804 break;
5805 default:
5806 break;
5807 }
5808 break;
5809 default:
5810 break;
5811 }
5812 pat.field[0] = symbol;
5813 pat.field[1] = sign;
5814 pat.field[2] = none;
5815 pat.field[3] = value;
5816}
5817
5818template<>
5819void
5820moneypunct_byname<char, false>::init(const char* nm)
5821{
5822 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005823 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005824 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005825 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005826 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005827
Ben Craig3756b922016-03-09 15:39:39 +00005828 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005829 if (!checked_string_to_char_convert(__decimal_point_,
5830 lc->mon_decimal_point,
5831 loc.get()))
5832 __decimal_point_ = base::do_decimal_point();
5833 if (!checked_string_to_char_convert(__thousands_sep_,
5834 lc->mon_thousands_sep,
5835 loc.get()))
5836 __thousands_sep_ = base::do_thousands_sep();
5837
Howard Hinnantc51e1022010-05-11 19:42:16 +00005838 __grouping_ = lc->mon_grouping;
5839 __curr_symbol_ = lc->currency_symbol;
5840 if (lc->frac_digits != CHAR_MAX)
5841 __frac_digits_ = lc->frac_digits;
5842 else
5843 __frac_digits_ = base::do_frac_digits();
5844 if (lc->p_sign_posn == 0)
5845 __positive_sign_ = "()";
5846 else
5847 __positive_sign_ = lc->positive_sign;
5848 if (lc->n_sign_posn == 0)
5849 __negative_sign_ = "()";
5850 else
5851 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005852 // Assume the positive and negative formats will want spaces in
5853 // the same places in curr_symbol since there's no way to
5854 // represent anything else.
5855 string_type __dummy_curr_symbol = __curr_symbol_;
5856 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5857 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5858 __init_pat(__neg_format_, __curr_symbol_, false,
5859 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005860}
5861
5862template<>
5863void
5864moneypunct_byname<char, true>::init(const char* nm)
5865{
5866 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005867 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005868 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005869 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005870 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005871
Ben Craig3756b922016-03-09 15:39:39 +00005872 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005873 if (!checked_string_to_char_convert(__decimal_point_,
5874 lc->mon_decimal_point,
5875 loc.get()))
5876 __decimal_point_ = base::do_decimal_point();
5877 if (!checked_string_to_char_convert(__thousands_sep_,
5878 lc->mon_thousands_sep,
5879 loc.get()))
5880 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005881 __grouping_ = lc->mon_grouping;
5882 __curr_symbol_ = lc->int_curr_symbol;
5883 if (lc->int_frac_digits != CHAR_MAX)
5884 __frac_digits_ = lc->int_frac_digits;
5885 else
5886 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005887#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005888 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005889#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005890 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005891#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005892 __positive_sign_ = "()";
5893 else
5894 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005895#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005896 if(lc->n_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_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005899#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005900 __negative_sign_ = "()";
5901 else
5902 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005903 // Assume the positive and negative formats will want spaces in
5904 // the same places in curr_symbol since there's no way to
5905 // represent anything else.
5906 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005907#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005908 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5909 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5910 __init_pat(__neg_format_, __curr_symbol_, true,
5911 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005912#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005913 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5914 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5915 lc->int_p_sign_posn, ' ');
5916 __init_pat(__neg_format_, __curr_symbol_, true,
5917 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5918 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005919#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005920}
5921
5922template<>
5923void
5924moneypunct_byname<wchar_t, false>::init(const char* nm)
5925{
5926 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005927 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005928 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005929 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005930 " failed to construct for " + string(nm));
Ben Craig3756b922016-03-09 15:39:39 +00005931 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005932 if (!checked_string_to_wchar_convert(__decimal_point_,
5933 lc->mon_decimal_point,
5934 loc.get()))
5935 __decimal_point_ = base::do_decimal_point();
5936 if (!checked_string_to_wchar_convert(__thousands_sep_,
5937 lc->mon_thousands_sep,
5938 loc.get()))
5939 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00005940 __grouping_ = lc->mon_grouping;
5941 wchar_t wbuf[100];
5942 mbstate_t mb = {0};
5943 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005944 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005945 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005946 __throw_runtime_error("locale not supported");
5947 wchar_t* wbe = wbuf + j;
5948 __curr_symbol_.assign(wbuf, wbe);
5949 if (lc->frac_digits != CHAR_MAX)
5950 __frac_digits_ = lc->frac_digits;
5951 else
5952 __frac_digits_ = base::do_frac_digits();
5953 if (lc->p_sign_posn == 0)
5954 __positive_sign_ = L"()";
5955 else
5956 {
5957 mb = mbstate_t();
5958 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005959 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005960 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005961 __throw_runtime_error("locale not supported");
5962 wbe = wbuf + j;
5963 __positive_sign_.assign(wbuf, wbe);
5964 }
5965 if (lc->n_sign_posn == 0)
5966 __negative_sign_ = L"()";
5967 else
5968 {
5969 mb = mbstate_t();
5970 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005971 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005972 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005973 __throw_runtime_error("locale not supported");
5974 wbe = wbuf + j;
5975 __negative_sign_.assign(wbuf, wbe);
5976 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005977 // Assume the positive and negative formats will want spaces in
5978 // the same places in curr_symbol since there's no way to
5979 // represent anything else.
5980 string_type __dummy_curr_symbol = __curr_symbol_;
5981 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5982 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5983 __init_pat(__neg_format_, __curr_symbol_, false,
5984 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005985}
5986
5987template<>
5988void
5989moneypunct_byname<wchar_t, true>::init(const char* nm)
5990{
5991 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005992 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant03de6f92012-03-07 20:37:43 +00005993 if (loc == nullptr)
Marshall Clow8fea1612016-08-25 15:09:01 +00005994 __throw_runtime_error("moneypunct_byname"
Howard Hinnantc51e1022010-05-11 19:42:16 +00005995 " failed to construct for " + string(nm));
Marshall Clow8fea1612016-08-25 15:09:01 +00005996
Ben Craig3756b922016-03-09 15:39:39 +00005997 lconv* lc = __libcpp_localeconv_l(loc.get());
Eric Fiselierbf945a22016-12-11 00:20:59 +00005998 if (!checked_string_to_wchar_convert(__decimal_point_,
5999 lc->mon_decimal_point,
6000 loc.get()))
6001 __decimal_point_ = base::do_decimal_point();
6002 if (!checked_string_to_wchar_convert(__thousands_sep_,
6003 lc->mon_thousands_sep,
6004 loc.get()))
6005 __thousands_sep_ = base::do_thousands_sep();
Howard Hinnantc51e1022010-05-11 19:42:16 +00006006 __grouping_ = lc->mon_grouping;
6007 wchar_t wbuf[100];
6008 mbstate_t mb = {0};
6009 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00006010 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006011 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006012 __throw_runtime_error("locale not supported");
6013 wchar_t* wbe = wbuf + j;
6014 __curr_symbol_.assign(wbuf, wbe);
6015 if (lc->int_frac_digits != CHAR_MAX)
6016 __frac_digits_ = lc->int_frac_digits;
6017 else
6018 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006019#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006020 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006021#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006022 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006023#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006024 __positive_sign_ = L"()";
6025 else
6026 {
6027 mb = mbstate_t();
6028 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006029 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006030 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006031 __throw_runtime_error("locale not supported");
6032 wbe = wbuf + j;
6033 __positive_sign_.assign(wbuf, wbe);
6034 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006035#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006036 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006037#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006038 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006039#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006040 __negative_sign_ = L"()";
6041 else
6042 {
6043 mb = mbstate_t();
6044 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006045 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006046 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006047 __throw_runtime_error("locale not supported");
6048 wbe = wbuf + j;
6049 __negative_sign_.assign(wbuf, wbe);
6050 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006051 // Assume the positive and negative formats will want spaces in
6052 // the same places in curr_symbol since there's no way to
6053 // represent anything else.
6054 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006055#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006056 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6057 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6058 __init_pat(__neg_format_, __curr_symbol_, true,
6059 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006060#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006061 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6062 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6063 lc->int_p_sign_posn, L' ');
6064 __init_pat(__neg_format_, __curr_symbol_, true,
6065 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6066 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006067#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006068}
6069
6070void __do_nothing(void*) {}
6071
6072void __throw_runtime_error(const char* msg)
6073{
Howard Hinnant72f73582010-08-11 17:04:31 +00006074#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006075 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006076#else
6077 (void)msg;
Marshall Clow8fea1612016-08-25 15:09:01 +00006078 _VSTD::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +00006079#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006080}
6081
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006082template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
6083template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006084
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006085template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
6086template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006087
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006088template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
6089template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006090
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006091template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
6092template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006093
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006094template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
6095template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006096
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006097template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
6098template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006099
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006100template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
6101template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006102
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006103template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
6104template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006105
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006106template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
6107template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006108
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006109template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
6110template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
6111template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
6112template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006113
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006114template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
6115template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
6116template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
6117template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006118
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006119template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
6120template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006121
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006122template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
6123template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006124
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006125template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
6126template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006127
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006128template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
6129template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006130
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006131template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
6132template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006133
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006134template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
6135template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006136
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006137template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
6138template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
6139template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
6140template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006141
Shoaib Meenai5ac10672016-09-19 18:29:07 +00006142template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006143
6144_LIBCPP_END_NAMESPACE_STD