blob: bc2427bfce9188dbd742c2629693009b52f7cfda [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{
Ed Schouten3d3341e2015-07-06 15:39:36 +00001663#ifndef __CloudABI__
Ben Craig3756b922016-03-09 15:39:39 +00001664 if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Ed Schouten3d3341e2015-07-06 15:39:36 +00001665 return -1;
1666#endif
1667
1668 // stateless encoding
Ben Craig3756b922016-03-09 15:39:39 +00001669 if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Ed Schouten3d3341e2015-07-06 15:39:36 +00001670 return 1; // which take more than 1 char to form a wchar_t
1671 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001672}
1673
1674bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001675codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001676{
1677 return false;
1678}
1679
1680int
1681codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1682 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1683{
1684 int nbytes = 0;
1685 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1686 {
Ben Craig3756b922016-03-09 15:39:39 +00001687 size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001688 switch (n)
1689 {
1690 case 0:
1691 ++nbytes;
1692 ++frm;
1693 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001694 case size_t(-1):
1695 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001696 return nbytes;
1697 default:
1698 nbytes += n;
1699 frm += n;
1700 break;
1701 }
1702 }
1703 return nbytes;
1704}
1705
1706int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001707codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001708{
Ben Craig3756b922016-03-09 15:39:39 +00001709 return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001710}
1711
1712// Valid UTF ranges
1713// UTF-32 UTF-16 UTF-8 # of code points
1714// first second first second third fourth
1715// 000000 - 00007F 0000 - 007F 00 - 7F 127
1716// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1717// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1718// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1719// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1720// 00D800 - 00DFFF invalid
1721// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1722// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1723// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1724// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1725
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001726static
1727codecvt_base::result
1728utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1729 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1730 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1731{
1732 frm_nxt = frm;
1733 to_nxt = to;
1734 if (mode & generate_header)
1735 {
1736 if (to_end-to_nxt < 3)
1737 return codecvt_base::partial;
1738 *to_nxt++ = static_cast<uint8_t>(0xEF);
1739 *to_nxt++ = static_cast<uint8_t>(0xBB);
1740 *to_nxt++ = static_cast<uint8_t>(0xBF);
1741 }
1742 for (; frm_nxt < frm_end; ++frm_nxt)
1743 {
1744 uint16_t wc1 = *frm_nxt;
1745 if (wc1 > Maxcode)
1746 return codecvt_base::error;
1747 if (wc1 < 0x0080)
1748 {
1749 if (to_end-to_nxt < 1)
1750 return codecvt_base::partial;
1751 *to_nxt++ = static_cast<uint8_t>(wc1);
1752 }
1753 else if (wc1 < 0x0800)
1754 {
1755 if (to_end-to_nxt < 2)
1756 return codecvt_base::partial;
1757 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1758 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1759 }
1760 else if (wc1 < 0xD800)
1761 {
1762 if (to_end-to_nxt < 3)
1763 return codecvt_base::partial;
1764 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1765 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1766 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1767 }
1768 else if (wc1 < 0xDC00)
1769 {
1770 if (frm_end-frm_nxt < 2)
1771 return codecvt_base::partial;
1772 uint16_t wc2 = frm_nxt[1];
1773 if ((wc2 & 0xFC00) != 0xDC00)
1774 return codecvt_base::error;
1775 if (to_end-to_nxt < 4)
1776 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001777 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1778 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001779 return codecvt_base::error;
1780 ++frm_nxt;
1781 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1782 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1783 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1784 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1785 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1786 }
1787 else if (wc1 < 0xE000)
1788 {
1789 return codecvt_base::error;
1790 }
1791 else
1792 {
1793 if (to_end-to_nxt < 3)
1794 return codecvt_base::partial;
1795 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1796 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1797 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1798 }
1799 }
1800 return codecvt_base::ok;
1801}
1802
1803static
1804codecvt_base::result
1805utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1806 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1807 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1808{
1809 frm_nxt = frm;
1810 to_nxt = to;
1811 if (mode & generate_header)
1812 {
1813 if (to_end-to_nxt < 3)
1814 return codecvt_base::partial;
1815 *to_nxt++ = static_cast<uint8_t>(0xEF);
1816 *to_nxt++ = static_cast<uint8_t>(0xBB);
1817 *to_nxt++ = static_cast<uint8_t>(0xBF);
1818 }
1819 for (; frm_nxt < frm_end; ++frm_nxt)
1820 {
1821 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1822 if (wc1 > Maxcode)
1823 return codecvt_base::error;
1824 if (wc1 < 0x0080)
1825 {
1826 if (to_end-to_nxt < 1)
1827 return codecvt_base::partial;
1828 *to_nxt++ = static_cast<uint8_t>(wc1);
1829 }
1830 else if (wc1 < 0x0800)
1831 {
1832 if (to_end-to_nxt < 2)
1833 return codecvt_base::partial;
1834 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1835 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1836 }
1837 else if (wc1 < 0xD800)
1838 {
1839 if (to_end-to_nxt < 3)
1840 return codecvt_base::partial;
1841 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1842 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1843 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1844 }
1845 else if (wc1 < 0xDC00)
1846 {
1847 if (frm_end-frm_nxt < 2)
1848 return codecvt_base::partial;
1849 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1850 if ((wc2 & 0xFC00) != 0xDC00)
1851 return codecvt_base::error;
1852 if (to_end-to_nxt < 4)
1853 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001854 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1855 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001856 return codecvt_base::error;
1857 ++frm_nxt;
1858 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1859 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1860 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1861 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1862 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1863 }
1864 else if (wc1 < 0xE000)
1865 {
1866 return codecvt_base::error;
1867 }
1868 else
1869 {
1870 if (to_end-to_nxt < 3)
1871 return codecvt_base::partial;
1872 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1873 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1874 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1875 }
1876 }
1877 return codecvt_base::ok;
1878}
1879
1880static
1881codecvt_base::result
1882utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1883 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1884 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1885{
1886 frm_nxt = frm;
1887 to_nxt = to;
1888 if (mode & consume_header)
1889 {
1890 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1891 frm_nxt[2] == 0xBF)
1892 frm_nxt += 3;
1893 }
1894 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1895 {
1896 uint8_t c1 = *frm_nxt;
1897 if (c1 > Maxcode)
1898 return codecvt_base::error;
1899 if (c1 < 0x80)
1900 {
1901 *to_nxt = static_cast<uint16_t>(c1);
1902 ++frm_nxt;
1903 }
1904 else if (c1 < 0xC2)
1905 {
1906 return codecvt_base::error;
1907 }
1908 else if (c1 < 0xE0)
1909 {
1910 if (frm_end-frm_nxt < 2)
1911 return codecvt_base::partial;
1912 uint8_t c2 = frm_nxt[1];
1913 if ((c2 & 0xC0) != 0x80)
1914 return codecvt_base::error;
1915 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1916 if (t > Maxcode)
1917 return codecvt_base::error;
1918 *to_nxt = t;
1919 frm_nxt += 2;
1920 }
1921 else if (c1 < 0xF0)
1922 {
1923 if (frm_end-frm_nxt < 3)
1924 return codecvt_base::partial;
1925 uint8_t c2 = frm_nxt[1];
1926 uint8_t c3 = frm_nxt[2];
1927 switch (c1)
1928 {
1929 case 0xE0:
1930 if ((c2 & 0xE0) != 0xA0)
1931 return codecvt_base::error;
1932 break;
1933 case 0xED:
1934 if ((c2 & 0xE0) != 0x80)
1935 return codecvt_base::error;
1936 break;
1937 default:
1938 if ((c2 & 0xC0) != 0x80)
1939 return codecvt_base::error;
1940 break;
1941 }
1942 if ((c3 & 0xC0) != 0x80)
1943 return codecvt_base::error;
1944 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1945 | ((c2 & 0x3F) << 6)
1946 | (c3 & 0x3F));
1947 if (t > Maxcode)
1948 return codecvt_base::error;
1949 *to_nxt = t;
1950 frm_nxt += 3;
1951 }
1952 else if (c1 < 0xF5)
1953 {
1954 if (frm_end-frm_nxt < 4)
1955 return codecvt_base::partial;
1956 uint8_t c2 = frm_nxt[1];
1957 uint8_t c3 = frm_nxt[2];
1958 uint8_t c4 = frm_nxt[3];
1959 switch (c1)
1960 {
1961 case 0xF0:
1962 if (!(0x90 <= c2 && c2 <= 0xBF))
1963 return codecvt_base::error;
1964 break;
1965 case 0xF4:
1966 if ((c2 & 0xF0) != 0x80)
1967 return codecvt_base::error;
1968 break;
1969 default:
1970 if ((c2 & 0xC0) != 0x80)
1971 return codecvt_base::error;
1972 break;
1973 }
1974 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1975 return codecvt_base::error;
1976 if (to_end-to_nxt < 2)
1977 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001978 if ((((c1 & 7UL) << 18) +
1979 ((c2 & 0x3FUL) << 12) +
1980 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001981 return codecvt_base::error;
1982 *to_nxt = static_cast<uint16_t>(
1983 0xD800
1984 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1985 | ((c2 & 0x0F) << 2)
1986 | ((c3 & 0x30) >> 4));
1987 *++to_nxt = static_cast<uint16_t>(
1988 0xDC00
1989 | ((c3 & 0x0F) << 6)
1990 | (c4 & 0x3F));
1991 frm_nxt += 4;
1992 }
1993 else
1994 {
1995 return codecvt_base::error;
1996 }
1997 }
1998 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1999}
2000
2001static
2002codecvt_base::result
2003utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2004 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2005 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2006{
2007 frm_nxt = frm;
2008 to_nxt = to;
2009 if (mode & consume_header)
2010 {
2011 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2012 frm_nxt[2] == 0xBF)
2013 frm_nxt += 3;
2014 }
2015 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2016 {
2017 uint8_t c1 = *frm_nxt;
2018 if (c1 > Maxcode)
2019 return codecvt_base::error;
2020 if (c1 < 0x80)
2021 {
2022 *to_nxt = static_cast<uint32_t>(c1);
2023 ++frm_nxt;
2024 }
2025 else if (c1 < 0xC2)
2026 {
2027 return codecvt_base::error;
2028 }
2029 else if (c1 < 0xE0)
2030 {
2031 if (frm_end-frm_nxt < 2)
2032 return codecvt_base::partial;
2033 uint8_t c2 = frm_nxt[1];
2034 if ((c2 & 0xC0) != 0x80)
2035 return codecvt_base::error;
2036 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2037 if (t > Maxcode)
2038 return codecvt_base::error;
2039 *to_nxt = static_cast<uint32_t>(t);
2040 frm_nxt += 2;
2041 }
2042 else if (c1 < 0xF0)
2043 {
2044 if (frm_end-frm_nxt < 3)
2045 return codecvt_base::partial;
2046 uint8_t c2 = frm_nxt[1];
2047 uint8_t c3 = frm_nxt[2];
2048 switch (c1)
2049 {
2050 case 0xE0:
2051 if ((c2 & 0xE0) != 0xA0)
2052 return codecvt_base::error;
2053 break;
2054 case 0xED:
2055 if ((c2 & 0xE0) != 0x80)
2056 return codecvt_base::error;
2057 break;
2058 default:
2059 if ((c2 & 0xC0) != 0x80)
2060 return codecvt_base::error;
2061 break;
2062 }
2063 if ((c3 & 0xC0) != 0x80)
2064 return codecvt_base::error;
2065 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2066 | ((c2 & 0x3F) << 6)
2067 | (c3 & 0x3F));
2068 if (t > Maxcode)
2069 return codecvt_base::error;
2070 *to_nxt = static_cast<uint32_t>(t);
2071 frm_nxt += 3;
2072 }
2073 else if (c1 < 0xF5)
2074 {
2075 if (frm_end-frm_nxt < 4)
2076 return codecvt_base::partial;
2077 uint8_t c2 = frm_nxt[1];
2078 uint8_t c3 = frm_nxt[2];
2079 uint8_t c4 = frm_nxt[3];
2080 switch (c1)
2081 {
2082 case 0xF0:
2083 if (!(0x90 <= c2 && c2 <= 0xBF))
2084 return codecvt_base::error;
2085 break;
2086 case 0xF4:
2087 if ((c2 & 0xF0) != 0x80)
2088 return codecvt_base::error;
2089 break;
2090 default:
2091 if ((c2 & 0xC0) != 0x80)
2092 return codecvt_base::error;
2093 break;
2094 }
2095 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2096 return codecvt_base::error;
2097 if (to_end-to_nxt < 2)
2098 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002099 if ((((c1 & 7UL) << 18) +
2100 ((c2 & 0x3FUL) << 12) +
2101 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002102 return codecvt_base::error;
2103 *to_nxt = static_cast<uint32_t>(
2104 0xD800
2105 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2106 | ((c2 & 0x0F) << 2)
2107 | ((c3 & 0x30) >> 4));
2108 *++to_nxt = static_cast<uint32_t>(
2109 0xDC00
2110 | ((c3 & 0x0F) << 6)
2111 | (c4 & 0x3F));
2112 frm_nxt += 4;
2113 }
2114 else
2115 {
2116 return codecvt_base::error;
2117 }
2118 }
2119 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2120}
2121
2122static
2123int
2124utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2125 size_t mx, unsigned long Maxcode = 0x10FFFF,
2126 codecvt_mode mode = codecvt_mode(0))
2127{
2128 const uint8_t* frm_nxt = frm;
2129 if (mode & consume_header)
2130 {
2131 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2132 frm_nxt[2] == 0xBF)
2133 frm_nxt += 3;
2134 }
2135 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2136 {
2137 uint8_t c1 = *frm_nxt;
2138 if (c1 > Maxcode)
2139 break;
2140 if (c1 < 0x80)
2141 {
2142 ++frm_nxt;
2143 }
2144 else if (c1 < 0xC2)
2145 {
2146 break;
2147 }
2148 else if (c1 < 0xE0)
2149 {
2150 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2151 break;
2152 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2153 if (t > Maxcode)
2154 break;
2155 frm_nxt += 2;
2156 }
2157 else if (c1 < 0xF0)
2158 {
2159 if (frm_end-frm_nxt < 3)
2160 break;
2161 uint8_t c2 = frm_nxt[1];
2162 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002163 switch (c1)
2164 {
2165 case 0xE0:
2166 if ((c2 & 0xE0) != 0xA0)
2167 return static_cast<int>(frm_nxt - frm);
2168 break;
2169 case 0xED:
2170 if ((c2 & 0xE0) != 0x80)
2171 return static_cast<int>(frm_nxt - frm);
2172 break;
2173 default:
2174 if ((c2 & 0xC0) != 0x80)
2175 return static_cast<int>(frm_nxt - frm);
2176 break;
2177 }
2178 if ((c3 & 0xC0) != 0x80)
2179 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002180 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002181 break;
2182 frm_nxt += 3;
2183 }
2184 else if (c1 < 0xF5)
2185 {
2186 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2187 break;
2188 uint8_t c2 = frm_nxt[1];
2189 uint8_t c3 = frm_nxt[2];
2190 uint8_t c4 = frm_nxt[3];
2191 switch (c1)
2192 {
2193 case 0xF0:
2194 if (!(0x90 <= c2 && c2 <= 0xBF))
2195 return static_cast<int>(frm_nxt - frm);
2196 break;
2197 case 0xF4:
2198 if ((c2 & 0xF0) != 0x80)
2199 return static_cast<int>(frm_nxt - frm);
2200 break;
2201 default:
2202 if ((c2 & 0xC0) != 0x80)
2203 return static_cast<int>(frm_nxt - frm);
2204 break;
2205 }
2206 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2207 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002208 if ((((c1 & 7UL) << 18) +
2209 ((c2 & 0x3FUL) << 12) +
2210 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002211 break;
2212 ++nchar16_t;
2213 frm_nxt += 4;
2214 }
2215 else
2216 {
2217 break;
2218 }
2219 }
2220 return static_cast<int>(frm_nxt - frm);
2221}
2222
2223static
2224codecvt_base::result
2225ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2226 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2227 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2228{
2229 frm_nxt = frm;
2230 to_nxt = to;
2231 if (mode & generate_header)
2232 {
2233 if (to_end-to_nxt < 3)
2234 return codecvt_base::partial;
2235 *to_nxt++ = static_cast<uint8_t>(0xEF);
2236 *to_nxt++ = static_cast<uint8_t>(0xBB);
2237 *to_nxt++ = static_cast<uint8_t>(0xBF);
2238 }
2239 for (; frm_nxt < frm_end; ++frm_nxt)
2240 {
2241 uint32_t wc = *frm_nxt;
2242 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2243 return codecvt_base::error;
2244 if (wc < 0x000080)
2245 {
2246 if (to_end-to_nxt < 1)
2247 return codecvt_base::partial;
2248 *to_nxt++ = static_cast<uint8_t>(wc);
2249 }
2250 else if (wc < 0x000800)
2251 {
2252 if (to_end-to_nxt < 2)
2253 return codecvt_base::partial;
2254 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2255 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2256 }
2257 else if (wc < 0x010000)
2258 {
2259 if (to_end-to_nxt < 3)
2260 return codecvt_base::partial;
2261 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2262 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2263 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2264 }
2265 else // if (wc < 0x110000)
2266 {
2267 if (to_end-to_nxt < 4)
2268 return codecvt_base::partial;
2269 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2270 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2271 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2272 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2273 }
2274 }
2275 return codecvt_base::ok;
2276}
2277
2278static
2279codecvt_base::result
2280utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2281 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2282 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2283{
2284 frm_nxt = frm;
2285 to_nxt = to;
2286 if (mode & consume_header)
2287 {
2288 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2289 frm_nxt[2] == 0xBF)
2290 frm_nxt += 3;
2291 }
2292 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2293 {
2294 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2295 if (c1 < 0x80)
2296 {
2297 if (c1 > Maxcode)
2298 return codecvt_base::error;
2299 *to_nxt = static_cast<uint32_t>(c1);
2300 ++frm_nxt;
2301 }
2302 else if (c1 < 0xC2)
2303 {
2304 return codecvt_base::error;
2305 }
2306 else if (c1 < 0xE0)
2307 {
2308 if (frm_end-frm_nxt < 2)
2309 return codecvt_base::partial;
2310 uint8_t c2 = frm_nxt[1];
2311 if ((c2 & 0xC0) != 0x80)
2312 return codecvt_base::error;
2313 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2314 | (c2 & 0x3F));
2315 if (t > Maxcode)
2316 return codecvt_base::error;
2317 *to_nxt = t;
2318 frm_nxt += 2;
2319 }
2320 else if (c1 < 0xF0)
2321 {
2322 if (frm_end-frm_nxt < 3)
2323 return codecvt_base::partial;
2324 uint8_t c2 = frm_nxt[1];
2325 uint8_t c3 = frm_nxt[2];
2326 switch (c1)
2327 {
2328 case 0xE0:
2329 if ((c2 & 0xE0) != 0xA0)
2330 return codecvt_base::error;
2331 break;
2332 case 0xED:
2333 if ((c2 & 0xE0) != 0x80)
2334 return codecvt_base::error;
2335 break;
2336 default:
2337 if ((c2 & 0xC0) != 0x80)
2338 return codecvt_base::error;
2339 break;
2340 }
2341 if ((c3 & 0xC0) != 0x80)
2342 return codecvt_base::error;
2343 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2344 | ((c2 & 0x3F) << 6)
2345 | (c3 & 0x3F));
2346 if (t > Maxcode)
2347 return codecvt_base::error;
2348 *to_nxt = t;
2349 frm_nxt += 3;
2350 }
2351 else if (c1 < 0xF5)
2352 {
2353 if (frm_end-frm_nxt < 4)
2354 return codecvt_base::partial;
2355 uint8_t c2 = frm_nxt[1];
2356 uint8_t c3 = frm_nxt[2];
2357 uint8_t c4 = frm_nxt[3];
2358 switch (c1)
2359 {
2360 case 0xF0:
2361 if (!(0x90 <= c2 && c2 <= 0xBF))
2362 return codecvt_base::error;
2363 break;
2364 case 0xF4:
2365 if ((c2 & 0xF0) != 0x80)
2366 return codecvt_base::error;
2367 break;
2368 default:
2369 if ((c2 & 0xC0) != 0x80)
2370 return codecvt_base::error;
2371 break;
2372 }
2373 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2374 return codecvt_base::error;
2375 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2376 | ((c2 & 0x3F) << 12)
2377 | ((c3 & 0x3F) << 6)
2378 | (c4 & 0x3F));
2379 if (t > Maxcode)
2380 return codecvt_base::error;
2381 *to_nxt = t;
2382 frm_nxt += 4;
2383 }
2384 else
2385 {
2386 return codecvt_base::error;
2387 }
2388 }
2389 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2390}
2391
2392static
2393int
2394utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2395 size_t mx, unsigned long Maxcode = 0x10FFFF,
2396 codecvt_mode mode = codecvt_mode(0))
2397{
2398 const uint8_t* frm_nxt = frm;
2399 if (mode & consume_header)
2400 {
2401 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2402 frm_nxt[2] == 0xBF)
2403 frm_nxt += 3;
2404 }
2405 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2406 {
2407 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2408 if (c1 < 0x80)
2409 {
2410 if (c1 > Maxcode)
2411 break;
2412 ++frm_nxt;
2413 }
2414 else if (c1 < 0xC2)
2415 {
2416 break;
2417 }
2418 else if (c1 < 0xE0)
2419 {
2420 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2421 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002422 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002423 break;
2424 frm_nxt += 2;
2425 }
2426 else if (c1 < 0xF0)
2427 {
2428 if (frm_end-frm_nxt < 3)
2429 break;
2430 uint8_t c2 = frm_nxt[1];
2431 uint8_t c3 = frm_nxt[2];
2432 switch (c1)
2433 {
2434 case 0xE0:
2435 if ((c2 & 0xE0) != 0xA0)
2436 return static_cast<int>(frm_nxt - frm);
2437 break;
2438 case 0xED:
2439 if ((c2 & 0xE0) != 0x80)
2440 return static_cast<int>(frm_nxt - frm);
2441 break;
2442 default:
2443 if ((c2 & 0xC0) != 0x80)
2444 return static_cast<int>(frm_nxt - frm);
2445 break;
2446 }
2447 if ((c3 & 0xC0) != 0x80)
2448 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002449 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002450 break;
2451 frm_nxt += 3;
2452 }
2453 else if (c1 < 0xF5)
2454 {
2455 if (frm_end-frm_nxt < 4)
2456 break;
2457 uint8_t c2 = frm_nxt[1];
2458 uint8_t c3 = frm_nxt[2];
2459 uint8_t c4 = frm_nxt[3];
2460 switch (c1)
2461 {
2462 case 0xF0:
2463 if (!(0x90 <= c2 && c2 <= 0xBF))
2464 return static_cast<int>(frm_nxt - frm);
2465 break;
2466 case 0xF4:
2467 if ((c2 & 0xF0) != 0x80)
2468 return static_cast<int>(frm_nxt - frm);
2469 break;
2470 default:
2471 if ((c2 & 0xC0) != 0x80)
2472 return static_cast<int>(frm_nxt - frm);
2473 break;
2474 }
2475 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2476 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002477 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2478 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002479 break;
2480 frm_nxt += 4;
2481 }
2482 else
2483 {
2484 break;
2485 }
2486 }
2487 return static_cast<int>(frm_nxt - frm);
2488}
2489
2490static
2491codecvt_base::result
2492ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2493 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2494 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2495{
2496 frm_nxt = frm;
2497 to_nxt = to;
2498 if (mode & generate_header)
2499 {
2500 if (to_end-to_nxt < 3)
2501 return codecvt_base::partial;
2502 *to_nxt++ = static_cast<uint8_t>(0xEF);
2503 *to_nxt++ = static_cast<uint8_t>(0xBB);
2504 *to_nxt++ = static_cast<uint8_t>(0xBF);
2505 }
2506 for (; frm_nxt < frm_end; ++frm_nxt)
2507 {
2508 uint16_t wc = *frm_nxt;
2509 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2510 return codecvt_base::error;
2511 if (wc < 0x0080)
2512 {
2513 if (to_end-to_nxt < 1)
2514 return codecvt_base::partial;
2515 *to_nxt++ = static_cast<uint8_t>(wc);
2516 }
2517 else if (wc < 0x0800)
2518 {
2519 if (to_end-to_nxt < 2)
2520 return codecvt_base::partial;
2521 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2522 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2523 }
2524 else // if (wc <= 0xFFFF)
2525 {
2526 if (to_end-to_nxt < 3)
2527 return codecvt_base::partial;
2528 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2529 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2530 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2531 }
2532 }
2533 return codecvt_base::ok;
2534}
2535
2536static
2537codecvt_base::result
2538utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2539 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2540 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2541{
2542 frm_nxt = frm;
2543 to_nxt = to;
2544 if (mode & consume_header)
2545 {
2546 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2547 frm_nxt[2] == 0xBF)
2548 frm_nxt += 3;
2549 }
2550 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2551 {
2552 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2553 if (c1 < 0x80)
2554 {
2555 if (c1 > Maxcode)
2556 return codecvt_base::error;
2557 *to_nxt = static_cast<uint16_t>(c1);
2558 ++frm_nxt;
2559 }
2560 else if (c1 < 0xC2)
2561 {
2562 return codecvt_base::error;
2563 }
2564 else if (c1 < 0xE0)
2565 {
2566 if (frm_end-frm_nxt < 2)
2567 return codecvt_base::partial;
2568 uint8_t c2 = frm_nxt[1];
2569 if ((c2 & 0xC0) != 0x80)
2570 return codecvt_base::error;
2571 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2572 | (c2 & 0x3F));
2573 if (t > Maxcode)
2574 return codecvt_base::error;
2575 *to_nxt = t;
2576 frm_nxt += 2;
2577 }
2578 else if (c1 < 0xF0)
2579 {
2580 if (frm_end-frm_nxt < 3)
2581 return codecvt_base::partial;
2582 uint8_t c2 = frm_nxt[1];
2583 uint8_t c3 = frm_nxt[2];
2584 switch (c1)
2585 {
2586 case 0xE0:
2587 if ((c2 & 0xE0) != 0xA0)
2588 return codecvt_base::error;
2589 break;
2590 case 0xED:
2591 if ((c2 & 0xE0) != 0x80)
2592 return codecvt_base::error;
2593 break;
2594 default:
2595 if ((c2 & 0xC0) != 0x80)
2596 return codecvt_base::error;
2597 break;
2598 }
2599 if ((c3 & 0xC0) != 0x80)
2600 return codecvt_base::error;
2601 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2602 | ((c2 & 0x3F) << 6)
2603 | (c3 & 0x3F));
2604 if (t > Maxcode)
2605 return codecvt_base::error;
2606 *to_nxt = t;
2607 frm_nxt += 3;
2608 }
2609 else
2610 {
2611 return codecvt_base::error;
2612 }
2613 }
2614 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2615}
2616
2617static
2618int
2619utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2620 size_t mx, unsigned long Maxcode = 0x10FFFF,
2621 codecvt_mode mode = codecvt_mode(0))
2622{
2623 const uint8_t* frm_nxt = frm;
2624 if (mode & consume_header)
2625 {
2626 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2627 frm_nxt[2] == 0xBF)
2628 frm_nxt += 3;
2629 }
2630 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2631 {
2632 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2633 if (c1 < 0x80)
2634 {
2635 if (c1 > Maxcode)
2636 break;
2637 ++frm_nxt;
2638 }
2639 else if (c1 < 0xC2)
2640 {
2641 break;
2642 }
2643 else if (c1 < 0xE0)
2644 {
2645 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2646 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002647 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002648 break;
2649 frm_nxt += 2;
2650 }
2651 else if (c1 < 0xF0)
2652 {
2653 if (frm_end-frm_nxt < 3)
2654 break;
2655 uint8_t c2 = frm_nxt[1];
2656 uint8_t c3 = frm_nxt[2];
2657 switch (c1)
2658 {
2659 case 0xE0:
2660 if ((c2 & 0xE0) != 0xA0)
2661 return static_cast<int>(frm_nxt - frm);
2662 break;
2663 case 0xED:
2664 if ((c2 & 0xE0) != 0x80)
2665 return static_cast<int>(frm_nxt - frm);
2666 break;
2667 default:
2668 if ((c2 & 0xC0) != 0x80)
2669 return static_cast<int>(frm_nxt - frm);
2670 break;
2671 }
2672 if ((c3 & 0xC0) != 0x80)
2673 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002674 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002675 break;
2676 frm_nxt += 3;
2677 }
2678 else
2679 {
2680 break;
2681 }
2682 }
2683 return static_cast<int>(frm_nxt - frm);
2684}
2685
2686static
2687codecvt_base::result
2688ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2689 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2690 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2691{
2692 frm_nxt = frm;
2693 to_nxt = to;
2694 if (mode & generate_header)
2695 {
2696 if (to_end-to_nxt < 2)
2697 return codecvt_base::partial;
2698 *to_nxt++ = static_cast<uint8_t>(0xFE);
2699 *to_nxt++ = static_cast<uint8_t>(0xFF);
2700 }
2701 for (; frm_nxt < frm_end; ++frm_nxt)
2702 {
2703 uint32_t wc = *frm_nxt;
2704 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2705 return codecvt_base::error;
2706 if (wc < 0x010000)
2707 {
2708 if (to_end-to_nxt < 2)
2709 return codecvt_base::partial;
2710 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2711 *to_nxt++ = static_cast<uint8_t>(wc);
2712 }
2713 else
2714 {
2715 if (to_end-to_nxt < 4)
2716 return codecvt_base::partial;
2717 uint16_t t = static_cast<uint16_t>(
2718 0xD800
2719 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2720 | ((wc & 0x00FC00) >> 10));
2721 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2722 *to_nxt++ = static_cast<uint8_t>(t);
2723 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2724 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2725 *to_nxt++ = static_cast<uint8_t>(t);
2726 }
2727 }
2728 return codecvt_base::ok;
2729}
2730
2731static
2732codecvt_base::result
2733utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2734 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2735 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2736{
2737 frm_nxt = frm;
2738 to_nxt = to;
2739 if (mode & consume_header)
2740 {
2741 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2742 frm_nxt += 2;
2743 }
2744 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2745 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002746 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002747 if ((c1 & 0xFC00) == 0xDC00)
2748 return codecvt_base::error;
2749 if ((c1 & 0xFC00) != 0xD800)
2750 {
2751 if (c1 > Maxcode)
2752 return codecvt_base::error;
2753 *to_nxt = static_cast<uint32_t>(c1);
2754 frm_nxt += 2;
2755 }
2756 else
2757 {
2758 if (frm_end-frm_nxt < 4)
2759 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002760 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002761 if ((c2 & 0xFC00) != 0xDC00)
2762 return codecvt_base::error;
2763 uint32_t t = static_cast<uint32_t>(
2764 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2765 | ((c1 & 0x003F) << 10)
2766 | (c2 & 0x03FF));
2767 if (t > Maxcode)
2768 return codecvt_base::error;
2769 *to_nxt = t;
2770 frm_nxt += 4;
2771 }
2772 }
2773 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2774}
2775
2776static
2777int
2778utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2779 size_t mx, unsigned long Maxcode = 0x10FFFF,
2780 codecvt_mode mode = codecvt_mode(0))
2781{
2782 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002783 if (mode & consume_header)
2784 {
2785 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2786 frm_nxt += 2;
2787 }
2788 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2789 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002790 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002791 if ((c1 & 0xFC00) == 0xDC00)
2792 break;
2793 if ((c1 & 0xFC00) != 0xD800)
2794 {
2795 if (c1 > Maxcode)
2796 break;
2797 frm_nxt += 2;
2798 }
2799 else
2800 {
2801 if (frm_end-frm_nxt < 4)
2802 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002803 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002804 if ((c2 & 0xFC00) != 0xDC00)
2805 break;
2806 uint32_t t = static_cast<uint32_t>(
2807 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2808 | ((c1 & 0x003F) << 10)
2809 | (c2 & 0x03FF));
2810 if (t > Maxcode)
2811 break;
2812 frm_nxt += 4;
2813 }
2814 }
2815 return static_cast<int>(frm_nxt - frm);
2816}
2817
2818static
2819codecvt_base::result
2820ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2821 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2822 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2823{
2824 frm_nxt = frm;
2825 to_nxt = to;
2826 if (mode & generate_header)
2827 {
Eric Fiselier6585c752016-04-21 22:54:21 +00002828 if (to_end - to_nxt < 2)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002829 return codecvt_base::partial;
Eric Fiselier6585c752016-04-21 22:54:21 +00002830 *to_nxt++ = static_cast<uint8_t>(0xFF);
2831 *to_nxt++ = static_cast<uint8_t>(0xFE);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002832 }
2833 for (; frm_nxt < frm_end; ++frm_nxt)
2834 {
2835 uint32_t wc = *frm_nxt;
2836 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2837 return codecvt_base::error;
2838 if (wc < 0x010000)
2839 {
2840 if (to_end-to_nxt < 2)
2841 return codecvt_base::partial;
2842 *to_nxt++ = static_cast<uint8_t>(wc);
2843 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2844 }
2845 else
2846 {
2847 if (to_end-to_nxt < 4)
2848 return codecvt_base::partial;
2849 uint16_t t = static_cast<uint16_t>(
2850 0xD800
2851 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2852 | ((wc & 0x00FC00) >> 10));
2853 *to_nxt++ = static_cast<uint8_t>(t);
2854 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2855 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2856 *to_nxt++ = static_cast<uint8_t>(t);
2857 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2858 }
2859 }
2860 return codecvt_base::ok;
2861}
2862
2863static
2864codecvt_base::result
2865utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2866 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2867 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2868{
2869 frm_nxt = frm;
2870 to_nxt = to;
2871 if (mode & consume_header)
2872 {
2873 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2874 frm_nxt += 2;
2875 }
2876 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2877 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002878 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002879 if ((c1 & 0xFC00) == 0xDC00)
2880 return codecvt_base::error;
2881 if ((c1 & 0xFC00) != 0xD800)
2882 {
2883 if (c1 > Maxcode)
2884 return codecvt_base::error;
2885 *to_nxt = static_cast<uint32_t>(c1);
2886 frm_nxt += 2;
2887 }
2888 else
2889 {
2890 if (frm_end-frm_nxt < 4)
2891 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002892 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002893 if ((c2 & 0xFC00) != 0xDC00)
2894 return codecvt_base::error;
2895 uint32_t t = static_cast<uint32_t>(
2896 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2897 | ((c1 & 0x003F) << 10)
2898 | (c2 & 0x03FF));
2899 if (t > Maxcode)
2900 return codecvt_base::error;
2901 *to_nxt = t;
2902 frm_nxt += 4;
2903 }
2904 }
2905 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2906}
2907
2908static
2909int
2910utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2911 size_t mx, unsigned long Maxcode = 0x10FFFF,
2912 codecvt_mode mode = codecvt_mode(0))
2913{
2914 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002915 if (mode & consume_header)
2916 {
2917 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2918 frm_nxt += 2;
2919 }
2920 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2921 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002922 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002923 if ((c1 & 0xFC00) == 0xDC00)
2924 break;
2925 if ((c1 & 0xFC00) != 0xD800)
2926 {
2927 if (c1 > Maxcode)
2928 break;
2929 frm_nxt += 2;
2930 }
2931 else
2932 {
2933 if (frm_end-frm_nxt < 4)
2934 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002935 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002936 if ((c2 & 0xFC00) != 0xDC00)
2937 break;
2938 uint32_t t = static_cast<uint32_t>(
2939 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2940 | ((c1 & 0x003F) << 10)
2941 | (c2 & 0x03FF));
2942 if (t > Maxcode)
2943 break;
2944 frm_nxt += 4;
2945 }
2946 }
2947 return static_cast<int>(frm_nxt - frm);
2948}
2949
2950static
2951codecvt_base::result
2952ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2953 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2954 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2955{
2956 frm_nxt = frm;
2957 to_nxt = to;
2958 if (mode & generate_header)
2959 {
2960 if (to_end-to_nxt < 2)
2961 return codecvt_base::partial;
2962 *to_nxt++ = static_cast<uint8_t>(0xFE);
2963 *to_nxt++ = static_cast<uint8_t>(0xFF);
2964 }
2965 for (; frm_nxt < frm_end; ++frm_nxt)
2966 {
2967 uint16_t wc = *frm_nxt;
2968 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2969 return codecvt_base::error;
2970 if (to_end-to_nxt < 2)
2971 return codecvt_base::partial;
2972 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2973 *to_nxt++ = static_cast<uint8_t>(wc);
2974 }
2975 return codecvt_base::ok;
2976}
2977
2978static
2979codecvt_base::result
2980utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2981 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2982 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2983{
2984 frm_nxt = frm;
2985 to_nxt = to;
2986 if (mode & consume_header)
2987 {
2988 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2989 frm_nxt += 2;
2990 }
2991 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2992 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002993 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002994 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2995 return codecvt_base::error;
2996 *to_nxt = c1;
2997 frm_nxt += 2;
2998 }
2999 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3000}
3001
3002static
3003int
3004utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3005 size_t mx, unsigned long Maxcode = 0x10FFFF,
3006 codecvt_mode mode = codecvt_mode(0))
3007{
3008 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003009 if (mode & consume_header)
3010 {
3011 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3012 frm_nxt += 2;
3013 }
3014 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3015 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003016 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003017 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3018 break;
3019 frm_nxt += 2;
3020 }
3021 return static_cast<int>(frm_nxt - frm);
3022}
3023
3024static
3025codecvt_base::result
3026ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3027 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3028 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3029{
3030 frm_nxt = frm;
3031 to_nxt = to;
3032 if (mode & generate_header)
3033 {
3034 if (to_end-to_nxt < 2)
3035 return codecvt_base::partial;
3036 *to_nxt++ = static_cast<uint8_t>(0xFF);
3037 *to_nxt++ = static_cast<uint8_t>(0xFE);
3038 }
3039 for (; frm_nxt < frm_end; ++frm_nxt)
3040 {
3041 uint16_t wc = *frm_nxt;
3042 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3043 return codecvt_base::error;
3044 if (to_end-to_nxt < 2)
3045 return codecvt_base::partial;
3046 *to_nxt++ = static_cast<uint8_t>(wc);
3047 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3048 }
3049 return codecvt_base::ok;
3050}
3051
3052static
3053codecvt_base::result
3054utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3055 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3056 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3057{
3058 frm_nxt = frm;
3059 to_nxt = to;
3060 if (mode & consume_header)
3061 {
3062 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3063 frm_nxt += 2;
3064 }
3065 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3066 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003067 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003068 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3069 return codecvt_base::error;
3070 *to_nxt = c1;
3071 frm_nxt += 2;
3072 }
3073 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3074}
3075
3076static
3077int
3078utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3079 size_t mx, unsigned long Maxcode = 0x10FFFF,
3080 codecvt_mode mode = codecvt_mode(0))
3081{
3082 const uint8_t* frm_nxt = frm;
3083 frm_nxt = frm;
3084 if (mode & consume_header)
3085 {
3086 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3087 frm_nxt += 2;
3088 }
3089 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3090 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003091 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003092 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3093 break;
3094 frm_nxt += 2;
3095 }
3096 return static_cast<int>(frm_nxt - frm);
3097}
3098
Howard Hinnantc51e1022010-05-11 19:42:16 +00003099// template <> class codecvt<char16_t, char, mbstate_t>
3100
Howard Hinnantffb308e2010-08-22 00:03:27 +00003101locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003102
3103codecvt<char16_t, char, mbstate_t>::~codecvt()
3104{
3105}
3106
3107codecvt<char16_t, char, mbstate_t>::result
3108codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003109 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003110 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3111{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003112 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3113 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3114 const uint16_t* _frm_nxt = _frm;
3115 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3116 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3117 uint8_t* _to_nxt = _to;
3118 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3119 frm_nxt = frm + (_frm_nxt - _frm);
3120 to_nxt = to + (_to_nxt - _to);
3121 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003122}
3123
3124codecvt<char16_t, char, mbstate_t>::result
3125codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003126 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003127 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3128{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003129 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3130 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3131 const uint8_t* _frm_nxt = _frm;
3132 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3133 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3134 uint16_t* _to_nxt = _to;
3135 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3136 frm_nxt = frm + (_frm_nxt - _frm);
3137 to_nxt = to + (_to_nxt - _to);
3138 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003139}
3140
3141codecvt<char16_t, char, mbstate_t>::result
3142codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3143 extern_type* to, extern_type*, extern_type*& to_nxt) const
3144{
3145 to_nxt = to;
3146 return noconv;
3147}
3148
3149int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003150codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003151{
3152 return 0;
3153}
3154
3155bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003156codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003157{
3158 return false;
3159}
3160
3161int
3162codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3163 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3164{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003165 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3166 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3167 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003168}
3169
3170int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003171codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003172{
3173 return 4;
3174}
3175
3176// template <> class codecvt<char32_t, char, mbstate_t>
3177
Howard Hinnantffb308e2010-08-22 00:03:27 +00003178locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003179
3180codecvt<char32_t, char, mbstate_t>::~codecvt()
3181{
3182}
3183
3184codecvt<char32_t, char, mbstate_t>::result
3185codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003186 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003187 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3188{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003189 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3190 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3191 const uint32_t* _frm_nxt = _frm;
3192 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3193 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3194 uint8_t* _to_nxt = _to;
3195 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3196 frm_nxt = frm + (_frm_nxt - _frm);
3197 to_nxt = to + (_to_nxt - _to);
3198 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003199}
3200
3201codecvt<char32_t, char, mbstate_t>::result
3202codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003203 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003204 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3205{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003206 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3207 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3208 const uint8_t* _frm_nxt = _frm;
3209 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3210 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3211 uint32_t* _to_nxt = _to;
3212 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3213 frm_nxt = frm + (_frm_nxt - _frm);
3214 to_nxt = to + (_to_nxt - _to);
3215 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003216}
3217
3218codecvt<char32_t, char, mbstate_t>::result
3219codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3220 extern_type* to, extern_type*, extern_type*& to_nxt) const
3221{
3222 to_nxt = to;
3223 return noconv;
3224}
3225
3226int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003227codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003228{
3229 return 0;
3230}
3231
3232bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003233codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003234{
3235 return false;
3236}
3237
3238int
3239codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3240 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3241{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003242 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3243 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3244 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003245}
3246
3247int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003248codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003249{
3250 return 4;
3251}
3252
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003253// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003254
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003255__codecvt_utf8<wchar_t>::result
3256__codecvt_utf8<wchar_t>::do_out(state_type&,
3257 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003258 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3259{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003260#if _WIN32
3261 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3262 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3263 const uint16_t* _frm_nxt = _frm;
3264#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003265 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3266 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3267 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003268#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003269 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3270 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3271 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003272#if _WIN32
3273 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3274 _Maxcode_, _Mode_);
3275#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003276 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3277 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003278#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003279 frm_nxt = frm + (_frm_nxt - _frm);
3280 to_nxt = to + (_to_nxt - _to);
3281 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003282}
3283
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003284__codecvt_utf8<wchar_t>::result
3285__codecvt_utf8<wchar_t>::do_in(state_type&,
3286 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003287 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3288{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003289 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3290 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3291 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003292#if _WIN32
3293 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3294 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3295 uint16_t* _to_nxt = _to;
3296 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3297 _Maxcode_, _Mode_);
3298#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003299 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3300 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3301 uint32_t* _to_nxt = _to;
3302 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3303 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003304#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003305 frm_nxt = frm + (_frm_nxt - _frm);
3306 to_nxt = to + (_to_nxt - _to);
3307 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003308}
3309
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003310__codecvt_utf8<wchar_t>::result
3311__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003312 extern_type* to, extern_type*, extern_type*& to_nxt) const
3313{
3314 to_nxt = to;
3315 return noconv;
3316}
3317
3318int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003319__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003320{
3321 return 0;
3322}
3323
3324bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003325__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003326{
3327 return false;
3328}
3329
3330int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003331__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003332 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3333{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003334 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3335 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3336 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003337}
3338
3339int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003340__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003341{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003342 if (_Mode_ & consume_header)
3343 return 7;
3344 return 4;
3345}
3346
3347// __codecvt_utf8<char16_t>
3348
3349__codecvt_utf8<char16_t>::result
3350__codecvt_utf8<char16_t>::do_out(state_type&,
3351 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3352 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3353{
3354 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3355 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3356 const uint16_t* _frm_nxt = _frm;
3357 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3358 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3359 uint8_t* _to_nxt = _to;
3360 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3361 _Maxcode_, _Mode_);
3362 frm_nxt = frm + (_frm_nxt - _frm);
3363 to_nxt = to + (_to_nxt - _to);
3364 return r;
3365}
3366
3367__codecvt_utf8<char16_t>::result
3368__codecvt_utf8<char16_t>::do_in(state_type&,
3369 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3370 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3371{
3372 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3373 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3374 const uint8_t* _frm_nxt = _frm;
3375 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3376 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3377 uint16_t* _to_nxt = _to;
3378 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3379 _Maxcode_, _Mode_);
3380 frm_nxt = frm + (_frm_nxt - _frm);
3381 to_nxt = to + (_to_nxt - _to);
3382 return r;
3383}
3384
3385__codecvt_utf8<char16_t>::result
3386__codecvt_utf8<char16_t>::do_unshift(state_type&,
3387 extern_type* to, extern_type*, extern_type*& to_nxt) const
3388{
3389 to_nxt = to;
3390 return noconv;
3391}
3392
3393int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003394__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003395{
3396 return 0;
3397}
3398
3399bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003400__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003401{
3402 return false;
3403}
3404
3405int
3406__codecvt_utf8<char16_t>::do_length(state_type&,
3407 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3408{
3409 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3410 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3411 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3412}
3413
3414int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003415__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003416{
3417 if (_Mode_ & consume_header)
3418 return 6;
3419 return 3;
3420}
3421
3422// __codecvt_utf8<char32_t>
3423
3424__codecvt_utf8<char32_t>::result
3425__codecvt_utf8<char32_t>::do_out(state_type&,
3426 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3427 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3428{
3429 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3430 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3431 const uint32_t* _frm_nxt = _frm;
3432 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3433 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3434 uint8_t* _to_nxt = _to;
3435 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3436 _Maxcode_, _Mode_);
3437 frm_nxt = frm + (_frm_nxt - _frm);
3438 to_nxt = to + (_to_nxt - _to);
3439 return r;
3440}
3441
3442__codecvt_utf8<char32_t>::result
3443__codecvt_utf8<char32_t>::do_in(state_type&,
3444 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3445 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3446{
3447 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3448 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3449 const uint8_t* _frm_nxt = _frm;
3450 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3451 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3452 uint32_t* _to_nxt = _to;
3453 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3454 _Maxcode_, _Mode_);
3455 frm_nxt = frm + (_frm_nxt - _frm);
3456 to_nxt = to + (_to_nxt - _to);
3457 return r;
3458}
3459
3460__codecvt_utf8<char32_t>::result
3461__codecvt_utf8<char32_t>::do_unshift(state_type&,
3462 extern_type* to, extern_type*, extern_type*& to_nxt) const
3463{
3464 to_nxt = to;
3465 return noconv;
3466}
3467
3468int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003469__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003470{
3471 return 0;
3472}
3473
3474bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003475__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003476{
3477 return false;
3478}
3479
3480int
3481__codecvt_utf8<char32_t>::do_length(state_type&,
3482 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3483{
3484 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3485 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3486 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3487}
3488
3489int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003490__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003491{
3492 if (_Mode_ & consume_header)
3493 return 7;
3494 return 4;
3495}
3496
3497// __codecvt_utf16<wchar_t, false>
3498
3499__codecvt_utf16<wchar_t, false>::result
3500__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3501 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3502 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3503{
3504 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3505 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3506 const uint32_t* _frm_nxt = _frm;
3507 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3508 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3509 uint8_t* _to_nxt = _to;
3510 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3511 _Maxcode_, _Mode_);
3512 frm_nxt = frm + (_frm_nxt - _frm);
3513 to_nxt = to + (_to_nxt - _to);
3514 return r;
3515}
3516
3517__codecvt_utf16<wchar_t, false>::result
3518__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3519 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3520 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3521{
3522 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3523 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3524 const uint8_t* _frm_nxt = _frm;
3525 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3526 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3527 uint32_t* _to_nxt = _to;
3528 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3529 _Maxcode_, _Mode_);
3530 frm_nxt = frm + (_frm_nxt - _frm);
3531 to_nxt = to + (_to_nxt - _to);
3532 return r;
3533}
3534
3535__codecvt_utf16<wchar_t, false>::result
3536__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3537 extern_type* to, extern_type*, extern_type*& to_nxt) const
3538{
3539 to_nxt = to;
3540 return noconv;
3541}
3542
3543int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003544__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003545{
3546 return 0;
3547}
3548
3549bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003550__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003551{
3552 return false;
3553}
3554
3555int
3556__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3557 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3558{
3559 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3560 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3561 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3562}
3563
3564int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003565__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003566{
3567 if (_Mode_ & consume_header)
3568 return 6;
3569 return 4;
3570}
3571
3572// __codecvt_utf16<wchar_t, true>
3573
3574__codecvt_utf16<wchar_t, true>::result
3575__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3576 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3577 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3578{
3579 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3580 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3581 const uint32_t* _frm_nxt = _frm;
3582 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3583 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3584 uint8_t* _to_nxt = _to;
3585 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3586 _Maxcode_, _Mode_);
3587 frm_nxt = frm + (_frm_nxt - _frm);
3588 to_nxt = to + (_to_nxt - _to);
3589 return r;
3590}
3591
3592__codecvt_utf16<wchar_t, true>::result
3593__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3594 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3595 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3596{
3597 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3598 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3599 const uint8_t* _frm_nxt = _frm;
3600 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3601 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3602 uint32_t* _to_nxt = _to;
3603 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3604 _Maxcode_, _Mode_);
3605 frm_nxt = frm + (_frm_nxt - _frm);
3606 to_nxt = to + (_to_nxt - _to);
3607 return r;
3608}
3609
3610__codecvt_utf16<wchar_t, true>::result
3611__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3612 extern_type* to, extern_type*, extern_type*& to_nxt) const
3613{
3614 to_nxt = to;
3615 return noconv;
3616}
3617
3618int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003619__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003620{
3621 return 0;
3622}
3623
3624bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003625__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003626{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003627 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003628}
3629
3630int
3631__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3632 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3633{
3634 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3635 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3636 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3637}
3638
3639int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003640__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003641{
3642 if (_Mode_ & consume_header)
3643 return 6;
3644 return 4;
3645}
3646
3647// __codecvt_utf16<char16_t, false>
3648
3649__codecvt_utf16<char16_t, false>::result
3650__codecvt_utf16<char16_t, false>::do_out(state_type&,
3651 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3652 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3653{
3654 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3655 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3656 const uint16_t* _frm_nxt = _frm;
3657 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3658 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3659 uint8_t* _to_nxt = _to;
3660 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3661 _Maxcode_, _Mode_);
3662 frm_nxt = frm + (_frm_nxt - _frm);
3663 to_nxt = to + (_to_nxt - _to);
3664 return r;
3665}
3666
3667__codecvt_utf16<char16_t, false>::result
3668__codecvt_utf16<char16_t, false>::do_in(state_type&,
3669 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3670 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3671{
3672 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3673 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3674 const uint8_t* _frm_nxt = _frm;
3675 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3676 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3677 uint16_t* _to_nxt = _to;
3678 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3679 _Maxcode_, _Mode_);
3680 frm_nxt = frm + (_frm_nxt - _frm);
3681 to_nxt = to + (_to_nxt - _to);
3682 return r;
3683}
3684
3685__codecvt_utf16<char16_t, false>::result
3686__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3687 extern_type* to, extern_type*, extern_type*& to_nxt) const
3688{
3689 to_nxt = to;
3690 return noconv;
3691}
3692
3693int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003694__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003695{
3696 return 0;
3697}
3698
3699bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003700__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003701{
3702 return false;
3703}
3704
3705int
3706__codecvt_utf16<char16_t, false>::do_length(state_type&,
3707 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3708{
3709 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3710 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3711 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3712}
3713
3714int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003715__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003716{
3717 if (_Mode_ & consume_header)
3718 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003719 return 2;
3720}
3721
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003722// __codecvt_utf16<char16_t, true>
3723
3724__codecvt_utf16<char16_t, true>::result
3725__codecvt_utf16<char16_t, true>::do_out(state_type&,
3726 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3727 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3728{
3729 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3730 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3731 const uint16_t* _frm_nxt = _frm;
3732 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3733 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3734 uint8_t* _to_nxt = _to;
3735 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3736 _Maxcode_, _Mode_);
3737 frm_nxt = frm + (_frm_nxt - _frm);
3738 to_nxt = to + (_to_nxt - _to);
3739 return r;
3740}
3741
3742__codecvt_utf16<char16_t, true>::result
3743__codecvt_utf16<char16_t, true>::do_in(state_type&,
3744 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3745 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3746{
3747 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3748 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3749 const uint8_t* _frm_nxt = _frm;
3750 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3751 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3752 uint16_t* _to_nxt = _to;
3753 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3754 _Maxcode_, _Mode_);
3755 frm_nxt = frm + (_frm_nxt - _frm);
3756 to_nxt = to + (_to_nxt - _to);
3757 return r;
3758}
3759
3760__codecvt_utf16<char16_t, true>::result
3761__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3762 extern_type* to, extern_type*, extern_type*& to_nxt) const
3763{
3764 to_nxt = to;
3765 return noconv;
3766}
3767
3768int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003769__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003770{
3771 return 0;
3772}
3773
3774bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003775__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003776{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003777 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003778}
3779
3780int
3781__codecvt_utf16<char16_t, true>::do_length(state_type&,
3782 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3783{
3784 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3785 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3786 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3787}
3788
3789int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003790__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003791{
3792 if (_Mode_ & consume_header)
3793 return 4;
3794 return 2;
3795}
3796
3797// __codecvt_utf16<char32_t, false>
3798
3799__codecvt_utf16<char32_t, false>::result
3800__codecvt_utf16<char32_t, false>::do_out(state_type&,
3801 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3802 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3803{
3804 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3805 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3806 const uint32_t* _frm_nxt = _frm;
3807 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3808 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3809 uint8_t* _to_nxt = _to;
3810 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3811 _Maxcode_, _Mode_);
3812 frm_nxt = frm + (_frm_nxt - _frm);
3813 to_nxt = to + (_to_nxt - _to);
3814 return r;
3815}
3816
3817__codecvt_utf16<char32_t, false>::result
3818__codecvt_utf16<char32_t, false>::do_in(state_type&,
3819 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3820 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3821{
3822 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3823 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3824 const uint8_t* _frm_nxt = _frm;
3825 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3826 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3827 uint32_t* _to_nxt = _to;
3828 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3829 _Maxcode_, _Mode_);
3830 frm_nxt = frm + (_frm_nxt - _frm);
3831 to_nxt = to + (_to_nxt - _to);
3832 return r;
3833}
3834
3835__codecvt_utf16<char32_t, false>::result
3836__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3837 extern_type* to, extern_type*, extern_type*& to_nxt) const
3838{
3839 to_nxt = to;
3840 return noconv;
3841}
3842
3843int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003844__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003845{
3846 return 0;
3847}
3848
3849bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003850__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003851{
3852 return false;
3853}
3854
3855int
3856__codecvt_utf16<char32_t, false>::do_length(state_type&,
3857 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3858{
3859 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3860 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3861 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3862}
3863
3864int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003865__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003866{
3867 if (_Mode_ & consume_header)
3868 return 6;
3869 return 4;
3870}
3871
3872// __codecvt_utf16<char32_t, true>
3873
3874__codecvt_utf16<char32_t, true>::result
3875__codecvt_utf16<char32_t, true>::do_out(state_type&,
3876 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3877 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3878{
3879 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3880 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3881 const uint32_t* _frm_nxt = _frm;
3882 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3883 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3884 uint8_t* _to_nxt = _to;
3885 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3886 _Maxcode_, _Mode_);
3887 frm_nxt = frm + (_frm_nxt - _frm);
3888 to_nxt = to + (_to_nxt - _to);
3889 return r;
3890}
3891
3892__codecvt_utf16<char32_t, true>::result
3893__codecvt_utf16<char32_t, true>::do_in(state_type&,
3894 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3895 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3896{
3897 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3898 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3899 const uint8_t* _frm_nxt = _frm;
3900 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3901 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3902 uint32_t* _to_nxt = _to;
3903 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3904 _Maxcode_, _Mode_);
3905 frm_nxt = frm + (_frm_nxt - _frm);
3906 to_nxt = to + (_to_nxt - _to);
3907 return r;
3908}
3909
3910__codecvt_utf16<char32_t, true>::result
3911__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3912 extern_type* to, extern_type*, extern_type*& to_nxt) const
3913{
3914 to_nxt = to;
3915 return noconv;
3916}
3917
3918int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003919__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003920{
3921 return 0;
3922}
3923
3924bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003925__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003926{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003927 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003928}
3929
3930int
3931__codecvt_utf16<char32_t, true>::do_length(state_type&,
3932 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3933{
3934 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3935 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3936 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3937}
3938
3939int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003940__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003941{
3942 if (_Mode_ & consume_header)
3943 return 6;
3944 return 4;
3945}
3946
3947// __codecvt_utf8_utf16<wchar_t>
3948
3949__codecvt_utf8_utf16<wchar_t>::result
3950__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3951 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3952 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3953{
3954 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3955 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3956 const uint32_t* _frm_nxt = _frm;
3957 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3958 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3959 uint8_t* _to_nxt = _to;
3960 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3961 _Maxcode_, _Mode_);
3962 frm_nxt = frm + (_frm_nxt - _frm);
3963 to_nxt = to + (_to_nxt - _to);
3964 return r;
3965}
3966
3967__codecvt_utf8_utf16<wchar_t>::result
3968__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3969 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3970 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3971{
3972 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3973 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3974 const uint8_t* _frm_nxt = _frm;
3975 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3976 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3977 uint32_t* _to_nxt = _to;
3978 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3979 _Maxcode_, _Mode_);
3980 frm_nxt = frm + (_frm_nxt - _frm);
3981 to_nxt = to + (_to_nxt - _to);
3982 return r;
3983}
3984
3985__codecvt_utf8_utf16<wchar_t>::result
3986__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3987 extern_type* to, extern_type*, extern_type*& to_nxt) const
3988{
3989 to_nxt = to;
3990 return noconv;
3991}
3992
3993int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003994__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003995{
3996 return 0;
3997}
3998
3999bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004000__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004001{
4002 return false;
4003}
4004
4005int
4006__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4007 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4008{
4009 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4010 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4011 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4012}
4013
4014int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004015__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004016{
4017 if (_Mode_ & consume_header)
4018 return 7;
4019 return 4;
4020}
4021
4022// __codecvt_utf8_utf16<char16_t>
4023
4024__codecvt_utf8_utf16<char16_t>::result
4025__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4026 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4027 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4028{
4029 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4030 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4031 const uint16_t* _frm_nxt = _frm;
4032 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4033 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4034 uint8_t* _to_nxt = _to;
4035 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4036 _Maxcode_, _Mode_);
4037 frm_nxt = frm + (_frm_nxt - _frm);
4038 to_nxt = to + (_to_nxt - _to);
4039 return r;
4040}
4041
4042__codecvt_utf8_utf16<char16_t>::result
4043__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4044 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4045 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4046{
4047 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4048 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4049 const uint8_t* _frm_nxt = _frm;
4050 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4051 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4052 uint16_t* _to_nxt = _to;
4053 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4054 _Maxcode_, _Mode_);
4055 frm_nxt = frm + (_frm_nxt - _frm);
4056 to_nxt = to + (_to_nxt - _to);
4057 return r;
4058}
4059
4060__codecvt_utf8_utf16<char16_t>::result
4061__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4062 extern_type* to, extern_type*, extern_type*& to_nxt) const
4063{
4064 to_nxt = to;
4065 return noconv;
4066}
4067
4068int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004069__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004070{
4071 return 0;
4072}
4073
4074bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004075__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004076{
4077 return false;
4078}
4079
4080int
4081__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4082 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4083{
4084 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4085 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4086 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4087}
4088
4089int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004090__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004091{
4092 if (_Mode_ & consume_header)
4093 return 7;
4094 return 4;
4095}
4096
4097// __codecvt_utf8_utf16<char32_t>
4098
4099__codecvt_utf8_utf16<char32_t>::result
4100__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4101 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4102 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4103{
4104 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4105 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4106 const uint32_t* _frm_nxt = _frm;
4107 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4108 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4109 uint8_t* _to_nxt = _to;
4110 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4111 _Maxcode_, _Mode_);
4112 frm_nxt = frm + (_frm_nxt - _frm);
4113 to_nxt = to + (_to_nxt - _to);
4114 return r;
4115}
4116
4117__codecvt_utf8_utf16<char32_t>::result
4118__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4119 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4120 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4121{
4122 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4123 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4124 const uint8_t* _frm_nxt = _frm;
4125 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4126 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4127 uint32_t* _to_nxt = _to;
4128 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4129 _Maxcode_, _Mode_);
4130 frm_nxt = frm + (_frm_nxt - _frm);
4131 to_nxt = to + (_to_nxt - _to);
4132 return r;
4133}
4134
4135__codecvt_utf8_utf16<char32_t>::result
4136__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4137 extern_type* to, extern_type*, extern_type*& to_nxt) const
4138{
4139 to_nxt = to;
4140 return noconv;
4141}
4142
4143int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004144__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004145{
4146 return 0;
4147}
4148
4149bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004150__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004151{
4152 return false;
4153}
4154
4155int
4156__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4157 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4158{
4159 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4160 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4161 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4162}
4163
4164int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004165__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004166{
4167 if (_Mode_ & consume_header)
4168 return 7;
4169 return 4;
4170}
4171
Howard Hinnantc51e1022010-05-11 19:42:16 +00004172// __narrow_to_utf8<16>
4173
4174__narrow_to_utf8<16>::~__narrow_to_utf8()
4175{
4176}
4177
4178// __narrow_to_utf8<32>
4179
4180__narrow_to_utf8<32>::~__narrow_to_utf8()
4181{
4182}
4183
4184// __widen_from_utf8<16>
4185
4186__widen_from_utf8<16>::~__widen_from_utf8()
4187{
4188}
4189
4190// __widen_from_utf8<32>
4191
4192__widen_from_utf8<32>::~__widen_from_utf8()
4193{
4194}
4195
4196// numpunct<char> && numpunct<wchar_t>
4197
4198locale::id numpunct< char >::id;
4199locale::id numpunct<wchar_t>::id;
4200
4201numpunct<char>::numpunct(size_t refs)
4202 : locale::facet(refs),
4203 __decimal_point_('.'),
4204 __thousands_sep_(',')
4205{
4206}
4207
4208numpunct<wchar_t>::numpunct(size_t refs)
4209 : locale::facet(refs),
4210 __decimal_point_(L'.'),
4211 __thousands_sep_(L',')
4212{
4213}
4214
4215numpunct<char>::~numpunct()
4216{
4217}
4218
4219numpunct<wchar_t>::~numpunct()
4220{
4221}
4222
4223 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4224wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4225
4226 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4227wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4228
4229string numpunct< char >::do_grouping() const {return __grouping_;}
4230string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4231
4232 string numpunct< char >::do_truename() const {return "true";}
4233wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4234
4235 string numpunct< char >::do_falsename() const {return "false";}
4236wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4237
4238// numpunct_byname<char>
4239
4240numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4241 : numpunct<char>(refs)
4242{
4243 __init(nm);
4244}
4245
4246numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4247 : numpunct<char>(refs)
4248{
4249 __init(nm.c_str());
4250}
4251
4252numpunct_byname<char>::~numpunct_byname()
4253{
4254}
4255
4256void
4257numpunct_byname<char>::__init(const char* nm)
4258{
4259 if (strcmp(nm, "C") != 0)
4260 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004261 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004262#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004263 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004264 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4265 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004266#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00004267 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004268 if (*lc->decimal_point)
4269 __decimal_point_ = *lc->decimal_point;
4270 if (*lc->thousands_sep)
4271 __thousands_sep_ = *lc->thousands_sep;
4272 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004273 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004274 }
4275}
4276
4277// numpunct_byname<wchar_t>
4278
4279numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4280 : numpunct<wchar_t>(refs)
4281{
4282 __init(nm);
4283}
4284
4285numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4286 : numpunct<wchar_t>(refs)
4287{
4288 __init(nm.c_str());
4289}
4290
4291numpunct_byname<wchar_t>::~numpunct_byname()
4292{
4293}
4294
4295void
4296numpunct_byname<wchar_t>::__init(const char* nm)
4297{
4298 if (strcmp(nm, "C") != 0)
4299 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004300 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004301#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004302 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004303 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4304 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004305#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00004306 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00004307 if (*lc->decimal_point)
4308 __decimal_point_ = *lc->decimal_point;
4309 if (*lc->thousands_sep)
4310 __thousands_sep_ = *lc->thousands_sep;
4311 __grouping_ = lc->grouping;
4312 // locallization for truename and falsename is not available
4313 }
4314}
4315
4316// num_get helpers
4317
4318int
4319__num_get_base::__get_base(ios_base& iob)
4320{
4321 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4322 if (__basefield == ios_base::oct)
4323 return 8;
4324 else if (__basefield == ios_base::hex)
4325 return 16;
4326 else if (__basefield == 0)
4327 return 0;
4328 return 10;
4329}
4330
4331const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4332
4333void
4334__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4335 ios_base::iostate& __err)
4336{
4337 if (__grouping.size() != 0)
4338 {
4339 reverse(__g, __g_end);
4340 const char* __ig = __grouping.data();
4341 const char* __eg = __ig + __grouping.size();
4342 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4343 {
4344 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4345 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004346 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004347 {
4348 __err = ios_base::failbit;
4349 return;
4350 }
4351 }
4352 if (__eg - __ig > 1)
4353 ++__ig;
4354 }
4355 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4356 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004357 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004358 __err = ios_base::failbit;
4359 }
4360 }
4361}
4362
4363void
4364__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4365 ios_base::fmtflags __flags)
4366{
4367 if (__flags & ios_base::showpos)
4368 *__fmtp++ = '+';
4369 if (__flags & ios_base::showbase)
4370 *__fmtp++ = '#';
4371 while(*__len)
4372 *__fmtp++ = *__len++;
4373 if ((__flags & ios_base::basefield) == ios_base::oct)
4374 *__fmtp = 'o';
4375 else if ((__flags & ios_base::basefield) == ios_base::hex)
4376 {
4377 if (__flags & ios_base::uppercase)
4378 *__fmtp = 'X';
4379 else
4380 *__fmtp = 'x';
4381 }
4382 else if (__signd)
4383 *__fmtp = 'd';
4384 else
4385 *__fmtp = 'u';
4386}
4387
4388bool
4389__num_put_base::__format_float(char* __fmtp, const char* __len,
4390 ios_base::fmtflags __flags)
4391{
4392 bool specify_precision = true;
4393 if (__flags & ios_base::showpos)
4394 *__fmtp++ = '+';
4395 if (__flags & ios_base::showpoint)
4396 *__fmtp++ = '#';
4397 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004398 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004399 if (floatfield == (ios_base::fixed | ios_base::scientific))
4400 specify_precision = false;
4401 else
4402 {
4403 *__fmtp++ = '.';
4404 *__fmtp++ = '*';
4405 }
4406 while(*__len)
4407 *__fmtp++ = *__len++;
4408 if (floatfield == ios_base::fixed)
4409 {
4410 if (uppercase)
4411 *__fmtp = 'F';
4412 else
4413 *__fmtp = 'f';
4414 }
4415 else if (floatfield == ios_base::scientific)
4416 {
4417 if (uppercase)
4418 *__fmtp = 'E';
4419 else
4420 *__fmtp = 'e';
4421 }
4422 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4423 {
4424 if (uppercase)
4425 *__fmtp = 'A';
4426 else
4427 *__fmtp = 'a';
4428 }
4429 else
4430 {
4431 if (uppercase)
4432 *__fmtp = 'G';
4433 else
4434 *__fmtp = 'g';
4435 }
4436 return specify_precision;
4437}
4438
4439char*
4440__num_put_base::__identify_padding(char* __nb, char* __ne,
4441 const ios_base& __iob)
4442{
4443 switch (__iob.flags() & ios_base::adjustfield)
4444 {
4445 case ios_base::internal:
4446 if (__nb[0] == '-' || __nb[0] == '+')
4447 return __nb+1;
4448 if (__ne - __nb >= 2 && __nb[0] == '0'
4449 && (__nb[1] == 'x' || __nb[1] == 'X'))
4450 return __nb+2;
4451 break;
4452 case ios_base::left:
4453 return __ne;
4454 case ios_base::right:
4455 default:
4456 break;
4457 }
4458 return __nb;
4459}
4460
4461// time_get
4462
4463static
4464string*
4465init_weeks()
4466{
4467 static string weeks[14];
4468 weeks[0] = "Sunday";
4469 weeks[1] = "Monday";
4470 weeks[2] = "Tuesday";
4471 weeks[3] = "Wednesday";
4472 weeks[4] = "Thursday";
4473 weeks[5] = "Friday";
4474 weeks[6] = "Saturday";
4475 weeks[7] = "Sun";
4476 weeks[8] = "Mon";
4477 weeks[9] = "Tue";
4478 weeks[10] = "Wed";
4479 weeks[11] = "Thu";
4480 weeks[12] = "Fri";
4481 weeks[13] = "Sat";
4482 return weeks;
4483}
4484
4485static
4486wstring*
4487init_wweeks()
4488{
4489 static wstring weeks[14];
4490 weeks[0] = L"Sunday";
4491 weeks[1] = L"Monday";
4492 weeks[2] = L"Tuesday";
4493 weeks[3] = L"Wednesday";
4494 weeks[4] = L"Thursday";
4495 weeks[5] = L"Friday";
4496 weeks[6] = L"Saturday";
4497 weeks[7] = L"Sun";
4498 weeks[8] = L"Mon";
4499 weeks[9] = L"Tue";
4500 weeks[10] = L"Wed";
4501 weeks[11] = L"Thu";
4502 weeks[12] = L"Fri";
4503 weeks[13] = L"Sat";
4504 return weeks;
4505}
4506
4507template <>
4508const string*
4509__time_get_c_storage<char>::__weeks() const
4510{
4511 static const string* weeks = init_weeks();
4512 return weeks;
4513}
4514
4515template <>
4516const wstring*
4517__time_get_c_storage<wchar_t>::__weeks() const
4518{
4519 static const wstring* weeks = init_wweeks();
4520 return weeks;
4521}
4522
4523static
4524string*
4525init_months()
4526{
4527 static string months[24];
4528 months[0] = "January";
4529 months[1] = "February";
4530 months[2] = "March";
4531 months[3] = "April";
4532 months[4] = "May";
4533 months[5] = "June";
4534 months[6] = "July";
4535 months[7] = "August";
4536 months[8] = "September";
4537 months[9] = "October";
4538 months[10] = "November";
4539 months[11] = "December";
4540 months[12] = "Jan";
4541 months[13] = "Feb";
4542 months[14] = "Mar";
4543 months[15] = "Apr";
4544 months[16] = "May";
4545 months[17] = "Jun";
4546 months[18] = "Jul";
4547 months[19] = "Aug";
4548 months[20] = "Sep";
4549 months[21] = "Oct";
4550 months[22] = "Nov";
4551 months[23] = "Dec";
4552 return months;
4553}
4554
4555static
4556wstring*
4557init_wmonths()
4558{
4559 static wstring months[24];
4560 months[0] = L"January";
4561 months[1] = L"February";
4562 months[2] = L"March";
4563 months[3] = L"April";
4564 months[4] = L"May";
4565 months[5] = L"June";
4566 months[6] = L"July";
4567 months[7] = L"August";
4568 months[8] = L"September";
4569 months[9] = L"October";
4570 months[10] = L"November";
4571 months[11] = L"December";
4572 months[12] = L"Jan";
4573 months[13] = L"Feb";
4574 months[14] = L"Mar";
4575 months[15] = L"Apr";
4576 months[16] = L"May";
4577 months[17] = L"Jun";
4578 months[18] = L"Jul";
4579 months[19] = L"Aug";
4580 months[20] = L"Sep";
4581 months[21] = L"Oct";
4582 months[22] = L"Nov";
4583 months[23] = L"Dec";
4584 return months;
4585}
4586
4587template <>
4588const string*
4589__time_get_c_storage<char>::__months() const
4590{
4591 static const string* months = init_months();
4592 return months;
4593}
4594
4595template <>
4596const wstring*
4597__time_get_c_storage<wchar_t>::__months() const
4598{
4599 static const wstring* months = init_wmonths();
4600 return months;
4601}
4602
4603static
4604string*
4605init_am_pm()
4606{
4607 static string am_pm[24];
4608 am_pm[0] = "AM";
4609 am_pm[1] = "PM";
4610 return am_pm;
4611}
4612
4613static
4614wstring*
4615init_wam_pm()
4616{
4617 static wstring am_pm[24];
4618 am_pm[0] = L"AM";
4619 am_pm[1] = L"PM";
4620 return am_pm;
4621}
4622
4623template <>
4624const string*
4625__time_get_c_storage<char>::__am_pm() const
4626{
4627 static const string* am_pm = init_am_pm();
4628 return am_pm;
4629}
4630
4631template <>
4632const wstring*
4633__time_get_c_storage<wchar_t>::__am_pm() const
4634{
4635 static const wstring* am_pm = init_wam_pm();
4636 return am_pm;
4637}
4638
4639template <>
4640const string&
4641__time_get_c_storage<char>::__x() const
4642{
4643 static string s("%m/%d/%y");
4644 return s;
4645}
4646
4647template <>
4648const wstring&
4649__time_get_c_storage<wchar_t>::__x() const
4650{
4651 static wstring s(L"%m/%d/%y");
4652 return s;
4653}
4654
4655template <>
4656const string&
4657__time_get_c_storage<char>::__X() const
4658{
4659 static string s("%H:%M:%S");
4660 return s;
4661}
4662
4663template <>
4664const wstring&
4665__time_get_c_storage<wchar_t>::__X() const
4666{
4667 static wstring s(L"%H:%M:%S");
4668 return s;
4669}
4670
4671template <>
4672const string&
4673__time_get_c_storage<char>::__c() const
4674{
4675 static string s("%a %b %d %H:%M:%S %Y");
4676 return s;
4677}
4678
4679template <>
4680const wstring&
4681__time_get_c_storage<wchar_t>::__c() const
4682{
4683 static wstring s(L"%a %b %d %H:%M:%S %Y");
4684 return s;
4685}
4686
4687template <>
4688const string&
4689__time_get_c_storage<char>::__r() const
4690{
4691 static string s("%I:%M:%S %p");
4692 return s;
4693}
4694
4695template <>
4696const wstring&
4697__time_get_c_storage<wchar_t>::__r() const
4698{
4699 static wstring s(L"%I:%M:%S %p");
4700 return s;
4701}
4702
4703// time_get_byname
4704
4705__time_get::__time_get(const char* nm)
4706 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4707{
Howard Hinnant72f73582010-08-11 17:04:31 +00004708#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004709 if (__loc_ == 0)
4710 throw runtime_error("time_get_byname"
4711 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004712#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004713}
4714
4715__time_get::__time_get(const string& nm)
4716 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4717{
Howard Hinnant72f73582010-08-11 17:04:31 +00004718#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004719 if (__loc_ == 0)
4720 throw runtime_error("time_get_byname"
4721 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004722#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004723}
4724
4725__time_get::~__time_get()
4726{
4727 freelocale(__loc_);
4728}
Marshall Clowd920eea2013-10-21 15:07:28 +00004729#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004730#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004731#endif
4732#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004733#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004734#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004735
Howard Hinnantc51e1022010-05-11 19:42:16 +00004736template <>
4737string
4738__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4739{
Howard Hinnant990207c2012-02-19 14:55:32 +00004740 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004741 t.tm_sec = 59;
4742 t.tm_min = 55;
4743 t.tm_hour = 23;
4744 t.tm_mday = 31;
4745 t.tm_mon = 11;
4746 t.tm_year = 161;
4747 t.tm_wday = 6;
4748 t.tm_yday = 364;
4749 t.tm_isdst = -1;
4750 char buf[100];
4751 char f[3] = {0};
4752 f[0] = '%';
4753 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004754 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004755 char* bb = buf;
4756 char* be = buf + n;
4757 string result;
4758 while (bb != be)
4759 {
4760 if (ct.is(ctype_base::space, *bb))
4761 {
4762 result.push_back(' ');
4763 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4764 ;
4765 continue;
4766 }
4767 char* w = bb;
4768 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004769 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004770 ct, err, false)
4771 - this->__weeks_;
4772 if (i < 14)
4773 {
4774 result.push_back('%');
4775 if (i < 7)
4776 result.push_back('A');
4777 else
4778 result.push_back('a');
4779 bb = w;
4780 continue;
4781 }
4782 w = bb;
4783 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4784 ct, err, false)
4785 - this->__months_;
4786 if (i < 24)
4787 {
4788 result.push_back('%');
4789 if (i < 12)
4790 result.push_back('B');
4791 else
4792 result.push_back('b');
4793 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4794 result.back() = 'm';
4795 bb = w;
4796 continue;
4797 }
4798 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4799 {
4800 w = bb;
4801 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4802 ct, err, false) - this->__am_pm_;
4803 if (i < 2)
4804 {
4805 result.push_back('%');
4806 result.push_back('p');
4807 bb = w;
4808 continue;
4809 }
4810 }
4811 w = bb;
4812 if (ct.is(ctype_base::digit, *bb))
4813 {
4814 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4815 {
4816 case 6:
4817 result.push_back('%');
4818 result.push_back('w');
4819 break;
4820 case 7:
4821 result.push_back('%');
4822 result.push_back('u');
4823 break;
4824 case 11:
4825 result.push_back('%');
4826 result.push_back('I');
4827 break;
4828 case 12:
4829 result.push_back('%');
4830 result.push_back('m');
4831 break;
4832 case 23:
4833 result.push_back('%');
4834 result.push_back('H');
4835 break;
4836 case 31:
4837 result.push_back('%');
4838 result.push_back('d');
4839 break;
4840 case 55:
4841 result.push_back('%');
4842 result.push_back('M');
4843 break;
4844 case 59:
4845 result.push_back('%');
4846 result.push_back('S');
4847 break;
4848 case 61:
4849 result.push_back('%');
4850 result.push_back('y');
4851 break;
4852 case 364:
4853 result.push_back('%');
4854 result.push_back('j');
4855 break;
4856 case 2061:
4857 result.push_back('%');
4858 result.push_back('Y');
4859 break;
4860 default:
4861 for (; w != bb; ++w)
4862 result.push_back(*w);
4863 break;
4864 }
4865 continue;
4866 }
4867 if (*bb == '%')
4868 {
4869 result.push_back('%');
4870 result.push_back('%');
4871 ++bb;
4872 continue;
4873 }
4874 result.push_back(*bb);
4875 ++bb;
4876 }
4877 return result;
4878}
4879
Marshall Clowd920eea2013-10-21 15:07:28 +00004880#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004881#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004882#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004883
Howard Hinnantc51e1022010-05-11 19:42:16 +00004884template <>
4885wstring
4886__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4887{
Howard Hinnant990207c2012-02-19 14:55:32 +00004888 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004889 t.tm_sec = 59;
4890 t.tm_min = 55;
4891 t.tm_hour = 23;
4892 t.tm_mday = 31;
4893 t.tm_mon = 11;
4894 t.tm_year = 161;
4895 t.tm_wday = 6;
4896 t.tm_yday = 364;
4897 t.tm_isdst = -1;
4898 char buf[100];
4899 char f[3] = {0};
4900 f[0] = '%';
4901 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004902 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004903 wchar_t wbuf[100];
4904 wchar_t* wbb = wbuf;
4905 mbstate_t mb = {0};
4906 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00004907 size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00004908 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004909 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004910 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004911 wstring result;
4912 while (wbb != wbe)
4913 {
4914 if (ct.is(ctype_base::space, *wbb))
4915 {
4916 result.push_back(L' ');
4917 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4918 ;
4919 continue;
4920 }
4921 wchar_t* w = wbb;
4922 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004923 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004924 ct, err, false)
4925 - this->__weeks_;
4926 if (i < 14)
4927 {
4928 result.push_back(L'%');
4929 if (i < 7)
4930 result.push_back(L'A');
4931 else
4932 result.push_back(L'a');
4933 wbb = w;
4934 continue;
4935 }
4936 w = wbb;
4937 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4938 ct, err, false)
4939 - this->__months_;
4940 if (i < 24)
4941 {
4942 result.push_back(L'%');
4943 if (i < 12)
4944 result.push_back(L'B');
4945 else
4946 result.push_back(L'b');
4947 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4948 result.back() = L'm';
4949 wbb = w;
4950 continue;
4951 }
4952 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4953 {
4954 w = wbb;
4955 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4956 ct, err, false) - this->__am_pm_;
4957 if (i < 2)
4958 {
4959 result.push_back(L'%');
4960 result.push_back(L'p');
4961 wbb = w;
4962 continue;
4963 }
4964 }
4965 w = wbb;
4966 if (ct.is(ctype_base::digit, *wbb))
4967 {
4968 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4969 {
4970 case 6:
4971 result.push_back(L'%');
4972 result.push_back(L'w');
4973 break;
4974 case 7:
4975 result.push_back(L'%');
4976 result.push_back(L'u');
4977 break;
4978 case 11:
4979 result.push_back(L'%');
4980 result.push_back(L'I');
4981 break;
4982 case 12:
4983 result.push_back(L'%');
4984 result.push_back(L'm');
4985 break;
4986 case 23:
4987 result.push_back(L'%');
4988 result.push_back(L'H');
4989 break;
4990 case 31:
4991 result.push_back(L'%');
4992 result.push_back(L'd');
4993 break;
4994 case 55:
4995 result.push_back(L'%');
4996 result.push_back(L'M');
4997 break;
4998 case 59:
4999 result.push_back(L'%');
5000 result.push_back(L'S');
5001 break;
5002 case 61:
5003 result.push_back(L'%');
5004 result.push_back(L'y');
5005 break;
5006 case 364:
5007 result.push_back(L'%');
5008 result.push_back(L'j');
5009 break;
5010 case 2061:
5011 result.push_back(L'%');
5012 result.push_back(L'Y');
5013 break;
5014 default:
5015 for (; w != wbb; ++w)
5016 result.push_back(*w);
5017 break;
5018 }
5019 continue;
5020 }
5021 if (ct.narrow(*wbb, 0) == '%')
5022 {
5023 result.push_back(L'%');
5024 result.push_back(L'%');
5025 ++wbb;
5026 continue;
5027 }
5028 result.push_back(*wbb);
5029 ++wbb;
5030 }
5031 return result;
5032}
5033
5034template <>
5035void
5036__time_get_storage<char>::init(const ctype<char>& ct)
5037{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005038 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005039 char buf[100];
5040 // __weeks_
5041 for (int i = 0; i < 7; ++i)
5042 {
5043 t.tm_wday = i;
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] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005046 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005047 __weeks_[i+7] = buf;
5048 }
5049 // __months_
5050 for (int i = 0; i < 12; ++i)
5051 {
5052 t.tm_mon = i;
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] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005055 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005056 __months_[i+12] = buf;
5057 }
5058 // __am_pm_
5059 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005060 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005061 __am_pm_[0] = buf;
5062 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005063 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005064 __am_pm_[1] = buf;
5065 __c_ = __analyze('c', ct);
5066 __r_ = __analyze('r', ct);
5067 __x_ = __analyze('x', ct);
5068 __X_ = __analyze('X', ct);
5069}
5070
5071template <>
5072void
5073__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5074{
5075 tm t = {0};
5076 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005077 wchar_t wbuf[100];
5078 wchar_t* wbe;
5079 mbstate_t mb = {0};
5080 // __weeks_
5081 for (int i = 0; i < 7; ++i)
5082 {
5083 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005084 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005085 mb = mbstate_t();
5086 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005087 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005088 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005089 __throw_runtime_error("locale not supported");
5090 wbe = wbuf + j;
5091 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005092 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005093 mb = mbstate_t();
5094 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005095 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005096 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005097 __throw_runtime_error("locale not supported");
5098 wbe = wbuf + j;
5099 __weeks_[i+7].assign(wbuf, wbe);
5100 }
5101 // __months_
5102 for (int i = 0; i < 12; ++i)
5103 {
5104 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005105 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005106 mb = mbstate_t();
5107 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005108 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005109 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005110 __throw_runtime_error("locale not supported");
5111 wbe = wbuf + j;
5112 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005113 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005114 mb = mbstate_t();
5115 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005116 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005117 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005118 __throw_runtime_error("locale not supported");
5119 wbe = wbuf + j;
5120 __months_[i+12].assign(wbuf, wbe);
5121 }
5122 // __am_pm_
5123 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005124 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005125 mb = mbstate_t();
5126 const char* bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005127 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005128 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005129 __throw_runtime_error("locale not supported");
5130 wbe = wbuf + j;
5131 __am_pm_[0].assign(wbuf, wbe);
5132 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005133 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005134 mb = mbstate_t();
5135 bb = buf;
Ben Craig3756b922016-03-09 15:39:39 +00005136 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005137 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005138 __throw_runtime_error("locale not supported");
5139 wbe = wbuf + j;
5140 __am_pm_[1].assign(wbuf, wbe);
5141 __c_ = __analyze('c', ct);
5142 __r_ = __analyze('r', ct);
5143 __x_ = __analyze('x', ct);
5144 __X_ = __analyze('X', ct);
5145}
5146
5147template <class CharT>
5148struct _LIBCPP_HIDDEN __time_get_temp
5149 : public ctype_byname<CharT>
5150{
5151 explicit __time_get_temp(const char* nm)
5152 : ctype_byname<CharT>(nm, 1) {}
5153 explicit __time_get_temp(const string& nm)
5154 : ctype_byname<CharT>(nm, 1) {}
5155};
5156
5157template <>
5158__time_get_storage<char>::__time_get_storage(const char* __nm)
5159 : __time_get(__nm)
5160{
5161 const __time_get_temp<char> ct(__nm);
5162 init(ct);
5163}
5164
5165template <>
5166__time_get_storage<char>::__time_get_storage(const string& __nm)
5167 : __time_get(__nm)
5168{
5169 const __time_get_temp<char> ct(__nm);
5170 init(ct);
5171}
5172
5173template <>
5174__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5175 : __time_get(__nm)
5176{
5177 const __time_get_temp<wchar_t> ct(__nm);
5178 init(ct);
5179}
5180
5181template <>
5182__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5183 : __time_get(__nm)
5184{
5185 const __time_get_temp<wchar_t> ct(__nm);
5186 init(ct);
5187}
5188
5189template <>
5190time_base::dateorder
5191__time_get_storage<char>::__do_date_order() const
5192{
5193 unsigned i;
5194 for (i = 0; i < __x_.size(); ++i)
5195 if (__x_[i] == '%')
5196 break;
5197 ++i;
5198 switch (__x_[i])
5199 {
5200 case 'y':
5201 case 'Y':
5202 for (++i; i < __x_.size(); ++i)
5203 if (__x_[i] == '%')
5204 break;
5205 if (i == __x_.size())
5206 break;
5207 ++i;
5208 switch (__x_[i])
5209 {
5210 case 'm':
5211 for (++i; i < __x_.size(); ++i)
5212 if (__x_[i] == '%')
5213 break;
5214 if (i == __x_.size())
5215 break;
5216 ++i;
5217 if (__x_[i] == 'd')
5218 return time_base::ymd;
5219 break;
5220 case 'd':
5221 for (++i; i < __x_.size(); ++i)
5222 if (__x_[i] == '%')
5223 break;
5224 if (i == __x_.size())
5225 break;
5226 ++i;
5227 if (__x_[i] == 'm')
5228 return time_base::ydm;
5229 break;
5230 }
5231 break;
5232 case 'm':
5233 for (++i; i < __x_.size(); ++i)
5234 if (__x_[i] == '%')
5235 break;
5236 if (i == __x_.size())
5237 break;
5238 ++i;
5239 if (__x_[i] == 'd')
5240 {
5241 for (++i; i < __x_.size(); ++i)
5242 if (__x_[i] == '%')
5243 break;
5244 if (i == __x_.size())
5245 break;
5246 ++i;
5247 if (__x_[i] == 'y' || __x_[i] == 'Y')
5248 return time_base::mdy;
5249 break;
5250 }
5251 break;
5252 case 'd':
5253 for (++i; i < __x_.size(); ++i)
5254 if (__x_[i] == '%')
5255 break;
5256 if (i == __x_.size())
5257 break;
5258 ++i;
5259 if (__x_[i] == 'm')
5260 {
5261 for (++i; i < __x_.size(); ++i)
5262 if (__x_[i] == '%')
5263 break;
5264 if (i == __x_.size())
5265 break;
5266 ++i;
5267 if (__x_[i] == 'y' || __x_[i] == 'Y')
5268 return time_base::dmy;
5269 break;
5270 }
5271 break;
5272 }
5273 return time_base::no_order;
5274}
5275
5276template <>
5277time_base::dateorder
5278__time_get_storage<wchar_t>::__do_date_order() const
5279{
5280 unsigned i;
5281 for (i = 0; i < __x_.size(); ++i)
5282 if (__x_[i] == L'%')
5283 break;
5284 ++i;
5285 switch (__x_[i])
5286 {
5287 case L'y':
5288 case L'Y':
5289 for (++i; i < __x_.size(); ++i)
5290 if (__x_[i] == L'%')
5291 break;
5292 if (i == __x_.size())
5293 break;
5294 ++i;
5295 switch (__x_[i])
5296 {
5297 case L'm':
5298 for (++i; i < __x_.size(); ++i)
5299 if (__x_[i] == L'%')
5300 break;
5301 if (i == __x_.size())
5302 break;
5303 ++i;
5304 if (__x_[i] == L'd')
5305 return time_base::ymd;
5306 break;
5307 case L'd':
5308 for (++i; i < __x_.size(); ++i)
5309 if (__x_[i] == L'%')
5310 break;
5311 if (i == __x_.size())
5312 break;
5313 ++i;
5314 if (__x_[i] == L'm')
5315 return time_base::ydm;
5316 break;
5317 }
5318 break;
5319 case L'm':
5320 for (++i; i < __x_.size(); ++i)
5321 if (__x_[i] == L'%')
5322 break;
5323 if (i == __x_.size())
5324 break;
5325 ++i;
5326 if (__x_[i] == L'd')
5327 {
5328 for (++i; i < __x_.size(); ++i)
5329 if (__x_[i] == L'%')
5330 break;
5331 if (i == __x_.size())
5332 break;
5333 ++i;
5334 if (__x_[i] == L'y' || __x_[i] == L'Y')
5335 return time_base::mdy;
5336 break;
5337 }
5338 break;
5339 case L'd':
5340 for (++i; i < __x_.size(); ++i)
5341 if (__x_[i] == L'%')
5342 break;
5343 if (i == __x_.size())
5344 break;
5345 ++i;
5346 if (__x_[i] == L'm')
5347 {
5348 for (++i; i < __x_.size(); ++i)
5349 if (__x_[i] == L'%')
5350 break;
5351 if (i == __x_.size())
5352 break;
5353 ++i;
5354 if (__x_[i] == L'y' || __x_[i] == L'Y')
5355 return time_base::dmy;
5356 break;
5357 }
5358 break;
5359 }
5360 return time_base::no_order;
5361}
5362
5363// time_put
5364
5365__time_put::__time_put(const char* nm)
5366 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5367{
Howard Hinnant72f73582010-08-11 17:04:31 +00005368#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005369 if (__loc_ == 0)
5370 throw runtime_error("time_put_byname"
5371 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005372#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005373}
5374
5375__time_put::__time_put(const string& nm)
5376 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5377{
Howard Hinnant72f73582010-08-11 17:04:31 +00005378#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005379 if (__loc_ == 0)
5380 throw runtime_error("time_put_byname"
5381 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005382#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005383}
5384
5385__time_put::~__time_put()
5386{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005387 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005388 freelocale(__loc_);
5389}
5390
5391void
5392__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5393 char __fmt, char __mod) const
5394{
5395 char fmt[] = {'%', __fmt, __mod, 0};
5396 if (__mod != 0)
5397 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005398 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005399 __ne = __nb + n;
5400}
5401
5402void
5403__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5404 char __fmt, char __mod) const
5405{
5406 char __nar[100];
5407 char* __ne = __nar + 100;
5408 __do_put(__nar, __ne, __tm, __fmt, __mod);
5409 mbstate_t mb = {0};
5410 const char* __nb = __nar;
Ben Craig3756b922016-03-09 15:39:39 +00005411 size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Howard Hinnant28b24882011-12-01 20:21:04 +00005412 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005413 __throw_runtime_error("locale not supported");
5414 __we = __wb + j;
5415}
5416
5417// moneypunct_byname
5418
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005419template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005420static
5421void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005422__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5423 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5424 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005425{
5426 const char sign = static_cast<char>(money_base::sign);
5427 const char space = static_cast<char>(money_base::space);
5428 const char none = static_cast<char>(money_base::none);
5429 const char symbol = static_cast<char>(money_base::symbol);
5430 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005431 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5432
5433 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5434 // function'. "Space between sign and symbol or value" means that
5435 // if the sign is adjacent to the symbol, there's a space between
5436 // them, and otherwise there's a space between the sign and value.
5437 //
5438 // C11's localeconv specifies that the fourth character of an
5439 // international curr_symbol is used to separate the sign and
5440 // value when sep_by_space says to do so. C++ can't represent
5441 // that, so we just use a space. When sep_by_space says to
5442 // separate the symbol and value-or-sign with a space, we rearrange the
5443 // curr_symbol to put its spacing character on the correct side of
5444 // the symbol.
5445 //
5446 // We also need to avoid adding an extra space between the sign
5447 // and value when the currency symbol is suppressed (by not
5448 // setting showbase). We match glibc's strfmon by interpreting
5449 // sep_by_space==1 as "omit the space when the currency symbol is
5450 // absent".
5451 //
5452 // Users who want to get this right should use ICU instead.
5453
Howard Hinnantc51e1022010-05-11 19:42:16 +00005454 switch (cs_precedes)
5455 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005456 case 0: // value before curr_symbol
5457 if (symbol_contains_sep) {
5458 // Move the separator to before the symbol, to place it
5459 // between the value and symbol.
5460 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5461 __curr_symbol_.end());
5462 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005463 switch (sign_posn)
5464 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005465 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005466 pat.field[0] = sign;
5467 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005468 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005469 pat.field[3] = symbol;
5470 switch (sep_by_space)
5471 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005472 case 0: // No space separates the currency symbol and value.
5473 // This case may have changed between C99 and C11;
5474 // assume the currency symbol matches the intention.
5475 case 2: // Space between sign and currency or value.
5476 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005477 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005478 case 1: // Space between currency-and-sign or currency and value.
5479 if (!symbol_contains_sep) {
5480 // We insert the space into the symbol instead of
5481 // setting pat.field[2]=space so that when
5482 // showbase is not set, the space goes away too.
5483 __curr_symbol_.insert(0, 1, space_char);
5484 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005485 return;
5486 default:
5487 break;
5488 }
5489 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005490 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005491 pat.field[0] = sign;
5492 pat.field[3] = symbol;
5493 switch (sep_by_space)
5494 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005495 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005496 pat.field[1] = value;
5497 pat.field[2] = none;
5498 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005499 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005500 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005501 pat.field[2] = none;
5502 if (!symbol_contains_sep) {
5503 // We insert the space into the symbol instead of
5504 // setting pat.field[2]=space so that when
5505 // showbase is not set, the space goes away too.
5506 __curr_symbol_.insert(0, 1, space_char);
5507 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005508 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005509 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005510 pat.field[1] = space;
5511 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005512 if (symbol_contains_sep) {
5513 // Remove the separator from the symbol, since it
5514 // has already appeared after the sign.
5515 __curr_symbol_.erase(__curr_symbol_.begin());
5516 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005517 return;
5518 default:
5519 break;
5520 }
5521 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005522 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005523 pat.field[0] = value;
5524 pat.field[3] = sign;
5525 switch (sep_by_space)
5526 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005527 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005528 pat.field[1] = none;
5529 pat.field[2] = symbol;
5530 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005531 case 1: // Space between currency-and-sign or currency and value.
5532 if (!symbol_contains_sep) {
5533 // We insert the space into the symbol instead of
5534 // setting pat.field[1]=space so that when
5535 // showbase is not set, the space goes away too.
5536 __curr_symbol_.insert(0, 1, space_char);
5537 }
5538 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005539 pat.field[2] = symbol;
5540 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005541 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005542 pat.field[1] = symbol;
5543 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005544 if (symbol_contains_sep) {
5545 // Remove the separator from the symbol, since it
5546 // should not be removed if showbase is absent.
5547 __curr_symbol_.erase(__curr_symbol_.begin());
5548 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005549 return;
5550 default:
5551 break;
5552 }
5553 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005554 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005555 pat.field[0] = value;
5556 pat.field[3] = symbol;
5557 switch (sep_by_space)
5558 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005559 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005560 pat.field[1] = none;
5561 pat.field[2] = sign;
5562 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005563 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005564 pat.field[1] = space;
5565 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005566 if (symbol_contains_sep) {
5567 // Remove the separator from the symbol, since it
5568 // has already appeared before the sign.
5569 __curr_symbol_.erase(__curr_symbol_.begin());
5570 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005571 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005572 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005573 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005574 pat.field[2] = none;
5575 if (!symbol_contains_sep) {
5576 // We insert the space into the symbol instead of
5577 // setting pat.field[2]=space so that when
5578 // showbase is not set, the space goes away too.
5579 __curr_symbol_.insert(0, 1, space_char);
5580 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005581 return;
5582 default:
5583 break;
5584 }
5585 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005586 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005587 pat.field[0] = value;
5588 pat.field[3] = sign;
5589 switch (sep_by_space)
5590 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005591 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005592 pat.field[1] = none;
5593 pat.field[2] = symbol;
5594 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005595 case 1: // Space between currency-and-sign or currency and value.
5596 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005597 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005598 if (!symbol_contains_sep) {
5599 // We insert the space into the symbol instead of
5600 // setting pat.field[1]=space so that when
5601 // showbase is not set, the space goes away too.
5602 __curr_symbol_.insert(0, 1, space_char);
5603 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005604 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005605 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005606 pat.field[1] = symbol;
5607 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005608 if (symbol_contains_sep) {
5609 // Remove the separator from the symbol, since it
5610 // should not disappear when showbase is absent.
5611 __curr_symbol_.erase(__curr_symbol_.begin());
5612 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005613 return;
5614 default:
5615 break;
5616 }
5617 break;
5618 default:
5619 break;
5620 }
5621 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005622 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005623 switch (sign_posn)
5624 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005625 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005626 pat.field[0] = sign;
5627 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005628 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005629 pat.field[3] = value;
5630 switch (sep_by_space)
5631 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005632 case 0: // No space separates the currency symbol and value.
5633 // This case may have changed between C99 and C11;
5634 // assume the currency symbol matches the intention.
5635 case 2: // Space between sign and currency or value.
5636 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005637 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005638 case 1: // Space between currency-and-sign or currency and value.
5639 if (!symbol_contains_sep) {
5640 // We insert the space into the symbol instead of
5641 // setting pat.field[2]=space so that when
5642 // showbase is not set, the space goes away too.
5643 __curr_symbol_.insert(0, 1, space_char);
5644 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005645 return;
5646 default:
5647 break;
5648 }
5649 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005650 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005651 pat.field[0] = sign;
5652 pat.field[3] = value;
5653 switch (sep_by_space)
5654 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005655 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005656 pat.field[1] = symbol;
5657 pat.field[2] = none;
5658 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005659 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005660 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005661 pat.field[2] = none;
5662 if (!symbol_contains_sep) {
5663 // We insert the space into the symbol instead of
5664 // setting pat.field[2]=space so that when
5665 // showbase is not set, the space goes away too.
5666 __curr_symbol_.push_back(space_char);
5667 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005668 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005669 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005670 pat.field[1] = space;
5671 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005672 if (symbol_contains_sep) {
5673 // Remove the separator from the symbol, since it
5674 // has already appeared after the sign.
5675 __curr_symbol_.pop_back();
5676 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005677 return;
5678 default:
5679 break;
5680 }
5681 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005682 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005683 pat.field[0] = symbol;
5684 pat.field[3] = sign;
5685 switch (sep_by_space)
5686 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005687 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005688 pat.field[1] = none;
5689 pat.field[2] = value;
5690 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005691 case 1: // Space between currency-and-sign or currency and value.
5692 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005693 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005694 if (!symbol_contains_sep) {
5695 // We insert the space into the symbol instead of
5696 // setting pat.field[1]=space so that when
5697 // showbase is not set, the space goes away too.
5698 __curr_symbol_.push_back(space_char);
5699 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005700 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005701 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005702 pat.field[1] = value;
5703 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005704 if (symbol_contains_sep) {
5705 // Remove the separator from the symbol, since it
5706 // will appear before the sign.
5707 __curr_symbol_.pop_back();
5708 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005709 return;
5710 default:
5711 break;
5712 }
5713 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005714 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005715 pat.field[0] = sign;
5716 pat.field[3] = value;
5717 switch (sep_by_space)
5718 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005719 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005720 pat.field[1] = symbol;
5721 pat.field[2] = none;
5722 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005723 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005724 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005725 pat.field[2] = none;
5726 if (!symbol_contains_sep) {
5727 // We insert the space into the symbol instead of
5728 // setting pat.field[2]=space so that when
5729 // showbase is not set, the space goes away too.
5730 __curr_symbol_.push_back(space_char);
5731 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005732 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005733 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005734 pat.field[1] = space;
5735 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005736 if (symbol_contains_sep) {
5737 // Remove the separator from the symbol, since it
5738 // has already appeared after the sign.
5739 __curr_symbol_.pop_back();
5740 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005741 return;
5742 default:
5743 break;
5744 }
5745 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005746 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005747 pat.field[0] = symbol;
5748 pat.field[3] = value;
5749 switch (sep_by_space)
5750 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005751 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005752 pat.field[1] = sign;
5753 pat.field[2] = none;
5754 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005755 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005756 pat.field[1] = sign;
5757 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005758 if (symbol_contains_sep) {
5759 // Remove the separator from the symbol, since it
5760 // should not disappear when showbase is absent.
5761 __curr_symbol_.pop_back();
5762 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005763 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005764 case 2: // Space between sign and currency or value.
5765 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005766 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005767 if (!symbol_contains_sep) {
5768 // We insert the space into the symbol instead of
5769 // setting pat.field[1]=space so that when
5770 // showbase is not set, the space goes away too.
5771 __curr_symbol_.push_back(space_char);
5772 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005773 return;
5774 default:
5775 break;
5776 }
5777 break;
5778 default:
5779 break;
5780 }
5781 break;
5782 default:
5783 break;
5784 }
5785 pat.field[0] = symbol;
5786 pat.field[1] = sign;
5787 pat.field[2] = none;
5788 pat.field[3] = value;
5789}
5790
5791template<>
5792void
5793moneypunct_byname<char, false>::init(const char* nm)
5794{
5795 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005796 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005797#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005798 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005799 throw runtime_error("moneypunct_byname"
5800 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005801#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005802 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005803 if (*lc->mon_decimal_point)
5804 __decimal_point_ = *lc->mon_decimal_point;
5805 else
5806 __decimal_point_ = base::do_decimal_point();
5807 if (*lc->mon_thousands_sep)
5808 __thousands_sep_ = *lc->mon_thousands_sep;
5809 else
5810 __thousands_sep_ = base::do_thousands_sep();
5811 __grouping_ = lc->mon_grouping;
5812 __curr_symbol_ = lc->currency_symbol;
5813 if (lc->frac_digits != CHAR_MAX)
5814 __frac_digits_ = lc->frac_digits;
5815 else
5816 __frac_digits_ = base::do_frac_digits();
5817 if (lc->p_sign_posn == 0)
5818 __positive_sign_ = "()";
5819 else
5820 __positive_sign_ = lc->positive_sign;
5821 if (lc->n_sign_posn == 0)
5822 __negative_sign_ = "()";
5823 else
5824 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005825 // Assume the positive and negative formats will want spaces in
5826 // the same places in curr_symbol since there's no way to
5827 // represent anything else.
5828 string_type __dummy_curr_symbol = __curr_symbol_;
5829 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5830 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5831 __init_pat(__neg_format_, __curr_symbol_, false,
5832 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005833}
5834
5835template<>
5836void
5837moneypunct_byname<char, true>::init(const char* nm)
5838{
5839 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005840 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005841#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005842 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005843 throw runtime_error("moneypunct_byname"
5844 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005845#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005846 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005847 if (*lc->mon_decimal_point)
5848 __decimal_point_ = *lc->mon_decimal_point;
5849 else
5850 __decimal_point_ = base::do_decimal_point();
5851 if (*lc->mon_thousands_sep)
5852 __thousands_sep_ = *lc->mon_thousands_sep;
5853 else
5854 __thousands_sep_ = base::do_thousands_sep();
5855 __grouping_ = lc->mon_grouping;
5856 __curr_symbol_ = lc->int_curr_symbol;
5857 if (lc->int_frac_digits != CHAR_MAX)
5858 __frac_digits_ = lc->int_frac_digits;
5859 else
5860 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005861#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005862 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005863#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005864 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005865#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005866 __positive_sign_ = "()";
5867 else
5868 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005869#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005870 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005871#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005872 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005873#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005874 __negative_sign_ = "()";
5875 else
5876 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005877 // Assume the positive and negative formats will want spaces in
5878 // the same places in curr_symbol since there's no way to
5879 // represent anything else.
5880 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005881#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005882 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5883 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5884 __init_pat(__neg_format_, __curr_symbol_, true,
5885 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005886#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005887 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5888 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5889 lc->int_p_sign_posn, ' ');
5890 __init_pat(__neg_format_, __curr_symbol_, true,
5891 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5892 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005893#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005894}
5895
5896template<>
5897void
5898moneypunct_byname<wchar_t, false>::init(const char* nm)
5899{
5900 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005901 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005902#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005903 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005904 throw runtime_error("moneypunct_byname"
5905 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005906#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005907 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005908 if (*lc->mon_decimal_point)
5909 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5910 else
5911 __decimal_point_ = base::do_decimal_point();
5912 if (*lc->mon_thousands_sep)
5913 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5914 else
5915 __thousands_sep_ = base::do_thousands_sep();
5916 __grouping_ = lc->mon_grouping;
5917 wchar_t wbuf[100];
5918 mbstate_t mb = {0};
5919 const char* bb = lc->currency_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005920 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005921 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005922 __throw_runtime_error("locale not supported");
5923 wchar_t* wbe = wbuf + j;
5924 __curr_symbol_.assign(wbuf, wbe);
5925 if (lc->frac_digits != CHAR_MAX)
5926 __frac_digits_ = lc->frac_digits;
5927 else
5928 __frac_digits_ = base::do_frac_digits();
5929 if (lc->p_sign_posn == 0)
5930 __positive_sign_ = L"()";
5931 else
5932 {
5933 mb = mbstate_t();
5934 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005935 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005936 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005937 __throw_runtime_error("locale not supported");
5938 wbe = wbuf + j;
5939 __positive_sign_.assign(wbuf, wbe);
5940 }
5941 if (lc->n_sign_posn == 0)
5942 __negative_sign_ = L"()";
5943 else
5944 {
5945 mb = mbstate_t();
5946 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00005947 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005948 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005949 __throw_runtime_error("locale not supported");
5950 wbe = wbuf + j;
5951 __negative_sign_.assign(wbuf, wbe);
5952 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005953 // Assume the positive and negative formats will want spaces in
5954 // the same places in curr_symbol since there's no way to
5955 // represent anything else.
5956 string_type __dummy_curr_symbol = __curr_symbol_;
5957 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5958 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5959 __init_pat(__neg_format_, __curr_symbol_, false,
5960 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005961}
5962
5963template<>
5964void
5965moneypunct_byname<wchar_t, true>::init(const char* nm)
5966{
5967 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005968 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005969#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005970 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005971 throw runtime_error("moneypunct_byname"
5972 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005973#endif // _LIBCPP_NO_EXCEPTIONS
Ben Craig3756b922016-03-09 15:39:39 +00005974 lconv* lc = __libcpp_localeconv_l(loc.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00005975 if (*lc->mon_decimal_point)
5976 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5977 else
5978 __decimal_point_ = base::do_decimal_point();
5979 if (*lc->mon_thousands_sep)
5980 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5981 else
5982 __thousands_sep_ = base::do_thousands_sep();
5983 __grouping_ = lc->mon_grouping;
5984 wchar_t wbuf[100];
5985 mbstate_t mb = {0};
5986 const char* bb = lc->int_curr_symbol;
Ben Craig3756b922016-03-09 15:39:39 +00005987 size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00005988 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005989 __throw_runtime_error("locale not supported");
5990 wchar_t* wbe = wbuf + j;
5991 __curr_symbol_.assign(wbuf, wbe);
5992 if (lc->int_frac_digits != CHAR_MAX)
5993 __frac_digits_ = lc->int_frac_digits;
5994 else
5995 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005996#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005997 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005998#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005999 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006000#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006001 __positive_sign_ = L"()";
6002 else
6003 {
6004 mb = mbstate_t();
6005 bb = lc->positive_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006006 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006007 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006008 __throw_runtime_error("locale not supported");
6009 wbe = wbuf + j;
6010 __positive_sign_.assign(wbuf, wbe);
6011 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006012#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006013 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006014#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006015 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006016#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006017 __negative_sign_ = L"()";
6018 else
6019 {
6020 mb = mbstate_t();
6021 bb = lc->negative_sign;
Ben Craig3756b922016-03-09 15:39:39 +00006022 j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Howard Hinnant28b24882011-12-01 20:21:04 +00006023 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006024 __throw_runtime_error("locale not supported");
6025 wbe = wbuf + j;
6026 __negative_sign_.assign(wbuf, wbe);
6027 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006028 // Assume the positive and negative formats will want spaces in
6029 // the same places in curr_symbol since there's no way to
6030 // represent anything else.
6031 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006032#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006033 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6034 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6035 __init_pat(__neg_format_, __curr_symbol_, true,
6036 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006037#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006038 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6039 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6040 lc->int_p_sign_posn, L' ');
6041 __init_pat(__neg_format_, __curr_symbol_, true,
6042 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6043 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006044#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006045}
6046
6047void __do_nothing(void*) {}
6048
6049void __throw_runtime_error(const char* msg)
6050{
Howard Hinnant72f73582010-08-11 17:04:31 +00006051#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006052 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006053#else
6054 (void)msg;
Howard Hinnant72f73582010-08-11 17:04:31 +00006055#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006056}
6057
6058template class collate<char>;
6059template class collate<wchar_t>;
6060
6061template class num_get<char>;
6062template class num_get<wchar_t>;
6063
Howard Hinnant28b24882011-12-01 20:21:04 +00006064template struct __num_get<char>;
6065template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006066
6067template class num_put<char>;
6068template class num_put<wchar_t>;
6069
Howard Hinnant28b24882011-12-01 20:21:04 +00006070template struct __num_put<char>;
6071template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006072
6073template class time_get<char>;
6074template class time_get<wchar_t>;
6075
6076template class time_get_byname<char>;
6077template class time_get_byname<wchar_t>;
6078
6079template class time_put<char>;
6080template class time_put<wchar_t>;
6081
6082template class time_put_byname<char>;
6083template class time_put_byname<wchar_t>;
6084
6085template class moneypunct<char, false>;
6086template class moneypunct<char, true>;
6087template class moneypunct<wchar_t, false>;
6088template class moneypunct<wchar_t, true>;
6089
6090template class moneypunct_byname<char, false>;
6091template class moneypunct_byname<char, true>;
6092template class moneypunct_byname<wchar_t, false>;
6093template class moneypunct_byname<wchar_t, true>;
6094
6095template class money_get<char>;
6096template class money_get<wchar_t>;
6097
6098template class __money_get<char>;
6099template class __money_get<wchar_t>;
6100
6101template class money_put<char>;
6102template class money_put<wchar_t>;
6103
6104template class __money_put<char>;
6105template class __money_put<wchar_t>;
6106
6107template class messages<char>;
6108template class messages<wchar_t>;
6109
6110template class messages_byname<char>;
6111template class messages_byname<wchar_t>;
6112
6113template class codecvt_byname<char, char, mbstate_t>;
6114template class codecvt_byname<wchar_t, char, mbstate_t>;
6115template class codecvt_byname<char16_t, char, mbstate_t>;
6116template class codecvt_byname<char32_t, char, mbstate_t>;
6117
6118template class __vector_base_common<true>;
6119
6120_LIBCPP_END_NAMESPACE_STD