blob: da2fd11678d6094076782868f237ca5e28b27fd4 [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"
27#include "cwctype"
28#include "__sso_allocator"
Howard Hinnant8ad70912013-09-17 01:34:47 +000029#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Marshall Clowccb92572015-06-23 14:45:02 +000030#include "support/win32/locale_win32.h"
Marshall Clow3477ec92014-07-10 15:20:28 +000031#elif !defined(__ANDROID__)
Howard Hinnantc51e1022010-05-11 19:42:16 +000032#include <langinfo.h>
Marshall Clow3477ec92014-07-10 15:20:28 +000033#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000034#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000035#include <stdio.h>
Howard Hinnantc51e1022010-05-11 19:42:16 +000036
Marshall Clowab9c1772013-02-07 17:20:56 +000037// On Linux, wint_t and wchar_t have different signed-ness, and this causes
38// lots of noise in the build log, but no bugs that I know of.
Marshall Clowd920eea2013-10-21 15:07:28 +000039#if defined(__clang__)
Marshall Clowab9c1772013-02-07 17:20:56 +000040#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowd920eea2013-10-21 15:07:28 +000041#endif
Marshall Clowab9c1772013-02-07 17:20:56 +000042
Howard Hinnantc51e1022010-05-11 19:42:16 +000043_LIBCPP_BEGIN_NAMESPACE_STD
44
Howard Hinnantf312e3e2011-09-28 23:39:33 +000045#ifdef __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000046locale_t __cloc() {
47 // In theory this could create a race condition. In practice
48 // the race condition is non-fatal since it will just create
49 // a little resource leak. Better approach would be appreciated.
Alexis Hunt92b0c812011-07-09 00:56:23 +000050 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
51 return result;
Alexis Hunt92b0c812011-07-09 00:56:23 +000052}
Howard Hinnantf312e3e2011-09-28 23:39:33 +000053#endif // __cloc_defined
Alexis Hunt92b0c812011-07-09 00:56:23 +000054
Howard Hinnantc51e1022010-05-11 19:42:16 +000055namespace {
56
57struct release
58{
59 void operator()(locale::facet* p) {p->__release_shared();}
60};
61
62template <class T, class A0>
63inline
64T&
65make(A0 a0)
66{
67 static typename aligned_storage<sizeof(T)>::type buf;
68 ::new (&buf) T(a0);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000069 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000070}
71
72template <class T, class A0, class A1>
73inline
74T&
75make(A0 a0, A1 a1)
76{
77 static typename aligned_storage<sizeof(T)>::type buf;
78 ::new (&buf) T(a0, a1);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000079 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000080}
81
82template <class T, class A0, class A1, class A2>
83inline
84T&
85make(A0 a0, A1 a1, A2 a2)
86{
87 static typename aligned_storage<sizeof(T)>::type buf;
88 ::new (&buf) T(a0, a1, a2);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000089 return *reinterpret_cast<T*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +000090}
91
Howard Hinnant3d2417c2012-12-27 21:17:53 +000092template <typename T, size_t N>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +000093inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +000094_LIBCPP_CONSTEXPR
95size_t
96countof(const T (&)[N])
97{
98 return N;
99}
100
101template <typename T>
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000102inline
Howard Hinnant3d2417c2012-12-27 21:17:53 +0000103_LIBCPP_CONSTEXPR
104size_t
105countof(const T * const begin, const T * const end)
106{
107 return static_cast<size_t>(end - begin);
108}
109
Howard Hinnantc51e1022010-05-11 19:42:16 +0000110}
111
Howard Hinnantdd099492013-08-29 23:37:50 +0000112#if defined(_AIX)
113// Set priority to INT_MIN + 256 + 150
114# pragma priority ( -2147483242 )
115#endif
116
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000117const locale::category locale::none;
118const locale::category locale::collate;
119const locale::category locale::ctype;
120const locale::category locale::monetary;
121const locale::category locale::numeric;
122const locale::category locale::time;
123const locale::category locale::messages;
124const locale::category locale::all;
125
Howard Hinnantc51e1022010-05-11 19:42:16 +0000126class _LIBCPP_HIDDEN locale::__imp
127 : public facet
128{
129 enum {N = 28};
Marshall Clowd920eea2013-10-21 15:07:28 +0000130#if defined(_LIBCPP_MSVC)
131// FIXME: MSVC doesn't support aligned parameters by value.
132// I can't get the __sso_allocator to work here
133// for MSVC I think for this reason.
134 vector<facet*> facets_;
135#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000136 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000137#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000138 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000139public:
140 explicit __imp(size_t refs = 0);
141 explicit __imp(const string& name, size_t refs = 0);
142 __imp(const __imp&);
143 __imp(const __imp&, const string&, locale::category c);
144 __imp(const __imp& other, const __imp& one, locale::category c);
145 __imp(const __imp&, facet* f, long id);
146 ~__imp();
147
148 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000149 bool has_facet(long id) const
150 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000151 const locale::facet* use_facet(long id) const;
152
153 static const locale& make_classic();
154 static locale& make_global();
155private:
156 void install(facet* f, long id);
157 template <class F> void install(F* f) {install(f, f->id.__get());}
158 template <class F> void install_from(const __imp& other);
159};
160
161locale::__imp::__imp(size_t refs)
162 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000163 facets_(N),
164 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000165{
166 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000167 install(&make<_VSTD::collate<char> >(1u));
168 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000169 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000170 install(&make<_VSTD::ctype<wchar_t> >(1u));
171 install(&make<codecvt<char, char, mbstate_t> >(1u));
172 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
173 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
174 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
175 install(&make<numpunct<char> >(1u));
176 install(&make<numpunct<wchar_t> >(1u));
177 install(&make<num_get<char> >(1u));
178 install(&make<num_get<wchar_t> >(1u));
179 install(&make<num_put<char> >(1u));
180 install(&make<num_put<wchar_t> >(1u));
181 install(&make<moneypunct<char, false> >(1u));
182 install(&make<moneypunct<char, true> >(1u));
183 install(&make<moneypunct<wchar_t, false> >(1u));
184 install(&make<moneypunct<wchar_t, true> >(1u));
185 install(&make<money_get<char> >(1u));
186 install(&make<money_get<wchar_t> >(1u));
187 install(&make<money_put<char> >(1u));
188 install(&make<money_put<wchar_t> >(1u));
189 install(&make<time_get<char> >(1u));
190 install(&make<time_get<wchar_t> >(1u));
191 install(&make<time_put<char> >(1u));
192 install(&make<time_put<wchar_t> >(1u));
193 install(&make<_VSTD::messages<char> >(1u));
194 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000195}
196
197locale::__imp::__imp(const string& name, size_t refs)
198 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000199 facets_(N),
200 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000201{
Howard Hinnant72f73582010-08-11 17:04:31 +0000202#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000203 try
204 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000205#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000206 facets_ = locale::classic().__locale_->facets_;
207 for (unsigned i = 0; i < facets_.size(); ++i)
208 if (facets_[i])
209 facets_[i]->__add_shared();
210 install(new collate_byname<char>(name_));
211 install(new collate_byname<wchar_t>(name_));
212 install(new ctype_byname<char>(name_));
213 install(new ctype_byname<wchar_t>(name_));
214 install(new codecvt_byname<char, char, mbstate_t>(name_));
215 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
216 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
217 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
218 install(new numpunct_byname<char>(name_));
219 install(new numpunct_byname<wchar_t>(name_));
220 install(new moneypunct_byname<char, false>(name_));
221 install(new moneypunct_byname<char, true>(name_));
222 install(new moneypunct_byname<wchar_t, false>(name_));
223 install(new moneypunct_byname<wchar_t, true>(name_));
224 install(new time_get_byname<char>(name_));
225 install(new time_get_byname<wchar_t>(name_));
226 install(new time_put_byname<char>(name_));
227 install(new time_put_byname<wchar_t>(name_));
228 install(new messages_byname<char>(name_));
229 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000230#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000231 }
232 catch (...)
233 {
234 for (unsigned i = 0; i < facets_.size(); ++i)
235 if (facets_[i])
236 facets_[i]->__release_shared();
237 throw;
238 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000239#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000240}
241
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000242// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000243// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000244#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000245#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000246#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000247#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000248
Howard Hinnantc51e1022010-05-11 19:42:16 +0000249locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000250 : facets_(max<size_t>(N, other.facets_.size())),
251 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000252{
253 facets_ = other.facets_;
254 for (unsigned i = 0; i < facets_.size(); ++i)
255 if (facets_[i])
256 facets_[i]->__add_shared();
257}
258
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000259#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000260#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000261#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000262
Howard Hinnantc51e1022010-05-11 19:42:16 +0000263locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000264 : facets_(N),
265 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000266{
267 facets_ = other.facets_;
268 for (unsigned i = 0; i < facets_.size(); ++i)
269 if (facets_[i])
270 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000271#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000272 try
273 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000274#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000275 if (c & locale::collate)
276 {
277 install(new collate_byname<char>(name));
278 install(new collate_byname<wchar_t>(name));
279 }
280 if (c & locale::ctype)
281 {
282 install(new ctype_byname<char>(name));
283 install(new ctype_byname<wchar_t>(name));
284 install(new codecvt_byname<char, char, mbstate_t>(name));
285 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
286 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
287 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
288 }
289 if (c & locale::monetary)
290 {
291 install(new moneypunct_byname<char, false>(name));
292 install(new moneypunct_byname<char, true>(name));
293 install(new moneypunct_byname<wchar_t, false>(name));
294 install(new moneypunct_byname<wchar_t, true>(name));
295 }
296 if (c & locale::numeric)
297 {
298 install(new numpunct_byname<char>(name));
299 install(new numpunct_byname<wchar_t>(name));
300 }
301 if (c & locale::time)
302 {
303 install(new time_get_byname<char>(name));
304 install(new time_get_byname<wchar_t>(name));
305 install(new time_put_byname<char>(name));
306 install(new time_put_byname<wchar_t>(name));
307 }
308 if (c & locale::messages)
309 {
310 install(new messages_byname<char>(name));
311 install(new messages_byname<wchar_t>(name));
312 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000313#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000314 }
315 catch (...)
316 {
317 for (unsigned i = 0; i < facets_.size(); ++i)
318 if (facets_[i])
319 facets_[i]->__release_shared();
320 throw;
321 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000322#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000323}
324
325template<class F>
326inline
327void
328locale::__imp::install_from(const locale::__imp& one)
329{
330 long id = F::id.__get();
331 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
332}
333
334locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000335 : facets_(N),
336 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000337{
338 facets_ = other.facets_;
339 for (unsigned i = 0; i < facets_.size(); ++i)
340 if (facets_[i])
341 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000342#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000343 try
344 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000345#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000346 if (c & locale::collate)
347 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000348 install_from<_VSTD::collate<char> >(one);
349 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000350 }
351 if (c & locale::ctype)
352 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000353 install_from<_VSTD::ctype<char> >(one);
354 install_from<_VSTD::ctype<wchar_t> >(one);
355 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
356 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
357 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
358 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000359 }
360 if (c & locale::monetary)
361 {
362 install_from<moneypunct<char, false> >(one);
363 install_from<moneypunct<char, true> >(one);
364 install_from<moneypunct<wchar_t, false> >(one);
365 install_from<moneypunct<wchar_t, true> >(one);
366 install_from<money_get<char> >(one);
367 install_from<money_get<wchar_t> >(one);
368 install_from<money_put<char> >(one);
369 install_from<money_put<wchar_t> >(one);
370 }
371 if (c & locale::numeric)
372 {
373 install_from<numpunct<char> >(one);
374 install_from<numpunct<wchar_t> >(one);
375 install_from<num_get<char> >(one);
376 install_from<num_get<wchar_t> >(one);
377 install_from<num_put<char> >(one);
378 install_from<num_put<wchar_t> >(one);
379 }
380 if (c & locale::time)
381 {
382 install_from<time_get<char> >(one);
383 install_from<time_get<wchar_t> >(one);
384 install_from<time_put<char> >(one);
385 install_from<time_put<wchar_t> >(one);
386 }
387 if (c & locale::messages)
388 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000389 install_from<_VSTD::messages<char> >(one);
390 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000391 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000392#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000393 }
394 catch (...)
395 {
396 for (unsigned i = 0; i < facets_.size(); ++i)
397 if (facets_[i])
398 facets_[i]->__release_shared();
399 throw;
400 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000401#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000402}
403
404locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000405 : facets_(max<size_t>(N, other.facets_.size()+1)),
406 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000407{
408 f->__add_shared();
409 unique_ptr<facet, release> hold(f);
410 facets_ = other.facets_;
411 for (unsigned i = 0; i < other.facets_.size(); ++i)
412 if (facets_[i])
413 facets_[i]->__add_shared();
414 install(hold.get(), id);
415}
416
417locale::__imp::~__imp()
418{
419 for (unsigned i = 0; i < facets_.size(); ++i)
420 if (facets_[i])
421 facets_[i]->__release_shared();
422}
423
424void
425locale::__imp::install(facet* f, long id)
426{
427 f->__add_shared();
428 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000429 if (static_cast<size_t>(id) >= facets_.size())
430 facets_.resize(static_cast<size_t>(id+1));
431 if (facets_[static_cast<size_t>(id)])
432 facets_[static_cast<size_t>(id)]->__release_shared();
433 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000434}
435
436const locale::facet*
437locale::__imp::use_facet(long id) const
438{
Howard Hinnant72f73582010-08-11 17:04:31 +0000439#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000440 if (!has_facet(id))
441 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000442#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000443 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000444}
445
446// locale
447
448const locale&
449locale::__imp::make_classic()
450{
451 // only one thread can get in here and it only gets in once
452 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000453 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000454 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000455 return *c;
456}
457
458const locale&
459locale::classic()
460{
461 static const locale& c = __imp::make_classic();
462 return c;
463}
464
465locale&
466locale::__imp::make_global()
467{
468 // only one thread can get in here and it only gets in once
469 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000470 ::new (&buf) locale(locale::classic());
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000471 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000472}
473
474locale&
475locale::__global()
476{
477 static locale& g = __imp::make_global();
478 return g;
479}
480
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000481locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000482 : __locale_(__global().__locale_)
483{
484 __locale_->__add_shared();
485}
486
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000487locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000488 : __locale_(l.__locale_)
489{
490 __locale_->__add_shared();
491}
492
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000493locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000494{
495 __locale_->__release_shared();
496}
497
498const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000499locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000500{
501 other.__locale_->__add_shared();
502 __locale_->__release_shared();
503 __locale_ = other.__locale_;
504 return *this;
505}
506
507locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000508#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509 : __locale_(name ? new __imp(name)
510 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000511#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000512 : __locale_(new __imp(name))
513#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000514{
515 __locale_->__add_shared();
516}
517
518locale::locale(const string& name)
519 : __locale_(new __imp(name))
520{
521 __locale_->__add_shared();
522}
523
524locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000525#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000526 : __locale_(name ? new __imp(*other.__locale_, name, c)
527 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000528#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000529 : __locale_(new __imp(*other.__locale_, name, c))
530#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000531{
532 __locale_->__add_shared();
533}
534
535locale::locale(const locale& other, const string& name, category c)
536 : __locale_(new __imp(*other.__locale_, name, c))
537{
538 __locale_->__add_shared();
539}
540
541locale::locale(const locale& other, const locale& one, category c)
542 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
543{
544 __locale_->__add_shared();
545}
546
547string
548locale::name() const
549{
550 return __locale_->name();
551}
552
553void
554locale::__install_ctor(const locale& other, facet* f, long id)
555{
556 if (f)
557 __locale_ = new __imp(*other.__locale_, f, id);
558 else
559 __locale_ = other.__locale_;
560 __locale_->__add_shared();
561}
562
563locale
564locale::global(const locale& loc)
565{
566 locale& g = __global();
567 locale r = g;
568 g = loc;
Ed Schouten3d3341e2015-07-06 15:39:36 +0000569#ifndef __CloudABI__
Howard Hinnantc51e1022010-05-11 19:42:16 +0000570 if (g.name() != "*")
571 setlocale(LC_ALL, g.name().c_str());
Ed Schouten3d3341e2015-07-06 15:39:36 +0000572#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000573 return r;
574}
575
576bool
577locale::has_facet(id& x) const
578{
579 return __locale_->has_facet(x.__get());
580}
581
582const locale::facet*
583locale::use_facet(id& x) const
584{
585 return __locale_->use_facet(x.__get());
586}
587
588bool
589locale::operator==(const locale& y) const
590{
591 return (__locale_ == y.__locale_)
592 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
593}
594
595// locale::facet
596
597locale::facet::~facet()
598{
599}
600
601void
Howard Hinnant719bda32011-05-28 14:41:13 +0000602locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000603{
604 delete this;
605}
606
607// locale::id
608
609int32_t locale::id::__next_id = 0;
610
611namespace
612{
613
614class __fake_bind
615{
616 locale::id* id_;
617 void (locale::id::* pmf_)();
618public:
619 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
620 : id_(id), pmf_(pmf) {}
621
622 void operator()() const
623 {
624 (id_->*pmf_)();
625 }
626};
627
628}
629
630long
631locale::id::__get()
632{
633 call_once(__flag_, __fake_bind(&locale::id::__init, this));
634 return __id_ - 1;
635}
636
637void
638locale::id::__init()
639{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000640 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000641}
642
643// template <> class collate_byname<char>
644
645collate_byname<char>::collate_byname(const char* n, size_t refs)
646 : collate<char>(refs),
647 __l(newlocale(LC_ALL_MASK, n, 0))
648{
Howard Hinnant72f73582010-08-11 17:04:31 +0000649#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000650 if (__l == 0)
651 throw runtime_error("collate_byname<char>::collate_byname"
652 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000653#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000654}
655
656collate_byname<char>::collate_byname(const string& name, size_t refs)
657 : collate<char>(refs),
658 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
659{
Howard Hinnant72f73582010-08-11 17:04:31 +0000660#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000661 if (__l == 0)
662 throw runtime_error("collate_byname<char>::collate_byname"
663 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000664#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000665}
666
667collate_byname<char>::~collate_byname()
668{
669 freelocale(__l);
670}
671
672int
673collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
674 const char_type* __lo2, const char_type* __hi2) const
675{
676 string_type lhs(__lo1, __hi1);
677 string_type rhs(__lo2, __hi2);
678 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
679 if (r < 0)
680 return -1;
681 if (r > 0)
682 return 1;
683 return r;
684}
685
686collate_byname<char>::string_type
687collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
688{
689 const string_type in(lo, hi);
690 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
691 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
692 return out;
693}
694
695// template <> class collate_byname<wchar_t>
696
697collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
698 : collate<wchar_t>(refs),
699 __l(newlocale(LC_ALL_MASK, n, 0))
700{
Howard Hinnant72f73582010-08-11 17:04:31 +0000701#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000702 if (__l == 0)
703 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
704 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000705#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000706}
707
708collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
709 : collate<wchar_t>(refs),
710 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
711{
Howard Hinnant72f73582010-08-11 17:04:31 +0000712#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000713 if (__l == 0)
714 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
715 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000716#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000717}
718
719collate_byname<wchar_t>::~collate_byname()
720{
721 freelocale(__l);
722}
723
724int
725collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
726 const char_type* __lo2, const char_type* __hi2) const
727{
728 string_type lhs(__lo1, __hi1);
729 string_type rhs(__lo2, __hi2);
730 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
731 if (r < 0)
732 return -1;
733 if (r > 0)
734 return 1;
735 return r;
736}
737
738collate_byname<wchar_t>::string_type
739collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
740{
741 const string_type in(lo, hi);
742 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
743 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
744 return out;
745}
746
747// template <> class ctype<wchar_t>;
748
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000749const ctype_base::mask ctype_base::space;
750const ctype_base::mask ctype_base::print;
751const ctype_base::mask ctype_base::cntrl;
752const ctype_base::mask ctype_base::upper;
753const ctype_base::mask ctype_base::lower;
754const ctype_base::mask ctype_base::alpha;
755const ctype_base::mask ctype_base::digit;
756const ctype_base::mask ctype_base::punct;
757const ctype_base::mask ctype_base::xdigit;
758const ctype_base::mask ctype_base::blank;
759const ctype_base::mask ctype_base::alnum;
760const ctype_base::mask ctype_base::graph;
761
Howard Hinnantc51e1022010-05-11 19:42:16 +0000762locale::id ctype<wchar_t>::id;
763
764ctype<wchar_t>::~ctype()
765{
766}
767
768bool
769ctype<wchar_t>::do_is(mask m, char_type c) const
770{
Marshall Clowd920eea2013-10-21 15:07:28 +0000771 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000772}
773
774const wchar_t*
775ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
776{
777 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000778 *vec = static_cast<mask>(isascii(*low) ?
779 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000780 return low;
781}
782
783const wchar_t*
784ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
785{
786 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000787 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000788 break;
789 return low;
790}
791
792const wchar_t*
793ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
794{
795 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000796 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000797 break;
798 return low;
799}
800
801wchar_t
802ctype<wchar_t>::do_toupper(char_type c) const
803{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000804#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
805 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000806#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000807 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000808 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000809#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000810 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000811#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000812}
813
814const wchar_t*
815ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
816{
817 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000818#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
819 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000820#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000821 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000822 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
823 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000824#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000825 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000826#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000827 return low;
828}
829
830wchar_t
831ctype<wchar_t>::do_tolower(char_type c) const
832{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000833#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
834 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000835#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000836 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000837 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000838#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000839 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000840#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000841}
842
843const wchar_t*
844ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
845{
846 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000847#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
848 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000849#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000850 defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000851 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
852 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000853#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000854 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000855#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000856 return low;
857}
858
859wchar_t
860ctype<wchar_t>::do_widen(char c) const
861{
862 return c;
863}
864
865const char*
866ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
867{
868 for (; low != high; ++low, ++dest)
869 *dest = *low;
870 return low;
871}
872
873char
874ctype<wchar_t>::do_narrow(char_type c, char dfault) const
875{
876 if (isascii(c))
877 return static_cast<char>(c);
878 return dfault;
879}
880
881const wchar_t*
882ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
883{
884 for (; low != high; ++low, ++dest)
885 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000886 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000887 else
888 *dest = dfault;
889 return low;
890}
891
892// template <> class ctype<char>;
893
894locale::id ctype<char>::id;
895
896ctype<char>::ctype(const mask* tab, bool del, size_t refs)
897 : locale::facet(refs),
898 __tab_(tab),
899 __del_(del)
900{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000901 if (__tab_ == 0)
902 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000903}
904
905ctype<char>::~ctype()
906{
907 if (__tab_ && __del_)
908 delete [] __tab_;
909}
910
911char
912ctype<char>::do_toupper(char_type c) const
913{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000914#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000915 return isascii(c) ?
916 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000917#elif defined(__NetBSD__)
918 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000919#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Vasileios Kalintiris281b4cf2015-11-09 10:21:04 +0000920 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000921 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000922#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000923 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000924#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000925}
926
927const char*
928ctype<char>::do_toupper(char_type* low, const char_type* high) const
929{
930 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000931#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000932 *low = isascii(*low) ?
933 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000934#elif defined(__NetBSD__)
935 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000936#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000937 *low = isascii(*low) ?
938 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000939#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000940 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000941#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000942 return low;
943}
944
945char
946ctype<char>::do_tolower(char_type c) const
947{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000948#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000949 return isascii(c) ?
950 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000951#elif defined(__NetBSD__)
952 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000953#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000954 return isascii(c) ?
955 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000956#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000957 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000958#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000959}
960
961const char*
962ctype<char>::do_tolower(char_type* low, const char_type* high) const
963{
964 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000965#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000966 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000967#elif defined(__NetBSD__)
968 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +0000969#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000970 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000971#else
Ed Schouten7c54ead2015-07-06 15:37:40 +0000972 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000973#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000974 return low;
975}
976
977char
978ctype<char>::do_widen(char c) const
979{
980 return c;
981}
982
983const char*
984ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
985{
986 for (; low != high; ++low, ++dest)
987 *dest = *low;
988 return low;
989}
990
991char
992ctype<char>::do_narrow(char_type c, char dfault) const
993{
994 if (isascii(c))
995 return static_cast<char>(c);
996 return dfault;
997}
998
999const char*
1000ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1001{
1002 for (; low != high; ++low, ++dest)
1003 if (isascii(*low))
1004 *dest = *low;
1005 else
1006 *dest = dfault;
1007 return low;
1008}
1009
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001010#if defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001011extern "C" const unsigned short ** __ctype_b_loc();
1012extern "C" const int ** __ctype_tolower_loc();
1013extern "C" const int ** __ctype_toupper_loc();
1014#endif
1015
Marshall Clow8f870232015-03-04 16:50:02 +00001016#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clowb3f62842015-03-04 16:10:14 +00001017const ctype<char>::mask*
1018ctype<char>::classic_table() _NOEXCEPT
1019{
1020 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1021 cntrl, cntrl,
1022 cntrl, cntrl,
1023 cntrl, cntrl,
1024 cntrl, cntrl,
1025 cntrl, cntrl | space | blank,
1026 cntrl | space, cntrl | space,
1027 cntrl | space, cntrl | space,
1028 cntrl, cntrl,
1029 cntrl, cntrl,
1030 cntrl, cntrl,
1031 cntrl, cntrl,
1032 cntrl, cntrl,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 space | blank | print, punct | print,
1038 punct | print, punct | print,
1039 punct | print, punct | print,
1040 punct | print, punct | print,
1041 punct | print, punct | print,
1042 punct | print, punct | print,
1043 punct | print, punct | print,
1044 punct | print, punct | print,
1045 digit | print | xdigit, digit | print | xdigit,
1046 digit | print | xdigit, digit | print | xdigit,
1047 digit | print | xdigit, digit | print | xdigit,
1048 digit | print | xdigit, digit | print | xdigit,
1049 digit | print | xdigit, digit | print | xdigit,
1050 punct | print, punct | print,
1051 punct | print, punct | print,
1052 punct | print, punct | print,
1053 punct | print, upper | xdigit | print | alpha,
1054 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1055 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1056 upper | xdigit | print | alpha, upper | print | alpha,
1057 upper | print | alpha, upper | print | alpha,
1058 upper | print | alpha, upper | print | alpha,
1059 upper | 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, punct | print,
1067 punct | print, punct | print,
1068 punct | print, punct | print,
1069 punct | print, lower | xdigit | print | alpha,
1070 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1071 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1072 lower | xdigit | print | alpha, lower | print | alpha,
1073 lower | print | alpha, lower | print | alpha,
1074 lower | print | alpha, lower | print | alpha,
1075 lower | 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, punct | print,
1083 punct | print, punct | print,
1084 punct | print, cntrl,
1085 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1086 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1087 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 };
1094 return builtin_table;
1095}
1096#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001097const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001098ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001099{
David Chisnall1d581062011-09-21 08:39:44 +00001100#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001101 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001102#elif defined(__NetBSD__)
1103 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001104#elif defined(__GLIBC__)
Ed Schouten7c54ead2015-07-06 15:37:40 +00001105 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001106#elif __sun__
1107 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001108#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001109 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnall1d581062011-09-21 08:39:44 +00001110// This is assumed to be safe, which is a nonsense assumption because we're
1111// going to end up dereferencing it later...
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001112#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001113 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001114#elif defined(_NEWLIB_VERSION)
1115 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1116 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001117#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001118 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001119#else
David Chisnall8074c342012-02-29 13:05:08 +00001120 // Platform not supported: abort so the person doing the port knows what to
1121 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001122# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001123 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001124 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001125 return NULL;
1126#endif
1127}
Marshall Clowb3f62842015-03-04 16:10:14 +00001128#endif
Alexis Hunt92b0c812011-07-09 00:56:23 +00001129
Howard Hinnantd7a78632011-09-29 13:33:15 +00001130#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001131const int*
1132ctype<char>::__classic_lower_table() _NOEXCEPT
1133{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001134 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001135}
1136
1137const int*
1138ctype<char>::__classic_upper_table() _NOEXCEPT
1139{
Ed Schouten7c54ead2015-07-06 15:37:40 +00001140 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001141}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001142#elif __NetBSD__
1143const short*
1144ctype<char>::__classic_lower_table() _NOEXCEPT
1145{
1146 return _C_tolower_tab_ + 1;
1147}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001148
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001149const short*
1150ctype<char>::__classic_upper_table() _NOEXCEPT
1151{
1152 return _C_toupper_tab_ + 1;
1153}
1154
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001155#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001156const int*
1157ctype<char>::__classic_lower_table() _NOEXCEPT
1158{
1159 return *__ctype_tolower_loc();
1160}
1161
1162const int*
1163ctype<char>::__classic_upper_table() _NOEXCEPT
1164{
1165 return *__ctype_toupper_loc();
1166}
Vasileios Kalintirisc5dd8942015-11-24 10:24:54 +00001167#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001168
Howard Hinnantc51e1022010-05-11 19:42:16 +00001169// template <> class ctype_byname<char>
1170
1171ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1172 : ctype<char>(0, false, refs),
1173 __l(newlocale(LC_ALL_MASK, name, 0))
1174{
Howard Hinnant72f73582010-08-11 17:04:31 +00001175#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001176 if (__l == 0)
1177 throw runtime_error("ctype_byname<char>::ctype_byname"
1178 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001179#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001180}
1181
1182ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1183 : ctype<char>(0, false, refs),
1184 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1185{
Howard Hinnant72f73582010-08-11 17:04:31 +00001186#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001187 if (__l == 0)
1188 throw runtime_error("ctype_byname<char>::ctype_byname"
1189 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001190#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001191}
1192
1193ctype_byname<char>::~ctype_byname()
1194{
1195 freelocale(__l);
1196}
1197
1198char
1199ctype_byname<char>::do_toupper(char_type c) const
1200{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001201 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001202}
1203
1204const char*
1205ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1206{
1207 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001208 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001209 return low;
1210}
1211
1212char
1213ctype_byname<char>::do_tolower(char_type c) const
1214{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001215 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001216}
1217
1218const char*
1219ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1220{
1221 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001222 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001223 return low;
1224}
1225
1226// template <> class ctype_byname<wchar_t>
1227
1228ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1229 : ctype<wchar_t>(refs),
1230 __l(newlocale(LC_ALL_MASK, name, 0))
1231{
Howard Hinnant72f73582010-08-11 17:04:31 +00001232#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001233 if (__l == 0)
1234 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1235 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001236#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001237}
1238
1239ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1240 : ctype<wchar_t>(refs),
1241 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1242{
Howard Hinnant72f73582010-08-11 17:04:31 +00001243#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001244 if (__l == 0)
1245 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1246 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001247#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001248}
1249
1250ctype_byname<wchar_t>::~ctype_byname()
1251{
1252 freelocale(__l);
1253}
1254
1255bool
1256ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1257{
Alexis Huntc2017f12011-07-09 03:40:04 +00001258#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001259 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001260#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001261 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001262 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001263 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1264 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1265 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1266 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1267 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1268 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1269 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1270 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1271 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1272 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001273 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001274#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001275}
1276
1277const wchar_t*
1278ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1279{
1280 for (; low != high; ++low, ++vec)
1281 {
1282 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001283 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001284 else
1285 {
1286 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001287 wint_t ch = static_cast<wint_t>(*low);
1288 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001289 *vec |= space;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001290#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clowada0f732013-02-07 14:22:51 +00001291 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001292 *vec |= print;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001293#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001294 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001295 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001296 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001297 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001298 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001299 *vec |= lower;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001300#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clowada0f732013-02-07 14:22:51 +00001301 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001302 *vec |= alpha;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001303#endif
Marshall Clowada0f732013-02-07 14:22:51 +00001304 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001305 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001306 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001307 *vec |= punct;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001308#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clowada0f732013-02-07 14:22:51 +00001309 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001310 *vec |= xdigit;
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001311#endif
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001312#if !defined(__sun__)
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001313 if (iswblank_l(ch, __l))
1314 *vec |= blank;
Jonathan Roelofsfe5cea42015-03-13 15:09:42 +00001315#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001316 }
1317 }
1318 return low;
1319}
1320
1321const wchar_t*
1322ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1323{
1324 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001325 {
1326#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001327 if (iswctype_l(*low, m, __l))
1328 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001329#else
Marshall Clowada0f732013-02-07 14:22:51 +00001330 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001331 if ((m & space) == space && iswspace_l(ch, __l)) break;
1332 if ((m & print) == print && iswprint_l(ch, __l)) break;
1333 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1334 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1335 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1336 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1337 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1338 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1339 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1340 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001341#endif
1342 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001343 return low;
1344}
1345
1346const wchar_t*
1347ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1348{
1349 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001350 {
1351#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001352 if (!iswctype_l(*low, m, __l))
1353 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001354#else
Marshall Clowada0f732013-02-07 14:22:51 +00001355 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofsae9ab252015-03-11 17:00:28 +00001356 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1357 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1358 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1359 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1360 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1361 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1362 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1363 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1364 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1365 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001366 break;
1367#endif
1368 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001369 return low;
1370}
1371
1372wchar_t
1373ctype_byname<wchar_t>::do_toupper(char_type c) const
1374{
1375 return towupper_l(c, __l);
1376}
1377
1378const wchar_t*
1379ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1380{
1381 for (; low != high; ++low)
1382 *low = towupper_l(*low, __l);
1383 return low;
1384}
1385
1386wchar_t
1387ctype_byname<wchar_t>::do_tolower(char_type c) const
1388{
1389 return towlower_l(c, __l);
1390}
1391
1392const wchar_t*
1393ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1394{
1395 for (; low != high; ++low)
1396 *low = towlower_l(*low, __l);
1397 return low;
1398}
1399
1400wchar_t
1401ctype_byname<wchar_t>::do_widen(char c) const
1402{
Ben Craig3756b922016-03-09 15:39:39 +00001403 return __libcpp_btowc_l(c, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001404}
1405
1406const char*
1407ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1408{
1409 for (; low != high; ++low, ++dest)
Ben Craig3756b922016-03-09 15:39:39 +00001410 *dest = __libcpp_btowc_l(*low, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001411 return low;
1412}
1413
1414char
1415ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1416{
Ben Craig3756b922016-03-09 15:39:39 +00001417 int r = __libcpp_wctob_l(c, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001418 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001419}
1420
1421const wchar_t*
1422ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1423{
1424 for (; low != high; ++low, ++dest)
1425 {
Ben Craig3756b922016-03-09 15:39:39 +00001426 int r = __libcpp_wctob_l(*low, __l);
Howard Hinnant434ebf72012-12-27 18:46:00 +00001427 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001428 }
1429 return low;
1430}
1431
1432// template <> class codecvt<char, char, mbstate_t>
1433
Howard Hinnantffb308e2010-08-22 00:03:27 +00001434locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001435
1436codecvt<char, char, mbstate_t>::~codecvt()
1437{
1438}
1439
1440codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001441codecvt<char, char, mbstate_t>::do_out(state_type&,
1442 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001443 extern_type* to, extern_type*, extern_type*& to_nxt) const
1444{
1445 frm_nxt = frm;
1446 to_nxt = to;
1447 return noconv;
1448}
1449
1450codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001451codecvt<char, char, mbstate_t>::do_in(state_type&,
1452 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001453 intern_type* to, intern_type*, intern_type*& to_nxt) const
1454{
1455 frm_nxt = frm;
1456 to_nxt = to;
1457 return noconv;
1458}
1459
1460codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001461codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001462 extern_type* to, extern_type*, extern_type*& to_nxt) const
1463{
1464 to_nxt = to;
1465 return noconv;
1466}
1467
1468int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001469codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001470{
1471 return 1;
1472}
1473
1474bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001475codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001476{
1477 return true;
1478}
1479
1480int
1481codecvt<char, char, mbstate_t>::do_length(state_type&,
1482 const extern_type* frm, const extern_type* end, size_t mx) const
1483{
Howard Hinnant28b24882011-12-01 20:21:04 +00001484 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001485}
1486
1487int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001488codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001489{
1490 return 1;
1491}
1492
1493// template <> class codecvt<wchar_t, char, mbstate_t>
1494
Howard Hinnantffb308e2010-08-22 00:03:27 +00001495locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001496
1497codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1498 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001499 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001500{
1501}
1502
1503codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1504 : locale::facet(refs),
1505 __l(newlocale(LC_ALL_MASK, nm, 0))
1506{
Howard Hinnant72f73582010-08-11 17:04:31 +00001507#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001508 if (__l == 0)
1509 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1510 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001511#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001512}
1513
1514codecvt<wchar_t, char, mbstate_t>::~codecvt()
1515{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001516 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001517 freelocale(__l);
1518}
1519
1520codecvt<wchar_t, char, mbstate_t>::result
1521codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001522 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001523 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1524{
1525 // look for first internal null in frm
1526 const intern_type* fend = frm;
1527 for (; fend != frm_end; ++fend)
1528 if (*fend == 0)
1529 break;
1530 // loop over all null-terminated sequences in frm
1531 to_nxt = to;
1532 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1533 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001534 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001535 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001536 size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1537 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001538 if (n == size_t(-1))
1539 {
1540 // need to recover to_nxt
1541 for (to_nxt = to; frm != frm_nxt; ++frm)
1542 {
Ben Craig3756b922016-03-09 15:39:39 +00001543 n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001544 if (n == size_t(-1))
1545 break;
1546 to_nxt += n;
1547 }
1548 frm_nxt = frm;
1549 return error;
1550 }
1551 if (n == 0)
1552 return partial;
1553 to_nxt += n;
1554 if (to_nxt == to_end)
1555 break;
1556 if (fend != frm_end) // set up next null terminated sequence
1557 {
1558 // Try to write the terminating null
1559 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001560 n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001561 if (n == size_t(-1)) // on error
1562 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001563 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001564 return partial;
1565 for (extern_type* p = tmp; n; --n) // write it
1566 *to_nxt++ = *p++;
1567 ++frm_nxt;
1568 // look for next null in frm
1569 for (fend = frm_nxt; fend != frm_end; ++fend)
1570 if (*fend == 0)
1571 break;
1572 }
1573 }
1574 return frm_nxt == frm_end ? ok : partial;
1575}
1576
1577codecvt<wchar_t, char, mbstate_t>::result
1578codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001579 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001580 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1581{
1582 // look for first internal null in frm
1583 const extern_type* fend = frm;
1584 for (; fend != frm_end; ++fend)
1585 if (*fend == 0)
1586 break;
1587 // loop over all null-terminated sequences in frm
1588 to_nxt = to;
1589 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1590 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001591 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001592 mbstate_t save_state = st;
Ben Craig3756b922016-03-09 15:39:39 +00001593 size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1594 static_cast<size_t>(to_end-to), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001595 if (n == size_t(-1))
1596 {
1597 // need to recover to_nxt
1598 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1599 {
Ben Craig3756b922016-03-09 15:39:39 +00001600 n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1601 &save_state, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001602 switch (n)
1603 {
1604 case 0:
1605 ++frm;
1606 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001607 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001608 frm_nxt = frm;
1609 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001610 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611 frm_nxt = frm;
1612 return partial;
1613 default:
1614 frm += n;
1615 break;
1616 }
1617 }
1618 frm_nxt = frm;
1619 return frm_nxt == frm_end ? ok : partial;
1620 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001621 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 return error;
1623 to_nxt += n;
1624 if (to_nxt == to_end)
1625 break;
1626 if (fend != frm_end) // set up next null terminated sequence
1627 {
1628 // Try to write the terminating null
Ben Craig3756b922016-03-09 15:39:39 +00001629 n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001630 if (n != 0) // on error
1631 return error;
1632 ++to_nxt;
1633 ++frm_nxt;
1634 // look for next null in frm
1635 for (fend = frm_nxt; fend != frm_end; ++fend)
1636 if (*fend == 0)
1637 break;
1638 }
1639 }
1640 return frm_nxt == frm_end ? ok : partial;
1641}
1642
1643codecvt<wchar_t, char, mbstate_t>::result
1644codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1645 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1646{
1647 to_nxt = to;
1648 extern_type tmp[MB_LEN_MAX];
Ben Craig3756b922016-03-09 15:39:39 +00001649 size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001650 if (n == size_t(-1) || n == 0) // on error
1651 return error;
1652 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001653 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001654 return partial;
1655 for (extern_type* p = tmp; n; --n) // write it
1656 *to_nxt++ = *p++;
1657 return ok;
1658}
1659
1660int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001661codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001662{
Ben Craig3756b922016-03-09 15:39:39 +00001663 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001664 return -1;
Ed Schouten3d3341e2015-07-06 15:39:36 +00001665
1666 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001667 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001668 return 1; // which take more than 1 char to form a wchar_t
1669 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001670}
1671
1672bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001673codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001674{
1675 return false;
1676}
1677
1678int
1679codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1680 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1681{
1682 int nbytes = 0;
1683 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1684 {
Ben Craig3756b922016-03-09 15:39:39 +00001685 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001686 switch (n)
1687 {
1688 case 0:
1689 ++nbytes;
1690 ++frm;
1691 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001692 case size_t(-1):
1693 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001694 return nbytes;
1695 default:
1696 nbytes += n;
1697 frm += n;
1698 break;
1699 }
1700 }
1701 return nbytes;
1702}
1703
1704int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001705codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001706{
Ben Craig3756b922016-03-09 15:39:39 +00001707 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001708}
1709
1710// Valid UTF ranges
1711// UTF-32 UTF-16 UTF-8 # of code points
1712// first second first second third fourth
1713// 000000 - 00007F 0000 - 007F 00 - 7F 127
1714// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1715// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1716// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1717// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1718// 00D800 - 00DFFF invalid
1719// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1720// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1721// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1722// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1723
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001724static
1725codecvt_base::result
1726utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1727 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1728 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1729{
1730 frm_nxt = frm;
1731 to_nxt = to;
1732 if (mode & generate_header)
1733 {
1734 if (to_end-to_nxt < 3)
1735 return codecvt_base::partial;
1736 *to_nxt++ = static_cast<uint8_t>(0xEF);
1737 *to_nxt++ = static_cast<uint8_t>(0xBB);
1738 *to_nxt++ = static_cast<uint8_t>(0xBF);
1739 }
1740 for (; frm_nxt < frm_end; ++frm_nxt)
1741 {
1742 uint16_t wc1 = *frm_nxt;
1743 if (wc1 > Maxcode)
1744 return codecvt_base::error;
1745 if (wc1 < 0x0080)
1746 {
1747 if (to_end-to_nxt < 1)
1748 return codecvt_base::partial;
1749 *to_nxt++ = static_cast<uint8_t>(wc1);
1750 }
1751 else if (wc1 < 0x0800)
1752 {
1753 if (to_end-to_nxt < 2)
1754 return codecvt_base::partial;
1755 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1756 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1757 }
1758 else if (wc1 < 0xD800)
1759 {
1760 if (to_end-to_nxt < 3)
1761 return codecvt_base::partial;
1762 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1763 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1764 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1765 }
1766 else if (wc1 < 0xDC00)
1767 {
1768 if (frm_end-frm_nxt < 2)
1769 return codecvt_base::partial;
1770 uint16_t wc2 = frm_nxt[1];
1771 if ((wc2 & 0xFC00) != 0xDC00)
1772 return codecvt_base::error;
1773 if (to_end-to_nxt < 4)
1774 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001775 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1776 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001777 return codecvt_base::error;
1778 ++frm_nxt;
1779 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1780 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1781 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1782 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1783 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1784 }
1785 else if (wc1 < 0xE000)
1786 {
1787 return codecvt_base::error;
1788 }
1789 else
1790 {
1791 if (to_end-to_nxt < 3)
1792 return codecvt_base::partial;
1793 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1794 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1795 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1796 }
1797 }
1798 return codecvt_base::ok;
1799}
1800
1801static
1802codecvt_base::result
1803utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1804 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1805 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1806{
1807 frm_nxt = frm;
1808 to_nxt = to;
1809 if (mode & generate_header)
1810 {
1811 if (to_end-to_nxt < 3)
1812 return codecvt_base::partial;
1813 *to_nxt++ = static_cast<uint8_t>(0xEF);
1814 *to_nxt++ = static_cast<uint8_t>(0xBB);
1815 *to_nxt++ = static_cast<uint8_t>(0xBF);
1816 }
1817 for (; frm_nxt < frm_end; ++frm_nxt)
1818 {
1819 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1820 if (wc1 > Maxcode)
1821 return codecvt_base::error;
1822 if (wc1 < 0x0080)
1823 {
1824 if (to_end-to_nxt < 1)
1825 return codecvt_base::partial;
1826 *to_nxt++ = static_cast<uint8_t>(wc1);
1827 }
1828 else if (wc1 < 0x0800)
1829 {
1830 if (to_end-to_nxt < 2)
1831 return codecvt_base::partial;
1832 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1833 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1834 }
1835 else if (wc1 < 0xD800)
1836 {
1837 if (to_end-to_nxt < 3)
1838 return codecvt_base::partial;
1839 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1840 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1841 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1842 }
1843 else if (wc1 < 0xDC00)
1844 {
1845 if (frm_end-frm_nxt < 2)
1846 return codecvt_base::partial;
1847 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1848 if ((wc2 & 0xFC00) != 0xDC00)
1849 return codecvt_base::error;
1850 if (to_end-to_nxt < 4)
1851 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001852 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1853 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001854 return codecvt_base::error;
1855 ++frm_nxt;
1856 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1857 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1858 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1859 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1860 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1861 }
1862 else if (wc1 < 0xE000)
1863 {
1864 return codecvt_base::error;
1865 }
1866 else
1867 {
1868 if (to_end-to_nxt < 3)
1869 return codecvt_base::partial;
1870 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1871 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1872 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1873 }
1874 }
1875 return codecvt_base::ok;
1876}
1877
1878static
1879codecvt_base::result
1880utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1881 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1882 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1883{
1884 frm_nxt = frm;
1885 to_nxt = to;
1886 if (mode & consume_header)
1887 {
1888 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1889 frm_nxt[2] == 0xBF)
1890 frm_nxt += 3;
1891 }
1892 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1893 {
1894 uint8_t c1 = *frm_nxt;
1895 if (c1 > Maxcode)
1896 return codecvt_base::error;
1897 if (c1 < 0x80)
1898 {
1899 *to_nxt = static_cast<uint16_t>(c1);
1900 ++frm_nxt;
1901 }
1902 else if (c1 < 0xC2)
1903 {
1904 return codecvt_base::error;
1905 }
1906 else if (c1 < 0xE0)
1907 {
1908 if (frm_end-frm_nxt < 2)
1909 return codecvt_base::partial;
1910 uint8_t c2 = frm_nxt[1];
1911 if ((c2 & 0xC0) != 0x80)
1912 return codecvt_base::error;
1913 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1914 if (t > Maxcode)
1915 return codecvt_base::error;
1916 *to_nxt = t;
1917 frm_nxt += 2;
1918 }
1919 else if (c1 < 0xF0)
1920 {
1921 if (frm_end-frm_nxt < 3)
1922 return codecvt_base::partial;
1923 uint8_t c2 = frm_nxt[1];
1924 uint8_t c3 = frm_nxt[2];
1925 switch (c1)
1926 {
1927 case 0xE0:
1928 if ((c2 & 0xE0) != 0xA0)
1929 return codecvt_base::error;
1930 break;
1931 case 0xED:
1932 if ((c2 & 0xE0) != 0x80)
1933 return codecvt_base::error;
1934 break;
1935 default:
1936 if ((c2 & 0xC0) != 0x80)
1937 return codecvt_base::error;
1938 break;
1939 }
1940 if ((c3 & 0xC0) != 0x80)
1941 return codecvt_base::error;
1942 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1943 | ((c2 & 0x3F) << 6)
1944 | (c3 & 0x3F));
1945 if (t > Maxcode)
1946 return codecvt_base::error;
1947 *to_nxt = t;
1948 frm_nxt += 3;
1949 }
1950 else if (c1 < 0xF5)
1951 {
1952 if (frm_end-frm_nxt < 4)
1953 return codecvt_base::partial;
1954 uint8_t c2 = frm_nxt[1];
1955 uint8_t c3 = frm_nxt[2];
1956 uint8_t c4 = frm_nxt[3];
1957 switch (c1)
1958 {
1959 case 0xF0:
1960 if (!(0x90 <= c2 && c2 <= 0xBF))
1961 return codecvt_base::error;
1962 break;
1963 case 0xF4:
1964 if ((c2 & 0xF0) != 0x80)
1965 return codecvt_base::error;
1966 break;
1967 default:
1968 if ((c2 & 0xC0) != 0x80)
1969 return codecvt_base::error;
1970 break;
1971 }
1972 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1973 return codecvt_base::error;
1974 if (to_end-to_nxt < 2)
1975 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001976 if ((((c1 & 7UL) << 18) +
1977 ((c2 & 0x3FUL) << 12) +
1978 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001979 return codecvt_base::error;
1980 *to_nxt = static_cast<uint16_t>(
1981 0xD800
1982 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1983 | ((c2 & 0x0F) << 2)
1984 | ((c3 & 0x30) >> 4));
1985 *++to_nxt = static_cast<uint16_t>(
1986 0xDC00
1987 | ((c3 & 0x0F) << 6)
1988 | (c4 & 0x3F));
1989 frm_nxt += 4;
1990 }
1991 else
1992 {
1993 return codecvt_base::error;
1994 }
1995 }
1996 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1997}
1998
1999static
2000codecvt_base::result
2001utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2002 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2003 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2004{
2005 frm_nxt = frm;
2006 to_nxt = to;
2007 if (mode & consume_header)
2008 {
2009 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2010 frm_nxt[2] == 0xBF)
2011 frm_nxt += 3;
2012 }
2013 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2014 {
2015 uint8_t c1 = *frm_nxt;
2016 if (c1 > Maxcode)
2017 return codecvt_base::error;
2018 if (c1 < 0x80)
2019 {
2020 *to_nxt = static_cast<uint32_t>(c1);
2021 ++frm_nxt;
2022 }
2023 else if (c1 < 0xC2)
2024 {
2025 return codecvt_base::error;
2026 }
2027 else if (c1 < 0xE0)
2028 {
2029 if (frm_end-frm_nxt < 2)
2030 return codecvt_base::partial;
2031 uint8_t c2 = frm_nxt[1];
2032 if ((c2 & 0xC0) != 0x80)
2033 return codecvt_base::error;
2034 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2035 if (t > Maxcode)
2036 return codecvt_base::error;
2037 *to_nxt = static_cast<uint32_t>(t);
2038 frm_nxt += 2;
2039 }
2040 else if (c1 < 0xF0)
2041 {
2042 if (frm_end-frm_nxt < 3)
2043 return codecvt_base::partial;
2044 uint8_t c2 = frm_nxt[1];
2045 uint8_t c3 = frm_nxt[2];
2046 switch (c1)
2047 {
2048 case 0xE0:
2049 if ((c2 & 0xE0) != 0xA0)
2050 return codecvt_base::error;
2051 break;
2052 case 0xED:
2053 if ((c2 & 0xE0) != 0x80)
2054 return codecvt_base::error;
2055 break;
2056 default:
2057 if ((c2 & 0xC0) != 0x80)
2058 return codecvt_base::error;
2059 break;
2060 }
2061 if ((c3 & 0xC0) != 0x80)
2062 return codecvt_base::error;
2063 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2064 | ((c2 & 0x3F) << 6)
2065 | (c3 & 0x3F));
2066 if (t > Maxcode)
2067 return codecvt_base::error;
2068 *to_nxt = static_cast<uint32_t>(t);
2069 frm_nxt += 3;
2070 }
2071 else if (c1 < 0xF5)
2072 {
2073 if (frm_end-frm_nxt < 4)
2074 return codecvt_base::partial;
2075 uint8_t c2 = frm_nxt[1];
2076 uint8_t c3 = frm_nxt[2];
2077 uint8_t c4 = frm_nxt[3];
2078 switch (c1)
2079 {
2080 case 0xF0:
2081 if (!(0x90 <= c2 && c2 <= 0xBF))
2082 return codecvt_base::error;
2083 break;
2084 case 0xF4:
2085 if ((c2 & 0xF0) != 0x80)
2086 return codecvt_base::error;
2087 break;
2088 default:
2089 if ((c2 & 0xC0) != 0x80)
2090 return codecvt_base::error;
2091 break;
2092 }
2093 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2094 return codecvt_base::error;
2095 if (to_end-to_nxt < 2)
2096 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002097 if ((((c1 & 7UL) << 18) +
2098 ((c2 & 0x3FUL) << 12) +
2099 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002100 return codecvt_base::error;
2101 *to_nxt = static_cast<uint32_t>(
2102 0xD800
2103 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2104 | ((c2 & 0x0F) << 2)
2105 | ((c3 & 0x30) >> 4));
2106 *++to_nxt = static_cast<uint32_t>(
2107 0xDC00
2108 | ((c3 & 0x0F) << 6)
2109 | (c4 & 0x3F));
2110 frm_nxt += 4;
2111 }
2112 else
2113 {
2114 return codecvt_base::error;
2115 }
2116 }
2117 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2118}
2119
2120static
2121int
2122utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2123 size_t mx, unsigned long Maxcode = 0x10FFFF,
2124 codecvt_mode mode = codecvt_mode(0))
2125{
2126 const uint8_t* frm_nxt = frm;
2127 if (mode & consume_header)
2128 {
2129 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2130 frm_nxt[2] == 0xBF)
2131 frm_nxt += 3;
2132 }
2133 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2134 {
2135 uint8_t c1 = *frm_nxt;
2136 if (c1 > Maxcode)
2137 break;
2138 if (c1 < 0x80)
2139 {
2140 ++frm_nxt;
2141 }
2142 else if (c1 < 0xC2)
2143 {
2144 break;
2145 }
2146 else if (c1 < 0xE0)
2147 {
2148 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2149 break;
2150 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2151 if (t > Maxcode)
2152 break;
2153 frm_nxt += 2;
2154 }
2155 else if (c1 < 0xF0)
2156 {
2157 if (frm_end-frm_nxt < 3)
2158 break;
2159 uint8_t c2 = frm_nxt[1];
2160 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002161 switch (c1)
2162 {
2163 case 0xE0:
2164 if ((c2 & 0xE0) != 0xA0)
2165 return static_cast<int>(frm_nxt - frm);
2166 break;
2167 case 0xED:
2168 if ((c2 & 0xE0) != 0x80)
2169 return static_cast<int>(frm_nxt - frm);
2170 break;
2171 default:
2172 if ((c2 & 0xC0) != 0x80)
2173 return static_cast<int>(frm_nxt - frm);
2174 break;
2175 }
2176 if ((c3 & 0xC0) != 0x80)
2177 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002178 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002179 break;
2180 frm_nxt += 3;
2181 }
2182 else if (c1 < 0xF5)
2183 {
2184 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2185 break;
2186 uint8_t c2 = frm_nxt[1];
2187 uint8_t c3 = frm_nxt[2];
2188 uint8_t c4 = frm_nxt[3];
2189 switch (c1)
2190 {
2191 case 0xF0:
2192 if (!(0x90 <= c2 && c2 <= 0xBF))
2193 return static_cast<int>(frm_nxt - frm);
2194 break;
2195 case 0xF4:
2196 if ((c2 & 0xF0) != 0x80)
2197 return static_cast<int>(frm_nxt - frm);
2198 break;
2199 default:
2200 if ((c2 & 0xC0) != 0x80)
2201 return static_cast<int>(frm_nxt - frm);
2202 break;
2203 }
2204 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2205 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002206 if ((((c1 & 7UL) << 18) +
2207 ((c2 & 0x3FUL) << 12) +
2208 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002209 break;
2210 ++nchar16_t;
2211 frm_nxt += 4;
2212 }
2213 else
2214 {
2215 break;
2216 }
2217 }
2218 return static_cast<int>(frm_nxt - frm);
2219}
2220
2221static
2222codecvt_base::result
2223ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2224 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2225 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2226{
2227 frm_nxt = frm;
2228 to_nxt = to;
2229 if (mode & generate_header)
2230 {
2231 if (to_end-to_nxt < 3)
2232 return codecvt_base::partial;
2233 *to_nxt++ = static_cast<uint8_t>(0xEF);
2234 *to_nxt++ = static_cast<uint8_t>(0xBB);
2235 *to_nxt++ = static_cast<uint8_t>(0xBF);
2236 }
2237 for (; frm_nxt < frm_end; ++frm_nxt)
2238 {
2239 uint32_t wc = *frm_nxt;
2240 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2241 return codecvt_base::error;
2242 if (wc < 0x000080)
2243 {
2244 if (to_end-to_nxt < 1)
2245 return codecvt_base::partial;
2246 *to_nxt++ = static_cast<uint8_t>(wc);
2247 }
2248 else if (wc < 0x000800)
2249 {
2250 if (to_end-to_nxt < 2)
2251 return codecvt_base::partial;
2252 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2253 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2254 }
2255 else if (wc < 0x010000)
2256 {
2257 if (to_end-to_nxt < 3)
2258 return codecvt_base::partial;
2259 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2260 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2261 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2262 }
2263 else // if (wc < 0x110000)
2264 {
2265 if (to_end-to_nxt < 4)
2266 return codecvt_base::partial;
2267 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2268 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2269 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2270 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2271 }
2272 }
2273 return codecvt_base::ok;
2274}
2275
2276static
2277codecvt_base::result
2278utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2279 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2280 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2281{
2282 frm_nxt = frm;
2283 to_nxt = to;
2284 if (mode & consume_header)
2285 {
2286 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2287 frm_nxt[2] == 0xBF)
2288 frm_nxt += 3;
2289 }
2290 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2291 {
2292 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2293 if (c1 < 0x80)
2294 {
2295 if (c1 > Maxcode)
2296 return codecvt_base::error;
2297 *to_nxt = static_cast<uint32_t>(c1);
2298 ++frm_nxt;
2299 }
2300 else if (c1 < 0xC2)
2301 {
2302 return codecvt_base::error;
2303 }
2304 else if (c1 < 0xE0)
2305 {
2306 if (frm_end-frm_nxt < 2)
2307 return codecvt_base::partial;
2308 uint8_t c2 = frm_nxt[1];
2309 if ((c2 & 0xC0) != 0x80)
2310 return codecvt_base::error;
2311 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2312 | (c2 & 0x3F));
2313 if (t > Maxcode)
2314 return codecvt_base::error;
2315 *to_nxt = t;
2316 frm_nxt += 2;
2317 }
2318 else if (c1 < 0xF0)
2319 {
2320 if (frm_end-frm_nxt < 3)
2321 return codecvt_base::partial;
2322 uint8_t c2 = frm_nxt[1];
2323 uint8_t c3 = frm_nxt[2];
2324 switch (c1)
2325 {
2326 case 0xE0:
2327 if ((c2 & 0xE0) != 0xA0)
2328 return codecvt_base::error;
2329 break;
2330 case 0xED:
2331 if ((c2 & 0xE0) != 0x80)
2332 return codecvt_base::error;
2333 break;
2334 default:
2335 if ((c2 & 0xC0) != 0x80)
2336 return codecvt_base::error;
2337 break;
2338 }
2339 if ((c3 & 0xC0) != 0x80)
2340 return codecvt_base::error;
2341 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2342 | ((c2 & 0x3F) << 6)
2343 | (c3 & 0x3F));
2344 if (t > Maxcode)
2345 return codecvt_base::error;
2346 *to_nxt = t;
2347 frm_nxt += 3;
2348 }
2349 else if (c1 < 0xF5)
2350 {
2351 if (frm_end-frm_nxt < 4)
2352 return codecvt_base::partial;
2353 uint8_t c2 = frm_nxt[1];
2354 uint8_t c3 = frm_nxt[2];
2355 uint8_t c4 = frm_nxt[3];
2356 switch (c1)
2357 {
2358 case 0xF0:
2359 if (!(0x90 <= c2 && c2 <= 0xBF))
2360 return codecvt_base::error;
2361 break;
2362 case 0xF4:
2363 if ((c2 & 0xF0) != 0x80)
2364 return codecvt_base::error;
2365 break;
2366 default:
2367 if ((c2 & 0xC0) != 0x80)
2368 return codecvt_base::error;
2369 break;
2370 }
2371 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2372 return codecvt_base::error;
2373 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2374 | ((c2 & 0x3F) << 12)
2375 | ((c3 & 0x3F) << 6)
2376 | (c4 & 0x3F));
2377 if (t > Maxcode)
2378 return codecvt_base::error;
2379 *to_nxt = t;
2380 frm_nxt += 4;
2381 }
2382 else
2383 {
2384 return codecvt_base::error;
2385 }
2386 }
2387 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2388}
2389
2390static
2391int
2392utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2393 size_t mx, unsigned long Maxcode = 0x10FFFF,
2394 codecvt_mode mode = codecvt_mode(0))
2395{
2396 const uint8_t* frm_nxt = frm;
2397 if (mode & consume_header)
2398 {
2399 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2400 frm_nxt[2] == 0xBF)
2401 frm_nxt += 3;
2402 }
2403 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2404 {
2405 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2406 if (c1 < 0x80)
2407 {
2408 if (c1 > Maxcode)
2409 break;
2410 ++frm_nxt;
2411 }
2412 else if (c1 < 0xC2)
2413 {
2414 break;
2415 }
2416 else if (c1 < 0xE0)
2417 {
2418 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2419 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002420 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002421 break;
2422 frm_nxt += 2;
2423 }
2424 else if (c1 < 0xF0)
2425 {
2426 if (frm_end-frm_nxt < 3)
2427 break;
2428 uint8_t c2 = frm_nxt[1];
2429 uint8_t c3 = frm_nxt[2];
2430 switch (c1)
2431 {
2432 case 0xE0:
2433 if ((c2 & 0xE0) != 0xA0)
2434 return static_cast<int>(frm_nxt - frm);
2435 break;
2436 case 0xED:
2437 if ((c2 & 0xE0) != 0x80)
2438 return static_cast<int>(frm_nxt - frm);
2439 break;
2440 default:
2441 if ((c2 & 0xC0) != 0x80)
2442 return static_cast<int>(frm_nxt - frm);
2443 break;
2444 }
2445 if ((c3 & 0xC0) != 0x80)
2446 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002447 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002448 break;
2449 frm_nxt += 3;
2450 }
2451 else if (c1 < 0xF5)
2452 {
2453 if (frm_end-frm_nxt < 4)
2454 break;
2455 uint8_t c2 = frm_nxt[1];
2456 uint8_t c3 = frm_nxt[2];
2457 uint8_t c4 = frm_nxt[3];
2458 switch (c1)
2459 {
2460 case 0xF0:
2461 if (!(0x90 <= c2 && c2 <= 0xBF))
2462 return static_cast<int>(frm_nxt - frm);
2463 break;
2464 case 0xF4:
2465 if ((c2 & 0xF0) != 0x80)
2466 return static_cast<int>(frm_nxt - frm);
2467 break;
2468 default:
2469 if ((c2 & 0xC0) != 0x80)
2470 return static_cast<int>(frm_nxt - frm);
2471 break;
2472 }
2473 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2474 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002475 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2476 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002477 break;
2478 frm_nxt += 4;
2479 }
2480 else
2481 {
2482 break;
2483 }
2484 }
2485 return static_cast<int>(frm_nxt - frm);
2486}
2487
2488static
2489codecvt_base::result
2490ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2491 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2492 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2493{
2494 frm_nxt = frm;
2495 to_nxt = to;
2496 if (mode & generate_header)
2497 {
2498 if (to_end-to_nxt < 3)
2499 return codecvt_base::partial;
2500 *to_nxt++ = static_cast<uint8_t>(0xEF);
2501 *to_nxt++ = static_cast<uint8_t>(0xBB);
2502 *to_nxt++ = static_cast<uint8_t>(0xBF);
2503 }
2504 for (; frm_nxt < frm_end; ++frm_nxt)
2505 {
2506 uint16_t wc = *frm_nxt;
2507 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2508 return codecvt_base::error;
2509 if (wc < 0x0080)
2510 {
2511 if (to_end-to_nxt < 1)
2512 return codecvt_base::partial;
2513 *to_nxt++ = static_cast<uint8_t>(wc);
2514 }
2515 else if (wc < 0x0800)
2516 {
2517 if (to_end-to_nxt < 2)
2518 return codecvt_base::partial;
2519 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2520 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2521 }
2522 else // if (wc <= 0xFFFF)
2523 {
2524 if (to_end-to_nxt < 3)
2525 return codecvt_base::partial;
2526 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2527 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2528 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2529 }
2530 }
2531 return codecvt_base::ok;
2532}
2533
2534static
2535codecvt_base::result
2536utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2537 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2538 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2539{
2540 frm_nxt = frm;
2541 to_nxt = to;
2542 if (mode & consume_header)
2543 {
2544 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2545 frm_nxt[2] == 0xBF)
2546 frm_nxt += 3;
2547 }
2548 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2549 {
2550 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2551 if (c1 < 0x80)
2552 {
2553 if (c1 > Maxcode)
2554 return codecvt_base::error;
2555 *to_nxt = static_cast<uint16_t>(c1);
2556 ++frm_nxt;
2557 }
2558 else if (c1 < 0xC2)
2559 {
2560 return codecvt_base::error;
2561 }
2562 else if (c1 < 0xE0)
2563 {
2564 if (frm_end-frm_nxt < 2)
2565 return codecvt_base::partial;
2566 uint8_t c2 = frm_nxt[1];
2567 if ((c2 & 0xC0) != 0x80)
2568 return codecvt_base::error;
2569 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2570 | (c2 & 0x3F));
2571 if (t > Maxcode)
2572 return codecvt_base::error;
2573 *to_nxt = t;
2574 frm_nxt += 2;
2575 }
2576 else if (c1 < 0xF0)
2577 {
2578 if (frm_end-frm_nxt < 3)
2579 return codecvt_base::partial;
2580 uint8_t c2 = frm_nxt[1];
2581 uint8_t c3 = frm_nxt[2];
2582 switch (c1)
2583 {
2584 case 0xE0:
2585 if ((c2 & 0xE0) != 0xA0)
2586 return codecvt_base::error;
2587 break;
2588 case 0xED:
2589 if ((c2 & 0xE0) != 0x80)
2590 return codecvt_base::error;
2591 break;
2592 default:
2593 if ((c2 & 0xC0) != 0x80)
2594 return codecvt_base::error;
2595 break;
2596 }
2597 if ((c3 & 0xC0) != 0x80)
2598 return codecvt_base::error;
2599 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2600 | ((c2 & 0x3F) << 6)
2601 | (c3 & 0x3F));
2602 if (t > Maxcode)
2603 return codecvt_base::error;
2604 *to_nxt = t;
2605 frm_nxt += 3;
2606 }
2607 else
2608 {
2609 return codecvt_base::error;
2610 }
2611 }
2612 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2613}
2614
2615static
2616int
2617utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2618 size_t mx, unsigned long Maxcode = 0x10FFFF,
2619 codecvt_mode mode = codecvt_mode(0))
2620{
2621 const uint8_t* frm_nxt = frm;
2622 if (mode & consume_header)
2623 {
2624 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2625 frm_nxt[2] == 0xBF)
2626 frm_nxt += 3;
2627 }
2628 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2629 {
2630 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2631 if (c1 < 0x80)
2632 {
2633 if (c1 > Maxcode)
2634 break;
2635 ++frm_nxt;
2636 }
2637 else if (c1 < 0xC2)
2638 {
2639 break;
2640 }
2641 else if (c1 < 0xE0)
2642 {
2643 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2644 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002645 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002646 break;
2647 frm_nxt += 2;
2648 }
2649 else if (c1 < 0xF0)
2650 {
2651 if (frm_end-frm_nxt < 3)
2652 break;
2653 uint8_t c2 = frm_nxt[1];
2654 uint8_t c3 = frm_nxt[2];
2655 switch (c1)
2656 {
2657 case 0xE0:
2658 if ((c2 & 0xE0) != 0xA0)
2659 return static_cast<int>(frm_nxt - frm);
2660 break;
2661 case 0xED:
2662 if ((c2 & 0xE0) != 0x80)
2663 return static_cast<int>(frm_nxt - frm);
2664 break;
2665 default:
2666 if ((c2 & 0xC0) != 0x80)
2667 return static_cast<int>(frm_nxt - frm);
2668 break;
2669 }
2670 if ((c3 & 0xC0) != 0x80)
2671 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002672 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002673 break;
2674 frm_nxt += 3;
2675 }
2676 else
2677 {
2678 break;
2679 }
2680 }
2681 return static_cast<int>(frm_nxt - frm);
2682}
2683
2684static
2685codecvt_base::result
2686ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2687 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2688 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2689{
2690 frm_nxt = frm;
2691 to_nxt = to;
2692 if (mode & generate_header)
2693 {
2694 if (to_end-to_nxt < 2)
2695 return codecvt_base::partial;
2696 *to_nxt++ = static_cast<uint8_t>(0xFE);
2697 *to_nxt++ = static_cast<uint8_t>(0xFF);
2698 }
2699 for (; frm_nxt < frm_end; ++frm_nxt)
2700 {
2701 uint32_t wc = *frm_nxt;
2702 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2703 return codecvt_base::error;
2704 if (wc < 0x010000)
2705 {
2706 if (to_end-to_nxt < 2)
2707 return codecvt_base::partial;
2708 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2709 *to_nxt++ = static_cast<uint8_t>(wc);
2710 }
2711 else
2712 {
2713 if (to_end-to_nxt < 4)
2714 return codecvt_base::partial;
2715 uint16_t t = static_cast<uint16_t>(
2716 0xD800
2717 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2718 | ((wc & 0x00FC00) >> 10));
2719 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2720 *to_nxt++ = static_cast<uint8_t>(t);
2721 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2722 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2723 *to_nxt++ = static_cast<uint8_t>(t);
2724 }
2725 }
2726 return codecvt_base::ok;
2727}
2728
2729static
2730codecvt_base::result
2731utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2732 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2733 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2734{
2735 frm_nxt = frm;
2736 to_nxt = to;
2737 if (mode & consume_header)
2738 {
2739 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2740 frm_nxt += 2;
2741 }
2742 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2743 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002744 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002745 if ((c1 & 0xFC00) == 0xDC00)
2746 return codecvt_base::error;
2747 if ((c1 & 0xFC00) != 0xD800)
2748 {
2749 if (c1 > Maxcode)
2750 return codecvt_base::error;
2751 *to_nxt = static_cast<uint32_t>(c1);
2752 frm_nxt += 2;
2753 }
2754 else
2755 {
2756 if (frm_end-frm_nxt < 4)
2757 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002758 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002759 if ((c2 & 0xFC00) != 0xDC00)
2760 return codecvt_base::error;
2761 uint32_t t = static_cast<uint32_t>(
2762 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2763 | ((c1 & 0x003F) << 10)
2764 | (c2 & 0x03FF));
2765 if (t > Maxcode)
2766 return codecvt_base::error;
2767 *to_nxt = t;
2768 frm_nxt += 4;
2769 }
2770 }
2771 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2772}
2773
2774static
2775int
2776utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2777 size_t mx, unsigned long Maxcode = 0x10FFFF,
2778 codecvt_mode mode = codecvt_mode(0))
2779{
2780 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002781 if (mode & consume_header)
2782 {
2783 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2784 frm_nxt += 2;
2785 }
2786 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2787 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002788 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002789 if ((c1 & 0xFC00) == 0xDC00)
2790 break;
2791 if ((c1 & 0xFC00) != 0xD800)
2792 {
2793 if (c1 > Maxcode)
2794 break;
2795 frm_nxt += 2;
2796 }
2797 else
2798 {
2799 if (frm_end-frm_nxt < 4)
2800 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002801 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002802 if ((c2 & 0xFC00) != 0xDC00)
2803 break;
2804 uint32_t t = static_cast<uint32_t>(
2805 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2806 | ((c1 & 0x003F) << 10)
2807 | (c2 & 0x03FF));
2808 if (t > Maxcode)
2809 break;
2810 frm_nxt += 4;
2811 }
2812 }
2813 return static_cast<int>(frm_nxt - frm);
2814}
2815
2816static
2817codecvt_base::result
2818ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2819 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2820 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2821{
2822 frm_nxt = frm;
2823 to_nxt = to;
2824 if (mode & generate_header)
2825 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002826 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002827 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002828 *to_nxt++ = static_cast<uint8_t>(0xFF);
2829 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002830 }
2831 for (; frm_nxt < frm_end; ++frm_nxt)
2832 {
2833 uint32_t wc = *frm_nxt;
2834 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2835 return codecvt_base::error;
2836 if (wc < 0x010000)
2837 {
2838 if (to_end-to_nxt < 2)
2839 return codecvt_base::partial;
2840 *to_nxt++ = static_cast<uint8_t>(wc);
2841 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2842 }
2843 else
2844 {
2845 if (to_end-to_nxt < 4)
2846 return codecvt_base::partial;
2847 uint16_t t = static_cast<uint16_t>(
2848 0xD800
2849 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2850 | ((wc & 0x00FC00) >> 10));
2851 *to_nxt++ = static_cast<uint8_t>(t);
2852 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2853 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2854 *to_nxt++ = static_cast<uint8_t>(t);
2855 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2856 }
2857 }
2858 return codecvt_base::ok;
2859}
2860
2861static
2862codecvt_base::result
2863utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2864 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2865 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2866{
2867 frm_nxt = frm;
2868 to_nxt = to;
2869 if (mode & consume_header)
2870 {
2871 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2872 frm_nxt += 2;
2873 }
2874 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2875 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002876 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002877 if ((c1 & 0xFC00) == 0xDC00)
2878 return codecvt_base::error;
2879 if ((c1 & 0xFC00) != 0xD800)
2880 {
2881 if (c1 > Maxcode)
2882 return codecvt_base::error;
2883 *to_nxt = static_cast<uint32_t>(c1);
2884 frm_nxt += 2;
2885 }
2886 else
2887 {
2888 if (frm_end-frm_nxt < 4)
2889 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002890 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002891 if ((c2 & 0xFC00) != 0xDC00)
2892 return codecvt_base::error;
2893 uint32_t t = static_cast<uint32_t>(
2894 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2895 | ((c1 & 0x003F) << 10)
2896 | (c2 & 0x03FF));
2897 if (t > Maxcode)
2898 return codecvt_base::error;
2899 *to_nxt = t;
2900 frm_nxt += 4;
2901 }
2902 }
2903 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2904}
2905
2906static
2907int
2908utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2909 size_t mx, unsigned long Maxcode = 0x10FFFF,
2910 codecvt_mode mode = codecvt_mode(0))
2911{
2912 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002913 if (mode & consume_header)
2914 {
2915 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2916 frm_nxt += 2;
2917 }
2918 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2919 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002920 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002921 if ((c1 & 0xFC00) == 0xDC00)
2922 break;
2923 if ((c1 & 0xFC00) != 0xD800)
2924 {
2925 if (c1 > Maxcode)
2926 break;
2927 frm_nxt += 2;
2928 }
2929 else
2930 {
2931 if (frm_end-frm_nxt < 4)
2932 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002933 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002934 if ((c2 & 0xFC00) != 0xDC00)
2935 break;
2936 uint32_t t = static_cast<uint32_t>(
2937 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2938 | ((c1 & 0x003F) << 10)
2939 | (c2 & 0x03FF));
2940 if (t > Maxcode)
2941 break;
2942 frm_nxt += 4;
2943 }
2944 }
2945 return static_cast<int>(frm_nxt - frm);
2946}
2947
2948static
2949codecvt_base::result
2950ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2951 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2952 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2953{
2954 frm_nxt = frm;
2955 to_nxt = to;
2956 if (mode & generate_header)
2957 {
2958 if (to_end-to_nxt < 2)
2959 return codecvt_base::partial;
2960 *to_nxt++ = static_cast<uint8_t>(0xFE);
2961 *to_nxt++ = static_cast<uint8_t>(0xFF);
2962 }
2963 for (; frm_nxt < frm_end; ++frm_nxt)
2964 {
2965 uint16_t wc = *frm_nxt;
2966 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2967 return codecvt_base::error;
2968 if (to_end-to_nxt < 2)
2969 return codecvt_base::partial;
2970 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2971 *to_nxt++ = static_cast<uint8_t>(wc);
2972 }
2973 return codecvt_base::ok;
2974}
2975
2976static
2977codecvt_base::result
2978utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2979 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2980 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2981{
2982 frm_nxt = frm;
2983 to_nxt = to;
2984 if (mode & consume_header)
2985 {
2986 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2987 frm_nxt += 2;
2988 }
2989 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2990 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002991 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002992 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2993 return codecvt_base::error;
2994 *to_nxt = c1;
2995 frm_nxt += 2;
2996 }
2997 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2998}
2999
3000static
3001int
3002utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3003 size_t mx, unsigned long Maxcode = 0x10FFFF,
3004 codecvt_mode mode = codecvt_mode(0))
3005{
3006 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003007 if (mode & consume_header)
3008 {
3009 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3010 frm_nxt += 2;
3011 }
3012 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3013 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003014 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003015 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3016 break;
3017 frm_nxt += 2;
3018 }
3019 return static_cast<int>(frm_nxt - frm);
3020}
3021
3022static
3023codecvt_base::result
3024ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3025 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3026 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3027{
3028 frm_nxt = frm;
3029 to_nxt = to;
3030 if (mode & generate_header)
3031 {
3032 if (to_end-to_nxt < 2)
3033 return codecvt_base::partial;
3034 *to_nxt++ = static_cast<uint8_t>(0xFF);
3035 *to_nxt++ = static_cast<uint8_t>(0xFE);
3036 }
3037 for (; frm_nxt < frm_end; ++frm_nxt)
3038 {
3039 uint16_t wc = *frm_nxt;
3040 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3041 return codecvt_base::error;
3042 if (to_end-to_nxt < 2)
3043 return codecvt_base::partial;
3044 *to_nxt++ = static_cast<uint8_t>(wc);
3045 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3046 }
3047 return codecvt_base::ok;
3048}
3049
3050static
3051codecvt_base::result
3052utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3053 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3054 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3055{
3056 frm_nxt = frm;
3057 to_nxt = to;
3058 if (mode & consume_header)
3059 {
3060 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3061 frm_nxt += 2;
3062 }
3063 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3064 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003065 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003066 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3067 return codecvt_base::error;
3068 *to_nxt = c1;
3069 frm_nxt += 2;
3070 }
3071 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3072}
3073
3074static
3075int
3076utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3077 size_t mx, unsigned long Maxcode = 0x10FFFF,
3078 codecvt_mode mode = codecvt_mode(0))
3079{
3080 const uint8_t* frm_nxt = frm;
3081 frm_nxt = frm;
3082 if (mode & consume_header)
3083 {
3084 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3085 frm_nxt += 2;
3086 }
3087 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3088 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003089 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003090 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3091 break;
3092 frm_nxt += 2;
3093 }
3094 return static_cast<int>(frm_nxt - frm);
3095}
3096
Howard Hinnantc51e1022010-05-11 19:42:16 +00003097// template <> class codecvt<char16_t, char, mbstate_t>
3098
Howard Hinnantffb308e2010-08-22 00:03:27 +00003099locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003100
3101codecvt<char16_t, char, mbstate_t>::~codecvt()
3102{
3103}
3104
3105codecvt<char16_t, char, mbstate_t>::result
3106codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003107 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003108 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3109{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003110 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3111 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3112 const uint16_t* _frm_nxt = _frm;
3113 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3114 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3115 uint8_t* _to_nxt = _to;
3116 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3117 frm_nxt = frm + (_frm_nxt - _frm);
3118 to_nxt = to + (_to_nxt - _to);
3119 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003120}
3121
3122codecvt<char16_t, char, mbstate_t>::result
3123codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003124 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003125 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3126{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003127 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3128 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3129 const uint8_t* _frm_nxt = _frm;
3130 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3131 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3132 uint16_t* _to_nxt = _to;
3133 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3134 frm_nxt = frm + (_frm_nxt - _frm);
3135 to_nxt = to + (_to_nxt - _to);
3136 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003137}
3138
3139codecvt<char16_t, char, mbstate_t>::result
3140codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3141 extern_type* to, extern_type*, extern_type*& to_nxt) const
3142{
3143 to_nxt = to;
3144 return noconv;
3145}
3146
3147int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003148codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003149{
3150 return 0;
3151}
3152
3153bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003154codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003155{
3156 return false;
3157}
3158
3159int
3160codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3161 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3162{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003163 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3164 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3165 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003166}
3167
3168int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003169codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003170{
3171 return 4;
3172}
3173
3174// template <> class codecvt<char32_t, char, mbstate_t>
3175
Howard Hinnantffb308e2010-08-22 00:03:27 +00003176locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003177
3178codecvt<char32_t, char, mbstate_t>::~codecvt()
3179{
3180}
3181
3182codecvt<char32_t, char, mbstate_t>::result
3183codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003184 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003185 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3186{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003187 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3188 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3189 const uint32_t* _frm_nxt = _frm;
3190 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3191 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3192 uint8_t* _to_nxt = _to;
3193 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3194 frm_nxt = frm + (_frm_nxt - _frm);
3195 to_nxt = to + (_to_nxt - _to);
3196 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003197}
3198
3199codecvt<char32_t, char, mbstate_t>::result
3200codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003201 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003202 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3203{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003204 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3205 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3206 const uint8_t* _frm_nxt = _frm;
3207 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3208 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3209 uint32_t* _to_nxt = _to;
3210 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3211 frm_nxt = frm + (_frm_nxt - _frm);
3212 to_nxt = to + (_to_nxt - _to);
3213 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003214}
3215
3216codecvt<char32_t, char, mbstate_t>::result
3217codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3218 extern_type* to, extern_type*, extern_type*& to_nxt) const
3219{
3220 to_nxt = to;
3221 return noconv;
3222}
3223
3224int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003225codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003226{
3227 return 0;
3228}
3229
3230bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003231codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003232{
3233 return false;
3234}
3235
3236int
3237codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3238 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3239{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003240 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3241 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3242 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003243}
3244
3245int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003246codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003247{
3248 return 4;
3249}
3250
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003251// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003252
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003253__codecvt_utf8<wchar_t>::result
3254__codecvt_utf8<wchar_t>::do_out(state_type&,
3255 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003256 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3257{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003258#if _WIN32
3259 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3260 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3261 const uint16_t* _frm_nxt = _frm;
3262#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003263 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3264 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3265 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003266#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003267 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3268 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3269 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003270#if _WIN32
3271 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3272 _Maxcode_, _Mode_);
3273#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003274 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3275 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003276#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003277 frm_nxt = frm + (_frm_nxt - _frm);
3278 to_nxt = to + (_to_nxt - _to);
3279 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003280}
3281
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003282__codecvt_utf8<wchar_t>::result
3283__codecvt_utf8<wchar_t>::do_in(state_type&,
3284 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003285 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3286{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003287 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3288 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3289 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003290#if _WIN32
3291 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3292 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3293 uint16_t* _to_nxt = _to;
3294 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3295 _Maxcode_, _Mode_);
3296#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003297 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3298 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3299 uint32_t* _to_nxt = _to;
3300 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3301 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003302#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003303 frm_nxt = frm + (_frm_nxt - _frm);
3304 to_nxt = to + (_to_nxt - _to);
3305 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003306}
3307
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003308__codecvt_utf8<wchar_t>::result
3309__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003310 extern_type* to, extern_type*, extern_type*& to_nxt) const
3311{
3312 to_nxt = to;
3313 return noconv;
3314}
3315
3316int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003317__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003318{
3319 return 0;
3320}
3321
3322bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003323__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003324{
3325 return false;
3326}
3327
3328int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003329__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003330 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3331{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003332 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3333 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3334 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003335}
3336
3337int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003338__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003339{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003340 if (_Mode_ & consume_header)
3341 return 7;
3342 return 4;
3343}
3344
3345// __codecvt_utf8<char16_t>
3346
3347__codecvt_utf8<char16_t>::result
3348__codecvt_utf8<char16_t>::do_out(state_type&,
3349 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3350 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3351{
3352 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3353 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3354 const uint16_t* _frm_nxt = _frm;
3355 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3356 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3357 uint8_t* _to_nxt = _to;
3358 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3359 _Maxcode_, _Mode_);
3360 frm_nxt = frm + (_frm_nxt - _frm);
3361 to_nxt = to + (_to_nxt - _to);
3362 return r;
3363}
3364
3365__codecvt_utf8<char16_t>::result
3366__codecvt_utf8<char16_t>::do_in(state_type&,
3367 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3368 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3369{
3370 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3371 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3372 const uint8_t* _frm_nxt = _frm;
3373 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3374 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3375 uint16_t* _to_nxt = _to;
3376 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3377 _Maxcode_, _Mode_);
3378 frm_nxt = frm + (_frm_nxt - _frm);
3379 to_nxt = to + (_to_nxt - _to);
3380 return r;
3381}
3382
3383__codecvt_utf8<char16_t>::result
3384__codecvt_utf8<char16_t>::do_unshift(state_type&,
3385 extern_type* to, extern_type*, extern_type*& to_nxt) const
3386{
3387 to_nxt = to;
3388 return noconv;
3389}
3390
3391int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003392__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003393{
3394 return 0;
3395}
3396
3397bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003398__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003399{
3400 return false;
3401}
3402
3403int
3404__codecvt_utf8<char16_t>::do_length(state_type&,
3405 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3406{
3407 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3408 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3409 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3410}
3411
3412int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003413__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003414{
3415 if (_Mode_ & consume_header)
3416 return 6;
3417 return 3;
3418}
3419
3420// __codecvt_utf8<char32_t>
3421
3422__codecvt_utf8<char32_t>::result
3423__codecvt_utf8<char32_t>::do_out(state_type&,
3424 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3425 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3426{
3427 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3428 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3429 const uint32_t* _frm_nxt = _frm;
3430 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3431 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3432 uint8_t* _to_nxt = _to;
3433 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3434 _Maxcode_, _Mode_);
3435 frm_nxt = frm + (_frm_nxt - _frm);
3436 to_nxt = to + (_to_nxt - _to);
3437 return r;
3438}
3439
3440__codecvt_utf8<char32_t>::result
3441__codecvt_utf8<char32_t>::do_in(state_type&,
3442 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3443 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3444{
3445 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3446 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3447 const uint8_t* _frm_nxt = _frm;
3448 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3449 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3450 uint32_t* _to_nxt = _to;
3451 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3452 _Maxcode_, _Mode_);
3453 frm_nxt = frm + (_frm_nxt - _frm);
3454 to_nxt = to + (_to_nxt - _to);
3455 return r;
3456}
3457
3458__codecvt_utf8<char32_t>::result
3459__codecvt_utf8<char32_t>::do_unshift(state_type&,
3460 extern_type* to, extern_type*, extern_type*& to_nxt) const
3461{
3462 to_nxt = to;
3463 return noconv;
3464}
3465
3466int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003467__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003468{
3469 return 0;
3470}
3471
3472bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003473__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003474{
3475 return false;
3476}
3477
3478int
3479__codecvt_utf8<char32_t>::do_length(state_type&,
3480 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3481{
3482 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3483 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3484 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3485}
3486
3487int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003488__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003489{
3490 if (_Mode_ & consume_header)
3491 return 7;
3492 return 4;
3493}
3494
3495// __codecvt_utf16<wchar_t, false>
3496
3497__codecvt_utf16<wchar_t, false>::result
3498__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3499 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3500 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3501{
3502 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3503 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3504 const uint32_t* _frm_nxt = _frm;
3505 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3506 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3507 uint8_t* _to_nxt = _to;
3508 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3509 _Maxcode_, _Mode_);
3510 frm_nxt = frm + (_frm_nxt - _frm);
3511 to_nxt = to + (_to_nxt - _to);
3512 return r;
3513}
3514
3515__codecvt_utf16<wchar_t, false>::result
3516__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3517 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3518 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3519{
3520 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3521 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3522 const uint8_t* _frm_nxt = _frm;
3523 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3524 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3525 uint32_t* _to_nxt = _to;
3526 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3527 _Maxcode_, _Mode_);
3528 frm_nxt = frm + (_frm_nxt - _frm);
3529 to_nxt = to + (_to_nxt - _to);
3530 return r;
3531}
3532
3533__codecvt_utf16<wchar_t, false>::result
3534__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3535 extern_type* to, extern_type*, extern_type*& to_nxt) const
3536{
3537 to_nxt = to;
3538 return noconv;
3539}
3540
3541int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003542__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003543{
3544 return 0;
3545}
3546
3547bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003548__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003549{
3550 return false;
3551}
3552
3553int
3554__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3555 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3556{
3557 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3558 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3559 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3560}
3561
3562int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003563__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003564{
3565 if (_Mode_ & consume_header)
3566 return 6;
3567 return 4;
3568}
3569
3570// __codecvt_utf16<wchar_t, true>
3571
3572__codecvt_utf16<wchar_t, true>::result
3573__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3574 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3575 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3576{
3577 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3578 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3579 const uint32_t* _frm_nxt = _frm;
3580 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3581 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3582 uint8_t* _to_nxt = _to;
3583 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3584 _Maxcode_, _Mode_);
3585 frm_nxt = frm + (_frm_nxt - _frm);
3586 to_nxt = to + (_to_nxt - _to);
3587 return r;
3588}
3589
3590__codecvt_utf16<wchar_t, true>::result
3591__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3592 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3593 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3594{
3595 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3596 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3597 const uint8_t* _frm_nxt = _frm;
3598 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3599 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3600 uint32_t* _to_nxt = _to;
3601 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3602 _Maxcode_, _Mode_);
3603 frm_nxt = frm + (_frm_nxt - _frm);
3604 to_nxt = to + (_to_nxt - _to);
3605 return r;
3606}
3607
3608__codecvt_utf16<wchar_t, true>::result
3609__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3610 extern_type* to, extern_type*, extern_type*& to_nxt) const
3611{
3612 to_nxt = to;
3613 return noconv;
3614}
3615
3616int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003617__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003618{
3619 return 0;
3620}
3621
3622bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003623__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003624{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003625 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003626}
3627
3628int
3629__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3630 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3631{
3632 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3633 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3634 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3635}
3636
3637int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003638__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003639{
3640 if (_Mode_ & consume_header)
3641 return 6;
3642 return 4;
3643}
3644
3645// __codecvt_utf16<char16_t, false>
3646
3647__codecvt_utf16<char16_t, false>::result
3648__codecvt_utf16<char16_t, false>::do_out(state_type&,
3649 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3650 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3651{
3652 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3653 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3654 const uint16_t* _frm_nxt = _frm;
3655 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3656 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3657 uint8_t* _to_nxt = _to;
3658 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3659 _Maxcode_, _Mode_);
3660 frm_nxt = frm + (_frm_nxt - _frm);
3661 to_nxt = to + (_to_nxt - _to);
3662 return r;
3663}
3664
3665__codecvt_utf16<char16_t, false>::result
3666__codecvt_utf16<char16_t, false>::do_in(state_type&,
3667 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3668 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3669{
3670 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3671 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3672 const uint8_t* _frm_nxt = _frm;
3673 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3674 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3675 uint16_t* _to_nxt = _to;
3676 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3677 _Maxcode_, _Mode_);
3678 frm_nxt = frm + (_frm_nxt - _frm);
3679 to_nxt = to + (_to_nxt - _to);
3680 return r;
3681}
3682
3683__codecvt_utf16<char16_t, false>::result
3684__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3685 extern_type* to, extern_type*, extern_type*& to_nxt) const
3686{
3687 to_nxt = to;
3688 return noconv;
3689}
3690
3691int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003692__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003693{
3694 return 0;
3695}
3696
3697bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003698__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003699{
3700 return false;
3701}
3702
3703int
3704__codecvt_utf16<char16_t, false>::do_length(state_type&,
3705 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3706{
3707 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3708 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3709 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3710}
3711
3712int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003713__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003714{
3715 if (_Mode_ & consume_header)
3716 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003717 return 2;
3718}
3719
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003720// __codecvt_utf16<char16_t, true>
3721
3722__codecvt_utf16<char16_t, true>::result
3723__codecvt_utf16<char16_t, true>::do_out(state_type&,
3724 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3725 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3726{
3727 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3728 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3729 const uint16_t* _frm_nxt = _frm;
3730 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3731 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3732 uint8_t* _to_nxt = _to;
3733 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3734 _Maxcode_, _Mode_);
3735 frm_nxt = frm + (_frm_nxt - _frm);
3736 to_nxt = to + (_to_nxt - _to);
3737 return r;
3738}
3739
3740__codecvt_utf16<char16_t, true>::result
3741__codecvt_utf16<char16_t, true>::do_in(state_type&,
3742 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3743 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3744{
3745 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3746 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3747 const uint8_t* _frm_nxt = _frm;
3748 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3749 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3750 uint16_t* _to_nxt = _to;
3751 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3752 _Maxcode_, _Mode_);
3753 frm_nxt = frm + (_frm_nxt - _frm);
3754 to_nxt = to + (_to_nxt - _to);
3755 return r;
3756}
3757
3758__codecvt_utf16<char16_t, true>::result
3759__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3760 extern_type* to, extern_type*, extern_type*& to_nxt) const
3761{
3762 to_nxt = to;
3763 return noconv;
3764}
3765
3766int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003767__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003768{
3769 return 0;
3770}
3771
3772bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003773__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003774{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003775 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003776}
3777
3778int
3779__codecvt_utf16<char16_t, true>::do_length(state_type&,
3780 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3781{
3782 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3783 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3784 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3785}
3786
3787int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003788__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003789{
3790 if (_Mode_ & consume_header)
3791 return 4;
3792 return 2;
3793}
3794
3795// __codecvt_utf16<char32_t, false>
3796
3797__codecvt_utf16<char32_t, false>::result
3798__codecvt_utf16<char32_t, false>::do_out(state_type&,
3799 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3800 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3801{
3802 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3803 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3804 const uint32_t* _frm_nxt = _frm;
3805 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3806 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3807 uint8_t* _to_nxt = _to;
3808 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3809 _Maxcode_, _Mode_);
3810 frm_nxt = frm + (_frm_nxt - _frm);
3811 to_nxt = to + (_to_nxt - _to);
3812 return r;
3813}
3814
3815__codecvt_utf16<char32_t, false>::result
3816__codecvt_utf16<char32_t, false>::do_in(state_type&,
3817 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3818 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3819{
3820 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3821 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3822 const uint8_t* _frm_nxt = _frm;
3823 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3824 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3825 uint32_t* _to_nxt = _to;
3826 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3827 _Maxcode_, _Mode_);
3828 frm_nxt = frm + (_frm_nxt - _frm);
3829 to_nxt = to + (_to_nxt - _to);
3830 return r;
3831}
3832
3833__codecvt_utf16<char32_t, false>::result
3834__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3835 extern_type* to, extern_type*, extern_type*& to_nxt) const
3836{
3837 to_nxt = to;
3838 return noconv;
3839}
3840
3841int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003842__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003843{
3844 return 0;
3845}
3846
3847bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003848__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003849{
3850 return false;
3851}
3852
3853int
3854__codecvt_utf16<char32_t, false>::do_length(state_type&,
3855 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3856{
3857 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3858 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3859 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3860}
3861
3862int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003863__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003864{
3865 if (_Mode_ & consume_header)
3866 return 6;
3867 return 4;
3868}
3869
3870// __codecvt_utf16<char32_t, true>
3871
3872__codecvt_utf16<char32_t, true>::result
3873__codecvt_utf16<char32_t, true>::do_out(state_type&,
3874 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3875 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3876{
3877 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3878 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3879 const uint32_t* _frm_nxt = _frm;
3880 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3881 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3882 uint8_t* _to_nxt = _to;
3883 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3884 _Maxcode_, _Mode_);
3885 frm_nxt = frm + (_frm_nxt - _frm);
3886 to_nxt = to + (_to_nxt - _to);
3887 return r;
3888}
3889
3890__codecvt_utf16<char32_t, true>::result
3891__codecvt_utf16<char32_t, true>::do_in(state_type&,
3892 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3893 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3894{
3895 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3896 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3897 const uint8_t* _frm_nxt = _frm;
3898 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3899 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3900 uint32_t* _to_nxt = _to;
3901 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3902 _Maxcode_, _Mode_);
3903 frm_nxt = frm + (_frm_nxt - _frm);
3904 to_nxt = to + (_to_nxt - _to);
3905 return r;
3906}
3907
3908__codecvt_utf16<char32_t, true>::result
3909__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3910 extern_type* to, extern_type*, extern_type*& to_nxt) const
3911{
3912 to_nxt = to;
3913 return noconv;
3914}
3915
3916int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003917__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003918{
3919 return 0;
3920}
3921
3922bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003923__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003924{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003925 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003926}
3927
3928int
3929__codecvt_utf16<char32_t, true>::do_length(state_type&,
3930 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3931{
3932 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3933 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3934 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3935}
3936
3937int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003938__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003939{
3940 if (_Mode_ & consume_header)
3941 return 6;
3942 return 4;
3943}
3944
3945// __codecvt_utf8_utf16<wchar_t>
3946
3947__codecvt_utf8_utf16<wchar_t>::result
3948__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3949 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3950 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3951{
3952 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3953 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3954 const uint32_t* _frm_nxt = _frm;
3955 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3956 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3957 uint8_t* _to_nxt = _to;
3958 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3959 _Maxcode_, _Mode_);
3960 frm_nxt = frm + (_frm_nxt - _frm);
3961 to_nxt = to + (_to_nxt - _to);
3962 return r;
3963}
3964
3965__codecvt_utf8_utf16<wchar_t>::result
3966__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3967 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3968 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3969{
3970 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3971 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3972 const uint8_t* _frm_nxt = _frm;
3973 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3974 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3975 uint32_t* _to_nxt = _to;
3976 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3977 _Maxcode_, _Mode_);
3978 frm_nxt = frm + (_frm_nxt - _frm);
3979 to_nxt = to + (_to_nxt - _to);
3980 return r;
3981}
3982
3983__codecvt_utf8_utf16<wchar_t>::result
3984__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3985 extern_type* to, extern_type*, extern_type*& to_nxt) const
3986{
3987 to_nxt = to;
3988 return noconv;
3989}
3990
3991int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003992__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003993{
3994 return 0;
3995}
3996
3997bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003998__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003999{
4000 return false;
4001}
4002
4003int
4004__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4005 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4006{
4007 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4008 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4009 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4010}
4011
4012int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004013__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004014{
4015 if (_Mode_ & consume_header)
4016 return 7;
4017 return 4;
4018}
4019
4020// __codecvt_utf8_utf16<char16_t>
4021
4022__codecvt_utf8_utf16<char16_t>::result
4023__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4024 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4025 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4026{
4027 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4028 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4029 const uint16_t* _frm_nxt = _frm;
4030 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4031 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4032 uint8_t* _to_nxt = _to;
4033 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4034 _Maxcode_, _Mode_);
4035 frm_nxt = frm + (_frm_nxt - _frm);
4036 to_nxt = to + (_to_nxt - _to);
4037 return r;
4038}
4039
4040__codecvt_utf8_utf16<char16_t>::result
4041__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4042 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4043 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4044{
4045 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4046 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4047 const uint8_t* _frm_nxt = _frm;
4048 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4049 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4050 uint16_t* _to_nxt = _to;
4051 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4052 _Maxcode_, _Mode_);
4053 frm_nxt = frm + (_frm_nxt - _frm);
4054 to_nxt = to + (_to_nxt - _to);
4055 return r;
4056}
4057
4058__codecvt_utf8_utf16<char16_t>::result
4059__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4060 extern_type* to, extern_type*, extern_type*& to_nxt) const
4061{
4062 to_nxt = to;
4063 return noconv;
4064}
4065
4066int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004067__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004068{
4069 return 0;
4070}
4071
4072bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004073__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004074{
4075 return false;
4076}
4077
4078int
4079__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4080 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4081{
4082 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4083 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4084 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4085}
4086
4087int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004088__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004089{
4090 if (_Mode_ & consume_header)
4091 return 7;
4092 return 4;
4093}
4094
4095// __codecvt_utf8_utf16<char32_t>
4096
4097__codecvt_utf8_utf16<char32_t>::result
4098__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4099 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4100 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4101{
4102 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4103 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4104 const uint32_t* _frm_nxt = _frm;
4105 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4106 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4107 uint8_t* _to_nxt = _to;
4108 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4109 _Maxcode_, _Mode_);
4110 frm_nxt = frm + (_frm_nxt - _frm);
4111 to_nxt = to + (_to_nxt - _to);
4112 return r;
4113}
4114
4115__codecvt_utf8_utf16<char32_t>::result
4116__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4117 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4118 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4119{
4120 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4121 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4122 const uint8_t* _frm_nxt = _frm;
4123 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4124 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4125 uint32_t* _to_nxt = _to;
4126 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4127 _Maxcode_, _Mode_);
4128 frm_nxt = frm + (_frm_nxt - _frm);
4129 to_nxt = to + (_to_nxt - _to);
4130 return r;
4131}
4132
4133__codecvt_utf8_utf16<char32_t>::result
4134__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4135 extern_type* to, extern_type*, extern_type*& to_nxt) const
4136{
4137 to_nxt = to;
4138 return noconv;
4139}
4140
4141int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004142__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004143{
4144 return 0;
4145}
4146
4147bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004148__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004149{
4150 return false;
4151}
4152
4153int
4154__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4155 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4156{
4157 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4158 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4159 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4160}
4161
4162int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004163__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004164{
4165 if (_Mode_ & consume_header)
4166 return 7;
4167 return 4;
4168}
4169
Howard Hinnantc51e1022010-05-11 19:42:16 +00004170// __narrow_to_utf8<16>
4171
4172__narrow_to_utf8<16>::~__narrow_to_utf8()
4173{
4174}
4175
4176// __narrow_to_utf8<32>
4177
4178__narrow_to_utf8<32>::~__narrow_to_utf8()
4179{
4180}
4181
4182// __widen_from_utf8<16>
4183
4184__widen_from_utf8<16>::~__widen_from_utf8()
4185{
4186}
4187
4188// __widen_from_utf8<32>
4189
4190__widen_from_utf8<32>::~__widen_from_utf8()
4191{
4192}
4193
4194// numpunct<char> && numpunct<wchar_t>
4195
4196locale::id numpunct< char >::id;
4197locale::id numpunct<wchar_t>::id;
4198
4199numpunct<char>::numpunct(size_t refs)
4200 : locale::facet(refs),
4201 __decimal_point_('.'),
4202 __thousands_sep_(',')
4203{
4204}
4205
4206numpunct<wchar_t>::numpunct(size_t refs)
4207 : locale::facet(refs),
4208 __decimal_point_(L'.'),
4209 __thousands_sep_(L',')
4210{
4211}
4212
4213numpunct<char>::~numpunct()
4214{
4215}
4216
4217numpunct<wchar_t>::~numpunct()
4218{
4219}
4220
4221 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4222wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4223
4224 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4225wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4226
4227string numpunct< char >::do_grouping() const {return __grouping_;}
4228string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4229
4230 string numpunct< char >::do_truename() const {return "true";}
4231wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4232
4233 string numpunct< char >::do_falsename() const {return "false";}
4234wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4235
4236// numpunct_byname<char>
4237
4238numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4239 : numpunct<char>(refs)
4240{
4241 __init(nm);
4242}
4243
4244numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4245 : numpunct<char>(refs)
4246{
4247 __init(nm.c_str());
4248}
4249
4250numpunct_byname<char>::~numpunct_byname()
4251{
4252}
4253
4254void
4255numpunct_byname<char>::__init(const char* nm)
4256{
4257 if (strcmp(nm, "C") != 0)
4258 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004259 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004260#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004261 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004262 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4263 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004264#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00004265 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004266 if (*lc->decimal_point)
4267 __decimal_point_ = *lc->decimal_point;
4268 if (*lc->thousands_sep)
4269 __thousands_sep_ = *lc->thousands_sep;
4270 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004271 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004272 }
4273}
4274
4275// numpunct_byname<wchar_t>
4276
4277numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4278 : numpunct<wchar_t>(refs)
4279{
4280 __init(nm);
4281}
4282
4283numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4284 : numpunct<wchar_t>(refs)
4285{
4286 __init(nm.c_str());
4287}
4288
4289numpunct_byname<wchar_t>::~numpunct_byname()
4290{
4291}
4292
4293void
4294numpunct_byname<wchar_t>::__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 Hinnant72f73582010-08-11 17:04:31 +00004299#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004300 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004301 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4302 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004303#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00004304 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004305 if (*lc->decimal_point)
4306 __decimal_point_ = *lc->decimal_point;
4307 if (*lc->thousands_sep)
4308 __thousands_sep_ = *lc->thousands_sep;
4309 __grouping_ = lc->grouping;
4310 // locallization for truename and falsename is not available
4311 }
4312}
4313
4314// num_get helpers
4315
4316int
4317__num_get_base::__get_base(ios_base& iob)
4318{
4319 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4320 if (__basefield == ios_base::oct)
4321 return 8;
4322 else if (__basefield == ios_base::hex)
4323 return 16;
4324 else if (__basefield == 0)
4325 return 0;
4326 return 10;
4327}
4328
4329const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4330
4331void
4332__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4333 ios_base::iostate& __err)
4334{
4335 if (__grouping.size() != 0)
4336 {
4337 reverse(__g, __g_end);
4338 const char* __ig = __grouping.data();
4339 const char* __eg = __ig + __grouping.size();
4340 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4341 {
4342 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4343 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004344 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004345 {
4346 __err = ios_base::failbit;
4347 return;
4348 }
4349 }
4350 if (__eg - __ig > 1)
4351 ++__ig;
4352 }
4353 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4354 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004355 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004356 __err = ios_base::failbit;
4357 }
4358 }
4359}
4360
4361void
4362__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4363 ios_base::fmtflags __flags)
4364{
4365 if (__flags & ios_base::showpos)
4366 *__fmtp++ = '+';
4367 if (__flags & ios_base::showbase)
4368 *__fmtp++ = '#';
4369 while(*__len)
4370 *__fmtp++ = *__len++;
4371 if ((__flags & ios_base::basefield) == ios_base::oct)
4372 *__fmtp = 'o';
4373 else if ((__flags & ios_base::basefield) == ios_base::hex)
4374 {
4375 if (__flags & ios_base::uppercase)
4376 *__fmtp = 'X';
4377 else
4378 *__fmtp = 'x';
4379 }
4380 else if (__signd)
4381 *__fmtp = 'd';
4382 else
4383 *__fmtp = 'u';
4384}
4385
4386bool
4387__num_put_base::__format_float(char* __fmtp, const char* __len,
4388 ios_base::fmtflags __flags)
4389{
4390 bool specify_precision = true;
4391 if (__flags & ios_base::showpos)
4392 *__fmtp++ = '+';
4393 if (__flags & ios_base::showpoint)
4394 *__fmtp++ = '#';
4395 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004396 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004397 if (floatfield == (ios_base::fixed | ios_base::scientific))
4398 specify_precision = false;
4399 else
4400 {
4401 *__fmtp++ = '.';
4402 *__fmtp++ = '*';
4403 }
4404 while(*__len)
4405 *__fmtp++ = *__len++;
4406 if (floatfield == ios_base::fixed)
4407 {
4408 if (uppercase)
4409 *__fmtp = 'F';
4410 else
4411 *__fmtp = 'f';
4412 }
4413 else if (floatfield == ios_base::scientific)
4414 {
4415 if (uppercase)
4416 *__fmtp = 'E';
4417 else
4418 *__fmtp = 'e';
4419 }
4420 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4421 {
4422 if (uppercase)
4423 *__fmtp = 'A';
4424 else
4425 *__fmtp = 'a';
4426 }
4427 else
4428 {
4429 if (uppercase)
4430 *__fmtp = 'G';
4431 else
4432 *__fmtp = 'g';
4433 }
4434 return specify_precision;
4435}
4436
4437char*
4438__num_put_base::__identify_padding(char* __nb, char* __ne,
4439 const ios_base& __iob)
4440{
4441 switch (__iob.flags() & ios_base::adjustfield)
4442 {
4443 case ios_base::internal:
4444 if (__nb[0] == '-' || __nb[0] == '+')
4445 return __nb+1;
4446 if (__ne - __nb >= 2 && __nb[0] == '0'
4447 && (__nb[1] == 'x' || __nb[1] == 'X'))
4448 return __nb+2;
4449 break;
4450 case ios_base::left:
4451 return __ne;
4452 case ios_base::right:
4453 default:
4454 break;
4455 }
4456 return __nb;
4457}
4458
4459// time_get
4460
4461static
4462string*
4463init_weeks()
4464{
4465 static string weeks[14];
4466 weeks[0] = "Sunday";
4467 weeks[1] = "Monday";
4468 weeks[2] = "Tuesday";
4469 weeks[3] = "Wednesday";
4470 weeks[4] = "Thursday";
4471 weeks[5] = "Friday";
4472 weeks[6] = "Saturday";
4473 weeks[7] = "Sun";
4474 weeks[8] = "Mon";
4475 weeks[9] = "Tue";
4476 weeks[10] = "Wed";
4477 weeks[11] = "Thu";
4478 weeks[12] = "Fri";
4479 weeks[13] = "Sat";
4480 return weeks;
4481}
4482
4483static
4484wstring*
4485init_wweeks()
4486{
4487 static wstring weeks[14];
4488 weeks[0] = L"Sunday";
4489 weeks[1] = L"Monday";
4490 weeks[2] = L"Tuesday";
4491 weeks[3] = L"Wednesday";
4492 weeks[4] = L"Thursday";
4493 weeks[5] = L"Friday";
4494 weeks[6] = L"Saturday";
4495 weeks[7] = L"Sun";
4496 weeks[8] = L"Mon";
4497 weeks[9] = L"Tue";
4498 weeks[10] = L"Wed";
4499 weeks[11] = L"Thu";
4500 weeks[12] = L"Fri";
4501 weeks[13] = L"Sat";
4502 return weeks;
4503}
4504
4505template <>
4506const string*
4507__time_get_c_storage<char>::__weeks() const
4508{
4509 static const string* weeks = init_weeks();
4510 return weeks;
4511}
4512
4513template <>
4514const wstring*
4515__time_get_c_storage<wchar_t>::__weeks() const
4516{
4517 static const wstring* weeks = init_wweeks();
4518 return weeks;
4519}
4520
4521static
4522string*
4523init_months()
4524{
4525 static string months[24];
4526 months[0] = "January";
4527 months[1] = "February";
4528 months[2] = "March";
4529 months[3] = "April";
4530 months[4] = "May";
4531 months[5] = "June";
4532 months[6] = "July";
4533 months[7] = "August";
4534 months[8] = "September";
4535 months[9] = "October";
4536 months[10] = "November";
4537 months[11] = "December";
4538 months[12] = "Jan";
4539 months[13] = "Feb";
4540 months[14] = "Mar";
4541 months[15] = "Apr";
4542 months[16] = "May";
4543 months[17] = "Jun";
4544 months[18] = "Jul";
4545 months[19] = "Aug";
4546 months[20] = "Sep";
4547 months[21] = "Oct";
4548 months[22] = "Nov";
4549 months[23] = "Dec";
4550 return months;
4551}
4552
4553static
4554wstring*
4555init_wmonths()
4556{
4557 static wstring months[24];
4558 months[0] = L"January";
4559 months[1] = L"February";
4560 months[2] = L"March";
4561 months[3] = L"April";
4562 months[4] = L"May";
4563 months[5] = L"June";
4564 months[6] = L"July";
4565 months[7] = L"August";
4566 months[8] = L"September";
4567 months[9] = L"October";
4568 months[10] = L"November";
4569 months[11] = L"December";
4570 months[12] = L"Jan";
4571 months[13] = L"Feb";
4572 months[14] = L"Mar";
4573 months[15] = L"Apr";
4574 months[16] = L"May";
4575 months[17] = L"Jun";
4576 months[18] = L"Jul";
4577 months[19] = L"Aug";
4578 months[20] = L"Sep";
4579 months[21] = L"Oct";
4580 months[22] = L"Nov";
4581 months[23] = L"Dec";
4582 return months;
4583}
4584
4585template <>
4586const string*
4587__time_get_c_storage<char>::__months() const
4588{
4589 static const string* months = init_months();
4590 return months;
4591}
4592
4593template <>
4594const wstring*
4595__time_get_c_storage<wchar_t>::__months() const
4596{
4597 static const wstring* months = init_wmonths();
4598 return months;
4599}
4600
4601static
4602string*
4603init_am_pm()
4604{
4605 static string am_pm[24];
4606 am_pm[0] = "AM";
4607 am_pm[1] = "PM";
4608 return am_pm;
4609}
4610
4611static
4612wstring*
4613init_wam_pm()
4614{
4615 static wstring am_pm[24];
4616 am_pm[0] = L"AM";
4617 am_pm[1] = L"PM";
4618 return am_pm;
4619}
4620
4621template <>
4622const string*
4623__time_get_c_storage<char>::__am_pm() const
4624{
4625 static const string* am_pm = init_am_pm();
4626 return am_pm;
4627}
4628
4629template <>
4630const wstring*
4631__time_get_c_storage<wchar_t>::__am_pm() const
4632{
4633 static const wstring* am_pm = init_wam_pm();
4634 return am_pm;
4635}
4636
4637template <>
4638const string&
4639__time_get_c_storage<char>::__x() const
4640{
4641 static string s("%m/%d/%y");
4642 return s;
4643}
4644
4645template <>
4646const wstring&
4647__time_get_c_storage<wchar_t>::__x() const
4648{
4649 static wstring s(L"%m/%d/%y");
4650 return s;
4651}
4652
4653template <>
4654const string&
4655__time_get_c_storage<char>::__X() const
4656{
4657 static string s("%H:%M:%S");
4658 return s;
4659}
4660
4661template <>
4662const wstring&
4663__time_get_c_storage<wchar_t>::__X() const
4664{
4665 static wstring s(L"%H:%M:%S");
4666 return s;
4667}
4668
4669template <>
4670const string&
4671__time_get_c_storage<char>::__c() const
4672{
4673 static string s("%a %b %d %H:%M:%S %Y");
4674 return s;
4675}
4676
4677template <>
4678const wstring&
4679__time_get_c_storage<wchar_t>::__c() const
4680{
4681 static wstring s(L"%a %b %d %H:%M:%S %Y");
4682 return s;
4683}
4684
4685template <>
4686const string&
4687__time_get_c_storage<char>::__r() const
4688{
4689 static string s("%I:%M:%S %p");
4690 return s;
4691}
4692
4693template <>
4694const wstring&
4695__time_get_c_storage<wchar_t>::__r() const
4696{
4697 static wstring s(L"%I:%M:%S %p");
4698 return s;
4699}
4700
4701// time_get_byname
4702
4703__time_get::__time_get(const char* nm)
4704 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4705{
Howard Hinnant72f73582010-08-11 17:04:31 +00004706#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004707 if (__loc_ == 0)
4708 throw runtime_error("time_get_byname"
4709 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004710#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004711}
4712
4713__time_get::__time_get(const string& nm)
4714 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4715{
Howard Hinnant72f73582010-08-11 17:04:31 +00004716#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004717 if (__loc_ == 0)
4718 throw runtime_error("time_get_byname"
4719 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004720#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004721}
4722
4723__time_get::~__time_get()
4724{
4725 freelocale(__loc_);
4726}
Marshall Clowd920eea2013-10-21 15:07:28 +00004727#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004728#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004729#endif
4730#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004731#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004732#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004733
Howard Hinnantc51e1022010-05-11 19:42:16 +00004734template <>
4735string
4736__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4737{
Howard Hinnant990207c2012-02-19 14:55:32 +00004738 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004739 t.tm_sec = 59;
4740 t.tm_min = 55;
4741 t.tm_hour = 23;
4742 t.tm_mday = 31;
4743 t.tm_mon = 11;
4744 t.tm_year = 161;
4745 t.tm_wday = 6;
4746 t.tm_yday = 364;
4747 t.tm_isdst = -1;
4748 char buf[100];
4749 char f[3] = {0};
4750 f[0] = '%';
4751 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004752 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004753 char* bb = buf;
4754 char* be = buf + n;
4755 string result;
4756 while (bb != be)
4757 {
4758 if (ct.is(ctype_base::space, *bb))
4759 {
4760 result.push_back(' ');
4761 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4762 ;
4763 continue;
4764 }
4765 char* w = bb;
4766 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004767 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004768 ct, err, false)
4769 - this->__weeks_;
4770 if (i < 14)
4771 {
4772 result.push_back('%');
4773 if (i < 7)
4774 result.push_back('A');
4775 else
4776 result.push_back('a');
4777 bb = w;
4778 continue;
4779 }
4780 w = bb;
4781 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4782 ct, err, false)
4783 - this->__months_;
4784 if (i < 24)
4785 {
4786 result.push_back('%');
4787 if (i < 12)
4788 result.push_back('B');
4789 else
4790 result.push_back('b');
4791 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4792 result.back() = 'm';
4793 bb = w;
4794 continue;
4795 }
4796 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4797 {
4798 w = bb;
4799 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4800 ct, err, false) - this->__am_pm_;
4801 if (i < 2)
4802 {
4803 result.push_back('%');
4804 result.push_back('p');
4805 bb = w;
4806 continue;
4807 }
4808 }
4809 w = bb;
4810 if (ct.is(ctype_base::digit, *bb))
4811 {
4812 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4813 {
4814 case 6:
4815 result.push_back('%');
4816 result.push_back('w');
4817 break;
4818 case 7:
4819 result.push_back('%');
4820 result.push_back('u');
4821 break;
4822 case 11:
4823 result.push_back('%');
4824 result.push_back('I');
4825 break;
4826 case 12:
4827 result.push_back('%');
4828 result.push_back('m');
4829 break;
4830 case 23:
4831 result.push_back('%');
4832 result.push_back('H');
4833 break;
4834 case 31:
4835 result.push_back('%');
4836 result.push_back('d');
4837 break;
4838 case 55:
4839 result.push_back('%');
4840 result.push_back('M');
4841 break;
4842 case 59:
4843 result.push_back('%');
4844 result.push_back('S');
4845 break;
4846 case 61:
4847 result.push_back('%');
4848 result.push_back('y');
4849 break;
4850 case 364:
4851 result.push_back('%');
4852 result.push_back('j');
4853 break;
4854 case 2061:
4855 result.push_back('%');
4856 result.push_back('Y');
4857 break;
4858 default:
4859 for (; w != bb; ++w)
4860 result.push_back(*w);
4861 break;
4862 }
4863 continue;
4864 }
4865 if (*bb == '%')
4866 {
4867 result.push_back('%');
4868 result.push_back('%');
4869 ++bb;
4870 continue;
4871 }
4872 result.push_back(*bb);
4873 ++bb;
4874 }
4875 return result;
4876}
4877
Marshall Clowd920eea2013-10-21 15:07:28 +00004878#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004879#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004880#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004881
Howard Hinnantc51e1022010-05-11 19:42:16 +00004882template <>
4883wstring
4884__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4885{
Howard Hinnant990207c2012-02-19 14:55:32 +00004886 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004887 t.tm_sec = 59;
4888 t.tm_min = 55;
4889 t.tm_hour = 23;
4890 t.tm_mday = 31;
4891 t.tm_mon = 11;
4892 t.tm_year = 161;
4893 t.tm_wday = 6;
4894 t.tm_yday = 364;
4895 t.tm_isdst = -1;
4896 char buf[100];
4897 char f[3] = {0};
4898 f[0] = '%';
4899 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004900 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004901 wchar_t wbuf[100];
4902 wchar_t* wbb = wbuf;
4903 mbstate_t mb = {0};
4904 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004905 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004906 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004907 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004908 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004909 wstring result;
4910 while (wbb != wbe)
4911 {
4912 if (ct.is(ctype_base::space, *wbb))
4913 {
4914 result.push_back(L' ');
4915 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4916 ;
4917 continue;
4918 }
4919 wchar_t* w = wbb;
4920 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004921 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004922 ct, err, false)
4923 - this->__weeks_;
4924 if (i < 14)
4925 {
4926 result.push_back(L'%');
4927 if (i < 7)
4928 result.push_back(L'A');
4929 else
4930 result.push_back(L'a');
4931 wbb = w;
4932 continue;
4933 }
4934 w = wbb;
4935 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4936 ct, err, false)
4937 - this->__months_;
4938 if (i < 24)
4939 {
4940 result.push_back(L'%');
4941 if (i < 12)
4942 result.push_back(L'B');
4943 else
4944 result.push_back(L'b');
4945 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4946 result.back() = L'm';
4947 wbb = w;
4948 continue;
4949 }
4950 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4951 {
4952 w = wbb;
4953 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4954 ct, err, false) - this->__am_pm_;
4955 if (i < 2)
4956 {
4957 result.push_back(L'%');
4958 result.push_back(L'p');
4959 wbb = w;
4960 continue;
4961 }
4962 }
4963 w = wbb;
4964 if (ct.is(ctype_base::digit, *wbb))
4965 {
4966 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4967 {
4968 case 6:
4969 result.push_back(L'%');
4970 result.push_back(L'w');
4971 break;
4972 case 7:
4973 result.push_back(L'%');
4974 result.push_back(L'u');
4975 break;
4976 case 11:
4977 result.push_back(L'%');
4978 result.push_back(L'I');
4979 break;
4980 case 12:
4981 result.push_back(L'%');
4982 result.push_back(L'm');
4983 break;
4984 case 23:
4985 result.push_back(L'%');
4986 result.push_back(L'H');
4987 break;
4988 case 31:
4989 result.push_back(L'%');
4990 result.push_back(L'd');
4991 break;
4992 case 55:
4993 result.push_back(L'%');
4994 result.push_back(L'M');
4995 break;
4996 case 59:
4997 result.push_back(L'%');
4998 result.push_back(L'S');
4999 break;
5000 case 61:
5001 result.push_back(L'%');
5002 result.push_back(L'y');
5003 break;
5004 case 364:
5005 result.push_back(L'%');
5006 result.push_back(L'j');
5007 break;
5008 case 2061:
5009 result.push_back(L'%');
5010 result.push_back(L'Y');
5011 break;
5012 default:
5013 for (; w != wbb; ++w)
5014 result.push_back(*w);
5015 break;
5016 }
5017 continue;
5018 }
5019 if (ct.narrow(*wbb, 0) == '%')
5020 {
5021 result.push_back(L'%');
5022 result.push_back(L'%');
5023 ++wbb;
5024 continue;
5025 }
5026 result.push_back(*wbb);
5027 ++wbb;
5028 }
5029 return result;
5030}
5031
5032template <>
5033void
5034__time_get_storage<char>::init(const ctype<char>& ct)
5035{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005036 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005037 char buf[100];
5038 // __weeks_
5039 for (int i = 0; i < 7; ++i)
5040 {
5041 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005042 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005043 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005044 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005045 __weeks_[i+7] = buf;
5046 }
5047 // __months_
5048 for (int i = 0; i < 12; ++i)
5049 {
5050 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005051 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005052 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005053 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005054 __months_[i+12] = buf;
5055 }
5056 // __am_pm_
5057 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005058 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005059 __am_pm_[0] = buf;
5060 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005061 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005062 __am_pm_[1] = buf;
5063 __c_ = __analyze('c', ct);
5064 __r_ = __analyze('r', ct);
5065 __x_ = __analyze('x', ct);
5066 __X_ = __analyze('X', ct);
5067}
5068
5069template <>
5070void
5071__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5072{
5073 tm t = {0};
5074 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005075 wchar_t wbuf[100];
5076 wchar_t* wbe;
5077 mbstate_t mb = {0};
5078 // __weeks_
5079 for (int i = 0; i < 7; ++i)
5080 {
5081 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005082 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005083 mb = mbstate_t();
5084 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005085 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005086 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005087 __throw_runtime_error("locale not supported");
5088 wbe = wbuf + j;
5089 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005090 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005091 mb = mbstate_t();
5092 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005093 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005094 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005095 __throw_runtime_error("locale not supported");
5096 wbe = wbuf + j;
5097 __weeks_[i+7].assign(wbuf, wbe);
5098 }
5099 // __months_
5100 for (int i = 0; i < 12; ++i)
5101 {
5102 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005103 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005104 mb = mbstate_t();
5105 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005106 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005107 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005108 __throw_runtime_error("locale not supported");
5109 wbe = wbuf + j;
5110 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005111 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005112 mb = mbstate_t();
5113 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005114 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005115 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005116 __throw_runtime_error("locale not supported");
5117 wbe = wbuf + j;
5118 __months_[i+12].assign(wbuf, wbe);
5119 }
5120 // __am_pm_
5121 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005122 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005123 mb = mbstate_t();
5124 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005125 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005126 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005127 __throw_runtime_error("locale not supported");
5128 wbe = wbuf + j;
5129 __am_pm_[0].assign(wbuf, wbe);
5130 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005131 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005132 mb = mbstate_t();
5133 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005134 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005135 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005136 __throw_runtime_error("locale not supported");
5137 wbe = wbuf + j;
5138 __am_pm_[1].assign(wbuf, wbe);
5139 __c_ = __analyze('c', ct);
5140 __r_ = __analyze('r', ct);
5141 __x_ = __analyze('x', ct);
5142 __X_ = __analyze('X', ct);
5143}
5144
5145template <class CharT>
5146struct _LIBCPP_HIDDEN __time_get_temp
5147 : public ctype_byname<CharT>
5148{
5149 explicit __time_get_temp(const char* nm)
5150 : ctype_byname<CharT>(nm, 1) {}
5151 explicit __time_get_temp(const string& nm)
5152 : ctype_byname<CharT>(nm, 1) {}
5153};
5154
5155template <>
5156__time_get_storage<char>::__time_get_storage(const char* __nm)
5157 : __time_get(__nm)
5158{
5159 const __time_get_temp<char> ct(__nm);
5160 init(ct);
5161}
5162
5163template <>
5164__time_get_storage<char>::__time_get_storage(const string& __nm)
5165 : __time_get(__nm)
5166{
5167 const __time_get_temp<char> ct(__nm);
5168 init(ct);
5169}
5170
5171template <>
5172__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5173 : __time_get(__nm)
5174{
5175 const __time_get_temp<wchar_t> ct(__nm);
5176 init(ct);
5177}
5178
5179template <>
5180__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5181 : __time_get(__nm)
5182{
5183 const __time_get_temp<wchar_t> ct(__nm);
5184 init(ct);
5185}
5186
5187template <>
5188time_base::dateorder
5189__time_get_storage<char>::__do_date_order() const
5190{
5191 unsigned i;
5192 for (i = 0; i < __x_.size(); ++i)
5193 if (__x_[i] == '%')
5194 break;
5195 ++i;
5196 switch (__x_[i])
5197 {
5198 case 'y':
5199 case 'Y':
5200 for (++i; i < __x_.size(); ++i)
5201 if (__x_[i] == '%')
5202 break;
5203 if (i == __x_.size())
5204 break;
5205 ++i;
5206 switch (__x_[i])
5207 {
5208 case 'm':
5209 for (++i; i < __x_.size(); ++i)
5210 if (__x_[i] == '%')
5211 break;
5212 if (i == __x_.size())
5213 break;
5214 ++i;
5215 if (__x_[i] == 'd')
5216 return time_base::ymd;
5217 break;
5218 case 'd':
5219 for (++i; i < __x_.size(); ++i)
5220 if (__x_[i] == '%')
5221 break;
5222 if (i == __x_.size())
5223 break;
5224 ++i;
5225 if (__x_[i] == 'm')
5226 return time_base::ydm;
5227 break;
5228 }
5229 break;
5230 case 'm':
5231 for (++i; i < __x_.size(); ++i)
5232 if (__x_[i] == '%')
5233 break;
5234 if (i == __x_.size())
5235 break;
5236 ++i;
5237 if (__x_[i] == 'd')
5238 {
5239 for (++i; i < __x_.size(); ++i)
5240 if (__x_[i] == '%')
5241 break;
5242 if (i == __x_.size())
5243 break;
5244 ++i;
5245 if (__x_[i] == 'y' || __x_[i] == 'Y')
5246 return time_base::mdy;
5247 break;
5248 }
5249 break;
5250 case 'd':
5251 for (++i; i < __x_.size(); ++i)
5252 if (__x_[i] == '%')
5253 break;
5254 if (i == __x_.size())
5255 break;
5256 ++i;
5257 if (__x_[i] == 'm')
5258 {
5259 for (++i; i < __x_.size(); ++i)
5260 if (__x_[i] == '%')
5261 break;
5262 if (i == __x_.size())
5263 break;
5264 ++i;
5265 if (__x_[i] == 'y' || __x_[i] == 'Y')
5266 return time_base::dmy;
5267 break;
5268 }
5269 break;
5270 }
5271 return time_base::no_order;
5272}
5273
5274template <>
5275time_base::dateorder
5276__time_get_storage<wchar_t>::__do_date_order() const
5277{
5278 unsigned i;
5279 for (i = 0; i < __x_.size(); ++i)
5280 if (__x_[i] == L'%')
5281 break;
5282 ++i;
5283 switch (__x_[i])
5284 {
5285 case L'y':
5286 case L'Y':
5287 for (++i; i < __x_.size(); ++i)
5288 if (__x_[i] == L'%')
5289 break;
5290 if (i == __x_.size())
5291 break;
5292 ++i;
5293 switch (__x_[i])
5294 {
5295 case L'm':
5296 for (++i; i < __x_.size(); ++i)
5297 if (__x_[i] == L'%')
5298 break;
5299 if (i == __x_.size())
5300 break;
5301 ++i;
5302 if (__x_[i] == L'd')
5303 return time_base::ymd;
5304 break;
5305 case L'd':
5306 for (++i; i < __x_.size(); ++i)
5307 if (__x_[i] == L'%')
5308 break;
5309 if (i == __x_.size())
5310 break;
5311 ++i;
5312 if (__x_[i] == L'm')
5313 return time_base::ydm;
5314 break;
5315 }
5316 break;
5317 case L'm':
5318 for (++i; i < __x_.size(); ++i)
5319 if (__x_[i] == L'%')
5320 break;
5321 if (i == __x_.size())
5322 break;
5323 ++i;
5324 if (__x_[i] == L'd')
5325 {
5326 for (++i; i < __x_.size(); ++i)
5327 if (__x_[i] == L'%')
5328 break;
5329 if (i == __x_.size())
5330 break;
5331 ++i;
5332 if (__x_[i] == L'y' || __x_[i] == L'Y')
5333 return time_base::mdy;
5334 break;
5335 }
5336 break;
5337 case L'd':
5338 for (++i; i < __x_.size(); ++i)
5339 if (__x_[i] == L'%')
5340 break;
5341 if (i == __x_.size())
5342 break;
5343 ++i;
5344 if (__x_[i] == L'm')
5345 {
5346 for (++i; i < __x_.size(); ++i)
5347 if (__x_[i] == L'%')
5348 break;
5349 if (i == __x_.size())
5350 break;
5351 ++i;
5352 if (__x_[i] == L'y' || __x_[i] == L'Y')
5353 return time_base::dmy;
5354 break;
5355 }
5356 break;
5357 }
5358 return time_base::no_order;
5359}
5360
5361// time_put
5362
5363__time_put::__time_put(const char* nm)
5364 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5365{
Howard Hinnant72f73582010-08-11 17:04:31 +00005366#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005367 if (__loc_ == 0)
5368 throw runtime_error("time_put_byname"
5369 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005370#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005371}
5372
5373__time_put::__time_put(const string& nm)
5374 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5375{
Howard Hinnant72f73582010-08-11 17:04:31 +00005376#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005377 if (__loc_ == 0)
5378 throw runtime_error("time_put_byname"
5379 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005380#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005381}
5382
5383__time_put::~__time_put()
5384{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005385 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005386 freelocale(__loc_);
5387}
5388
5389void
5390__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5391 char __fmt, char __mod) const
5392{
5393 char fmt[] = {'%', __fmt, __mod, 0};
5394 if (__mod != 0)
5395 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005396 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005397 __ne = __nb + n;
5398}
5399
5400void
5401__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5402 char __fmt, char __mod) const
5403{
5404 char __nar[100];
5405 char* __ne = __nar + 100;
5406 __do_put(__nar, __ne, __tm, __fmt, __mod);
5407 mbstate_t mb = {0};
5408 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005409 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005410 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005411 __throw_runtime_error("locale not supported");
5412 __we = __wb + j;
5413}
5414
5415// moneypunct_byname
5416
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005417template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005418static
5419void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005420__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5421 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5422 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005423{
5424 const char sign = static_cast<char>(money_base::sign);
5425 const char space = static_cast<char>(money_base::space);
5426 const char none = static_cast<char>(money_base::none);
5427 const char symbol = static_cast<char>(money_base::symbol);
5428 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005429 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5430
5431 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5432 // function'. "Space between sign and symbol or value" means that
5433 // if the sign is adjacent to the symbol, there's a space between
5434 // them, and otherwise there's a space between the sign and value.
5435 //
5436 // C11's localeconv specifies that the fourth character of an
5437 // international curr_symbol is used to separate the sign and
5438 // value when sep_by_space says to do so. C++ can't represent
5439 // that, so we just use a space. When sep_by_space says to
5440 // separate the symbol and value-or-sign with a space, we rearrange the
5441 // curr_symbol to put its spacing character on the correct side of
5442 // the symbol.
5443 //
5444 // We also need to avoid adding an extra space between the sign
5445 // and value when the currency symbol is suppressed (by not
5446 // setting showbase). We match glibc's strfmon by interpreting
5447 // sep_by_space==1 as "omit the space when the currency symbol is
5448 // absent".
5449 //
5450 // Users who want to get this right should use ICU instead.
5451
Howard Hinnantc51e1022010-05-11 19:42:16 +00005452 switch (cs_precedes)
5453 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005454 case 0: // value before curr_symbol
5455 if (symbol_contains_sep) {
5456 // Move the separator to before the symbol, to place it
5457 // between the value and symbol.
5458 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5459 __curr_symbol_.end());
5460 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005461 switch (sign_posn)
5462 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005463 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005464 pat.field[0] = sign;
5465 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005466 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005467 pat.field[3] = symbol;
5468 switch (sep_by_space)
5469 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005470 case 0: // No space separates the currency symbol and value.
5471 // This case may have changed between C99 and C11;
5472 // assume the currency symbol matches the intention.
5473 case 2: // Space between sign and currency or value.
5474 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005475 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005476 case 1: // Space between currency-and-sign or currency and value.
5477 if (!symbol_contains_sep) {
5478 // We insert the space into the symbol instead of
5479 // setting pat.field[2]=space so that when
5480 // showbase is not set, the space goes away too.
5481 __curr_symbol_.insert(0, 1, space_char);
5482 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005483 return;
5484 default:
5485 break;
5486 }
5487 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005488 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005489 pat.field[0] = sign;
5490 pat.field[3] = symbol;
5491 switch (sep_by_space)
5492 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005493 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005494 pat.field[1] = value;
5495 pat.field[2] = none;
5496 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005497 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005498 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005499 pat.field[2] = none;
5500 if (!symbol_contains_sep) {
5501 // We insert the space into the symbol instead of
5502 // setting pat.field[2]=space so that when
5503 // showbase is not set, the space goes away too.
5504 __curr_symbol_.insert(0, 1, space_char);
5505 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005506 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005507 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005508 pat.field[1] = space;
5509 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005510 if (symbol_contains_sep) {
5511 // Remove the separator from the symbol, since it
5512 // has already appeared after the sign.
5513 __curr_symbol_.erase(__curr_symbol_.begin());
5514 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005515 return;
5516 default:
5517 break;
5518 }
5519 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005520 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005521 pat.field[0] = value;
5522 pat.field[3] = sign;
5523 switch (sep_by_space)
5524 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005525 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005526 pat.field[1] = none;
5527 pat.field[2] = symbol;
5528 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005529 case 1: // Space between currency-and-sign or currency and value.
5530 if (!symbol_contains_sep) {
5531 // We insert the space into the symbol instead of
5532 // setting pat.field[1]=space so that when
5533 // showbase is not set, the space goes away too.
5534 __curr_symbol_.insert(0, 1, space_char);
5535 }
5536 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005537 pat.field[2] = symbol;
5538 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005539 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005540 pat.field[1] = symbol;
5541 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005542 if (symbol_contains_sep) {
5543 // Remove the separator from the symbol, since it
5544 // should not be removed if showbase is absent.
5545 __curr_symbol_.erase(__curr_symbol_.begin());
5546 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005547 return;
5548 default:
5549 break;
5550 }
5551 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005552 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005553 pat.field[0] = value;
5554 pat.field[3] = symbol;
5555 switch (sep_by_space)
5556 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005557 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005558 pat.field[1] = none;
5559 pat.field[2] = sign;
5560 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005561 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005562 pat.field[1] = space;
5563 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005564 if (symbol_contains_sep) {
5565 // Remove the separator from the symbol, since it
5566 // has already appeared before the sign.
5567 __curr_symbol_.erase(__curr_symbol_.begin());
5568 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005569 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005570 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005571 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005572 pat.field[2] = none;
5573 if (!symbol_contains_sep) {
5574 // We insert the space into the symbol instead of
5575 // setting pat.field[2]=space so that when
5576 // showbase is not set, the space goes away too.
5577 __curr_symbol_.insert(0, 1, space_char);
5578 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005579 return;
5580 default:
5581 break;
5582 }
5583 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005584 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005585 pat.field[0] = value;
5586 pat.field[3] = sign;
5587 switch (sep_by_space)
5588 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005589 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005590 pat.field[1] = none;
5591 pat.field[2] = symbol;
5592 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005593 case 1: // Space between currency-and-sign or currency and value.
5594 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005595 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005596 if (!symbol_contains_sep) {
5597 // We insert the space into the symbol instead of
5598 // setting pat.field[1]=space so that when
5599 // showbase is not set, the space goes away too.
5600 __curr_symbol_.insert(0, 1, space_char);
5601 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005602 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005603 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005604 pat.field[1] = symbol;
5605 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005606 if (symbol_contains_sep) {
5607 // Remove the separator from the symbol, since it
5608 // should not disappear when showbase is absent.
5609 __curr_symbol_.erase(__curr_symbol_.begin());
5610 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005611 return;
5612 default:
5613 break;
5614 }
5615 break;
5616 default:
5617 break;
5618 }
5619 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005620 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005621 switch (sign_posn)
5622 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005623 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005624 pat.field[0] = sign;
5625 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005626 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005627 pat.field[3] = value;
5628 switch (sep_by_space)
5629 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005630 case 0: // No space separates the currency symbol and value.
5631 // This case may have changed between C99 and C11;
5632 // assume the currency symbol matches the intention.
5633 case 2: // Space between sign and currency or value.
5634 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005635 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005636 case 1: // Space between currency-and-sign or currency and value.
5637 if (!symbol_contains_sep) {
5638 // We insert the space into the symbol instead of
5639 // setting pat.field[2]=space so that when
5640 // showbase is not set, the space goes away too.
5641 __curr_symbol_.insert(0, 1, space_char);
5642 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005643 return;
5644 default:
5645 break;
5646 }
5647 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005648 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005649 pat.field[0] = sign;
5650 pat.field[3] = value;
5651 switch (sep_by_space)
5652 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005653 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005654 pat.field[1] = symbol;
5655 pat.field[2] = none;
5656 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005657 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005658 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005659 pat.field[2] = none;
5660 if (!symbol_contains_sep) {
5661 // We insert the space into the symbol instead of
5662 // setting pat.field[2]=space so that when
5663 // showbase is not set, the space goes away too.
5664 __curr_symbol_.push_back(space_char);
5665 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005666 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005667 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005668 pat.field[1] = space;
5669 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005670 if (symbol_contains_sep) {
5671 // Remove the separator from the symbol, since it
5672 // has already appeared after the sign.
5673 __curr_symbol_.pop_back();
5674 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005675 return;
5676 default:
5677 break;
5678 }
5679 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005680 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005681 pat.field[0] = symbol;
5682 pat.field[3] = sign;
5683 switch (sep_by_space)
5684 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005685 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005686 pat.field[1] = none;
5687 pat.field[2] = value;
5688 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005689 case 1: // Space between currency-and-sign or currency and value.
5690 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005691 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005692 if (!symbol_contains_sep) {
5693 // We insert the space into the symbol instead of
5694 // setting pat.field[1]=space so that when
5695 // showbase is not set, the space goes away too.
5696 __curr_symbol_.push_back(space_char);
5697 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005698 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005699 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005700 pat.field[1] = value;
5701 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005702 if (symbol_contains_sep) {
5703 // Remove the separator from the symbol, since it
5704 // will appear before the sign.
5705 __curr_symbol_.pop_back();
5706 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005707 return;
5708 default:
5709 break;
5710 }
5711 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005712 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005713 pat.field[0] = sign;
5714 pat.field[3] = value;
5715 switch (sep_by_space)
5716 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005717 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005718 pat.field[1] = symbol;
5719 pat.field[2] = none;
5720 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005721 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005722 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005723 pat.field[2] = none;
5724 if (!symbol_contains_sep) {
5725 // We insert the space into the symbol instead of
5726 // setting pat.field[2]=space so that when
5727 // showbase is not set, the space goes away too.
5728 __curr_symbol_.push_back(space_char);
5729 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005730 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005731 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005732 pat.field[1] = space;
5733 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005734 if (symbol_contains_sep) {
5735 // Remove the separator from the symbol, since it
5736 // has already appeared after the sign.
5737 __curr_symbol_.pop_back();
5738 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005739 return;
5740 default:
5741 break;
5742 }
5743 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005744 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 pat.field[0] = symbol;
5746 pat.field[3] = value;
5747 switch (sep_by_space)
5748 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005749 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005750 pat.field[1] = sign;
5751 pat.field[2] = none;
5752 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005753 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005754 pat.field[1] = sign;
5755 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005756 if (symbol_contains_sep) {
5757 // Remove the separator from the symbol, since it
5758 // should not disappear when showbase is absent.
5759 __curr_symbol_.pop_back();
5760 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005761 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005762 case 2: // Space between sign and currency or value.
5763 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005764 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005765 if (!symbol_contains_sep) {
5766 // We insert the space into the symbol instead of
5767 // setting pat.field[1]=space so that when
5768 // showbase is not set, the space goes away too.
5769 __curr_symbol_.push_back(space_char);
5770 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005771 return;
5772 default:
5773 break;
5774 }
5775 break;
5776 default:
5777 break;
5778 }
5779 break;
5780 default:
5781 break;
5782 }
5783 pat.field[0] = symbol;
5784 pat.field[1] = sign;
5785 pat.field[2] = none;
5786 pat.field[3] = value;
5787}
5788
5789template<>
5790void
5791moneypunct_byname<char, false>::init(const char* nm)
5792{
5793 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005794 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005795#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005796 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005797 throw runtime_error("moneypunct_byname"
5798 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005799#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005800 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005801 if (*lc->mon_decimal_point)
5802 __decimal_point_ = *lc->mon_decimal_point;
5803 else
5804 __decimal_point_ = base::do_decimal_point();
5805 if (*lc->mon_thousands_sep)
5806 __thousands_sep_ = *lc->mon_thousands_sep;
5807 else
5808 __thousands_sep_ = base::do_thousands_sep();
5809 __grouping_ = lc->mon_grouping;
5810 __curr_symbol_ = lc->currency_symbol;
5811 if (lc->frac_digits != CHAR_MAX)
5812 __frac_digits_ = lc->frac_digits;
5813 else
5814 __frac_digits_ = base::do_frac_digits();
5815 if (lc->p_sign_posn == 0)
5816 __positive_sign_ = "()";
5817 else
5818 __positive_sign_ = lc->positive_sign;
5819 if (lc->n_sign_posn == 0)
5820 __negative_sign_ = "()";
5821 else
5822 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005823 // Assume the positive and negative formats will want spaces in
5824 // the same places in curr_symbol since there's no way to
5825 // represent anything else.
5826 string_type __dummy_curr_symbol = __curr_symbol_;
5827 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5828 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5829 __init_pat(__neg_format_, __curr_symbol_, false,
5830 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005831}
5832
5833template<>
5834void
5835moneypunct_byname<char, true>::init(const char* nm)
5836{
5837 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005838 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005839#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005840 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005841 throw runtime_error("moneypunct_byname"
5842 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005843#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005844 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005845 if (*lc->mon_decimal_point)
5846 __decimal_point_ = *lc->mon_decimal_point;
5847 else
5848 __decimal_point_ = base::do_decimal_point();
5849 if (*lc->mon_thousands_sep)
5850 __thousands_sep_ = *lc->mon_thousands_sep;
5851 else
5852 __thousands_sep_ = base::do_thousands_sep();
5853 __grouping_ = lc->mon_grouping;
5854 __curr_symbol_ = lc->int_curr_symbol;
5855 if (lc->int_frac_digits != CHAR_MAX)
5856 __frac_digits_ = lc->int_frac_digits;
5857 else
5858 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005859#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005860 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005861#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005862 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005863#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005864 __positive_sign_ = "()";
5865 else
5866 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005867#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005868 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005869#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005870 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005871#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005872 __negative_sign_ = "()";
5873 else
5874 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005875 // Assume the positive and negative formats will want spaces in
5876 // the same places in curr_symbol since there's no way to
5877 // represent anything else.
5878 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005879#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005880 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5881 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5882 __init_pat(__neg_format_, __curr_symbol_, true,
5883 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005884#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005885 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5886 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5887 lc->int_p_sign_posn, ' ');
5888 __init_pat(__neg_format_, __curr_symbol_, true,
5889 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5890 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005891#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005892}
5893
5894template<>
5895void
5896moneypunct_byname<wchar_t, false>::init(const char* nm)
5897{
5898 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005899 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005900#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005901 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005902 throw runtime_error("moneypunct_byname"
5903 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005904#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005905 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005906 if (*lc->mon_decimal_point)
5907 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5908 else
5909 __decimal_point_ = base::do_decimal_point();
5910 if (*lc->mon_thousands_sep)
5911 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5912 else
5913 __thousands_sep_ = base::do_thousands_sep();
5914 __grouping_ = lc->mon_grouping;
5915 wchar_t wbuf[100];
5916 mbstate_t mb = {0};
5917 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005918 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005919 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005920 __throw_runtime_error("locale not supported");
5921 wchar_t* wbe = wbuf + j;
5922 __curr_symbol_.assign(wbuf, wbe);
5923 if (lc->frac_digits != CHAR_MAX)
5924 __frac_digits_ = lc->frac_digits;
5925 else
5926 __frac_digits_ = base::do_frac_digits();
5927 if (lc->p_sign_posn == 0)
5928 __positive_sign_ = L"()";
5929 else
5930 {
5931 mb = mbstate_t();
5932 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005933 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005934 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005935 __throw_runtime_error("locale not supported");
5936 wbe = wbuf + j;
5937 __positive_sign_.assign(wbuf, wbe);
5938 }
5939 if (lc->n_sign_posn == 0)
5940 __negative_sign_ = L"()";
5941 else
5942 {
5943 mb = mbstate_t();
5944 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005945 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005946 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 __throw_runtime_error("locale not supported");
5948 wbe = wbuf + j;
5949 __negative_sign_.assign(wbuf, wbe);
5950 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005951 // Assume the positive and negative formats will want spaces in
5952 // the same places in curr_symbol since there's no way to
5953 // represent anything else.
5954 string_type __dummy_curr_symbol = __curr_symbol_;
5955 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5956 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5957 __init_pat(__neg_format_, __curr_symbol_, false,
5958 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005959}
5960
5961template<>
5962void
5963moneypunct_byname<wchar_t, true>::init(const char* nm)
5964{
5965 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005966 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005967#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005968 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 throw runtime_error("moneypunct_byname"
5970 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005971#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005972 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005973 if (*lc->mon_decimal_point)
5974 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5975 else
5976 __decimal_point_ = base::do_decimal_point();
5977 if (*lc->mon_thousands_sep)
5978 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5979 else
5980 __thousands_sep_ = base::do_thousands_sep();
5981 __grouping_ = lc->mon_grouping;
5982 wchar_t wbuf[100];
5983 mbstate_t mb = {0};
5984 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005985 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005986 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005987 __throw_runtime_error("locale not supported");
5988 wchar_t* wbe = wbuf + j;
5989 __curr_symbol_.assign(wbuf, wbe);
5990 if (lc->int_frac_digits != CHAR_MAX)
5991 __frac_digits_ = lc->int_frac_digits;
5992 else
5993 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005994#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005995 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005996#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005997 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005998#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005999 __positive_sign_ = L"()";
6000 else
6001 {
6002 mb = mbstate_t();
6003 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006004 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006005 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006006 __throw_runtime_error("locale not supported");
6007 wbe = wbuf + j;
6008 __positive_sign_.assign(wbuf, wbe);
6009 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006010#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006011 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006012#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006013 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006014#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006015 __negative_sign_ = L"()";
6016 else
6017 {
6018 mb = mbstate_t();
6019 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006020 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006021 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006022 __throw_runtime_error("locale not supported");
6023 wbe = wbuf + j;
6024 __negative_sign_.assign(wbuf, wbe);
6025 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006026 // Assume the positive and negative formats will want spaces in
6027 // the same places in curr_symbol since there's no way to
6028 // represent anything else.
6029 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006030#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006031 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6032 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6033 __init_pat(__neg_format_, __curr_symbol_, true,
6034 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006035#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006036 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6037 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6038 lc->int_p_sign_posn, L' ');
6039 __init_pat(__neg_format_, __curr_symbol_, true,
6040 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6041 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006042#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006043}
6044
6045void __do_nothing(void*) {}
6046
6047void __throw_runtime_error(const char* msg)
6048{
Howard Hinnant72f73582010-08-11 17:04:31 +00006049#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006050 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006051#else
6052 (void)msg;
Howard Hinnant72f73582010-08-11 17:04:31 +00006053#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006054}
6055
6056template class collate<char>;
6057template class collate<wchar_t>;
6058
6059template class num_get<char>;
6060template class num_get<wchar_t>;
6061
Howard Hinnant28b24882011-12-01 20:21:04 +00006062template struct __num_get<char>;
6063template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006064
6065template class num_put<char>;
6066template class num_put<wchar_t>;
6067
Howard Hinnant28b24882011-12-01 20:21:04 +00006068template struct __num_put<char>;
6069template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006070
6071template class time_get<char>;
6072template class time_get<wchar_t>;
6073
6074template class time_get_byname<char>;
6075template class time_get_byname<wchar_t>;
6076
6077template class time_put<char>;
6078template class time_put<wchar_t>;
6079
6080template class time_put_byname<char>;
6081template class time_put_byname<wchar_t>;
6082
6083template class moneypunct<char, false>;
6084template class moneypunct<char, true>;
6085template class moneypunct<wchar_t, false>;
6086template class moneypunct<wchar_t, true>;
6087
6088template class moneypunct_byname<char, false>;
6089template class moneypunct_byname<char, true>;
6090template class moneypunct_byname<wchar_t, false>;
6091template class moneypunct_byname<wchar_t, true>;
6092
6093template class money_get<char>;
6094template class money_get<wchar_t>;
6095
6096template class __money_get<char>;
6097template class __money_get<wchar_t>;
6098
6099template class money_put<char>;
6100template class money_put<wchar_t>;
6101
6102template class __money_put<char>;
6103template class __money_put<wchar_t>;
6104
6105template class messages<char>;
6106template class messages<wchar_t>;
6107
6108template class messages_byname<char>;
6109template class messages_byname<wchar_t>;
6110
6111template class codecvt_byname<char, char, mbstate_t>;
6112template class codecvt_byname<wchar_t, char, mbstate_t>;
6113template class codecvt_byname<char16_t, char, mbstate_t>;
6114template class codecvt_byname<char32_t, char, mbstate_t>;
6115
6116template class __vector_base_common<true>;
6117
6118_LIBCPP_END_NAMESPACE_STD