blob: c973e5825fbd9a4f5840d030426c04abdbe7f42c [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{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001403#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001404 return btowc_l(c, __l);
1405#else
1406 return __btowc_l(c, __l);
1407#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001408}
1409
1410const char*
1411ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1412{
1413 for (; low != high; ++low, ++dest)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001414#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001415 *dest = btowc_l(*low, __l);
1416#else
1417 *dest = __btowc_l(*low, __l);
1418#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001419 return low;
1420}
1421
1422char
1423ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1424{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001425#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001426 int r = wctob_l(c, __l);
1427#else
1428 int r = __wctob_l(c, __l);
1429#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001430 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001431}
1432
1433const wchar_t*
1434ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1435{
1436 for (; low != high; ++low, ++dest)
1437 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001438#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001439 int r = wctob_l(*low, __l);
1440#else
1441 int r = __wctob_l(*low, __l);
1442#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001443 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001444 }
1445 return low;
1446}
1447
1448// template <> class codecvt<char, char, mbstate_t>
1449
Howard Hinnantffb308e2010-08-22 00:03:27 +00001450locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001451
1452codecvt<char, char, mbstate_t>::~codecvt()
1453{
1454}
1455
1456codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001457codecvt<char, char, mbstate_t>::do_out(state_type&,
1458 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001459 extern_type* to, extern_type*, extern_type*& to_nxt) const
1460{
1461 frm_nxt = frm;
1462 to_nxt = to;
1463 return noconv;
1464}
1465
1466codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001467codecvt<char, char, mbstate_t>::do_in(state_type&,
1468 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001469 intern_type* to, intern_type*, intern_type*& to_nxt) const
1470{
1471 frm_nxt = frm;
1472 to_nxt = to;
1473 return noconv;
1474}
1475
1476codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001477codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001478 extern_type* to, extern_type*, extern_type*& to_nxt) const
1479{
1480 to_nxt = to;
1481 return noconv;
1482}
1483
1484int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001485codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001486{
1487 return 1;
1488}
1489
1490bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001491codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001492{
1493 return true;
1494}
1495
1496int
1497codecvt<char, char, mbstate_t>::do_length(state_type&,
1498 const extern_type* frm, const extern_type* end, size_t mx) const
1499{
Howard Hinnant28b24882011-12-01 20:21:04 +00001500 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001501}
1502
1503int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001504codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001505{
1506 return 1;
1507}
1508
1509// template <> class codecvt<wchar_t, char, mbstate_t>
1510
Howard Hinnantffb308e2010-08-22 00:03:27 +00001511locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001512
1513codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1514 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001515 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001516{
1517}
1518
1519codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1520 : locale::facet(refs),
1521 __l(newlocale(LC_ALL_MASK, nm, 0))
1522{
Howard Hinnant72f73582010-08-11 17:04:31 +00001523#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001524 if (__l == 0)
1525 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1526 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001527#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001528}
1529
1530codecvt<wchar_t, char, mbstate_t>::~codecvt()
1531{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001532 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001533 freelocale(__l);
1534}
1535
1536codecvt<wchar_t, char, mbstate_t>::result
1537codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001538 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001539 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1540{
1541 // look for first internal null in frm
1542 const intern_type* fend = frm;
1543 for (; fend != frm_end; ++fend)
1544 if (*fend == 0)
1545 break;
1546 // loop over all null-terminated sequences in frm
1547 to_nxt = to;
1548 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1549 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001550 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001551 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001552#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001553 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1554 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001555#else
1556 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1557#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001558 if (n == size_t(-1))
1559 {
1560 // need to recover to_nxt
1561 for (to_nxt = to; frm != frm_nxt; ++frm)
1562 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001563#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001564 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1565#else
1566 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1567#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001568 if (n == size_t(-1))
1569 break;
1570 to_nxt += n;
1571 }
1572 frm_nxt = frm;
1573 return error;
1574 }
1575 if (n == 0)
1576 return partial;
1577 to_nxt += n;
1578 if (to_nxt == to_end)
1579 break;
1580 if (fend != frm_end) // set up next null terminated sequence
1581 {
1582 // Try to write the terminating null
1583 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001584#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001585 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1586#else
1587 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1588#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001589 if (n == size_t(-1)) // on error
1590 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001591 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001592 return partial;
1593 for (extern_type* p = tmp; n; --n) // write it
1594 *to_nxt++ = *p++;
1595 ++frm_nxt;
1596 // look for next null in frm
1597 for (fend = frm_nxt; fend != frm_end; ++fend)
1598 if (*fend == 0)
1599 break;
1600 }
1601 }
1602 return frm_nxt == frm_end ? ok : partial;
1603}
1604
1605codecvt<wchar_t, char, mbstate_t>::result
1606codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001607 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001608 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1609{
1610 // look for first internal null in frm
1611 const extern_type* fend = frm;
1612 for (; fend != frm_end; ++fend)
1613 if (*fend == 0)
1614 break;
1615 // loop over all null-terminated sequences in frm
1616 to_nxt = to;
1617 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1618 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001619 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001620 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001621#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001622 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1623 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001624#else
1625 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1626#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001627 if (n == size_t(-1))
1628 {
1629 // need to recover to_nxt
1630 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1631 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001632#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001633 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1634 &save_state, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001635#else
1636 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1637#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001638 switch (n)
1639 {
1640 case 0:
1641 ++frm;
1642 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001643 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001644 frm_nxt = frm;
1645 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001646 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001647 frm_nxt = frm;
1648 return partial;
1649 default:
1650 frm += n;
1651 break;
1652 }
1653 }
1654 frm_nxt = frm;
1655 return frm_nxt == frm_end ? ok : partial;
1656 }
Joerg Sonnenberger850f24f2015-06-05 15:54:26 +00001657 if (n == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001658 return error;
1659 to_nxt += n;
1660 if (to_nxt == to_end)
1661 break;
1662 if (fend != frm_end) // set up next null terminated sequence
1663 {
1664 // Try to write the terminating null
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001665#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001666 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1667#else
1668 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1669#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001670 if (n != 0) // on error
1671 return error;
1672 ++to_nxt;
1673 ++frm_nxt;
1674 // look for next null in frm
1675 for (fend = frm_nxt; fend != frm_end; ++fend)
1676 if (*fend == 0)
1677 break;
1678 }
1679 }
1680 return frm_nxt == frm_end ? ok : partial;
1681}
1682
1683codecvt<wchar_t, char, mbstate_t>::result
1684codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1685 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1686{
1687 to_nxt = to;
1688 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001689#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001690 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1691#else
1692 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1693#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001694 if (n == size_t(-1) || n == 0) // on error
1695 return error;
1696 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001697 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001698 return partial;
1699 for (extern_type* p = tmp; n; --n) // write it
1700 *to_nxt++ = *p++;
1701 return ok;
1702}
1703
1704int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001705codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001706{
Ed Schouten3d3341e2015-07-06 15:39:36 +00001707#ifndef __CloudABI__
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001708#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Ed Schouten3d3341e2015-07-06 15:39:36 +00001709 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001710#else
Ed Schouten3d3341e2015-07-06 15:39:36 +00001711 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001712#endif
Ed Schouten3d3341e2015-07-06 15:39:36 +00001713 return -1;
1714#endif
1715
1716 // stateless encoding
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001717#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Ed Schouten3d3341e2015-07-06 15:39:36 +00001718 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001719#else
Ed Schouten3d3341e2015-07-06 15:39:36 +00001720 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001721#endif
Ed Schouten3d3341e2015-07-06 15:39:36 +00001722 return 1; // which take more than 1 char to form a wchar_t
1723 return 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001724}
1725
1726bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001727codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001728{
1729 return false;
1730}
1731
1732int
1733codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1734 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1735{
1736 int nbytes = 0;
1737 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1738 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001739#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001740 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001741#else
1742 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1743#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001744 switch (n)
1745 {
1746 case 0:
1747 ++nbytes;
1748 ++frm;
1749 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001750 case size_t(-1):
1751 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001752 return nbytes;
1753 default:
1754 nbytes += n;
1755 frm += n;
1756 break;
1757 }
1758 }
1759 return nbytes;
1760}
1761
1762int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001763codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001764{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001765#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clowab9c1772013-02-07 17:20:56 +00001766 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001767#else
Marshall Clowab9c1772013-02-07 17:20:56 +00001768 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001769#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001770}
1771
1772// Valid UTF ranges
1773// UTF-32 UTF-16 UTF-8 # of code points
1774// first second first second third fourth
1775// 000000 - 00007F 0000 - 007F 00 - 7F 127
1776// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1777// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1778// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1779// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1780// 00D800 - 00DFFF invalid
1781// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1782// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1783// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1784// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1785
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001786static
1787codecvt_base::result
1788utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1789 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1790 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1791{
1792 frm_nxt = frm;
1793 to_nxt = to;
1794 if (mode & generate_header)
1795 {
1796 if (to_end-to_nxt < 3)
1797 return codecvt_base::partial;
1798 *to_nxt++ = static_cast<uint8_t>(0xEF);
1799 *to_nxt++ = static_cast<uint8_t>(0xBB);
1800 *to_nxt++ = static_cast<uint8_t>(0xBF);
1801 }
1802 for (; frm_nxt < frm_end; ++frm_nxt)
1803 {
1804 uint16_t wc1 = *frm_nxt;
1805 if (wc1 > Maxcode)
1806 return codecvt_base::error;
1807 if (wc1 < 0x0080)
1808 {
1809 if (to_end-to_nxt < 1)
1810 return codecvt_base::partial;
1811 *to_nxt++ = static_cast<uint8_t>(wc1);
1812 }
1813 else if (wc1 < 0x0800)
1814 {
1815 if (to_end-to_nxt < 2)
1816 return codecvt_base::partial;
1817 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1818 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1819 }
1820 else if (wc1 < 0xD800)
1821 {
1822 if (to_end-to_nxt < 3)
1823 return codecvt_base::partial;
1824 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1825 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1826 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1827 }
1828 else if (wc1 < 0xDC00)
1829 {
1830 if (frm_end-frm_nxt < 2)
1831 return codecvt_base::partial;
1832 uint16_t wc2 = frm_nxt[1];
1833 if ((wc2 & 0xFC00) != 0xDC00)
1834 return codecvt_base::error;
1835 if (to_end-to_nxt < 4)
1836 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001837 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1838 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001839 return codecvt_base::error;
1840 ++frm_nxt;
1841 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1842 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1843 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1844 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1845 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1846 }
1847 else if (wc1 < 0xE000)
1848 {
1849 return codecvt_base::error;
1850 }
1851 else
1852 {
1853 if (to_end-to_nxt < 3)
1854 return codecvt_base::partial;
1855 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1856 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1857 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1858 }
1859 }
1860 return codecvt_base::ok;
1861}
1862
1863static
1864codecvt_base::result
1865utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1866 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1867 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1868{
1869 frm_nxt = frm;
1870 to_nxt = to;
1871 if (mode & generate_header)
1872 {
1873 if (to_end-to_nxt < 3)
1874 return codecvt_base::partial;
1875 *to_nxt++ = static_cast<uint8_t>(0xEF);
1876 *to_nxt++ = static_cast<uint8_t>(0xBB);
1877 *to_nxt++ = static_cast<uint8_t>(0xBF);
1878 }
1879 for (; frm_nxt < frm_end; ++frm_nxt)
1880 {
1881 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1882 if (wc1 > Maxcode)
1883 return codecvt_base::error;
1884 if (wc1 < 0x0080)
1885 {
1886 if (to_end-to_nxt < 1)
1887 return codecvt_base::partial;
1888 *to_nxt++ = static_cast<uint8_t>(wc1);
1889 }
1890 else if (wc1 < 0x0800)
1891 {
1892 if (to_end-to_nxt < 2)
1893 return codecvt_base::partial;
1894 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1895 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1896 }
1897 else if (wc1 < 0xD800)
1898 {
1899 if (to_end-to_nxt < 3)
1900 return codecvt_base::partial;
1901 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1902 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1903 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1904 }
1905 else if (wc1 < 0xDC00)
1906 {
1907 if (frm_end-frm_nxt < 2)
1908 return codecvt_base::partial;
1909 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1910 if ((wc2 & 0xFC00) != 0xDC00)
1911 return codecvt_base::error;
1912 if (to_end-to_nxt < 4)
1913 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001914 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1915 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001916 return codecvt_base::error;
1917 ++frm_nxt;
1918 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1919 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1920 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1921 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1922 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1923 }
1924 else if (wc1 < 0xE000)
1925 {
1926 return codecvt_base::error;
1927 }
1928 else
1929 {
1930 if (to_end-to_nxt < 3)
1931 return codecvt_base::partial;
1932 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1933 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1934 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1935 }
1936 }
1937 return codecvt_base::ok;
1938}
1939
1940static
1941codecvt_base::result
1942utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1943 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1944 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1945{
1946 frm_nxt = frm;
1947 to_nxt = to;
1948 if (mode & consume_header)
1949 {
1950 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1951 frm_nxt[2] == 0xBF)
1952 frm_nxt += 3;
1953 }
1954 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1955 {
1956 uint8_t c1 = *frm_nxt;
1957 if (c1 > Maxcode)
1958 return codecvt_base::error;
1959 if (c1 < 0x80)
1960 {
1961 *to_nxt = static_cast<uint16_t>(c1);
1962 ++frm_nxt;
1963 }
1964 else if (c1 < 0xC2)
1965 {
1966 return codecvt_base::error;
1967 }
1968 else if (c1 < 0xE0)
1969 {
1970 if (frm_end-frm_nxt < 2)
1971 return codecvt_base::partial;
1972 uint8_t c2 = frm_nxt[1];
1973 if ((c2 & 0xC0) != 0x80)
1974 return codecvt_base::error;
1975 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1976 if (t > Maxcode)
1977 return codecvt_base::error;
1978 *to_nxt = t;
1979 frm_nxt += 2;
1980 }
1981 else if (c1 < 0xF0)
1982 {
1983 if (frm_end-frm_nxt < 3)
1984 return codecvt_base::partial;
1985 uint8_t c2 = frm_nxt[1];
1986 uint8_t c3 = frm_nxt[2];
1987 switch (c1)
1988 {
1989 case 0xE0:
1990 if ((c2 & 0xE0) != 0xA0)
1991 return codecvt_base::error;
1992 break;
1993 case 0xED:
1994 if ((c2 & 0xE0) != 0x80)
1995 return codecvt_base::error;
1996 break;
1997 default:
1998 if ((c2 & 0xC0) != 0x80)
1999 return codecvt_base::error;
2000 break;
2001 }
2002 if ((c3 & 0xC0) != 0x80)
2003 return codecvt_base::error;
2004 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2005 | ((c2 & 0x3F) << 6)
2006 | (c3 & 0x3F));
2007 if (t > Maxcode)
2008 return codecvt_base::error;
2009 *to_nxt = t;
2010 frm_nxt += 3;
2011 }
2012 else if (c1 < 0xF5)
2013 {
2014 if (frm_end-frm_nxt < 4)
2015 return codecvt_base::partial;
2016 uint8_t c2 = frm_nxt[1];
2017 uint8_t c3 = frm_nxt[2];
2018 uint8_t c4 = frm_nxt[3];
2019 switch (c1)
2020 {
2021 case 0xF0:
2022 if (!(0x90 <= c2 && c2 <= 0xBF))
2023 return codecvt_base::error;
2024 break;
2025 case 0xF4:
2026 if ((c2 & 0xF0) != 0x80)
2027 return codecvt_base::error;
2028 break;
2029 default:
2030 if ((c2 & 0xC0) != 0x80)
2031 return codecvt_base::error;
2032 break;
2033 }
2034 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2035 return codecvt_base::error;
2036 if (to_end-to_nxt < 2)
2037 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002038 if ((((c1 & 7UL) << 18) +
2039 ((c2 & 0x3FUL) << 12) +
2040 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002041 return codecvt_base::error;
2042 *to_nxt = static_cast<uint16_t>(
2043 0xD800
2044 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2045 | ((c2 & 0x0F) << 2)
2046 | ((c3 & 0x30) >> 4));
2047 *++to_nxt = static_cast<uint16_t>(
2048 0xDC00
2049 | ((c3 & 0x0F) << 6)
2050 | (c4 & 0x3F));
2051 frm_nxt += 4;
2052 }
2053 else
2054 {
2055 return codecvt_base::error;
2056 }
2057 }
2058 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2059}
2060
2061static
2062codecvt_base::result
2063utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2064 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2065 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2066{
2067 frm_nxt = frm;
2068 to_nxt = to;
2069 if (mode & consume_header)
2070 {
2071 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2072 frm_nxt[2] == 0xBF)
2073 frm_nxt += 3;
2074 }
2075 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2076 {
2077 uint8_t c1 = *frm_nxt;
2078 if (c1 > Maxcode)
2079 return codecvt_base::error;
2080 if (c1 < 0x80)
2081 {
2082 *to_nxt = static_cast<uint32_t>(c1);
2083 ++frm_nxt;
2084 }
2085 else if (c1 < 0xC2)
2086 {
2087 return codecvt_base::error;
2088 }
2089 else if (c1 < 0xE0)
2090 {
2091 if (frm_end-frm_nxt < 2)
2092 return codecvt_base::partial;
2093 uint8_t c2 = frm_nxt[1];
2094 if ((c2 & 0xC0) != 0x80)
2095 return codecvt_base::error;
2096 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2097 if (t > Maxcode)
2098 return codecvt_base::error;
2099 *to_nxt = static_cast<uint32_t>(t);
2100 frm_nxt += 2;
2101 }
2102 else if (c1 < 0xF0)
2103 {
2104 if (frm_end-frm_nxt < 3)
2105 return codecvt_base::partial;
2106 uint8_t c2 = frm_nxt[1];
2107 uint8_t c3 = frm_nxt[2];
2108 switch (c1)
2109 {
2110 case 0xE0:
2111 if ((c2 & 0xE0) != 0xA0)
2112 return codecvt_base::error;
2113 break;
2114 case 0xED:
2115 if ((c2 & 0xE0) != 0x80)
2116 return codecvt_base::error;
2117 break;
2118 default:
2119 if ((c2 & 0xC0) != 0x80)
2120 return codecvt_base::error;
2121 break;
2122 }
2123 if ((c3 & 0xC0) != 0x80)
2124 return codecvt_base::error;
2125 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2126 | ((c2 & 0x3F) << 6)
2127 | (c3 & 0x3F));
2128 if (t > Maxcode)
2129 return codecvt_base::error;
2130 *to_nxt = static_cast<uint32_t>(t);
2131 frm_nxt += 3;
2132 }
2133 else if (c1 < 0xF5)
2134 {
2135 if (frm_end-frm_nxt < 4)
2136 return codecvt_base::partial;
2137 uint8_t c2 = frm_nxt[1];
2138 uint8_t c3 = frm_nxt[2];
2139 uint8_t c4 = frm_nxt[3];
2140 switch (c1)
2141 {
2142 case 0xF0:
2143 if (!(0x90 <= c2 && c2 <= 0xBF))
2144 return codecvt_base::error;
2145 break;
2146 case 0xF4:
2147 if ((c2 & 0xF0) != 0x80)
2148 return codecvt_base::error;
2149 break;
2150 default:
2151 if ((c2 & 0xC0) != 0x80)
2152 return codecvt_base::error;
2153 break;
2154 }
2155 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2156 return codecvt_base::error;
2157 if (to_end-to_nxt < 2)
2158 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002159 if ((((c1 & 7UL) << 18) +
2160 ((c2 & 0x3FUL) << 12) +
2161 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002162 return codecvt_base::error;
2163 *to_nxt = static_cast<uint32_t>(
2164 0xD800
2165 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2166 | ((c2 & 0x0F) << 2)
2167 | ((c3 & 0x30) >> 4));
2168 *++to_nxt = static_cast<uint32_t>(
2169 0xDC00
2170 | ((c3 & 0x0F) << 6)
2171 | (c4 & 0x3F));
2172 frm_nxt += 4;
2173 }
2174 else
2175 {
2176 return codecvt_base::error;
2177 }
2178 }
2179 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2180}
2181
2182static
2183int
2184utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2185 size_t mx, unsigned long Maxcode = 0x10FFFF,
2186 codecvt_mode mode = codecvt_mode(0))
2187{
2188 const uint8_t* frm_nxt = frm;
2189 if (mode & consume_header)
2190 {
2191 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2192 frm_nxt[2] == 0xBF)
2193 frm_nxt += 3;
2194 }
2195 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2196 {
2197 uint8_t c1 = *frm_nxt;
2198 if (c1 > Maxcode)
2199 break;
2200 if (c1 < 0x80)
2201 {
2202 ++frm_nxt;
2203 }
2204 else if (c1 < 0xC2)
2205 {
2206 break;
2207 }
2208 else if (c1 < 0xE0)
2209 {
2210 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2211 break;
2212 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2213 if (t > Maxcode)
2214 break;
2215 frm_nxt += 2;
2216 }
2217 else if (c1 < 0xF0)
2218 {
2219 if (frm_end-frm_nxt < 3)
2220 break;
2221 uint8_t c2 = frm_nxt[1];
2222 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002223 switch (c1)
2224 {
2225 case 0xE0:
2226 if ((c2 & 0xE0) != 0xA0)
2227 return static_cast<int>(frm_nxt - frm);
2228 break;
2229 case 0xED:
2230 if ((c2 & 0xE0) != 0x80)
2231 return static_cast<int>(frm_nxt - frm);
2232 break;
2233 default:
2234 if ((c2 & 0xC0) != 0x80)
2235 return static_cast<int>(frm_nxt - frm);
2236 break;
2237 }
2238 if ((c3 & 0xC0) != 0x80)
2239 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002240 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002241 break;
2242 frm_nxt += 3;
2243 }
2244 else if (c1 < 0xF5)
2245 {
2246 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2247 break;
2248 uint8_t c2 = frm_nxt[1];
2249 uint8_t c3 = frm_nxt[2];
2250 uint8_t c4 = frm_nxt[3];
2251 switch (c1)
2252 {
2253 case 0xF0:
2254 if (!(0x90 <= c2 && c2 <= 0xBF))
2255 return static_cast<int>(frm_nxt - frm);
2256 break;
2257 case 0xF4:
2258 if ((c2 & 0xF0) != 0x80)
2259 return static_cast<int>(frm_nxt - frm);
2260 break;
2261 default:
2262 if ((c2 & 0xC0) != 0x80)
2263 return static_cast<int>(frm_nxt - frm);
2264 break;
2265 }
2266 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2267 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002268 if ((((c1 & 7UL) << 18) +
2269 ((c2 & 0x3FUL) << 12) +
2270 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002271 break;
2272 ++nchar16_t;
2273 frm_nxt += 4;
2274 }
2275 else
2276 {
2277 break;
2278 }
2279 }
2280 return static_cast<int>(frm_nxt - frm);
2281}
2282
2283static
2284codecvt_base::result
2285ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2286 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2287 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2288{
2289 frm_nxt = frm;
2290 to_nxt = to;
2291 if (mode & generate_header)
2292 {
2293 if (to_end-to_nxt < 3)
2294 return codecvt_base::partial;
2295 *to_nxt++ = static_cast<uint8_t>(0xEF);
2296 *to_nxt++ = static_cast<uint8_t>(0xBB);
2297 *to_nxt++ = static_cast<uint8_t>(0xBF);
2298 }
2299 for (; frm_nxt < frm_end; ++frm_nxt)
2300 {
2301 uint32_t wc = *frm_nxt;
2302 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2303 return codecvt_base::error;
2304 if (wc < 0x000080)
2305 {
2306 if (to_end-to_nxt < 1)
2307 return codecvt_base::partial;
2308 *to_nxt++ = static_cast<uint8_t>(wc);
2309 }
2310 else if (wc < 0x000800)
2311 {
2312 if (to_end-to_nxt < 2)
2313 return codecvt_base::partial;
2314 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2315 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2316 }
2317 else if (wc < 0x010000)
2318 {
2319 if (to_end-to_nxt < 3)
2320 return codecvt_base::partial;
2321 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2322 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2323 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2324 }
2325 else // if (wc < 0x110000)
2326 {
2327 if (to_end-to_nxt < 4)
2328 return codecvt_base::partial;
2329 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2330 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2331 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2332 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2333 }
2334 }
2335 return codecvt_base::ok;
2336}
2337
2338static
2339codecvt_base::result
2340utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2341 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2342 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2343{
2344 frm_nxt = frm;
2345 to_nxt = to;
2346 if (mode & consume_header)
2347 {
2348 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2349 frm_nxt[2] == 0xBF)
2350 frm_nxt += 3;
2351 }
2352 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2353 {
2354 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2355 if (c1 < 0x80)
2356 {
2357 if (c1 > Maxcode)
2358 return codecvt_base::error;
2359 *to_nxt = static_cast<uint32_t>(c1);
2360 ++frm_nxt;
2361 }
2362 else if (c1 < 0xC2)
2363 {
2364 return codecvt_base::error;
2365 }
2366 else if (c1 < 0xE0)
2367 {
2368 if (frm_end-frm_nxt < 2)
2369 return codecvt_base::partial;
2370 uint8_t c2 = frm_nxt[1];
2371 if ((c2 & 0xC0) != 0x80)
2372 return codecvt_base::error;
2373 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2374 | (c2 & 0x3F));
2375 if (t > Maxcode)
2376 return codecvt_base::error;
2377 *to_nxt = t;
2378 frm_nxt += 2;
2379 }
2380 else if (c1 < 0xF0)
2381 {
2382 if (frm_end-frm_nxt < 3)
2383 return codecvt_base::partial;
2384 uint8_t c2 = frm_nxt[1];
2385 uint8_t c3 = frm_nxt[2];
2386 switch (c1)
2387 {
2388 case 0xE0:
2389 if ((c2 & 0xE0) != 0xA0)
2390 return codecvt_base::error;
2391 break;
2392 case 0xED:
2393 if ((c2 & 0xE0) != 0x80)
2394 return codecvt_base::error;
2395 break;
2396 default:
2397 if ((c2 & 0xC0) != 0x80)
2398 return codecvt_base::error;
2399 break;
2400 }
2401 if ((c3 & 0xC0) != 0x80)
2402 return codecvt_base::error;
2403 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2404 | ((c2 & 0x3F) << 6)
2405 | (c3 & 0x3F));
2406 if (t > Maxcode)
2407 return codecvt_base::error;
2408 *to_nxt = t;
2409 frm_nxt += 3;
2410 }
2411 else if (c1 < 0xF5)
2412 {
2413 if (frm_end-frm_nxt < 4)
2414 return codecvt_base::partial;
2415 uint8_t c2 = frm_nxt[1];
2416 uint8_t c3 = frm_nxt[2];
2417 uint8_t c4 = frm_nxt[3];
2418 switch (c1)
2419 {
2420 case 0xF0:
2421 if (!(0x90 <= c2 && c2 <= 0xBF))
2422 return codecvt_base::error;
2423 break;
2424 case 0xF4:
2425 if ((c2 & 0xF0) != 0x80)
2426 return codecvt_base::error;
2427 break;
2428 default:
2429 if ((c2 & 0xC0) != 0x80)
2430 return codecvt_base::error;
2431 break;
2432 }
2433 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2434 return codecvt_base::error;
2435 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2436 | ((c2 & 0x3F) << 12)
2437 | ((c3 & 0x3F) << 6)
2438 | (c4 & 0x3F));
2439 if (t > Maxcode)
2440 return codecvt_base::error;
2441 *to_nxt = t;
2442 frm_nxt += 4;
2443 }
2444 else
2445 {
2446 return codecvt_base::error;
2447 }
2448 }
2449 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2450}
2451
2452static
2453int
2454utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2455 size_t mx, unsigned long Maxcode = 0x10FFFF,
2456 codecvt_mode mode = codecvt_mode(0))
2457{
2458 const uint8_t* frm_nxt = frm;
2459 if (mode & consume_header)
2460 {
2461 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2462 frm_nxt[2] == 0xBF)
2463 frm_nxt += 3;
2464 }
2465 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2466 {
2467 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2468 if (c1 < 0x80)
2469 {
2470 if (c1 > Maxcode)
2471 break;
2472 ++frm_nxt;
2473 }
2474 else if (c1 < 0xC2)
2475 {
2476 break;
2477 }
2478 else if (c1 < 0xE0)
2479 {
2480 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2481 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002482 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002483 break;
2484 frm_nxt += 2;
2485 }
2486 else if (c1 < 0xF0)
2487 {
2488 if (frm_end-frm_nxt < 3)
2489 break;
2490 uint8_t c2 = frm_nxt[1];
2491 uint8_t c3 = frm_nxt[2];
2492 switch (c1)
2493 {
2494 case 0xE0:
2495 if ((c2 & 0xE0) != 0xA0)
2496 return static_cast<int>(frm_nxt - frm);
2497 break;
2498 case 0xED:
2499 if ((c2 & 0xE0) != 0x80)
2500 return static_cast<int>(frm_nxt - frm);
2501 break;
2502 default:
2503 if ((c2 & 0xC0) != 0x80)
2504 return static_cast<int>(frm_nxt - frm);
2505 break;
2506 }
2507 if ((c3 & 0xC0) != 0x80)
2508 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002509 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002510 break;
2511 frm_nxt += 3;
2512 }
2513 else if (c1 < 0xF5)
2514 {
2515 if (frm_end-frm_nxt < 4)
2516 break;
2517 uint8_t c2 = frm_nxt[1];
2518 uint8_t c3 = frm_nxt[2];
2519 uint8_t c4 = frm_nxt[3];
2520 switch (c1)
2521 {
2522 case 0xF0:
2523 if (!(0x90 <= c2 && c2 <= 0xBF))
2524 return static_cast<int>(frm_nxt - frm);
2525 break;
2526 case 0xF4:
2527 if ((c2 & 0xF0) != 0x80)
2528 return static_cast<int>(frm_nxt - frm);
2529 break;
2530 default:
2531 if ((c2 & 0xC0) != 0x80)
2532 return static_cast<int>(frm_nxt - frm);
2533 break;
2534 }
2535 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2536 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002537 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2538 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002539 break;
2540 frm_nxt += 4;
2541 }
2542 else
2543 {
2544 break;
2545 }
2546 }
2547 return static_cast<int>(frm_nxt - frm);
2548}
2549
2550static
2551codecvt_base::result
2552ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2553 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2554 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2555{
2556 frm_nxt = frm;
2557 to_nxt = to;
2558 if (mode & generate_header)
2559 {
2560 if (to_end-to_nxt < 3)
2561 return codecvt_base::partial;
2562 *to_nxt++ = static_cast<uint8_t>(0xEF);
2563 *to_nxt++ = static_cast<uint8_t>(0xBB);
2564 *to_nxt++ = static_cast<uint8_t>(0xBF);
2565 }
2566 for (; frm_nxt < frm_end; ++frm_nxt)
2567 {
2568 uint16_t wc = *frm_nxt;
2569 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2570 return codecvt_base::error;
2571 if (wc < 0x0080)
2572 {
2573 if (to_end-to_nxt < 1)
2574 return codecvt_base::partial;
2575 *to_nxt++ = static_cast<uint8_t>(wc);
2576 }
2577 else if (wc < 0x0800)
2578 {
2579 if (to_end-to_nxt < 2)
2580 return codecvt_base::partial;
2581 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2582 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2583 }
2584 else // if (wc <= 0xFFFF)
2585 {
2586 if (to_end-to_nxt < 3)
2587 return codecvt_base::partial;
2588 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2589 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2590 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2591 }
2592 }
2593 return codecvt_base::ok;
2594}
2595
2596static
2597codecvt_base::result
2598utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2599 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2600 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2601{
2602 frm_nxt = frm;
2603 to_nxt = to;
2604 if (mode & consume_header)
2605 {
2606 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2607 frm_nxt[2] == 0xBF)
2608 frm_nxt += 3;
2609 }
2610 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2611 {
2612 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2613 if (c1 < 0x80)
2614 {
2615 if (c1 > Maxcode)
2616 return codecvt_base::error;
2617 *to_nxt = static_cast<uint16_t>(c1);
2618 ++frm_nxt;
2619 }
2620 else if (c1 < 0xC2)
2621 {
2622 return codecvt_base::error;
2623 }
2624 else if (c1 < 0xE0)
2625 {
2626 if (frm_end-frm_nxt < 2)
2627 return codecvt_base::partial;
2628 uint8_t c2 = frm_nxt[1];
2629 if ((c2 & 0xC0) != 0x80)
2630 return codecvt_base::error;
2631 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2632 | (c2 & 0x3F));
2633 if (t > Maxcode)
2634 return codecvt_base::error;
2635 *to_nxt = t;
2636 frm_nxt += 2;
2637 }
2638 else if (c1 < 0xF0)
2639 {
2640 if (frm_end-frm_nxt < 3)
2641 return codecvt_base::partial;
2642 uint8_t c2 = frm_nxt[1];
2643 uint8_t c3 = frm_nxt[2];
2644 switch (c1)
2645 {
2646 case 0xE0:
2647 if ((c2 & 0xE0) != 0xA0)
2648 return codecvt_base::error;
2649 break;
2650 case 0xED:
2651 if ((c2 & 0xE0) != 0x80)
2652 return codecvt_base::error;
2653 break;
2654 default:
2655 if ((c2 & 0xC0) != 0x80)
2656 return codecvt_base::error;
2657 break;
2658 }
2659 if ((c3 & 0xC0) != 0x80)
2660 return codecvt_base::error;
2661 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2662 | ((c2 & 0x3F) << 6)
2663 | (c3 & 0x3F));
2664 if (t > Maxcode)
2665 return codecvt_base::error;
2666 *to_nxt = t;
2667 frm_nxt += 3;
2668 }
2669 else
2670 {
2671 return codecvt_base::error;
2672 }
2673 }
2674 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2675}
2676
2677static
2678int
2679utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2680 size_t mx, unsigned long Maxcode = 0x10FFFF,
2681 codecvt_mode mode = codecvt_mode(0))
2682{
2683 const uint8_t* frm_nxt = frm;
2684 if (mode & consume_header)
2685 {
2686 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2687 frm_nxt[2] == 0xBF)
2688 frm_nxt += 3;
2689 }
2690 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2691 {
2692 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2693 if (c1 < 0x80)
2694 {
2695 if (c1 > Maxcode)
2696 break;
2697 ++frm_nxt;
2698 }
2699 else if (c1 < 0xC2)
2700 {
2701 break;
2702 }
2703 else if (c1 < 0xE0)
2704 {
2705 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2706 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002707 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002708 break;
2709 frm_nxt += 2;
2710 }
2711 else if (c1 < 0xF0)
2712 {
2713 if (frm_end-frm_nxt < 3)
2714 break;
2715 uint8_t c2 = frm_nxt[1];
2716 uint8_t c3 = frm_nxt[2];
2717 switch (c1)
2718 {
2719 case 0xE0:
2720 if ((c2 & 0xE0) != 0xA0)
2721 return static_cast<int>(frm_nxt - frm);
2722 break;
2723 case 0xED:
2724 if ((c2 & 0xE0) != 0x80)
2725 return static_cast<int>(frm_nxt - frm);
2726 break;
2727 default:
2728 if ((c2 & 0xC0) != 0x80)
2729 return static_cast<int>(frm_nxt - frm);
2730 break;
2731 }
2732 if ((c3 & 0xC0) != 0x80)
2733 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002734 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002735 break;
2736 frm_nxt += 3;
2737 }
2738 else
2739 {
2740 break;
2741 }
2742 }
2743 return static_cast<int>(frm_nxt - frm);
2744}
2745
2746static
2747codecvt_base::result
2748ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2749 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2750 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2751{
2752 frm_nxt = frm;
2753 to_nxt = to;
2754 if (mode & generate_header)
2755 {
2756 if (to_end-to_nxt < 2)
2757 return codecvt_base::partial;
2758 *to_nxt++ = static_cast<uint8_t>(0xFE);
2759 *to_nxt++ = static_cast<uint8_t>(0xFF);
2760 }
2761 for (; frm_nxt < frm_end; ++frm_nxt)
2762 {
2763 uint32_t wc = *frm_nxt;
2764 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2765 return codecvt_base::error;
2766 if (wc < 0x010000)
2767 {
2768 if (to_end-to_nxt < 2)
2769 return codecvt_base::partial;
2770 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2771 *to_nxt++ = static_cast<uint8_t>(wc);
2772 }
2773 else
2774 {
2775 if (to_end-to_nxt < 4)
2776 return codecvt_base::partial;
2777 uint16_t t = static_cast<uint16_t>(
2778 0xD800
2779 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2780 | ((wc & 0x00FC00) >> 10));
2781 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2782 *to_nxt++ = static_cast<uint8_t>(t);
2783 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2784 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2785 *to_nxt++ = static_cast<uint8_t>(t);
2786 }
2787 }
2788 return codecvt_base::ok;
2789}
2790
2791static
2792codecvt_base::result
2793utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2794 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2795 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2796{
2797 frm_nxt = frm;
2798 to_nxt = to;
2799 if (mode & consume_header)
2800 {
2801 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2802 frm_nxt += 2;
2803 }
2804 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2805 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002806 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002807 if ((c1 & 0xFC00) == 0xDC00)
2808 return codecvt_base::error;
2809 if ((c1 & 0xFC00) != 0xD800)
2810 {
2811 if (c1 > Maxcode)
2812 return codecvt_base::error;
2813 *to_nxt = static_cast<uint32_t>(c1);
2814 frm_nxt += 2;
2815 }
2816 else
2817 {
2818 if (frm_end-frm_nxt < 4)
2819 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002820 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002821 if ((c2 & 0xFC00) != 0xDC00)
2822 return codecvt_base::error;
2823 uint32_t t = static_cast<uint32_t>(
2824 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2825 | ((c1 & 0x003F) << 10)
2826 | (c2 & 0x03FF));
2827 if (t > Maxcode)
2828 return codecvt_base::error;
2829 *to_nxt = t;
2830 frm_nxt += 4;
2831 }
2832 }
2833 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2834}
2835
2836static
2837int
2838utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2839 size_t mx, unsigned long Maxcode = 0x10FFFF,
2840 codecvt_mode mode = codecvt_mode(0))
2841{
2842 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002843 if (mode & consume_header)
2844 {
2845 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2846 frm_nxt += 2;
2847 }
2848 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2849 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002850 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002851 if ((c1 & 0xFC00) == 0xDC00)
2852 break;
2853 if ((c1 & 0xFC00) != 0xD800)
2854 {
2855 if (c1 > Maxcode)
2856 break;
2857 frm_nxt += 2;
2858 }
2859 else
2860 {
2861 if (frm_end-frm_nxt < 4)
2862 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002863 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002864 if ((c2 & 0xFC00) != 0xDC00)
2865 break;
2866 uint32_t t = static_cast<uint32_t>(
2867 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2868 | ((c1 & 0x003F) << 10)
2869 | (c2 & 0x03FF));
2870 if (t > Maxcode)
2871 break;
2872 frm_nxt += 4;
2873 }
2874 }
2875 return static_cast<int>(frm_nxt - frm);
2876}
2877
2878static
2879codecvt_base::result
2880ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2881 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2882 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2883{
2884 frm_nxt = frm;
2885 to_nxt = to;
2886 if (mode & generate_header)
2887 {
2888 if (to_end-to_nxt < 2)
2889 return codecvt_base::partial;
2890 *to_nxt++ = static_cast<uint8_t>(0xFF);
2891 *to_nxt++ = static_cast<uint8_t>(0xFE);
2892 }
2893 for (; frm_nxt < frm_end; ++frm_nxt)
2894 {
2895 uint32_t wc = *frm_nxt;
2896 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2897 return codecvt_base::error;
2898 if (wc < 0x010000)
2899 {
2900 if (to_end-to_nxt < 2)
2901 return codecvt_base::partial;
2902 *to_nxt++ = static_cast<uint8_t>(wc);
2903 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2904 }
2905 else
2906 {
2907 if (to_end-to_nxt < 4)
2908 return codecvt_base::partial;
2909 uint16_t t = static_cast<uint16_t>(
2910 0xD800
2911 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2912 | ((wc & 0x00FC00) >> 10));
2913 *to_nxt++ = static_cast<uint8_t>(t);
2914 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2915 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2916 *to_nxt++ = static_cast<uint8_t>(t);
2917 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2918 }
2919 }
2920 return codecvt_base::ok;
2921}
2922
2923static
2924codecvt_base::result
2925utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2926 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2927 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2928{
2929 frm_nxt = frm;
2930 to_nxt = to;
2931 if (mode & consume_header)
2932 {
2933 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2934 frm_nxt += 2;
2935 }
2936 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2937 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002938 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002939 if ((c1 & 0xFC00) == 0xDC00)
2940 return codecvt_base::error;
2941 if ((c1 & 0xFC00) != 0xD800)
2942 {
2943 if (c1 > Maxcode)
2944 return codecvt_base::error;
2945 *to_nxt = static_cast<uint32_t>(c1);
2946 frm_nxt += 2;
2947 }
2948 else
2949 {
2950 if (frm_end-frm_nxt < 4)
2951 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002952 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002953 if ((c2 & 0xFC00) != 0xDC00)
2954 return codecvt_base::error;
2955 uint32_t t = static_cast<uint32_t>(
2956 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2957 | ((c1 & 0x003F) << 10)
2958 | (c2 & 0x03FF));
2959 if (t > Maxcode)
2960 return codecvt_base::error;
2961 *to_nxt = t;
2962 frm_nxt += 4;
2963 }
2964 }
2965 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2966}
2967
2968static
2969int
2970utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2971 size_t mx, unsigned long Maxcode = 0x10FFFF,
2972 codecvt_mode mode = codecvt_mode(0))
2973{
2974 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002975 if (mode & consume_header)
2976 {
2977 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2978 frm_nxt += 2;
2979 }
2980 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2981 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002982 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002983 if ((c1 & 0xFC00) == 0xDC00)
2984 break;
2985 if ((c1 & 0xFC00) != 0xD800)
2986 {
2987 if (c1 > Maxcode)
2988 break;
2989 frm_nxt += 2;
2990 }
2991 else
2992 {
2993 if (frm_end-frm_nxt < 4)
2994 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002995 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002996 if ((c2 & 0xFC00) != 0xDC00)
2997 break;
2998 uint32_t t = static_cast<uint32_t>(
2999 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3000 | ((c1 & 0x003F) << 10)
3001 | (c2 & 0x03FF));
3002 if (t > Maxcode)
3003 break;
3004 frm_nxt += 4;
3005 }
3006 }
3007 return static_cast<int>(frm_nxt - frm);
3008}
3009
3010static
3011codecvt_base::result
3012ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3013 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3014 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3015{
3016 frm_nxt = frm;
3017 to_nxt = to;
3018 if (mode & generate_header)
3019 {
3020 if (to_end-to_nxt < 2)
3021 return codecvt_base::partial;
3022 *to_nxt++ = static_cast<uint8_t>(0xFE);
3023 *to_nxt++ = static_cast<uint8_t>(0xFF);
3024 }
3025 for (; frm_nxt < frm_end; ++frm_nxt)
3026 {
3027 uint16_t wc = *frm_nxt;
3028 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3029 return codecvt_base::error;
3030 if (to_end-to_nxt < 2)
3031 return codecvt_base::partial;
3032 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3033 *to_nxt++ = static_cast<uint8_t>(wc);
3034 }
3035 return codecvt_base::ok;
3036}
3037
3038static
3039codecvt_base::result
3040utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3041 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3042 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3043{
3044 frm_nxt = frm;
3045 to_nxt = to;
3046 if (mode & consume_header)
3047 {
3048 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3049 frm_nxt += 2;
3050 }
3051 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3052 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003053 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003054 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3055 return codecvt_base::error;
3056 *to_nxt = c1;
3057 frm_nxt += 2;
3058 }
3059 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3060}
3061
3062static
3063int
3064utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3065 size_t mx, unsigned long Maxcode = 0x10FFFF,
3066 codecvt_mode mode = codecvt_mode(0))
3067{
3068 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003069 if (mode & consume_header)
3070 {
3071 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3072 frm_nxt += 2;
3073 }
3074 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3075 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003076 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003077 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3078 break;
3079 frm_nxt += 2;
3080 }
3081 return static_cast<int>(frm_nxt - frm);
3082}
3083
3084static
3085codecvt_base::result
3086ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3087 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3088 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3089{
3090 frm_nxt = frm;
3091 to_nxt = to;
3092 if (mode & generate_header)
3093 {
3094 if (to_end-to_nxt < 2)
3095 return codecvt_base::partial;
3096 *to_nxt++ = static_cast<uint8_t>(0xFF);
3097 *to_nxt++ = static_cast<uint8_t>(0xFE);
3098 }
3099 for (; frm_nxt < frm_end; ++frm_nxt)
3100 {
3101 uint16_t wc = *frm_nxt;
3102 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3103 return codecvt_base::error;
3104 if (to_end-to_nxt < 2)
3105 return codecvt_base::partial;
3106 *to_nxt++ = static_cast<uint8_t>(wc);
3107 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3108 }
3109 return codecvt_base::ok;
3110}
3111
3112static
3113codecvt_base::result
3114utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3115 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3116 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3117{
3118 frm_nxt = frm;
3119 to_nxt = to;
3120 if (mode & consume_header)
3121 {
3122 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3123 frm_nxt += 2;
3124 }
3125 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3126 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003127 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003128 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3129 return codecvt_base::error;
3130 *to_nxt = c1;
3131 frm_nxt += 2;
3132 }
3133 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3134}
3135
3136static
3137int
3138utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3139 size_t mx, unsigned long Maxcode = 0x10FFFF,
3140 codecvt_mode mode = codecvt_mode(0))
3141{
3142 const uint8_t* frm_nxt = frm;
3143 frm_nxt = frm;
3144 if (mode & consume_header)
3145 {
3146 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3147 frm_nxt += 2;
3148 }
3149 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3150 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003151 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003152 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3153 break;
3154 frm_nxt += 2;
3155 }
3156 return static_cast<int>(frm_nxt - frm);
3157}
3158
Howard Hinnantc51e1022010-05-11 19:42:16 +00003159// template <> class codecvt<char16_t, char, mbstate_t>
3160
Howard Hinnantffb308e2010-08-22 00:03:27 +00003161locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003162
3163codecvt<char16_t, char, mbstate_t>::~codecvt()
3164{
3165}
3166
3167codecvt<char16_t, char, mbstate_t>::result
3168codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003169 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003170 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3171{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003172 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3173 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3174 const uint16_t* _frm_nxt = _frm;
3175 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3176 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3177 uint8_t* _to_nxt = _to;
3178 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3179 frm_nxt = frm + (_frm_nxt - _frm);
3180 to_nxt = to + (_to_nxt - _to);
3181 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003182}
3183
3184codecvt<char16_t, char, mbstate_t>::result
3185codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003186 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003187 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3188{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003189 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3190 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3191 const uint8_t* _frm_nxt = _frm;
3192 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3193 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3194 uint16_t* _to_nxt = _to;
3195 result r = utf8_to_utf16(_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<char16_t, char, mbstate_t>::result
3202codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3203 extern_type* to, extern_type*, extern_type*& to_nxt) const
3204{
3205 to_nxt = to;
3206 return noconv;
3207}
3208
3209int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003210codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003211{
3212 return 0;
3213}
3214
3215bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003216codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003217{
3218 return false;
3219}
3220
3221int
3222codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3223 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3224{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003225 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3226 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3227 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003228}
3229
3230int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003231codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003232{
3233 return 4;
3234}
3235
3236// template <> class codecvt<char32_t, char, mbstate_t>
3237
Howard Hinnantffb308e2010-08-22 00:03:27 +00003238locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003239
3240codecvt<char32_t, char, mbstate_t>::~codecvt()
3241{
3242}
3243
3244codecvt<char32_t, char, mbstate_t>::result
3245codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003246 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003247 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3248{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003249 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3250 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3251 const uint32_t* _frm_nxt = _frm;
3252 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3253 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3254 uint8_t* _to_nxt = _to;
3255 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3256 frm_nxt = frm + (_frm_nxt - _frm);
3257 to_nxt = to + (_to_nxt - _to);
3258 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003259}
3260
3261codecvt<char32_t, char, mbstate_t>::result
3262codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003263 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003264 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3265{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003266 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3267 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3268 const uint8_t* _frm_nxt = _frm;
3269 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3270 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3271 uint32_t* _to_nxt = _to;
3272 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3273 frm_nxt = frm + (_frm_nxt - _frm);
3274 to_nxt = to + (_to_nxt - _to);
3275 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003276}
3277
3278codecvt<char32_t, char, mbstate_t>::result
3279codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3280 extern_type* to, extern_type*, extern_type*& to_nxt) const
3281{
3282 to_nxt = to;
3283 return noconv;
3284}
3285
3286int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003287codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003288{
3289 return 0;
3290}
3291
3292bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003293codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003294{
3295 return false;
3296}
3297
3298int
3299codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3300 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3301{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003302 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3303 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3304 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003305}
3306
3307int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003308codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003309{
3310 return 4;
3311}
3312
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003313// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003314
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003315__codecvt_utf8<wchar_t>::result
3316__codecvt_utf8<wchar_t>::do_out(state_type&,
3317 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003318 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3319{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003320#if _WIN32
3321 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3322 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3323 const uint16_t* _frm_nxt = _frm;
3324#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003325 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3326 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3327 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003328#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003329 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3330 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3331 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003332#if _WIN32
3333 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3334 _Maxcode_, _Mode_);
3335#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003336 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3337 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003338#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003339 frm_nxt = frm + (_frm_nxt - _frm);
3340 to_nxt = to + (_to_nxt - _to);
3341 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003342}
3343
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003344__codecvt_utf8<wchar_t>::result
3345__codecvt_utf8<wchar_t>::do_in(state_type&,
3346 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003347 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3348{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003349 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3350 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3351 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003352#if _WIN32
3353 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3354 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3355 uint16_t* _to_nxt = _to;
3356 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3357 _Maxcode_, _Mode_);
3358#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003359 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3360 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3361 uint32_t* _to_nxt = _to;
3362 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3363 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003364#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003365 frm_nxt = frm + (_frm_nxt - _frm);
3366 to_nxt = to + (_to_nxt - _to);
3367 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003368}
3369
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003370__codecvt_utf8<wchar_t>::result
3371__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003372 extern_type* to, extern_type*, extern_type*& to_nxt) const
3373{
3374 to_nxt = to;
3375 return noconv;
3376}
3377
3378int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003379__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003380{
3381 return 0;
3382}
3383
3384bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003385__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003386{
3387 return false;
3388}
3389
3390int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003391__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003392 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3393{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003394 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3395 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3396 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003397}
3398
3399int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003400__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003401{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003402 if (_Mode_ & consume_header)
3403 return 7;
3404 return 4;
3405}
3406
3407// __codecvt_utf8<char16_t>
3408
3409__codecvt_utf8<char16_t>::result
3410__codecvt_utf8<char16_t>::do_out(state_type&,
3411 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3412 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3413{
3414 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3415 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3416 const uint16_t* _frm_nxt = _frm;
3417 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3418 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3419 uint8_t* _to_nxt = _to;
3420 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3421 _Maxcode_, _Mode_);
3422 frm_nxt = frm + (_frm_nxt - _frm);
3423 to_nxt = to + (_to_nxt - _to);
3424 return r;
3425}
3426
3427__codecvt_utf8<char16_t>::result
3428__codecvt_utf8<char16_t>::do_in(state_type&,
3429 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3430 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3431{
3432 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3433 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3434 const uint8_t* _frm_nxt = _frm;
3435 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3436 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3437 uint16_t* _to_nxt = _to;
3438 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3439 _Maxcode_, _Mode_);
3440 frm_nxt = frm + (_frm_nxt - _frm);
3441 to_nxt = to + (_to_nxt - _to);
3442 return r;
3443}
3444
3445__codecvt_utf8<char16_t>::result
3446__codecvt_utf8<char16_t>::do_unshift(state_type&,
3447 extern_type* to, extern_type*, extern_type*& to_nxt) const
3448{
3449 to_nxt = to;
3450 return noconv;
3451}
3452
3453int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003454__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003455{
3456 return 0;
3457}
3458
3459bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003460__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003461{
3462 return false;
3463}
3464
3465int
3466__codecvt_utf8<char16_t>::do_length(state_type&,
3467 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3468{
3469 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3470 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3471 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3472}
3473
3474int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003475__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003476{
3477 if (_Mode_ & consume_header)
3478 return 6;
3479 return 3;
3480}
3481
3482// __codecvt_utf8<char32_t>
3483
3484__codecvt_utf8<char32_t>::result
3485__codecvt_utf8<char32_t>::do_out(state_type&,
3486 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3487 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3488{
3489 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3490 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3491 const uint32_t* _frm_nxt = _frm;
3492 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3493 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3494 uint8_t* _to_nxt = _to;
3495 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3496 _Maxcode_, _Mode_);
3497 frm_nxt = frm + (_frm_nxt - _frm);
3498 to_nxt = to + (_to_nxt - _to);
3499 return r;
3500}
3501
3502__codecvt_utf8<char32_t>::result
3503__codecvt_utf8<char32_t>::do_in(state_type&,
3504 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3505 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3506{
3507 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3508 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3509 const uint8_t* _frm_nxt = _frm;
3510 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3511 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3512 uint32_t* _to_nxt = _to;
3513 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3514 _Maxcode_, _Mode_);
3515 frm_nxt = frm + (_frm_nxt - _frm);
3516 to_nxt = to + (_to_nxt - _to);
3517 return r;
3518}
3519
3520__codecvt_utf8<char32_t>::result
3521__codecvt_utf8<char32_t>::do_unshift(state_type&,
3522 extern_type* to, extern_type*, extern_type*& to_nxt) const
3523{
3524 to_nxt = to;
3525 return noconv;
3526}
3527
3528int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003529__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003530{
3531 return 0;
3532}
3533
3534bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003535__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003536{
3537 return false;
3538}
3539
3540int
3541__codecvt_utf8<char32_t>::do_length(state_type&,
3542 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3543{
3544 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3545 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3546 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3547}
3548
3549int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003550__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003551{
3552 if (_Mode_ & consume_header)
3553 return 7;
3554 return 4;
3555}
3556
3557// __codecvt_utf16<wchar_t, false>
3558
3559__codecvt_utf16<wchar_t, false>::result
3560__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3561 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3562 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3563{
3564 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3565 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3566 const uint32_t* _frm_nxt = _frm;
3567 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3568 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3569 uint8_t* _to_nxt = _to;
3570 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3571 _Maxcode_, _Mode_);
3572 frm_nxt = frm + (_frm_nxt - _frm);
3573 to_nxt = to + (_to_nxt - _to);
3574 return r;
3575}
3576
3577__codecvt_utf16<wchar_t, false>::result
3578__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3579 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3580 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3581{
3582 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3583 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3584 const uint8_t* _frm_nxt = _frm;
3585 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3586 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3587 uint32_t* _to_nxt = _to;
3588 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3589 _Maxcode_, _Mode_);
3590 frm_nxt = frm + (_frm_nxt - _frm);
3591 to_nxt = to + (_to_nxt - _to);
3592 return r;
3593}
3594
3595__codecvt_utf16<wchar_t, false>::result
3596__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3597 extern_type* to, extern_type*, extern_type*& to_nxt) const
3598{
3599 to_nxt = to;
3600 return noconv;
3601}
3602
3603int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003604__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003605{
3606 return 0;
3607}
3608
3609bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003610__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003611{
3612 return false;
3613}
3614
3615int
3616__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3617 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3618{
3619 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3620 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3621 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3622}
3623
3624int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003625__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003626{
3627 if (_Mode_ & consume_header)
3628 return 6;
3629 return 4;
3630}
3631
3632// __codecvt_utf16<wchar_t, true>
3633
3634__codecvt_utf16<wchar_t, true>::result
3635__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3636 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3637 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3638{
3639 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3640 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3641 const uint32_t* _frm_nxt = _frm;
3642 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3643 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3644 uint8_t* _to_nxt = _to;
3645 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3646 _Maxcode_, _Mode_);
3647 frm_nxt = frm + (_frm_nxt - _frm);
3648 to_nxt = to + (_to_nxt - _to);
3649 return r;
3650}
3651
3652__codecvt_utf16<wchar_t, true>::result
3653__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3654 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3655 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3656{
3657 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3658 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3659 const uint8_t* _frm_nxt = _frm;
3660 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3661 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3662 uint32_t* _to_nxt = _to;
3663 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3664 _Maxcode_, _Mode_);
3665 frm_nxt = frm + (_frm_nxt - _frm);
3666 to_nxt = to + (_to_nxt - _to);
3667 return r;
3668}
3669
3670__codecvt_utf16<wchar_t, true>::result
3671__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3672 extern_type* to, extern_type*, extern_type*& to_nxt) const
3673{
3674 to_nxt = to;
3675 return noconv;
3676}
3677
3678int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003679__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003680{
3681 return 0;
3682}
3683
3684bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003685__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003686{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003687 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003688}
3689
3690int
3691__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3692 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3693{
3694 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3695 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3696 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3697}
3698
3699int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003700__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003701{
3702 if (_Mode_ & consume_header)
3703 return 6;
3704 return 4;
3705}
3706
3707// __codecvt_utf16<char16_t, false>
3708
3709__codecvt_utf16<char16_t, false>::result
3710__codecvt_utf16<char16_t, false>::do_out(state_type&,
3711 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3712 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3713{
3714 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3715 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3716 const uint16_t* _frm_nxt = _frm;
3717 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3718 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3719 uint8_t* _to_nxt = _to;
3720 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3721 _Maxcode_, _Mode_);
3722 frm_nxt = frm + (_frm_nxt - _frm);
3723 to_nxt = to + (_to_nxt - _to);
3724 return r;
3725}
3726
3727__codecvt_utf16<char16_t, false>::result
3728__codecvt_utf16<char16_t, false>::do_in(state_type&,
3729 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3730 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3731{
3732 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3733 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3734 const uint8_t* _frm_nxt = _frm;
3735 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3736 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3737 uint16_t* _to_nxt = _to;
3738 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3739 _Maxcode_, _Mode_);
3740 frm_nxt = frm + (_frm_nxt - _frm);
3741 to_nxt = to + (_to_nxt - _to);
3742 return r;
3743}
3744
3745__codecvt_utf16<char16_t, false>::result
3746__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3747 extern_type* to, extern_type*, extern_type*& to_nxt) const
3748{
3749 to_nxt = to;
3750 return noconv;
3751}
3752
3753int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003754__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003755{
3756 return 0;
3757}
3758
3759bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003760__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003761{
3762 return false;
3763}
3764
3765int
3766__codecvt_utf16<char16_t, false>::do_length(state_type&,
3767 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3768{
3769 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3770 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3771 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3772}
3773
3774int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003775__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003776{
3777 if (_Mode_ & consume_header)
3778 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003779 return 2;
3780}
3781
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003782// __codecvt_utf16<char16_t, true>
3783
3784__codecvt_utf16<char16_t, true>::result
3785__codecvt_utf16<char16_t, true>::do_out(state_type&,
3786 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3787 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3788{
3789 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3790 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3791 const uint16_t* _frm_nxt = _frm;
3792 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3793 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3794 uint8_t* _to_nxt = _to;
3795 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3796 _Maxcode_, _Mode_);
3797 frm_nxt = frm + (_frm_nxt - _frm);
3798 to_nxt = to + (_to_nxt - _to);
3799 return r;
3800}
3801
3802__codecvt_utf16<char16_t, true>::result
3803__codecvt_utf16<char16_t, true>::do_in(state_type&,
3804 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3805 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3806{
3807 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3808 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3809 const uint8_t* _frm_nxt = _frm;
3810 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3811 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3812 uint16_t* _to_nxt = _to;
3813 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3814 _Maxcode_, _Mode_);
3815 frm_nxt = frm + (_frm_nxt - _frm);
3816 to_nxt = to + (_to_nxt - _to);
3817 return r;
3818}
3819
3820__codecvt_utf16<char16_t, true>::result
3821__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3822 extern_type* to, extern_type*, extern_type*& to_nxt) const
3823{
3824 to_nxt = to;
3825 return noconv;
3826}
3827
3828int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003829__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003830{
3831 return 0;
3832}
3833
3834bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003835__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003836{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003837 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003838}
3839
3840int
3841__codecvt_utf16<char16_t, true>::do_length(state_type&,
3842 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3843{
3844 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3845 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3846 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3847}
3848
3849int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003850__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003851{
3852 if (_Mode_ & consume_header)
3853 return 4;
3854 return 2;
3855}
3856
3857// __codecvt_utf16<char32_t, false>
3858
3859__codecvt_utf16<char32_t, false>::result
3860__codecvt_utf16<char32_t, false>::do_out(state_type&,
3861 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3862 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3863{
3864 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3865 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3866 const uint32_t* _frm_nxt = _frm;
3867 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3868 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3869 uint8_t* _to_nxt = _to;
3870 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3871 _Maxcode_, _Mode_);
3872 frm_nxt = frm + (_frm_nxt - _frm);
3873 to_nxt = to + (_to_nxt - _to);
3874 return r;
3875}
3876
3877__codecvt_utf16<char32_t, false>::result
3878__codecvt_utf16<char32_t, false>::do_in(state_type&,
3879 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3880 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3881{
3882 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3883 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3884 const uint8_t* _frm_nxt = _frm;
3885 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3886 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3887 uint32_t* _to_nxt = _to;
3888 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3889 _Maxcode_, _Mode_);
3890 frm_nxt = frm + (_frm_nxt - _frm);
3891 to_nxt = to + (_to_nxt - _to);
3892 return r;
3893}
3894
3895__codecvt_utf16<char32_t, false>::result
3896__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3897 extern_type* to, extern_type*, extern_type*& to_nxt) const
3898{
3899 to_nxt = to;
3900 return noconv;
3901}
3902
3903int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003904__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003905{
3906 return 0;
3907}
3908
3909bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003910__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003911{
3912 return false;
3913}
3914
3915int
3916__codecvt_utf16<char32_t, false>::do_length(state_type&,
3917 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3918{
3919 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3920 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3921 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3922}
3923
3924int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003925__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003926{
3927 if (_Mode_ & consume_header)
3928 return 6;
3929 return 4;
3930}
3931
3932// __codecvt_utf16<char32_t, true>
3933
3934__codecvt_utf16<char32_t, true>::result
3935__codecvt_utf16<char32_t, true>::do_out(state_type&,
3936 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3937 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3938{
3939 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3940 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3941 const uint32_t* _frm_nxt = _frm;
3942 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3943 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3944 uint8_t* _to_nxt = _to;
3945 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3946 _Maxcode_, _Mode_);
3947 frm_nxt = frm + (_frm_nxt - _frm);
3948 to_nxt = to + (_to_nxt - _to);
3949 return r;
3950}
3951
3952__codecvt_utf16<char32_t, true>::result
3953__codecvt_utf16<char32_t, true>::do_in(state_type&,
3954 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3955 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3956{
3957 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3958 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3959 const uint8_t* _frm_nxt = _frm;
3960 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3961 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3962 uint32_t* _to_nxt = _to;
3963 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3964 _Maxcode_, _Mode_);
3965 frm_nxt = frm + (_frm_nxt - _frm);
3966 to_nxt = to + (_to_nxt - _to);
3967 return r;
3968}
3969
3970__codecvt_utf16<char32_t, true>::result
3971__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3972 extern_type* to, extern_type*, extern_type*& to_nxt) const
3973{
3974 to_nxt = to;
3975 return noconv;
3976}
3977
3978int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003979__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003980{
3981 return 0;
3982}
3983
3984bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003985__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003986{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003987 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003988}
3989
3990int
3991__codecvt_utf16<char32_t, true>::do_length(state_type&,
3992 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3993{
3994 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3995 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3996 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3997}
3998
3999int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004000__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004001{
4002 if (_Mode_ & consume_header)
4003 return 6;
4004 return 4;
4005}
4006
4007// __codecvt_utf8_utf16<wchar_t>
4008
4009__codecvt_utf8_utf16<wchar_t>::result
4010__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4011 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4012 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4013{
4014 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4015 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4016 const uint32_t* _frm_nxt = _frm;
4017 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4018 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4019 uint8_t* _to_nxt = _to;
4020 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4021 _Maxcode_, _Mode_);
4022 frm_nxt = frm + (_frm_nxt - _frm);
4023 to_nxt = to + (_to_nxt - _to);
4024 return r;
4025}
4026
4027__codecvt_utf8_utf16<wchar_t>::result
4028__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4029 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4030 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4031{
4032 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4033 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4034 const uint8_t* _frm_nxt = _frm;
4035 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4036 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4037 uint32_t* _to_nxt = _to;
4038 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4039 _Maxcode_, _Mode_);
4040 frm_nxt = frm + (_frm_nxt - _frm);
4041 to_nxt = to + (_to_nxt - _to);
4042 return r;
4043}
4044
4045__codecvt_utf8_utf16<wchar_t>::result
4046__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4047 extern_type* to, extern_type*, extern_type*& to_nxt) const
4048{
4049 to_nxt = to;
4050 return noconv;
4051}
4052
4053int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004054__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004055{
4056 return 0;
4057}
4058
4059bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004060__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004061{
4062 return false;
4063}
4064
4065int
4066__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4067 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4068{
4069 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4070 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4071 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4072}
4073
4074int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004075__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004076{
4077 if (_Mode_ & consume_header)
4078 return 7;
4079 return 4;
4080}
4081
4082// __codecvt_utf8_utf16<char16_t>
4083
4084__codecvt_utf8_utf16<char16_t>::result
4085__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4086 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4087 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4088{
4089 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4090 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4091 const uint16_t* _frm_nxt = _frm;
4092 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4093 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4094 uint8_t* _to_nxt = _to;
4095 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4096 _Maxcode_, _Mode_);
4097 frm_nxt = frm + (_frm_nxt - _frm);
4098 to_nxt = to + (_to_nxt - _to);
4099 return r;
4100}
4101
4102__codecvt_utf8_utf16<char16_t>::result
4103__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4104 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4105 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4106{
4107 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4108 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4109 const uint8_t* _frm_nxt = _frm;
4110 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4111 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4112 uint16_t* _to_nxt = _to;
4113 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4114 _Maxcode_, _Mode_);
4115 frm_nxt = frm + (_frm_nxt - _frm);
4116 to_nxt = to + (_to_nxt - _to);
4117 return r;
4118}
4119
4120__codecvt_utf8_utf16<char16_t>::result
4121__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4122 extern_type* to, extern_type*, extern_type*& to_nxt) const
4123{
4124 to_nxt = to;
4125 return noconv;
4126}
4127
4128int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004129__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004130{
4131 return 0;
4132}
4133
4134bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004135__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004136{
4137 return false;
4138}
4139
4140int
4141__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4142 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4143{
4144 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4145 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4146 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4147}
4148
4149int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004150__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004151{
4152 if (_Mode_ & consume_header)
4153 return 7;
4154 return 4;
4155}
4156
4157// __codecvt_utf8_utf16<char32_t>
4158
4159__codecvt_utf8_utf16<char32_t>::result
4160__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4161 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4162 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4163{
4164 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4165 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4166 const uint32_t* _frm_nxt = _frm;
4167 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4168 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4169 uint8_t* _to_nxt = _to;
4170 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4171 _Maxcode_, _Mode_);
4172 frm_nxt = frm + (_frm_nxt - _frm);
4173 to_nxt = to + (_to_nxt - _to);
4174 return r;
4175}
4176
4177__codecvt_utf8_utf16<char32_t>::result
4178__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4179 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4180 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4181{
4182 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4183 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4184 const uint8_t* _frm_nxt = _frm;
4185 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4186 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4187 uint32_t* _to_nxt = _to;
4188 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4189 _Maxcode_, _Mode_);
4190 frm_nxt = frm + (_frm_nxt - _frm);
4191 to_nxt = to + (_to_nxt - _to);
4192 return r;
4193}
4194
4195__codecvt_utf8_utf16<char32_t>::result
4196__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4197 extern_type* to, extern_type*, extern_type*& to_nxt) const
4198{
4199 to_nxt = to;
4200 return noconv;
4201}
4202
4203int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004204__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004205{
4206 return 0;
4207}
4208
4209bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004210__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004211{
4212 return false;
4213}
4214
4215int
4216__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4217 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4218{
4219 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4220 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4221 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4222}
4223
4224int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004225__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004226{
4227 if (_Mode_ & consume_header)
4228 return 7;
4229 return 4;
4230}
4231
Howard Hinnantc51e1022010-05-11 19:42:16 +00004232// __narrow_to_utf8<16>
4233
4234__narrow_to_utf8<16>::~__narrow_to_utf8()
4235{
4236}
4237
4238// __narrow_to_utf8<32>
4239
4240__narrow_to_utf8<32>::~__narrow_to_utf8()
4241{
4242}
4243
4244// __widen_from_utf8<16>
4245
4246__widen_from_utf8<16>::~__widen_from_utf8()
4247{
4248}
4249
4250// __widen_from_utf8<32>
4251
4252__widen_from_utf8<32>::~__widen_from_utf8()
4253{
4254}
4255
4256// numpunct<char> && numpunct<wchar_t>
4257
4258locale::id numpunct< char >::id;
4259locale::id numpunct<wchar_t>::id;
4260
4261numpunct<char>::numpunct(size_t refs)
4262 : locale::facet(refs),
4263 __decimal_point_('.'),
4264 __thousands_sep_(',')
4265{
4266}
4267
4268numpunct<wchar_t>::numpunct(size_t refs)
4269 : locale::facet(refs),
4270 __decimal_point_(L'.'),
4271 __thousands_sep_(L',')
4272{
4273}
4274
4275numpunct<char>::~numpunct()
4276{
4277}
4278
4279numpunct<wchar_t>::~numpunct()
4280{
4281}
4282
4283 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4284wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4285
4286 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4287wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4288
4289string numpunct< char >::do_grouping() const {return __grouping_;}
4290string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4291
4292 string numpunct< char >::do_truename() const {return "true";}
4293wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4294
4295 string numpunct< char >::do_falsename() const {return "false";}
4296wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4297
4298// numpunct_byname<char>
4299
4300numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4301 : numpunct<char>(refs)
4302{
4303 __init(nm);
4304}
4305
4306numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4307 : numpunct<char>(refs)
4308{
4309 __init(nm.c_str());
4310}
4311
4312numpunct_byname<char>::~numpunct_byname()
4313{
4314}
4315
4316void
4317numpunct_byname<char>::__init(const char* nm)
4318{
4319 if (strcmp(nm, "C") != 0)
4320 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004321 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004322#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004323 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004324 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4325 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004326#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004327#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004328 lconv* lc = localeconv_l(loc.get());
4329#else
4330 lconv* lc = __localeconv_l(loc.get());
4331#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004332 if (*lc->decimal_point)
4333 __decimal_point_ = *lc->decimal_point;
4334 if (*lc->thousands_sep)
4335 __thousands_sep_ = *lc->thousands_sep;
4336 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004337 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004338 }
4339}
4340
4341// numpunct_byname<wchar_t>
4342
4343numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4344 : numpunct<wchar_t>(refs)
4345{
4346 __init(nm);
4347}
4348
4349numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4350 : numpunct<wchar_t>(refs)
4351{
4352 __init(nm.c_str());
4353}
4354
4355numpunct_byname<wchar_t>::~numpunct_byname()
4356{
4357}
4358
4359void
4360numpunct_byname<wchar_t>::__init(const char* nm)
4361{
4362 if (strcmp(nm, "C") != 0)
4363 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004364 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004365#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004366 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004367 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4368 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004369#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004370#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004371 lconv* lc = localeconv_l(loc.get());
4372#else
4373 lconv* lc = __localeconv_l(loc.get());
4374#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004375 if (*lc->decimal_point)
4376 __decimal_point_ = *lc->decimal_point;
4377 if (*lc->thousands_sep)
4378 __thousands_sep_ = *lc->thousands_sep;
4379 __grouping_ = lc->grouping;
4380 // locallization for truename and falsename is not available
4381 }
4382}
4383
4384// num_get helpers
4385
4386int
4387__num_get_base::__get_base(ios_base& iob)
4388{
4389 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4390 if (__basefield == ios_base::oct)
4391 return 8;
4392 else if (__basefield == ios_base::hex)
4393 return 16;
4394 else if (__basefield == 0)
4395 return 0;
4396 return 10;
4397}
4398
4399const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4400
4401void
4402__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4403 ios_base::iostate& __err)
4404{
4405 if (__grouping.size() != 0)
4406 {
4407 reverse(__g, __g_end);
4408 const char* __ig = __grouping.data();
4409 const char* __eg = __ig + __grouping.size();
4410 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4411 {
4412 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4413 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004414 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004415 {
4416 __err = ios_base::failbit;
4417 return;
4418 }
4419 }
4420 if (__eg - __ig > 1)
4421 ++__ig;
4422 }
4423 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4424 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004425 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004426 __err = ios_base::failbit;
4427 }
4428 }
4429}
4430
4431void
4432__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4433 ios_base::fmtflags __flags)
4434{
4435 if (__flags & ios_base::showpos)
4436 *__fmtp++ = '+';
4437 if (__flags & ios_base::showbase)
4438 *__fmtp++ = '#';
4439 while(*__len)
4440 *__fmtp++ = *__len++;
4441 if ((__flags & ios_base::basefield) == ios_base::oct)
4442 *__fmtp = 'o';
4443 else if ((__flags & ios_base::basefield) == ios_base::hex)
4444 {
4445 if (__flags & ios_base::uppercase)
4446 *__fmtp = 'X';
4447 else
4448 *__fmtp = 'x';
4449 }
4450 else if (__signd)
4451 *__fmtp = 'd';
4452 else
4453 *__fmtp = 'u';
4454}
4455
4456bool
4457__num_put_base::__format_float(char* __fmtp, const char* __len,
4458 ios_base::fmtflags __flags)
4459{
4460 bool specify_precision = true;
4461 if (__flags & ios_base::showpos)
4462 *__fmtp++ = '+';
4463 if (__flags & ios_base::showpoint)
4464 *__fmtp++ = '#';
4465 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004466 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004467 if (floatfield == (ios_base::fixed | ios_base::scientific))
4468 specify_precision = false;
4469 else
4470 {
4471 *__fmtp++ = '.';
4472 *__fmtp++ = '*';
4473 }
4474 while(*__len)
4475 *__fmtp++ = *__len++;
4476 if (floatfield == ios_base::fixed)
4477 {
4478 if (uppercase)
4479 *__fmtp = 'F';
4480 else
4481 *__fmtp = 'f';
4482 }
4483 else if (floatfield == ios_base::scientific)
4484 {
4485 if (uppercase)
4486 *__fmtp = 'E';
4487 else
4488 *__fmtp = 'e';
4489 }
4490 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4491 {
4492 if (uppercase)
4493 *__fmtp = 'A';
4494 else
4495 *__fmtp = 'a';
4496 }
4497 else
4498 {
4499 if (uppercase)
4500 *__fmtp = 'G';
4501 else
4502 *__fmtp = 'g';
4503 }
4504 return specify_precision;
4505}
4506
4507char*
4508__num_put_base::__identify_padding(char* __nb, char* __ne,
4509 const ios_base& __iob)
4510{
4511 switch (__iob.flags() & ios_base::adjustfield)
4512 {
4513 case ios_base::internal:
4514 if (__nb[0] == '-' || __nb[0] == '+')
4515 return __nb+1;
4516 if (__ne - __nb >= 2 && __nb[0] == '0'
4517 && (__nb[1] == 'x' || __nb[1] == 'X'))
4518 return __nb+2;
4519 break;
4520 case ios_base::left:
4521 return __ne;
4522 case ios_base::right:
4523 default:
4524 break;
4525 }
4526 return __nb;
4527}
4528
4529// time_get
4530
4531static
4532string*
4533init_weeks()
4534{
4535 static string weeks[14];
4536 weeks[0] = "Sunday";
4537 weeks[1] = "Monday";
4538 weeks[2] = "Tuesday";
4539 weeks[3] = "Wednesday";
4540 weeks[4] = "Thursday";
4541 weeks[5] = "Friday";
4542 weeks[6] = "Saturday";
4543 weeks[7] = "Sun";
4544 weeks[8] = "Mon";
4545 weeks[9] = "Tue";
4546 weeks[10] = "Wed";
4547 weeks[11] = "Thu";
4548 weeks[12] = "Fri";
4549 weeks[13] = "Sat";
4550 return weeks;
4551}
4552
4553static
4554wstring*
4555init_wweeks()
4556{
4557 static wstring weeks[14];
4558 weeks[0] = L"Sunday";
4559 weeks[1] = L"Monday";
4560 weeks[2] = L"Tuesday";
4561 weeks[3] = L"Wednesday";
4562 weeks[4] = L"Thursday";
4563 weeks[5] = L"Friday";
4564 weeks[6] = L"Saturday";
4565 weeks[7] = L"Sun";
4566 weeks[8] = L"Mon";
4567 weeks[9] = L"Tue";
4568 weeks[10] = L"Wed";
4569 weeks[11] = L"Thu";
4570 weeks[12] = L"Fri";
4571 weeks[13] = L"Sat";
4572 return weeks;
4573}
4574
4575template <>
4576const string*
4577__time_get_c_storage<char>::__weeks() const
4578{
4579 static const string* weeks = init_weeks();
4580 return weeks;
4581}
4582
4583template <>
4584const wstring*
4585__time_get_c_storage<wchar_t>::__weeks() const
4586{
4587 static const wstring* weeks = init_wweeks();
4588 return weeks;
4589}
4590
4591static
4592string*
4593init_months()
4594{
4595 static string months[24];
4596 months[0] = "January";
4597 months[1] = "February";
4598 months[2] = "March";
4599 months[3] = "April";
4600 months[4] = "May";
4601 months[5] = "June";
4602 months[6] = "July";
4603 months[7] = "August";
4604 months[8] = "September";
4605 months[9] = "October";
4606 months[10] = "November";
4607 months[11] = "December";
4608 months[12] = "Jan";
4609 months[13] = "Feb";
4610 months[14] = "Mar";
4611 months[15] = "Apr";
4612 months[16] = "May";
4613 months[17] = "Jun";
4614 months[18] = "Jul";
4615 months[19] = "Aug";
4616 months[20] = "Sep";
4617 months[21] = "Oct";
4618 months[22] = "Nov";
4619 months[23] = "Dec";
4620 return months;
4621}
4622
4623static
4624wstring*
4625init_wmonths()
4626{
4627 static wstring months[24];
4628 months[0] = L"January";
4629 months[1] = L"February";
4630 months[2] = L"March";
4631 months[3] = L"April";
4632 months[4] = L"May";
4633 months[5] = L"June";
4634 months[6] = L"July";
4635 months[7] = L"August";
4636 months[8] = L"September";
4637 months[9] = L"October";
4638 months[10] = L"November";
4639 months[11] = L"December";
4640 months[12] = L"Jan";
4641 months[13] = L"Feb";
4642 months[14] = L"Mar";
4643 months[15] = L"Apr";
4644 months[16] = L"May";
4645 months[17] = L"Jun";
4646 months[18] = L"Jul";
4647 months[19] = L"Aug";
4648 months[20] = L"Sep";
4649 months[21] = L"Oct";
4650 months[22] = L"Nov";
4651 months[23] = L"Dec";
4652 return months;
4653}
4654
4655template <>
4656const string*
4657__time_get_c_storage<char>::__months() const
4658{
4659 static const string* months = init_months();
4660 return months;
4661}
4662
4663template <>
4664const wstring*
4665__time_get_c_storage<wchar_t>::__months() const
4666{
4667 static const wstring* months = init_wmonths();
4668 return months;
4669}
4670
4671static
4672string*
4673init_am_pm()
4674{
4675 static string am_pm[24];
4676 am_pm[0] = "AM";
4677 am_pm[1] = "PM";
4678 return am_pm;
4679}
4680
4681static
4682wstring*
4683init_wam_pm()
4684{
4685 static wstring am_pm[24];
4686 am_pm[0] = L"AM";
4687 am_pm[1] = L"PM";
4688 return am_pm;
4689}
4690
4691template <>
4692const string*
4693__time_get_c_storage<char>::__am_pm() const
4694{
4695 static const string* am_pm = init_am_pm();
4696 return am_pm;
4697}
4698
4699template <>
4700const wstring*
4701__time_get_c_storage<wchar_t>::__am_pm() const
4702{
4703 static const wstring* am_pm = init_wam_pm();
4704 return am_pm;
4705}
4706
4707template <>
4708const string&
4709__time_get_c_storage<char>::__x() const
4710{
4711 static string s("%m/%d/%y");
4712 return s;
4713}
4714
4715template <>
4716const wstring&
4717__time_get_c_storage<wchar_t>::__x() const
4718{
4719 static wstring s(L"%m/%d/%y");
4720 return s;
4721}
4722
4723template <>
4724const string&
4725__time_get_c_storage<char>::__X() const
4726{
4727 static string s("%H:%M:%S");
4728 return s;
4729}
4730
4731template <>
4732const wstring&
4733__time_get_c_storage<wchar_t>::__X() const
4734{
4735 static wstring s(L"%H:%M:%S");
4736 return s;
4737}
4738
4739template <>
4740const string&
4741__time_get_c_storage<char>::__c() const
4742{
4743 static string s("%a %b %d %H:%M:%S %Y");
4744 return s;
4745}
4746
4747template <>
4748const wstring&
4749__time_get_c_storage<wchar_t>::__c() const
4750{
4751 static wstring s(L"%a %b %d %H:%M:%S %Y");
4752 return s;
4753}
4754
4755template <>
4756const string&
4757__time_get_c_storage<char>::__r() const
4758{
4759 static string s("%I:%M:%S %p");
4760 return s;
4761}
4762
4763template <>
4764const wstring&
4765__time_get_c_storage<wchar_t>::__r() const
4766{
4767 static wstring s(L"%I:%M:%S %p");
4768 return s;
4769}
4770
4771// time_get_byname
4772
4773__time_get::__time_get(const char* nm)
4774 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4775{
Howard Hinnant72f73582010-08-11 17:04:31 +00004776#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004777 if (__loc_ == 0)
4778 throw runtime_error("time_get_byname"
4779 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004780#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004781}
4782
4783__time_get::__time_get(const string& nm)
4784 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4785{
Howard Hinnant72f73582010-08-11 17:04:31 +00004786#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004787 if (__loc_ == 0)
4788 throw runtime_error("time_get_byname"
4789 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004790#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004791}
4792
4793__time_get::~__time_get()
4794{
4795 freelocale(__loc_);
4796}
Marshall Clowd920eea2013-10-21 15:07:28 +00004797#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004798#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004799#endif
4800#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004801#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004802#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004803
Howard Hinnantc51e1022010-05-11 19:42:16 +00004804template <>
4805string
4806__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4807{
Howard Hinnant990207c2012-02-19 14:55:32 +00004808 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004809 t.tm_sec = 59;
4810 t.tm_min = 55;
4811 t.tm_hour = 23;
4812 t.tm_mday = 31;
4813 t.tm_mon = 11;
4814 t.tm_year = 161;
4815 t.tm_wday = 6;
4816 t.tm_yday = 364;
4817 t.tm_isdst = -1;
4818 char buf[100];
4819 char f[3] = {0};
4820 f[0] = '%';
4821 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004822 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004823 char* bb = buf;
4824 char* be = buf + n;
4825 string result;
4826 while (bb != be)
4827 {
4828 if (ct.is(ctype_base::space, *bb))
4829 {
4830 result.push_back(' ');
4831 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4832 ;
4833 continue;
4834 }
4835 char* w = bb;
4836 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004837 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004838 ct, err, false)
4839 - this->__weeks_;
4840 if (i < 14)
4841 {
4842 result.push_back('%');
4843 if (i < 7)
4844 result.push_back('A');
4845 else
4846 result.push_back('a');
4847 bb = w;
4848 continue;
4849 }
4850 w = bb;
4851 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4852 ct, err, false)
4853 - this->__months_;
4854 if (i < 24)
4855 {
4856 result.push_back('%');
4857 if (i < 12)
4858 result.push_back('B');
4859 else
4860 result.push_back('b');
4861 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4862 result.back() = 'm';
4863 bb = w;
4864 continue;
4865 }
4866 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4867 {
4868 w = bb;
4869 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4870 ct, err, false) - this->__am_pm_;
4871 if (i < 2)
4872 {
4873 result.push_back('%');
4874 result.push_back('p');
4875 bb = w;
4876 continue;
4877 }
4878 }
4879 w = bb;
4880 if (ct.is(ctype_base::digit, *bb))
4881 {
4882 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4883 {
4884 case 6:
4885 result.push_back('%');
4886 result.push_back('w');
4887 break;
4888 case 7:
4889 result.push_back('%');
4890 result.push_back('u');
4891 break;
4892 case 11:
4893 result.push_back('%');
4894 result.push_back('I');
4895 break;
4896 case 12:
4897 result.push_back('%');
4898 result.push_back('m');
4899 break;
4900 case 23:
4901 result.push_back('%');
4902 result.push_back('H');
4903 break;
4904 case 31:
4905 result.push_back('%');
4906 result.push_back('d');
4907 break;
4908 case 55:
4909 result.push_back('%');
4910 result.push_back('M');
4911 break;
4912 case 59:
4913 result.push_back('%');
4914 result.push_back('S');
4915 break;
4916 case 61:
4917 result.push_back('%');
4918 result.push_back('y');
4919 break;
4920 case 364:
4921 result.push_back('%');
4922 result.push_back('j');
4923 break;
4924 case 2061:
4925 result.push_back('%');
4926 result.push_back('Y');
4927 break;
4928 default:
4929 for (; w != bb; ++w)
4930 result.push_back(*w);
4931 break;
4932 }
4933 continue;
4934 }
4935 if (*bb == '%')
4936 {
4937 result.push_back('%');
4938 result.push_back('%');
4939 ++bb;
4940 continue;
4941 }
4942 result.push_back(*bb);
4943 ++bb;
4944 }
4945 return result;
4946}
4947
Marshall Clowd920eea2013-10-21 15:07:28 +00004948#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004949#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004950#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004951
Howard Hinnantc51e1022010-05-11 19:42:16 +00004952template <>
4953wstring
4954__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4955{
Howard Hinnant990207c2012-02-19 14:55:32 +00004956 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004957 t.tm_sec = 59;
4958 t.tm_min = 55;
4959 t.tm_hour = 23;
4960 t.tm_mday = 31;
4961 t.tm_mon = 11;
4962 t.tm_year = 161;
4963 t.tm_wday = 6;
4964 t.tm_yday = 364;
4965 t.tm_isdst = -1;
4966 char buf[100];
4967 char f[3] = {0};
4968 f[0] = '%';
4969 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004970 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004971 wchar_t wbuf[100];
4972 wchar_t* wbb = wbuf;
4973 mbstate_t mb = {0};
4974 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004975#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004976 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004977#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004978 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004979#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004980 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004981 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004982 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004983 wstring result;
4984 while (wbb != wbe)
4985 {
4986 if (ct.is(ctype_base::space, *wbb))
4987 {
4988 result.push_back(L' ');
4989 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4990 ;
4991 continue;
4992 }
4993 wchar_t* w = wbb;
4994 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004995 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004996 ct, err, false)
4997 - this->__weeks_;
4998 if (i < 14)
4999 {
5000 result.push_back(L'%');
5001 if (i < 7)
5002 result.push_back(L'A');
5003 else
5004 result.push_back(L'a');
5005 wbb = w;
5006 continue;
5007 }
5008 w = wbb;
5009 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5010 ct, err, false)
5011 - this->__months_;
5012 if (i < 24)
5013 {
5014 result.push_back(L'%');
5015 if (i < 12)
5016 result.push_back(L'B');
5017 else
5018 result.push_back(L'b');
5019 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5020 result.back() = L'm';
5021 wbb = w;
5022 continue;
5023 }
5024 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5025 {
5026 w = wbb;
5027 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5028 ct, err, false) - this->__am_pm_;
5029 if (i < 2)
5030 {
5031 result.push_back(L'%');
5032 result.push_back(L'p');
5033 wbb = w;
5034 continue;
5035 }
5036 }
5037 w = wbb;
5038 if (ct.is(ctype_base::digit, *wbb))
5039 {
5040 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5041 {
5042 case 6:
5043 result.push_back(L'%');
5044 result.push_back(L'w');
5045 break;
5046 case 7:
5047 result.push_back(L'%');
5048 result.push_back(L'u');
5049 break;
5050 case 11:
5051 result.push_back(L'%');
5052 result.push_back(L'I');
5053 break;
5054 case 12:
5055 result.push_back(L'%');
5056 result.push_back(L'm');
5057 break;
5058 case 23:
5059 result.push_back(L'%');
5060 result.push_back(L'H');
5061 break;
5062 case 31:
5063 result.push_back(L'%');
5064 result.push_back(L'd');
5065 break;
5066 case 55:
5067 result.push_back(L'%');
5068 result.push_back(L'M');
5069 break;
5070 case 59:
5071 result.push_back(L'%');
5072 result.push_back(L'S');
5073 break;
5074 case 61:
5075 result.push_back(L'%');
5076 result.push_back(L'y');
5077 break;
5078 case 364:
5079 result.push_back(L'%');
5080 result.push_back(L'j');
5081 break;
5082 case 2061:
5083 result.push_back(L'%');
5084 result.push_back(L'Y');
5085 break;
5086 default:
5087 for (; w != wbb; ++w)
5088 result.push_back(*w);
5089 break;
5090 }
5091 continue;
5092 }
5093 if (ct.narrow(*wbb, 0) == '%')
5094 {
5095 result.push_back(L'%');
5096 result.push_back(L'%');
5097 ++wbb;
5098 continue;
5099 }
5100 result.push_back(*wbb);
5101 ++wbb;
5102 }
5103 return result;
5104}
5105
5106template <>
5107void
5108__time_get_storage<char>::init(const ctype<char>& ct)
5109{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005110 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005111 char buf[100];
5112 // __weeks_
5113 for (int i = 0; i < 7; ++i)
5114 {
5115 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005116 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005117 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005118 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005119 __weeks_[i+7] = buf;
5120 }
5121 // __months_
5122 for (int i = 0; i < 12; ++i)
5123 {
5124 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005125 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005126 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005127 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005128 __months_[i+12] = buf;
5129 }
5130 // __am_pm_
5131 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005132 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005133 __am_pm_[0] = buf;
5134 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005135 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005136 __am_pm_[1] = buf;
5137 __c_ = __analyze('c', ct);
5138 __r_ = __analyze('r', ct);
5139 __x_ = __analyze('x', ct);
5140 __X_ = __analyze('X', ct);
5141}
5142
5143template <>
5144void
5145__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5146{
5147 tm t = {0};
5148 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005149 wchar_t wbuf[100];
5150 wchar_t* wbe;
5151 mbstate_t mb = {0};
5152 // __weeks_
5153 for (int i = 0; i < 7; ++i)
5154 {
5155 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005156 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005157 mb = mbstate_t();
5158 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005159#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005160 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005161#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005162 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005163#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005164 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005165 __throw_runtime_error("locale not supported");
5166 wbe = wbuf + j;
5167 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005168 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005169 mb = mbstate_t();
5170 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005171#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005172 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005173#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005174 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005175#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005176 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005177 __throw_runtime_error("locale not supported");
5178 wbe = wbuf + j;
5179 __weeks_[i+7].assign(wbuf, wbe);
5180 }
5181 // __months_
5182 for (int i = 0; i < 12; ++i)
5183 {
5184 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005185 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005186 mb = mbstate_t();
5187 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005188#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005189 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005190#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005191 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005192#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005193 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005194 __throw_runtime_error("locale not supported");
5195 wbe = wbuf + j;
5196 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005197 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005198 mb = mbstate_t();
5199 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005200#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005201 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005202#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005203 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005204#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005205 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005206 __throw_runtime_error("locale not supported");
5207 wbe = wbuf + j;
5208 __months_[i+12].assign(wbuf, wbe);
5209 }
5210 // __am_pm_
5211 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005212 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005213 mb = mbstate_t();
5214 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005215#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005216 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005217#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005218 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005219#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005220 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005221 __throw_runtime_error("locale not supported");
5222 wbe = wbuf + j;
5223 __am_pm_[0].assign(wbuf, wbe);
5224 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005225 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005226 mb = mbstate_t();
5227 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005228#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005229 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005230#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005231 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005232#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005233 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005234 __throw_runtime_error("locale not supported");
5235 wbe = wbuf + j;
5236 __am_pm_[1].assign(wbuf, wbe);
5237 __c_ = __analyze('c', ct);
5238 __r_ = __analyze('r', ct);
5239 __x_ = __analyze('x', ct);
5240 __X_ = __analyze('X', ct);
5241}
5242
5243template <class CharT>
5244struct _LIBCPP_HIDDEN __time_get_temp
5245 : public ctype_byname<CharT>
5246{
5247 explicit __time_get_temp(const char* nm)
5248 : ctype_byname<CharT>(nm, 1) {}
5249 explicit __time_get_temp(const string& nm)
5250 : ctype_byname<CharT>(nm, 1) {}
5251};
5252
5253template <>
5254__time_get_storage<char>::__time_get_storage(const char* __nm)
5255 : __time_get(__nm)
5256{
5257 const __time_get_temp<char> ct(__nm);
5258 init(ct);
5259}
5260
5261template <>
5262__time_get_storage<char>::__time_get_storage(const string& __nm)
5263 : __time_get(__nm)
5264{
5265 const __time_get_temp<char> ct(__nm);
5266 init(ct);
5267}
5268
5269template <>
5270__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5271 : __time_get(__nm)
5272{
5273 const __time_get_temp<wchar_t> ct(__nm);
5274 init(ct);
5275}
5276
5277template <>
5278__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5279 : __time_get(__nm)
5280{
5281 const __time_get_temp<wchar_t> ct(__nm);
5282 init(ct);
5283}
5284
5285template <>
5286time_base::dateorder
5287__time_get_storage<char>::__do_date_order() const
5288{
5289 unsigned i;
5290 for (i = 0; i < __x_.size(); ++i)
5291 if (__x_[i] == '%')
5292 break;
5293 ++i;
5294 switch (__x_[i])
5295 {
5296 case 'y':
5297 case 'Y':
5298 for (++i; i < __x_.size(); ++i)
5299 if (__x_[i] == '%')
5300 break;
5301 if (i == __x_.size())
5302 break;
5303 ++i;
5304 switch (__x_[i])
5305 {
5306 case 'm':
5307 for (++i; i < __x_.size(); ++i)
5308 if (__x_[i] == '%')
5309 break;
5310 if (i == __x_.size())
5311 break;
5312 ++i;
5313 if (__x_[i] == 'd')
5314 return time_base::ymd;
5315 break;
5316 case 'd':
5317 for (++i; i < __x_.size(); ++i)
5318 if (__x_[i] == '%')
5319 break;
5320 if (i == __x_.size())
5321 break;
5322 ++i;
5323 if (__x_[i] == 'm')
5324 return time_base::ydm;
5325 break;
5326 }
5327 break;
5328 case 'm':
5329 for (++i; i < __x_.size(); ++i)
5330 if (__x_[i] == '%')
5331 break;
5332 if (i == __x_.size())
5333 break;
5334 ++i;
5335 if (__x_[i] == 'd')
5336 {
5337 for (++i; i < __x_.size(); ++i)
5338 if (__x_[i] == '%')
5339 break;
5340 if (i == __x_.size())
5341 break;
5342 ++i;
5343 if (__x_[i] == 'y' || __x_[i] == 'Y')
5344 return time_base::mdy;
5345 break;
5346 }
5347 break;
5348 case 'd':
5349 for (++i; i < __x_.size(); ++i)
5350 if (__x_[i] == '%')
5351 break;
5352 if (i == __x_.size())
5353 break;
5354 ++i;
5355 if (__x_[i] == 'm')
5356 {
5357 for (++i; i < __x_.size(); ++i)
5358 if (__x_[i] == '%')
5359 break;
5360 if (i == __x_.size())
5361 break;
5362 ++i;
5363 if (__x_[i] == 'y' || __x_[i] == 'Y')
5364 return time_base::dmy;
5365 break;
5366 }
5367 break;
5368 }
5369 return time_base::no_order;
5370}
5371
5372template <>
5373time_base::dateorder
5374__time_get_storage<wchar_t>::__do_date_order() const
5375{
5376 unsigned i;
5377 for (i = 0; i < __x_.size(); ++i)
5378 if (__x_[i] == L'%')
5379 break;
5380 ++i;
5381 switch (__x_[i])
5382 {
5383 case L'y':
5384 case L'Y':
5385 for (++i; i < __x_.size(); ++i)
5386 if (__x_[i] == L'%')
5387 break;
5388 if (i == __x_.size())
5389 break;
5390 ++i;
5391 switch (__x_[i])
5392 {
5393 case L'm':
5394 for (++i; i < __x_.size(); ++i)
5395 if (__x_[i] == L'%')
5396 break;
5397 if (i == __x_.size())
5398 break;
5399 ++i;
5400 if (__x_[i] == L'd')
5401 return time_base::ymd;
5402 break;
5403 case L'd':
5404 for (++i; i < __x_.size(); ++i)
5405 if (__x_[i] == L'%')
5406 break;
5407 if (i == __x_.size())
5408 break;
5409 ++i;
5410 if (__x_[i] == L'm')
5411 return time_base::ydm;
5412 break;
5413 }
5414 break;
5415 case L'm':
5416 for (++i; i < __x_.size(); ++i)
5417 if (__x_[i] == L'%')
5418 break;
5419 if (i == __x_.size())
5420 break;
5421 ++i;
5422 if (__x_[i] == L'd')
5423 {
5424 for (++i; i < __x_.size(); ++i)
5425 if (__x_[i] == L'%')
5426 break;
5427 if (i == __x_.size())
5428 break;
5429 ++i;
5430 if (__x_[i] == L'y' || __x_[i] == L'Y')
5431 return time_base::mdy;
5432 break;
5433 }
5434 break;
5435 case L'd':
5436 for (++i; i < __x_.size(); ++i)
5437 if (__x_[i] == L'%')
5438 break;
5439 if (i == __x_.size())
5440 break;
5441 ++i;
5442 if (__x_[i] == L'm')
5443 {
5444 for (++i; i < __x_.size(); ++i)
5445 if (__x_[i] == L'%')
5446 break;
5447 if (i == __x_.size())
5448 break;
5449 ++i;
5450 if (__x_[i] == L'y' || __x_[i] == L'Y')
5451 return time_base::dmy;
5452 break;
5453 }
5454 break;
5455 }
5456 return time_base::no_order;
5457}
5458
5459// time_put
5460
5461__time_put::__time_put(const char* nm)
5462 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5463{
Howard Hinnant72f73582010-08-11 17:04:31 +00005464#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005465 if (__loc_ == 0)
5466 throw runtime_error("time_put_byname"
5467 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005468#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005469}
5470
5471__time_put::__time_put(const string& nm)
5472 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5473{
Howard Hinnant72f73582010-08-11 17:04:31 +00005474#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005475 if (__loc_ == 0)
5476 throw runtime_error("time_put_byname"
5477 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005478#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005479}
5480
5481__time_put::~__time_put()
5482{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005483 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005484 freelocale(__loc_);
5485}
5486
5487void
5488__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5489 char __fmt, char __mod) const
5490{
5491 char fmt[] = {'%', __fmt, __mod, 0};
5492 if (__mod != 0)
5493 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005494 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005495 __ne = __nb + n;
5496}
5497
5498void
5499__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5500 char __fmt, char __mod) const
5501{
5502 char __nar[100];
5503 char* __ne = __nar + 100;
5504 __do_put(__nar, __ne, __tm, __fmt, __mod);
5505 mbstate_t mb = {0};
5506 const char* __nb = __nar;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005507#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005508 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005509#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005510 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005511#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005512 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005513 __throw_runtime_error("locale not supported");
5514 __we = __wb + j;
5515}
5516
5517// moneypunct_byname
5518
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005519template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005520static
5521void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005522__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5523 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5524 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005525{
5526 const char sign = static_cast<char>(money_base::sign);
5527 const char space = static_cast<char>(money_base::space);
5528 const char none = static_cast<char>(money_base::none);
5529 const char symbol = static_cast<char>(money_base::symbol);
5530 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005531 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5532
5533 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5534 // function'. "Space between sign and symbol or value" means that
5535 // if the sign is adjacent to the symbol, there's a space between
5536 // them, and otherwise there's a space between the sign and value.
5537 //
5538 // C11's localeconv specifies that the fourth character of an
5539 // international curr_symbol is used to separate the sign and
5540 // value when sep_by_space says to do so. C++ can't represent
5541 // that, so we just use a space. When sep_by_space says to
5542 // separate the symbol and value-or-sign with a space, we rearrange the
5543 // curr_symbol to put its spacing character on the correct side of
5544 // the symbol.
5545 //
5546 // We also need to avoid adding an extra space between the sign
5547 // and value when the currency symbol is suppressed (by not
5548 // setting showbase). We match glibc's strfmon by interpreting
5549 // sep_by_space==1 as "omit the space when the currency symbol is
5550 // absent".
5551 //
5552 // Users who want to get this right should use ICU instead.
5553
Howard Hinnantc51e1022010-05-11 19:42:16 +00005554 switch (cs_precedes)
5555 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005556 case 0: // value before curr_symbol
5557 if (symbol_contains_sep) {
5558 // Move the separator to before the symbol, to place it
5559 // between the value and symbol.
5560 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5561 __curr_symbol_.end());
5562 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005563 switch (sign_posn)
5564 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005565 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005566 pat.field[0] = sign;
5567 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005568 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005569 pat.field[3] = symbol;
5570 switch (sep_by_space)
5571 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005572 case 0: // No space separates the currency symbol and value.
5573 // This case may have changed between C99 and C11;
5574 // assume the currency symbol matches the intention.
5575 case 2: // Space between sign and currency or value.
5576 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005577 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005578 case 1: // Space between currency-and-sign or currency and value.
5579 if (!symbol_contains_sep) {
5580 // We insert the space into the symbol instead of
5581 // setting pat.field[2]=space so that when
5582 // showbase is not set, the space goes away too.
5583 __curr_symbol_.insert(0, 1, space_char);
5584 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005585 return;
5586 default:
5587 break;
5588 }
5589 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005590 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005591 pat.field[0] = sign;
5592 pat.field[3] = symbol;
5593 switch (sep_by_space)
5594 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005595 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005596 pat.field[1] = value;
5597 pat.field[2] = none;
5598 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005599 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005600 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005601 pat.field[2] = none;
5602 if (!symbol_contains_sep) {
5603 // We insert the space into the symbol instead of
5604 // setting pat.field[2]=space so that when
5605 // showbase is not set, the space goes away too.
5606 __curr_symbol_.insert(0, 1, space_char);
5607 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005608 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005609 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005610 pat.field[1] = space;
5611 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005612 if (symbol_contains_sep) {
5613 // Remove the separator from the symbol, since it
5614 // has already appeared after the sign.
5615 __curr_symbol_.erase(__curr_symbol_.begin());
5616 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005617 return;
5618 default:
5619 break;
5620 }
5621 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005622 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005623 pat.field[0] = value;
5624 pat.field[3] = sign;
5625 switch (sep_by_space)
5626 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005627 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005628 pat.field[1] = none;
5629 pat.field[2] = symbol;
5630 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005631 case 1: // Space between currency-and-sign or currency and value.
5632 if (!symbol_contains_sep) {
5633 // We insert the space into the symbol instead of
5634 // setting pat.field[1]=space so that when
5635 // showbase is not set, the space goes away too.
5636 __curr_symbol_.insert(0, 1, space_char);
5637 }
5638 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005639 pat.field[2] = symbol;
5640 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005641 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005642 pat.field[1] = symbol;
5643 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005644 if (symbol_contains_sep) {
5645 // Remove the separator from the symbol, since it
5646 // should not be removed if showbase is absent.
5647 __curr_symbol_.erase(__curr_symbol_.begin());
5648 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005649 return;
5650 default:
5651 break;
5652 }
5653 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005654 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005655 pat.field[0] = value;
5656 pat.field[3] = symbol;
5657 switch (sep_by_space)
5658 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005659 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005660 pat.field[1] = none;
5661 pat.field[2] = sign;
5662 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005663 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005664 pat.field[1] = space;
5665 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005666 if (symbol_contains_sep) {
5667 // Remove the separator from the symbol, since it
5668 // has already appeared before the sign.
5669 __curr_symbol_.erase(__curr_symbol_.begin());
5670 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005671 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005672 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005673 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005674 pat.field[2] = none;
5675 if (!symbol_contains_sep) {
5676 // We insert the space into the symbol instead of
5677 // setting pat.field[2]=space so that when
5678 // showbase is not set, the space goes away too.
5679 __curr_symbol_.insert(0, 1, space_char);
5680 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005681 return;
5682 default:
5683 break;
5684 }
5685 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005686 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005687 pat.field[0] = value;
5688 pat.field[3] = sign;
5689 switch (sep_by_space)
5690 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005691 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005692 pat.field[1] = none;
5693 pat.field[2] = symbol;
5694 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005695 case 1: // Space between currency-and-sign or currency and value.
5696 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005697 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005698 if (!symbol_contains_sep) {
5699 // We insert the space into the symbol instead of
5700 // setting pat.field[1]=space so that when
5701 // showbase is not set, the space goes away too.
5702 __curr_symbol_.insert(0, 1, space_char);
5703 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005704 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005705 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005706 pat.field[1] = symbol;
5707 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005708 if (symbol_contains_sep) {
5709 // Remove the separator from the symbol, since it
5710 // should not disappear when showbase is absent.
5711 __curr_symbol_.erase(__curr_symbol_.begin());
5712 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005713 return;
5714 default:
5715 break;
5716 }
5717 break;
5718 default:
5719 break;
5720 }
5721 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005722 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005723 switch (sign_posn)
5724 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005725 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005726 pat.field[0] = sign;
5727 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005728 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005729 pat.field[3] = value;
5730 switch (sep_by_space)
5731 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005732 case 0: // No space separates the currency symbol and value.
5733 // This case may have changed between C99 and C11;
5734 // assume the currency symbol matches the intention.
5735 case 2: // Space between sign and currency or value.
5736 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005737 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005738 case 1: // Space between currency-and-sign or currency and value.
5739 if (!symbol_contains_sep) {
5740 // We insert the space into the symbol instead of
5741 // setting pat.field[2]=space so that when
5742 // showbase is not set, the space goes away too.
5743 __curr_symbol_.insert(0, 1, space_char);
5744 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005745 return;
5746 default:
5747 break;
5748 }
5749 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005750 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005751 pat.field[0] = sign;
5752 pat.field[3] = value;
5753 switch (sep_by_space)
5754 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005755 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005756 pat.field[1] = symbol;
5757 pat.field[2] = none;
5758 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005759 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005760 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005761 pat.field[2] = none;
5762 if (!symbol_contains_sep) {
5763 // We insert the space into the symbol instead of
5764 // setting pat.field[2]=space so that when
5765 // showbase is not set, the space goes away too.
5766 __curr_symbol_.push_back(space_char);
5767 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005768 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005769 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005770 pat.field[1] = space;
5771 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005772 if (symbol_contains_sep) {
5773 // Remove the separator from the symbol, since it
5774 // has already appeared after the sign.
5775 __curr_symbol_.pop_back();
5776 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005777 return;
5778 default:
5779 break;
5780 }
5781 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005782 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005783 pat.field[0] = symbol;
5784 pat.field[3] = sign;
5785 switch (sep_by_space)
5786 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005787 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005788 pat.field[1] = none;
5789 pat.field[2] = value;
5790 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005791 case 1: // Space between currency-and-sign or currency and value.
5792 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005793 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005794 if (!symbol_contains_sep) {
5795 // We insert the space into the symbol instead of
5796 // setting pat.field[1]=space so that when
5797 // showbase is not set, the space goes away too.
5798 __curr_symbol_.push_back(space_char);
5799 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005800 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005801 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005802 pat.field[1] = value;
5803 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005804 if (symbol_contains_sep) {
5805 // Remove the separator from the symbol, since it
5806 // will appear before the sign.
5807 __curr_symbol_.pop_back();
5808 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005809 return;
5810 default:
5811 break;
5812 }
5813 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005814 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005815 pat.field[0] = sign;
5816 pat.field[3] = value;
5817 switch (sep_by_space)
5818 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005819 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005820 pat.field[1] = symbol;
5821 pat.field[2] = none;
5822 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005823 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005824 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005825 pat.field[2] = none;
5826 if (!symbol_contains_sep) {
5827 // We insert the space into the symbol instead of
5828 // setting pat.field[2]=space so that when
5829 // showbase is not set, the space goes away too.
5830 __curr_symbol_.push_back(space_char);
5831 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005832 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005833 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005834 pat.field[1] = space;
5835 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005836 if (symbol_contains_sep) {
5837 // Remove the separator from the symbol, since it
5838 // has already appeared after the sign.
5839 __curr_symbol_.pop_back();
5840 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005841 return;
5842 default:
5843 break;
5844 }
5845 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005846 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005847 pat.field[0] = symbol;
5848 pat.field[3] = value;
5849 switch (sep_by_space)
5850 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005851 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005852 pat.field[1] = sign;
5853 pat.field[2] = none;
5854 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005855 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005856 pat.field[1] = sign;
5857 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005858 if (symbol_contains_sep) {
5859 // Remove the separator from the symbol, since it
5860 // should not disappear when showbase is absent.
5861 __curr_symbol_.pop_back();
5862 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005863 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005864 case 2: // Space between sign and currency or value.
5865 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005866 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005867 if (!symbol_contains_sep) {
5868 // We insert the space into the symbol instead of
5869 // setting pat.field[1]=space so that when
5870 // showbase is not set, the space goes away too.
5871 __curr_symbol_.push_back(space_char);
5872 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005873 return;
5874 default:
5875 break;
5876 }
5877 break;
5878 default:
5879 break;
5880 }
5881 break;
5882 default:
5883 break;
5884 }
5885 pat.field[0] = symbol;
5886 pat.field[1] = sign;
5887 pat.field[2] = none;
5888 pat.field[3] = value;
5889}
5890
5891template<>
5892void
5893moneypunct_byname<char, false>::init(const char* nm)
5894{
5895 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005896 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005897#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005898 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005899 throw runtime_error("moneypunct_byname"
5900 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005901#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005902#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005903 lconv* lc = localeconv_l(loc.get());
5904#else
5905 lconv* lc = __localeconv_l(loc.get());
5906#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005907 if (*lc->mon_decimal_point)
5908 __decimal_point_ = *lc->mon_decimal_point;
5909 else
5910 __decimal_point_ = base::do_decimal_point();
5911 if (*lc->mon_thousands_sep)
5912 __thousands_sep_ = *lc->mon_thousands_sep;
5913 else
5914 __thousands_sep_ = base::do_thousands_sep();
5915 __grouping_ = lc->mon_grouping;
5916 __curr_symbol_ = lc->currency_symbol;
5917 if (lc->frac_digits != CHAR_MAX)
5918 __frac_digits_ = lc->frac_digits;
5919 else
5920 __frac_digits_ = base::do_frac_digits();
5921 if (lc->p_sign_posn == 0)
5922 __positive_sign_ = "()";
5923 else
5924 __positive_sign_ = lc->positive_sign;
5925 if (lc->n_sign_posn == 0)
5926 __negative_sign_ = "()";
5927 else
5928 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005929 // Assume the positive and negative formats will want spaces in
5930 // the same places in curr_symbol since there's no way to
5931 // represent anything else.
5932 string_type __dummy_curr_symbol = __curr_symbol_;
5933 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5934 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5935 __init_pat(__neg_format_, __curr_symbol_, false,
5936 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005937}
5938
5939template<>
5940void
5941moneypunct_byname<char, true>::init(const char* nm)
5942{
5943 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005944 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005945#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005946 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005947 throw runtime_error("moneypunct_byname"
5948 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005949#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005950#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005951 lconv* lc = localeconv_l(loc.get());
5952#else
5953 lconv* lc = __localeconv_l(loc.get());
5954#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005955 if (*lc->mon_decimal_point)
5956 __decimal_point_ = *lc->mon_decimal_point;
5957 else
5958 __decimal_point_ = base::do_decimal_point();
5959 if (*lc->mon_thousands_sep)
5960 __thousands_sep_ = *lc->mon_thousands_sep;
5961 else
5962 __thousands_sep_ = base::do_thousands_sep();
5963 __grouping_ = lc->mon_grouping;
5964 __curr_symbol_ = lc->int_curr_symbol;
5965 if (lc->int_frac_digits != CHAR_MAX)
5966 __frac_digits_ = lc->int_frac_digits;
5967 else
5968 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005969#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005970 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005971#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005972 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005973#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005974 __positive_sign_ = "()";
5975 else
5976 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005977#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005978 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005979#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005980 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005981#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005982 __negative_sign_ = "()";
5983 else
5984 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005985 // Assume the positive and negative formats will want spaces in
5986 // the same places in curr_symbol since there's no way to
5987 // represent anything else.
5988 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005989#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005990 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5991 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5992 __init_pat(__neg_format_, __curr_symbol_, true,
5993 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005994#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005995 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5996 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5997 lc->int_p_sign_posn, ' ');
5998 __init_pat(__neg_format_, __curr_symbol_, true,
5999 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6000 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006001#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006002}
6003
6004template<>
6005void
6006moneypunct_byname<wchar_t, false>::init(const char* nm)
6007{
6008 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006009 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00006010#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00006011 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006012 throw runtime_error("moneypunct_byname"
6013 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00006014#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006015#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006016 lconv* lc = localeconv_l(loc.get());
6017#else
6018 lconv* lc = __localeconv_l(loc.get());
6019#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006020 if (*lc->mon_decimal_point)
6021 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6022 else
6023 __decimal_point_ = base::do_decimal_point();
6024 if (*lc->mon_thousands_sep)
6025 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6026 else
6027 __thousands_sep_ = base::do_thousands_sep();
6028 __grouping_ = lc->mon_grouping;
6029 wchar_t wbuf[100];
6030 mbstate_t mb = {0};
6031 const char* bb = lc->currency_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006032#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006033 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006034#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006035 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006036#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006037 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006038 __throw_runtime_error("locale not supported");
6039 wchar_t* wbe = wbuf + j;
6040 __curr_symbol_.assign(wbuf, wbe);
6041 if (lc->frac_digits != CHAR_MAX)
6042 __frac_digits_ = lc->frac_digits;
6043 else
6044 __frac_digits_ = base::do_frac_digits();
6045 if (lc->p_sign_posn == 0)
6046 __positive_sign_ = L"()";
6047 else
6048 {
6049 mb = mbstate_t();
6050 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006051#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006052 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006053#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006054 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006055#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006056 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006057 __throw_runtime_error("locale not supported");
6058 wbe = wbuf + j;
6059 __positive_sign_.assign(wbuf, wbe);
6060 }
6061 if (lc->n_sign_posn == 0)
6062 __negative_sign_ = L"()";
6063 else
6064 {
6065 mb = mbstate_t();
6066 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006067#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006068 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006069#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006070 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006071#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006072 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006073 __throw_runtime_error("locale not supported");
6074 wbe = wbuf + j;
6075 __negative_sign_.assign(wbuf, wbe);
6076 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006077 // Assume the positive and negative formats will want spaces in
6078 // the same places in curr_symbol since there's no way to
6079 // represent anything else.
6080 string_type __dummy_curr_symbol = __curr_symbol_;
6081 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6082 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6083 __init_pat(__neg_format_, __curr_symbol_, false,
6084 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00006085}
6086
6087template<>
6088void
6089moneypunct_byname<wchar_t, true>::init(const char* nm)
6090{
6091 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006092 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00006093#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00006094 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006095 throw runtime_error("moneypunct_byname"
6096 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00006097#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006098#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006099 lconv* lc = localeconv_l(loc.get());
6100#else
6101 lconv* lc = __localeconv_l(loc.get());
6102#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006103 if (*lc->mon_decimal_point)
6104 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6105 else
6106 __decimal_point_ = base::do_decimal_point();
6107 if (*lc->mon_thousands_sep)
6108 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6109 else
6110 __thousands_sep_ = base::do_thousands_sep();
6111 __grouping_ = lc->mon_grouping;
6112 wchar_t wbuf[100];
6113 mbstate_t mb = {0};
6114 const char* bb = lc->int_curr_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006115#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006116 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006117#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006118 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006119#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006120 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006121 __throw_runtime_error("locale not supported");
6122 wchar_t* wbe = wbuf + j;
6123 __curr_symbol_.assign(wbuf, wbe);
6124 if (lc->int_frac_digits != CHAR_MAX)
6125 __frac_digits_ = lc->int_frac_digits;
6126 else
6127 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006128#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006129 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006130#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006131 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006132#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006133 __positive_sign_ = L"()";
6134 else
6135 {
6136 mb = mbstate_t();
6137 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006138#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006139 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006140#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006141 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006142#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006143 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006144 __throw_runtime_error("locale not supported");
6145 wbe = wbuf + j;
6146 __positive_sign_.assign(wbuf, wbe);
6147 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006148#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006149 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006150#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006151 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006152#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006153 __negative_sign_ = L"()";
6154 else
6155 {
6156 mb = mbstate_t();
6157 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006158#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006159 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006160#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006161 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006162#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006163 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006164 __throw_runtime_error("locale not supported");
6165 wbe = wbuf + j;
6166 __negative_sign_.assign(wbuf, wbe);
6167 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006168 // Assume the positive and negative formats will want spaces in
6169 // the same places in curr_symbol since there's no way to
6170 // represent anything else.
6171 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006172#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006173 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6174 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6175 __init_pat(__neg_format_, __curr_symbol_, true,
6176 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006177#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006178 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6179 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6180 lc->int_p_sign_posn, L' ');
6181 __init_pat(__neg_format_, __curr_symbol_, true,
6182 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6183 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006184#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006185}
6186
6187void __do_nothing(void*) {}
6188
6189void __throw_runtime_error(const char* msg)
6190{
Howard Hinnant72f73582010-08-11 17:04:31 +00006191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006192 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006193#else
6194 (void)msg;
Howard Hinnant72f73582010-08-11 17:04:31 +00006195#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006196}
6197
6198template class collate<char>;
6199template class collate<wchar_t>;
6200
6201template class num_get<char>;
6202template class num_get<wchar_t>;
6203
Howard Hinnant28b24882011-12-01 20:21:04 +00006204template struct __num_get<char>;
6205template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006206
6207template class num_put<char>;
6208template class num_put<wchar_t>;
6209
Howard Hinnant28b24882011-12-01 20:21:04 +00006210template struct __num_put<char>;
6211template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006212
6213template class time_get<char>;
6214template class time_get<wchar_t>;
6215
6216template class time_get_byname<char>;
6217template class time_get_byname<wchar_t>;
6218
6219template class time_put<char>;
6220template class time_put<wchar_t>;
6221
6222template class time_put_byname<char>;
6223template class time_put_byname<wchar_t>;
6224
6225template class moneypunct<char, false>;
6226template class moneypunct<char, true>;
6227template class moneypunct<wchar_t, false>;
6228template class moneypunct<wchar_t, true>;
6229
6230template class moneypunct_byname<char, false>;
6231template class moneypunct_byname<char, true>;
6232template class moneypunct_byname<wchar_t, false>;
6233template class moneypunct_byname<wchar_t, true>;
6234
6235template class money_get<char>;
6236template class money_get<wchar_t>;
6237
6238template class __money_get<char>;
6239template class __money_get<wchar_t>;
6240
6241template class money_put<char>;
6242template class money_put<wchar_t>;
6243
6244template class __money_put<char>;
6245template class __money_put<wchar_t>;
6246
6247template class messages<char>;
6248template class messages<wchar_t>;
6249
6250template class messages_byname<char>;
6251template class messages_byname<wchar_t>;
6252
6253template class codecvt_byname<char, char, mbstate_t>;
6254template class codecvt_byname<wchar_t, char, mbstate_t>;
6255template class codecvt_byname<char16_t, char, mbstate_t>;
6256template class codecvt_byname<char32_t, char, mbstate_t>;
6257
6258template class __vector_base_common<true>;
6259
6260_LIBCPP_END_NAMESPACE_STD