blob: 83052f605a65ad0b451ffe246c5b3d235cacbb9b [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__)
Howard Hinnantae0f80b2011-09-29 20:33:10 +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
Marshall Clowd920eea2013-10-21 15:07:28 +0000126#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +0000127#pragma clang diagnostic push
128#pragma clang diagnostic ignored "-Wpadded"
Marshall Clowd920eea2013-10-21 15:07:28 +0000129#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000130
Howard Hinnantc51e1022010-05-11 19:42:16 +0000131class _LIBCPP_HIDDEN locale::__imp
132 : public facet
133{
134 enum {N = 28};
Marshall Clowd920eea2013-10-21 15:07:28 +0000135#if defined(_LIBCPP_MSVC)
136// FIXME: MSVC doesn't support aligned parameters by value.
137// I can't get the __sso_allocator to work here
138// for MSVC I think for this reason.
139 vector<facet*> facets_;
140#else
Howard Hinnantc51e1022010-05-11 19:42:16 +0000141 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowd920eea2013-10-21 15:07:28 +0000142#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000143 string name_;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000144public:
145 explicit __imp(size_t refs = 0);
146 explicit __imp(const string& name, size_t refs = 0);
147 __imp(const __imp&);
148 __imp(const __imp&, const string&, locale::category c);
149 __imp(const __imp& other, const __imp& one, locale::category c);
150 __imp(const __imp&, facet* f, long id);
151 ~__imp();
152
153 const string& name() const {return name_;}
Howard Hinnant28b24882011-12-01 20:21:04 +0000154 bool has_facet(long id) const
155 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000156 const locale::facet* use_facet(long id) const;
157
158 static const locale& make_classic();
159 static locale& make_global();
160private:
161 void install(facet* f, long id);
162 template <class F> void install(F* f) {install(f, f->id.__get());}
163 template <class F> void install_from(const __imp& other);
164};
165
Marshall Clowd920eea2013-10-21 15:07:28 +0000166#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +0000167#pragma clang diagnostic pop
Marshall Clowd920eea2013-10-21 15:07:28 +0000168#endif
Howard Hinnant28b24882011-12-01 20:21:04 +0000169
Howard Hinnantc51e1022010-05-11 19:42:16 +0000170locale::__imp::__imp(size_t refs)
171 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000172 facets_(N),
173 name_("C")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000174{
175 facets_.clear();
Howard Hinnant28b24882011-12-01 20:21:04 +0000176 install(&make<_VSTD::collate<char> >(1u));
177 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000178 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnant28b24882011-12-01 20:21:04 +0000179 install(&make<_VSTD::ctype<wchar_t> >(1u));
180 install(&make<codecvt<char, char, mbstate_t> >(1u));
181 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
182 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
183 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
184 install(&make<numpunct<char> >(1u));
185 install(&make<numpunct<wchar_t> >(1u));
186 install(&make<num_get<char> >(1u));
187 install(&make<num_get<wchar_t> >(1u));
188 install(&make<num_put<char> >(1u));
189 install(&make<num_put<wchar_t> >(1u));
190 install(&make<moneypunct<char, false> >(1u));
191 install(&make<moneypunct<char, true> >(1u));
192 install(&make<moneypunct<wchar_t, false> >(1u));
193 install(&make<moneypunct<wchar_t, true> >(1u));
194 install(&make<money_get<char> >(1u));
195 install(&make<money_get<wchar_t> >(1u));
196 install(&make<money_put<char> >(1u));
197 install(&make<money_put<wchar_t> >(1u));
198 install(&make<time_get<char> >(1u));
199 install(&make<time_get<wchar_t> >(1u));
200 install(&make<time_put<char> >(1u));
201 install(&make<time_put<wchar_t> >(1u));
202 install(&make<_VSTD::messages<char> >(1u));
203 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000204}
205
206locale::__imp::__imp(const string& name, size_t refs)
207 : facet(refs),
Howard Hinnant28b24882011-12-01 20:21:04 +0000208 facets_(N),
209 name_(name)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000210{
Howard Hinnant72f73582010-08-11 17:04:31 +0000211#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000212 try
213 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000214#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000215 facets_ = locale::classic().__locale_->facets_;
216 for (unsigned i = 0; i < facets_.size(); ++i)
217 if (facets_[i])
218 facets_[i]->__add_shared();
219 install(new collate_byname<char>(name_));
220 install(new collate_byname<wchar_t>(name_));
221 install(new ctype_byname<char>(name_));
222 install(new ctype_byname<wchar_t>(name_));
223 install(new codecvt_byname<char, char, mbstate_t>(name_));
224 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
225 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
226 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
227 install(new numpunct_byname<char>(name_));
228 install(new numpunct_byname<wchar_t>(name_));
229 install(new moneypunct_byname<char, false>(name_));
230 install(new moneypunct_byname<char, true>(name_));
231 install(new moneypunct_byname<wchar_t, false>(name_));
232 install(new moneypunct_byname<wchar_t, true>(name_));
233 install(new time_get_byname<char>(name_));
234 install(new time_get_byname<wchar_t>(name_));
235 install(new time_put_byname<char>(name_));
236 install(new time_put_byname<wchar_t>(name_));
237 install(new messages_byname<char>(name_));
238 install(new messages_byname<wchar_t>(name_));
Howard Hinnant72f73582010-08-11 17:04:31 +0000239#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000240 }
241 catch (...)
242 {
243 for (unsigned i = 0; i < facets_.size(); ++i)
244 if (facets_[i])
245 facets_[i]->__release_shared();
246 throw;
247 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000248#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000249}
250
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000251// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant3f648332012-12-27 23:24:31 +0000252// copy constructor` warning emitted by GCC
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000253#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000254#pragma GCC diagnostic push
Howard Hinnanta80f1ec2012-12-28 18:15:01 +0000255#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000256#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000257
Howard Hinnantc51e1022010-05-11 19:42:16 +0000258locale::__imp::__imp(const __imp& other)
Howard Hinnant28b24882011-12-01 20:21:04 +0000259 : facets_(max<size_t>(N, other.facets_.size())),
260 name_(other.name_)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000261{
262 facets_ = other.facets_;
263 for (unsigned i = 0; i < facets_.size(); ++i)
264 if (facets_[i])
265 facets_[i]->__add_shared();
266}
267
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000268#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant3f648332012-12-27 23:24:31 +0000269#pragma GCC diagnostic pop
Joerg Sonnenberger7eace7e2013-05-02 19:34:26 +0000270#endif
Howard Hinnant3f648332012-12-27 23:24:31 +0000271
Howard Hinnantc51e1022010-05-11 19:42:16 +0000272locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000273 : facets_(N),
274 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000275{
276 facets_ = other.facets_;
277 for (unsigned i = 0; i < facets_.size(); ++i)
278 if (facets_[i])
279 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000280#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000281 try
282 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000283#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000284 if (c & locale::collate)
285 {
286 install(new collate_byname<char>(name));
287 install(new collate_byname<wchar_t>(name));
288 }
289 if (c & locale::ctype)
290 {
291 install(new ctype_byname<char>(name));
292 install(new ctype_byname<wchar_t>(name));
293 install(new codecvt_byname<char, char, mbstate_t>(name));
294 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
295 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
296 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
297 }
298 if (c & locale::monetary)
299 {
300 install(new moneypunct_byname<char, false>(name));
301 install(new moneypunct_byname<char, true>(name));
302 install(new moneypunct_byname<wchar_t, false>(name));
303 install(new moneypunct_byname<wchar_t, true>(name));
304 }
305 if (c & locale::numeric)
306 {
307 install(new numpunct_byname<char>(name));
308 install(new numpunct_byname<wchar_t>(name));
309 }
310 if (c & locale::time)
311 {
312 install(new time_get_byname<char>(name));
313 install(new time_get_byname<wchar_t>(name));
314 install(new time_put_byname<char>(name));
315 install(new time_put_byname<wchar_t>(name));
316 }
317 if (c & locale::messages)
318 {
319 install(new messages_byname<char>(name));
320 install(new messages_byname<wchar_t>(name));
321 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000322#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000323 }
324 catch (...)
325 {
326 for (unsigned i = 0; i < facets_.size(); ++i)
327 if (facets_[i])
328 facets_[i]->__release_shared();
329 throw;
330 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000331#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000332}
333
334template<class F>
335inline
336void
337locale::__imp::install_from(const locale::__imp& one)
338{
339 long id = F::id.__get();
340 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
341}
342
343locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnant28b24882011-12-01 20:21:04 +0000344 : facets_(N),
345 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000346{
347 facets_ = other.facets_;
348 for (unsigned i = 0; i < facets_.size(); ++i)
349 if (facets_[i])
350 facets_[i]->__add_shared();
Howard Hinnant72f73582010-08-11 17:04:31 +0000351#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000352 try
353 {
Howard Hinnantffb308e2010-08-22 00:03:27 +0000354#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000355 if (c & locale::collate)
356 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000357 install_from<_VSTD::collate<char> >(one);
358 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000359 }
360 if (c & locale::ctype)
361 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000362 install_from<_VSTD::ctype<char> >(one);
363 install_from<_VSTD::ctype<wchar_t> >(one);
364 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
365 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
366 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
367 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000368 }
369 if (c & locale::monetary)
370 {
371 install_from<moneypunct<char, false> >(one);
372 install_from<moneypunct<char, true> >(one);
373 install_from<moneypunct<wchar_t, false> >(one);
374 install_from<moneypunct<wchar_t, true> >(one);
375 install_from<money_get<char> >(one);
376 install_from<money_get<wchar_t> >(one);
377 install_from<money_put<char> >(one);
378 install_from<money_put<wchar_t> >(one);
379 }
380 if (c & locale::numeric)
381 {
382 install_from<numpunct<char> >(one);
383 install_from<numpunct<wchar_t> >(one);
384 install_from<num_get<char> >(one);
385 install_from<num_get<wchar_t> >(one);
386 install_from<num_put<char> >(one);
387 install_from<num_put<wchar_t> >(one);
388 }
389 if (c & locale::time)
390 {
391 install_from<time_get<char> >(one);
392 install_from<time_get<wchar_t> >(one);
393 install_from<time_put<char> >(one);
394 install_from<time_put<wchar_t> >(one);
395 }
396 if (c & locale::messages)
397 {
Howard Hinnantb1ad5a82011-06-30 21:18:19 +0000398 install_from<_VSTD::messages<char> >(one);
399 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000400 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000401#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000402 }
403 catch (...)
404 {
405 for (unsigned i = 0; i < facets_.size(); ++i)
406 if (facets_[i])
407 facets_[i]->__release_shared();
408 throw;
409 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000410#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000411}
412
413locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnant28b24882011-12-01 20:21:04 +0000414 : facets_(max<size_t>(N, other.facets_.size()+1)),
415 name_("*")
Howard Hinnantc51e1022010-05-11 19:42:16 +0000416{
417 f->__add_shared();
418 unique_ptr<facet, release> hold(f);
419 facets_ = other.facets_;
420 for (unsigned i = 0; i < other.facets_.size(); ++i)
421 if (facets_[i])
422 facets_[i]->__add_shared();
423 install(hold.get(), id);
424}
425
426locale::__imp::~__imp()
427{
428 for (unsigned i = 0; i < facets_.size(); ++i)
429 if (facets_[i])
430 facets_[i]->__release_shared();
431}
432
433void
434locale::__imp::install(facet* f, long id)
435{
436 f->__add_shared();
437 unique_ptr<facet, release> hold(f);
Howard Hinnant28b24882011-12-01 20:21:04 +0000438 if (static_cast<size_t>(id) >= facets_.size())
439 facets_.resize(static_cast<size_t>(id+1));
440 if (facets_[static_cast<size_t>(id)])
441 facets_[static_cast<size_t>(id)]->__release_shared();
442 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000443}
444
445const locale::facet*
446locale::__imp::use_facet(long id) const
447{
Howard Hinnant72f73582010-08-11 17:04:31 +0000448#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000449 if (!has_facet(id))
450 throw bad_cast();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000451#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant28b24882011-12-01 20:21:04 +0000452 return facets_[static_cast<size_t>(id)];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000453}
454
455// locale
456
457const locale&
458locale::__imp::make_classic()
459{
460 // only one thread can get in here and it only gets in once
461 static aligned_storage<sizeof(locale)>::type buf;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000462 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnant28b24882011-12-01 20:21:04 +0000463 c->__locale_ = &make<__imp>(1u);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000464 return *c;
465}
466
467const locale&
468locale::classic()
469{
470 static const locale& c = __imp::make_classic();
471 return c;
472}
473
474locale&
475locale::__imp::make_global()
476{
477 // only one thread can get in here and it only gets in once
478 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000479 ::new (&buf) locale(locale::classic());
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000480 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000481}
482
483locale&
484locale::__global()
485{
486 static locale& g = __imp::make_global();
487 return g;
488}
489
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000490locale::locale() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000491 : __locale_(__global().__locale_)
492{
493 __locale_->__add_shared();
494}
495
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000496locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000497 : __locale_(l.__locale_)
498{
499 __locale_->__add_shared();
500}
501
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000502locale::~locale()
Howard Hinnantc51e1022010-05-11 19:42:16 +0000503{
504 __locale_->__release_shared();
505}
506
507const locale&
Howard Hinnant7c9e5732011-05-31 15:34:58 +0000508locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509{
510 other.__locale_->__add_shared();
511 __locale_->__release_shared();
512 __locale_ = other.__locale_;
513 return *this;
514}
515
516locale::locale(const char* name)
Howard Hinnant72f73582010-08-11 17:04:31 +0000517#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000518 : __locale_(name ? new __imp(name)
519 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000520#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000521 : __locale_(new __imp(name))
522#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000523{
524 __locale_->__add_shared();
525}
526
527locale::locale(const string& name)
528 : __locale_(new __imp(name))
529{
530 __locale_->__add_shared();
531}
532
533locale::locale(const locale& other, const char* name, category c)
Howard Hinnant72f73582010-08-11 17:04:31 +0000534#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000535 : __locale_(name ? new __imp(*other.__locale_, name, c)
536 : throw runtime_error("locale constructed with null"))
Howard Hinnantffb308e2010-08-22 00:03:27 +0000537#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant72f73582010-08-11 17:04:31 +0000538 : __locale_(new __imp(*other.__locale_, name, c))
539#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000540{
541 __locale_->__add_shared();
542}
543
544locale::locale(const locale& other, const string& name, category c)
545 : __locale_(new __imp(*other.__locale_, name, c))
546{
547 __locale_->__add_shared();
548}
549
550locale::locale(const locale& other, const locale& one, category c)
551 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
552{
553 __locale_->__add_shared();
554}
555
556string
557locale::name() const
558{
559 return __locale_->name();
560}
561
562void
563locale::__install_ctor(const locale& other, facet* f, long id)
564{
565 if (f)
566 __locale_ = new __imp(*other.__locale_, f, id);
567 else
568 __locale_ = other.__locale_;
569 __locale_->__add_shared();
570}
571
572locale
573locale::global(const locale& loc)
574{
575 locale& g = __global();
576 locale r = g;
577 g = loc;
578 if (g.name() != "*")
579 setlocale(LC_ALL, g.name().c_str());
580 return r;
581}
582
583bool
584locale::has_facet(id& x) const
585{
586 return __locale_->has_facet(x.__get());
587}
588
589const locale::facet*
590locale::use_facet(id& x) const
591{
592 return __locale_->use_facet(x.__get());
593}
594
595bool
596locale::operator==(const locale& y) const
597{
598 return (__locale_ == y.__locale_)
599 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
600}
601
602// locale::facet
603
604locale::facet::~facet()
605{
606}
607
608void
Howard Hinnant719bda32011-05-28 14:41:13 +0000609locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000610{
611 delete this;
612}
613
614// locale::id
615
616int32_t locale::id::__next_id = 0;
617
618namespace
619{
620
621class __fake_bind
622{
623 locale::id* id_;
624 void (locale::id::* pmf_)();
625public:
626 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
627 : id_(id), pmf_(pmf) {}
628
629 void operator()() const
630 {
631 (id_->*pmf_)();
632 }
633};
634
635}
636
637long
638locale::id::__get()
639{
640 call_once(__flag_, __fake_bind(&locale::id::__init, this));
641 return __id_ - 1;
642}
643
644void
645locale::id::__init()
646{
Howard Hinnant155c2af2010-05-24 17:49:41 +0000647 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000648}
649
650// template <> class collate_byname<char>
651
652collate_byname<char>::collate_byname(const char* n, size_t refs)
653 : collate<char>(refs),
654 __l(newlocale(LC_ALL_MASK, n, 0))
655{
Howard Hinnant72f73582010-08-11 17:04:31 +0000656#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000657 if (__l == 0)
658 throw runtime_error("collate_byname<char>::collate_byname"
659 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000660#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000661}
662
663collate_byname<char>::collate_byname(const string& name, size_t refs)
664 : collate<char>(refs),
665 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
666{
Howard Hinnant72f73582010-08-11 17:04:31 +0000667#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000668 if (__l == 0)
669 throw runtime_error("collate_byname<char>::collate_byname"
670 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000671#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000672}
673
674collate_byname<char>::~collate_byname()
675{
676 freelocale(__l);
677}
678
679int
680collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
681 const char_type* __lo2, const char_type* __hi2) const
682{
683 string_type lhs(__lo1, __hi1);
684 string_type rhs(__lo2, __hi2);
685 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
686 if (r < 0)
687 return -1;
688 if (r > 0)
689 return 1;
690 return r;
691}
692
693collate_byname<char>::string_type
694collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
695{
696 const string_type in(lo, hi);
697 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
698 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
699 return out;
700}
701
702// template <> class collate_byname<wchar_t>
703
704collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
705 : collate<wchar_t>(refs),
706 __l(newlocale(LC_ALL_MASK, n, 0))
707{
Howard Hinnant72f73582010-08-11 17:04:31 +0000708#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000709 if (__l == 0)
710 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
711 " failed to construct for " + string(n));
Howard Hinnantffb308e2010-08-22 00:03:27 +0000712#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000713}
714
715collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
716 : collate<wchar_t>(refs),
717 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
718{
Howard Hinnant72f73582010-08-11 17:04:31 +0000719#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000720 if (__l == 0)
721 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
722 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000723#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000724}
725
726collate_byname<wchar_t>::~collate_byname()
727{
728 freelocale(__l);
729}
730
731int
732collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
733 const char_type* __lo2, const char_type* __hi2) const
734{
735 string_type lhs(__lo1, __hi1);
736 string_type rhs(__lo2, __hi2);
737 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
738 if (r < 0)
739 return -1;
740 if (r > 0)
741 return 1;
742 return r;
743}
744
745collate_byname<wchar_t>::string_type
746collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
747{
748 const string_type in(lo, hi);
749 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
750 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
751 return out;
752}
753
754// template <> class ctype<wchar_t>;
755
Howard Hinnant2c45cb42012-12-12 21:14:28 +0000756const ctype_base::mask ctype_base::space;
757const ctype_base::mask ctype_base::print;
758const ctype_base::mask ctype_base::cntrl;
759const ctype_base::mask ctype_base::upper;
760const ctype_base::mask ctype_base::lower;
761const ctype_base::mask ctype_base::alpha;
762const ctype_base::mask ctype_base::digit;
763const ctype_base::mask ctype_base::punct;
764const ctype_base::mask ctype_base::xdigit;
765const ctype_base::mask ctype_base::blank;
766const ctype_base::mask ctype_base::alnum;
767const ctype_base::mask ctype_base::graph;
768
Howard Hinnantc51e1022010-05-11 19:42:16 +0000769locale::id ctype<wchar_t>::id;
770
771ctype<wchar_t>::~ctype()
772{
773}
774
775bool
776ctype<wchar_t>::do_is(mask m, char_type c) const
777{
Marshall Clowd920eea2013-10-21 15:07:28 +0000778 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000779}
780
781const wchar_t*
782ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
783{
784 for (; low != high; ++low, ++vec)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000785 *vec = static_cast<mask>(isascii(*low) ?
786 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000787 return low;
788}
789
790const wchar_t*
791ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
792{
793 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000794 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000795 break;
796 return low;
797}
798
799const wchar_t*
800ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
801{
802 for (; low != high; ++low)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000803 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantc51e1022010-05-11 19:42:16 +0000804 break;
805 return low;
806}
807
808wchar_t
809ctype<wchar_t>::do_toupper(char_type c) const
810{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000811#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
812 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Marshall Cloweae03f62013-11-19 18:05:03 +0000813#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000814 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000815#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000816 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000817#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000818}
819
820const wchar_t*
821ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
822{
823 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000824#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
825 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Marshall Cloweae03f62013-11-19 18:05:03 +0000826#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000827 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
828 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000829#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000830 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000831#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000832 return low;
833}
834
835wchar_t
836ctype<wchar_t>::do_tolower(char_type c) const
837{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000838#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
839 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Marshall Cloweae03f62013-11-19 18:05:03 +0000840#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000841 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000842#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000843 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000844#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000845}
846
847const wchar_t*
848ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
849{
850 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000851#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
852 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Marshall Cloweae03f62013-11-19 18:05:03 +0000853#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Alexis Hunt92b0c812011-07-09 00:56:23 +0000854 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
855 : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000856#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000857 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000858#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000859 return low;
860}
861
862wchar_t
863ctype<wchar_t>::do_widen(char c) const
864{
865 return c;
866}
867
868const char*
869ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
870{
871 for (; low != high; ++low, ++dest)
872 *dest = *low;
873 return low;
874}
875
876char
877ctype<wchar_t>::do_narrow(char_type c, char dfault) const
878{
879 if (isascii(c))
880 return static_cast<char>(c);
881 return dfault;
882}
883
884const wchar_t*
885ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
886{
887 for (; low != high; ++low, ++dest)
888 if (isascii(*low))
Howard Hinnant28b24882011-12-01 20:21:04 +0000889 *dest = static_cast<char>(*low);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890 else
891 *dest = dfault;
892 return low;
893}
894
895// template <> class ctype<char>;
896
897locale::id ctype<char>::id;
898
899ctype<char>::ctype(const mask* tab, bool del, size_t refs)
900 : locale::facet(refs),
901 __tab_(tab),
902 __del_(del)
903{
Alexis Hunt92b0c812011-07-09 00:56:23 +0000904 if (__tab_ == 0)
905 __tab_ = classic_table();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000906}
907
908ctype<char>::~ctype()
909{
910 if (__tab_ && __del_)
911 delete [] __tab_;
912}
913
914char
915ctype<char>::do_toupper(char_type c) const
916{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000917#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000918 return isascii(c) ?
919 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000920#elif defined(__NetBSD__)
921 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000922#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000923 return isascii(c) ?
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000924 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000925#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000926 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000927#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000928}
929
930const char*
931ctype<char>::do_toupper(char_type* low, const char_type* high) const
932{
933 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000934#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000935 *low = isascii(*low) ?
936 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000937#elif defined(__NetBSD__)
938 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000939#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000940 *low = isascii(*low) ?
941 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000942#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000943 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000944#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000945 return low;
946}
947
948char
949ctype<char>::do_tolower(char_type c) const
950{
Howard Hinnantd7a78632011-09-29 13:33:15 +0000951#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000952 return isascii(c) ?
953 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000954#elif defined(__NetBSD__)
955 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000956#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Marshall Clowada0f732013-02-07 14:22:51 +0000957 return isascii(c) ?
958 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000959#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000960 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000961#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000962}
963
964const char*
965ctype<char>::do_tolower(char_type* low, const char_type* high) const
966{
967 for (; low != high; ++low)
Howard Hinnantd7a78632011-09-29 13:33:15 +0000968#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnant28b24882011-12-01 20:21:04 +0000969 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000970#elif defined(__NetBSD__)
971 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Marshall Cloweae03f62013-11-19 18:05:03 +0000972#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clowada0f732013-02-07 14:22:51 +0000973 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000974#else
Howard Hinnantd7a78632011-09-29 13:33:15 +0000975 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Alexis Hunt5a4dd562011-07-09 01:09:31 +0000976#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000977 return low;
978}
979
980char
981ctype<char>::do_widen(char c) const
982{
983 return c;
984}
985
986const char*
987ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
988{
989 for (; low != high; ++low, ++dest)
990 *dest = *low;
991 return low;
992}
993
994char
995ctype<char>::do_narrow(char_type c, char dfault) const
996{
997 if (isascii(c))
998 return static_cast<char>(c);
999 return dfault;
1000}
1001
1002const char*
1003ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1004{
1005 for (; low != high; ++low, ++dest)
1006 if (isascii(*low))
1007 *dest = *low;
1008 else
1009 *dest = dfault;
1010 return low;
1011}
1012
Marshall Cloweae03f62013-11-19 18:05:03 +00001013#ifdef __EMSCRIPTEN__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001014extern "C" const unsigned short ** __ctype_b_loc();
1015extern "C" const int ** __ctype_tolower_loc();
1016extern "C" const int ** __ctype_toupper_loc();
1017#endif
1018
Howard Hinnantc51e1022010-05-11 19:42:16 +00001019const ctype<char>::mask*
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001020ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001021{
David Chisnall1d581062011-09-21 08:39:44 +00001022#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001023 return _DefaultRuneLocale.__runetype;
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001024#elif defined(__NetBSD__)
1025 return _C_ctype_tab_ + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001026#elif defined(__GLIBC__)
1027 return __cloc()->__ctype_b;
David Chisnall8074c342012-02-29 13:05:08 +00001028#elif __sun__
1029 return __ctype_mask;
Howard Hinnant8ad70912013-09-17 01:34:47 +00001030#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnantd7a78632011-09-29 13:33:15 +00001031 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnall1d581062011-09-21 08:39:44 +00001032// This is assumed to be safe, which is a nonsense assumption because we're
1033// going to end up dereferencing it later...
Marshall Cloweae03f62013-11-19 18:05:03 +00001034#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001035 return *__ctype_b_loc();
JF Bastien0c265d82015-02-25 22:16:46 +00001036#elif defined(_NEWLIB_VERSION)
1037 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1038 return _ctype_ + 1;
Howard Hinnantea382952013-08-14 18:00:20 +00001039#elif defined(_AIX)
Marshall Clowd03f2c82013-11-19 19:16:03 +00001040 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Marshall Clow3477ec92014-07-10 15:20:28 +00001041#elif defined(__ANDROID__)
Dan Albertb380e8c2014-07-31 21:04:08 +00001042 return reinterpret_cast<const unsigned char*>(_ctype_) + 1;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001043#else
David Chisnall8074c342012-02-29 13:05:08 +00001044 // Platform not supported: abort so the person doing the port knows what to
1045 // fix
Howard Hinnant9e630d62012-02-29 16:08:57 +00001046# warning ctype<char>::classic_table() is not implemented
Howard Hinnant84f697e2013-07-23 16:05:56 +00001047 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall8074c342012-02-29 13:05:08 +00001048 abort();
Alexis Hunt92b0c812011-07-09 00:56:23 +00001049 return NULL;
1050#endif
1051}
1052
Howard Hinnantd7a78632011-09-29 13:33:15 +00001053#if defined(__GLIBC__)
Alexis Hunt92b0c812011-07-09 00:56:23 +00001054const int*
1055ctype<char>::__classic_lower_table() _NOEXCEPT
1056{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001057 return __cloc()->__ctype_tolower;
Alexis Hunt92b0c812011-07-09 00:56:23 +00001058}
1059
1060const int*
1061ctype<char>::__classic_upper_table() _NOEXCEPT
1062{
Alexis Hunt92b0c812011-07-09 00:56:23 +00001063 return __cloc()->__ctype_toupper;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001064}
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001065#elif __NetBSD__
1066const short*
1067ctype<char>::__classic_lower_table() _NOEXCEPT
1068{
1069 return _C_tolower_tab_ + 1;
1070}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001071
Joerg Sonnenberger153e4162013-05-17 21:17:34 +00001072const short*
1073ctype<char>::__classic_upper_table() _NOEXCEPT
1074{
1075 return _C_toupper_tab_ + 1;
1076}
1077
Marshall Cloweae03f62013-11-19 18:05:03 +00001078#elif defined(__EMSCRIPTEN__)
Howard Hinnant942dbd22013-03-29 18:27:28 +00001079const int*
1080ctype<char>::__classic_lower_table() _NOEXCEPT
1081{
1082 return *__ctype_tolower_loc();
1083}
1084
1085const int*
1086ctype<char>::__classic_upper_table() _NOEXCEPT
1087{
1088 return *__ctype_toupper_loc();
1089}
Marshall Cloweae03f62013-11-19 18:05:03 +00001090#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
Howard Hinnant942dbd22013-03-29 18:27:28 +00001091
Howard Hinnantc51e1022010-05-11 19:42:16 +00001092// template <> class ctype_byname<char>
1093
1094ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1095 : ctype<char>(0, false, refs),
1096 __l(newlocale(LC_ALL_MASK, name, 0))
1097{
Howard Hinnant72f73582010-08-11 17:04:31 +00001098#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001099 if (__l == 0)
1100 throw runtime_error("ctype_byname<char>::ctype_byname"
1101 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001102#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001103}
1104
1105ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1106 : ctype<char>(0, false, refs),
1107 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1108{
Howard Hinnant72f73582010-08-11 17:04:31 +00001109#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001110 if (__l == 0)
1111 throw runtime_error("ctype_byname<char>::ctype_byname"
1112 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001113#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001114}
1115
1116ctype_byname<char>::~ctype_byname()
1117{
1118 freelocale(__l);
1119}
1120
1121char
1122ctype_byname<char>::do_toupper(char_type c) const
1123{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001124 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001125}
1126
1127const char*
1128ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1129{
1130 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001131 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001132 return low;
1133}
1134
1135char
1136ctype_byname<char>::do_tolower(char_type c) const
1137{
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001138 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001139}
1140
1141const char*
1142ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1143{
1144 for (; low != high; ++low)
Joerg Sonnenbergerbf60e182013-05-02 19:17:48 +00001145 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001146 return low;
1147}
1148
1149// template <> class ctype_byname<wchar_t>
1150
1151ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1152 : ctype<wchar_t>(refs),
1153 __l(newlocale(LC_ALL_MASK, name, 0))
1154{
Howard Hinnant72f73582010-08-11 17:04:31 +00001155#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001156 if (__l == 0)
1157 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1158 " failed to construct for " + string(name));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001159#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001160}
1161
1162ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1163 : ctype<wchar_t>(refs),
1164 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1165{
Howard Hinnant72f73582010-08-11 17:04:31 +00001166#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001167 if (__l == 0)
1168 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1169 " failed to construct for " + name);
Howard Hinnantffb308e2010-08-22 00:03:27 +00001170#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001171}
1172
1173ctype_byname<wchar_t>::~ctype_byname()
1174{
1175 freelocale(__l);
1176}
1177
1178bool
1179ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1180{
Alexis Huntc2017f12011-07-09 03:40:04 +00001181#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001182 return static_cast<bool>(iswctype_l(c, m, __l));
Alexis Huntc2017f12011-07-09 03:40:04 +00001183#else
Howard Hinnant3cdea7a2012-08-02 18:35:07 +00001184 bool result = false;
Marshall Clowada0f732013-02-07 14:22:51 +00001185 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001186 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1187 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1188 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1189 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1190 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1191 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1192 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1193 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1194 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1195 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnantd7a78632011-09-29 13:33:15 +00001196 return result;
Alexis Huntc2017f12011-07-09 03:40:04 +00001197#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001198}
1199
1200const wchar_t*
1201ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1202{
1203 for (; low != high; ++low, ++vec)
1204 {
1205 if (isascii(*low))
Alexis Hunt92b0c812011-07-09 00:56:23 +00001206 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001207 else
1208 {
1209 *vec = 0;
Marshall Clowada0f732013-02-07 14:22:51 +00001210 wint_t ch = static_cast<wint_t>(*low);
1211 if (iswspace_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001212 *vec |= space;
Marshall Clowada0f732013-02-07 14:22:51 +00001213 if (iswprint_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001214 *vec |= print;
Marshall Clowada0f732013-02-07 14:22:51 +00001215 if (iswcntrl_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001216 *vec |= cntrl;
Marshall Clowada0f732013-02-07 14:22:51 +00001217 if (iswupper_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001218 *vec |= upper;
Marshall Clowada0f732013-02-07 14:22:51 +00001219 if (iswlower_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001220 *vec |= lower;
Marshall Clowada0f732013-02-07 14:22:51 +00001221 if (iswalpha_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001222 *vec |= alpha;
Marshall Clowada0f732013-02-07 14:22:51 +00001223 if (iswdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001224 *vec |= digit;
Marshall Clowada0f732013-02-07 14:22:51 +00001225 if (iswpunct_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001226 *vec |= punct;
Marshall Clowada0f732013-02-07 14:22:51 +00001227 if (iswxdigit_l(ch, __l))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001228 *vec |= xdigit;
1229 }
1230 }
1231 return low;
1232}
1233
1234const wchar_t*
1235ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1236{
1237 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001238 {
1239#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001240 if (iswctype_l(*low, m, __l))
1241 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001242#else
Marshall Clowada0f732013-02-07 14:22:51 +00001243 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001244 if (m & space && iswspace_l(ch, __l)) break;
1245 if (m & print && iswprint_l(ch, __l)) break;
1246 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1247 if (m & upper && iswupper_l(ch, __l)) break;
1248 if (m & lower && iswlower_l(ch, __l)) break;
1249 if (m & alpha && iswalpha_l(ch, __l)) break;
1250 if (m & digit && iswdigit_l(ch, __l)) break;
1251 if (m & punct && iswpunct_l(ch, __l)) break;
1252 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1253 if (m & blank && iswblank_l(ch, __l)) break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001254#endif
1255 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001256 return low;
1257}
1258
1259const wchar_t*
1260ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1261{
1262 for (; low != high; ++low)
Alexis Huntc2017f12011-07-09 03:40:04 +00001263 {
1264#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantc51e1022010-05-11 19:42:16 +00001265 if (!iswctype_l(*low, m, __l))
1266 break;
Alexis Huntc2017f12011-07-09 03:40:04 +00001267#else
Marshall Clowada0f732013-02-07 14:22:51 +00001268 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs60570512014-08-27 00:39:47 +00001269 if (m & space && iswspace_l(ch, __l)) continue;
1270 if (m & print && iswprint_l(ch, __l)) continue;
1271 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1272 if (m & upper && iswupper_l(ch, __l)) continue;
1273 if (m & lower && iswlower_l(ch, __l)) continue;
1274 if (m & alpha && iswalpha_l(ch, __l)) continue;
1275 if (m & digit && iswdigit_l(ch, __l)) continue;
1276 if (m & punct && iswpunct_l(ch, __l)) continue;
1277 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1278 if (m & blank && iswblank_l(ch, __l)) continue;
Alexis Huntc2017f12011-07-09 03:40:04 +00001279 break;
1280#endif
1281 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001282 return low;
1283}
1284
1285wchar_t
1286ctype_byname<wchar_t>::do_toupper(char_type c) const
1287{
1288 return towupper_l(c, __l);
1289}
1290
1291const wchar_t*
1292ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1293{
1294 for (; low != high; ++low)
1295 *low = towupper_l(*low, __l);
1296 return low;
1297}
1298
1299wchar_t
1300ctype_byname<wchar_t>::do_tolower(char_type c) const
1301{
1302 return towlower_l(c, __l);
1303}
1304
1305const wchar_t*
1306ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1307{
1308 for (; low != high; ++low)
1309 *low = towlower_l(*low, __l);
1310 return low;
1311}
1312
1313wchar_t
1314ctype_byname<wchar_t>::do_widen(char c) const
1315{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001316#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001317 return btowc_l(c, __l);
1318#else
1319 return __btowc_l(c, __l);
1320#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321}
1322
1323const char*
1324ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1325{
1326 for (; low != high; ++low, ++dest)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001327#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001328 *dest = btowc_l(*low, __l);
1329#else
1330 *dest = __btowc_l(*low, __l);
1331#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001332 return low;
1333}
1334
1335char
1336ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1337{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001338#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001339 int r = wctob_l(c, __l);
1340#else
1341 int r = __wctob_l(c, __l);
1342#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001343 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001344}
1345
1346const wchar_t*
1347ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1348{
1349 for (; low != high; ++low, ++dest)
1350 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001351#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001352 int r = wctob_l(*low, __l);
1353#else
1354 int r = __wctob_l(*low, __l);
1355#endif
Howard Hinnant434ebf72012-12-27 18:46:00 +00001356 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001357 }
1358 return low;
1359}
1360
1361// template <> class codecvt<char, char, mbstate_t>
1362
Howard Hinnantffb308e2010-08-22 00:03:27 +00001363locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001364
1365codecvt<char, char, mbstate_t>::~codecvt()
1366{
1367}
1368
1369codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001370codecvt<char, char, mbstate_t>::do_out(state_type&,
1371 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001372 extern_type* to, extern_type*, extern_type*& to_nxt) const
1373{
1374 frm_nxt = frm;
1375 to_nxt = to;
1376 return noconv;
1377}
1378
1379codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001380codecvt<char, char, mbstate_t>::do_in(state_type&,
1381 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001382 intern_type* to, intern_type*, intern_type*& to_nxt) const
1383{
1384 frm_nxt = frm;
1385 to_nxt = to;
1386 return noconv;
1387}
1388
1389codecvt<char, char, mbstate_t>::result
Howard Hinnantffb308e2010-08-22 00:03:27 +00001390codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001391 extern_type* to, extern_type*, extern_type*& to_nxt) const
1392{
1393 to_nxt = to;
1394 return noconv;
1395}
1396
1397int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001398codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001399{
1400 return 1;
1401}
1402
1403bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001404codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001405{
1406 return true;
1407}
1408
1409int
1410codecvt<char, char, mbstate_t>::do_length(state_type&,
1411 const extern_type* frm, const extern_type* end, size_t mx) const
1412{
Howard Hinnant28b24882011-12-01 20:21:04 +00001413 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001414}
1415
1416int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001417codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001418{
1419 return 1;
1420}
1421
1422// template <> class codecvt<wchar_t, char, mbstate_t>
1423
Howard Hinnantffb308e2010-08-22 00:03:27 +00001424locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001425
1426codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1427 : locale::facet(refs),
Joerg Sonnenberger076a0932013-05-09 19:00:18 +00001428 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001429{
1430}
1431
1432codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1433 : locale::facet(refs),
1434 __l(newlocale(LC_ALL_MASK, nm, 0))
1435{
Howard Hinnant72f73582010-08-11 17:04:31 +00001436#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001437 if (__l == 0)
1438 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1439 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00001440#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00001441}
1442
1443codecvt<wchar_t, char, mbstate_t>::~codecvt()
1444{
Joerg Sonnenbergerc6b58dd2013-05-09 23:06:35 +00001445 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001446 freelocale(__l);
1447}
1448
1449codecvt<wchar_t, char, mbstate_t>::result
1450codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001451 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001452 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1453{
1454 // look for first internal null in frm
1455 const intern_type* fend = frm;
1456 for (; fend != frm_end; ++fend)
1457 if (*fend == 0)
1458 break;
1459 // loop over all null-terminated sequences in frm
1460 to_nxt = to;
1461 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1462 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001463 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001464 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001465#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001466 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1467 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001468#else
1469 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1470#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001471 if (n == size_t(-1))
1472 {
1473 // need to recover to_nxt
1474 for (to_nxt = to; frm != frm_nxt; ++frm)
1475 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001476#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001477 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1478#else
1479 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1480#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001481 if (n == size_t(-1))
1482 break;
1483 to_nxt += n;
1484 }
1485 frm_nxt = frm;
1486 return error;
1487 }
1488 if (n == 0)
1489 return partial;
1490 to_nxt += n;
1491 if (to_nxt == to_end)
1492 break;
1493 if (fend != frm_end) // set up next null terminated sequence
1494 {
1495 // Try to write the terminating null
1496 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001497#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001498 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1499#else
1500 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1501#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001502 if (n == size_t(-1)) // on error
1503 return error;
Howard Hinnant28b24882011-12-01 20:21:04 +00001504 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001505 return partial;
1506 for (extern_type* p = tmp; n; --n) // write it
1507 *to_nxt++ = *p++;
1508 ++frm_nxt;
1509 // look for next null in frm
1510 for (fend = frm_nxt; fend != frm_end; ++fend)
1511 if (*fend == 0)
1512 break;
1513 }
1514 }
1515 return frm_nxt == frm_end ? ok : partial;
1516}
1517
1518codecvt<wchar_t, char, mbstate_t>::result
1519codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnantffb308e2010-08-22 00:03:27 +00001520 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001521 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1522{
1523 // look for first internal null in frm
1524 const extern_type* fend = frm;
1525 for (; fend != frm_end; ++fend)
1526 if (*fend == 0)
1527 break;
1528 // loop over all null-terminated sequences in frm
1529 to_nxt = to;
1530 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1531 {
Joerg Sonnenbergerfecd5442013-04-26 09:40:18 +00001532 // save state in case it is needed to recover to_nxt on error
Howard Hinnantc51e1022010-05-11 19:42:16 +00001533 mbstate_t save_state = st;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001534#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001535 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1536 static_cast<size_t>(to_end-to), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001537#else
1538 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1539#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001540 if (n == size_t(-1))
1541 {
1542 // need to recover to_nxt
1543 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1544 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001545#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001546 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1547 &save_state, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001548#else
1549 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1550#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001551 switch (n)
1552 {
1553 case 0:
1554 ++frm;
1555 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001556 case size_t(-1):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001557 frm_nxt = frm;
1558 return error;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001559 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001560 frm_nxt = frm;
1561 return partial;
1562 default:
1563 frm += n;
1564 break;
1565 }
1566 }
1567 frm_nxt = frm;
1568 return frm_nxt == frm_end ? ok : partial;
1569 }
1570 if (n == 0)
1571 return error;
1572 to_nxt += n;
1573 if (to_nxt == to_end)
1574 break;
1575 if (fend != frm_end) // set up next null terminated sequence
1576 {
1577 // Try to write the terminating null
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001578#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001579 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1580#else
1581 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1582#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001583 if (n != 0) // on error
1584 return error;
1585 ++to_nxt;
1586 ++frm_nxt;
1587 // look for next null in frm
1588 for (fend = frm_nxt; fend != frm_end; ++fend)
1589 if (*fend == 0)
1590 break;
1591 }
1592 }
1593 return frm_nxt == frm_end ? ok : partial;
1594}
1595
1596codecvt<wchar_t, char, mbstate_t>::result
1597codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1598 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1599{
1600 to_nxt = to;
1601 extern_type tmp[MB_LEN_MAX];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001602#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001603 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1604#else
1605 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1606#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001607 if (n == size_t(-1) || n == 0) // on error
1608 return error;
1609 --n;
Howard Hinnant28b24882011-12-01 20:21:04 +00001610 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantc51e1022010-05-11 19:42:16 +00001611 return partial;
1612 for (extern_type* p = tmp; n; --n) // write it
1613 *to_nxt++ = *p++;
1614 return ok;
1615}
1616
1617int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001618codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001619{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001620#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001621 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001622#else
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001623 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001624#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001625 {
1626 // stateless encoding
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001627#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001628 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1629#else
1630 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1631#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001632 return 1; // which take more than 1 char to form a wchar_t
1633 return 0;
1634 }
1635 return -1;
1636}
1637
1638bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001639codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001640{
1641 return false;
1642}
1643
1644int
1645codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1646 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1647{
1648 int nbytes = 0;
1649 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1650 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001651#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00001652 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001653#else
1654 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1655#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001656 switch (n)
1657 {
1658 case 0:
1659 ++nbytes;
1660 ++frm;
1661 break;
Howard Hinnant4aea1582012-02-08 19:15:06 +00001662 case size_t(-1):
1663 case size_t(-2):
Howard Hinnantc51e1022010-05-11 19:42:16 +00001664 return nbytes;
1665 default:
1666 nbytes += n;
1667 frm += n;
1668 break;
1669 }
1670 }
1671 return nbytes;
1672}
1673
1674int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00001675codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00001676{
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001677#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clowab9c1772013-02-07 17:20:56 +00001678 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001679#else
Marshall Clowab9c1772013-02-07 17:20:56 +00001680 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001681#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001682}
1683
1684// Valid UTF ranges
1685// UTF-32 UTF-16 UTF-8 # of code points
1686// first second first second third fourth
1687// 000000 - 00007F 0000 - 007F 00 - 7F 127
1688// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1689// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1690// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1691// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1692// 00D800 - 00DFFF invalid
1693// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1694// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1695// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1696// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1697
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001698static
1699codecvt_base::result
1700utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1701 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1702 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1703{
1704 frm_nxt = frm;
1705 to_nxt = to;
1706 if (mode & generate_header)
1707 {
1708 if (to_end-to_nxt < 3)
1709 return codecvt_base::partial;
1710 *to_nxt++ = static_cast<uint8_t>(0xEF);
1711 *to_nxt++ = static_cast<uint8_t>(0xBB);
1712 *to_nxt++ = static_cast<uint8_t>(0xBF);
1713 }
1714 for (; frm_nxt < frm_end; ++frm_nxt)
1715 {
1716 uint16_t wc1 = *frm_nxt;
1717 if (wc1 > Maxcode)
1718 return codecvt_base::error;
1719 if (wc1 < 0x0080)
1720 {
1721 if (to_end-to_nxt < 1)
1722 return codecvt_base::partial;
1723 *to_nxt++ = static_cast<uint8_t>(wc1);
1724 }
1725 else if (wc1 < 0x0800)
1726 {
1727 if (to_end-to_nxt < 2)
1728 return codecvt_base::partial;
1729 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1730 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1731 }
1732 else if (wc1 < 0xD800)
1733 {
1734 if (to_end-to_nxt < 3)
1735 return codecvt_base::partial;
1736 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1737 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1738 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1739 }
1740 else if (wc1 < 0xDC00)
1741 {
1742 if (frm_end-frm_nxt < 2)
1743 return codecvt_base::partial;
1744 uint16_t wc2 = frm_nxt[1];
1745 if ((wc2 & 0xFC00) != 0xDC00)
1746 return codecvt_base::error;
1747 if (to_end-to_nxt < 4)
1748 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001749 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1750 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001751 return codecvt_base::error;
1752 ++frm_nxt;
1753 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1754 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1756 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1757 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1758 }
1759 else if (wc1 < 0xE000)
1760 {
1761 return codecvt_base::error;
1762 }
1763 else
1764 {
1765 if (to_end-to_nxt < 3)
1766 return codecvt_base::partial;
1767 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1768 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1769 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1770 }
1771 }
1772 return codecvt_base::ok;
1773}
1774
1775static
1776codecvt_base::result
1777utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1778 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1779 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1780{
1781 frm_nxt = frm;
1782 to_nxt = to;
1783 if (mode & generate_header)
1784 {
1785 if (to_end-to_nxt < 3)
1786 return codecvt_base::partial;
1787 *to_nxt++ = static_cast<uint8_t>(0xEF);
1788 *to_nxt++ = static_cast<uint8_t>(0xBB);
1789 *to_nxt++ = static_cast<uint8_t>(0xBF);
1790 }
1791 for (; frm_nxt < frm_end; ++frm_nxt)
1792 {
1793 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1794 if (wc1 > Maxcode)
1795 return codecvt_base::error;
1796 if (wc1 < 0x0080)
1797 {
1798 if (to_end-to_nxt < 1)
1799 return codecvt_base::partial;
1800 *to_nxt++ = static_cast<uint8_t>(wc1);
1801 }
1802 else if (wc1 < 0x0800)
1803 {
1804 if (to_end-to_nxt < 2)
1805 return codecvt_base::partial;
1806 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1807 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1808 }
1809 else if (wc1 < 0xD800)
1810 {
1811 if (to_end-to_nxt < 3)
1812 return codecvt_base::partial;
1813 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1814 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1815 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1816 }
1817 else if (wc1 < 0xDC00)
1818 {
1819 if (frm_end-frm_nxt < 2)
1820 return codecvt_base::partial;
1821 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1822 if ((wc2 & 0xFC00) != 0xDC00)
1823 return codecvt_base::error;
1824 if (to_end-to_nxt < 4)
1825 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001826 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1827 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001828 return codecvt_base::error;
1829 ++frm_nxt;
1830 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1831 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1832 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1833 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1834 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1835 }
1836 else if (wc1 < 0xE000)
1837 {
1838 return codecvt_base::error;
1839 }
1840 else
1841 {
1842 if (to_end-to_nxt < 3)
1843 return codecvt_base::partial;
1844 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1845 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1846 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1847 }
1848 }
1849 return codecvt_base::ok;
1850}
1851
1852static
1853codecvt_base::result
1854utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1855 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1856 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1857{
1858 frm_nxt = frm;
1859 to_nxt = to;
1860 if (mode & consume_header)
1861 {
1862 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1863 frm_nxt[2] == 0xBF)
1864 frm_nxt += 3;
1865 }
1866 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1867 {
1868 uint8_t c1 = *frm_nxt;
1869 if (c1 > Maxcode)
1870 return codecvt_base::error;
1871 if (c1 < 0x80)
1872 {
1873 *to_nxt = static_cast<uint16_t>(c1);
1874 ++frm_nxt;
1875 }
1876 else if (c1 < 0xC2)
1877 {
1878 return codecvt_base::error;
1879 }
1880 else if (c1 < 0xE0)
1881 {
1882 if (frm_end-frm_nxt < 2)
1883 return codecvt_base::partial;
1884 uint8_t c2 = frm_nxt[1];
1885 if ((c2 & 0xC0) != 0x80)
1886 return codecvt_base::error;
1887 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1888 if (t > Maxcode)
1889 return codecvt_base::error;
1890 *to_nxt = t;
1891 frm_nxt += 2;
1892 }
1893 else if (c1 < 0xF0)
1894 {
1895 if (frm_end-frm_nxt < 3)
1896 return codecvt_base::partial;
1897 uint8_t c2 = frm_nxt[1];
1898 uint8_t c3 = frm_nxt[2];
1899 switch (c1)
1900 {
1901 case 0xE0:
1902 if ((c2 & 0xE0) != 0xA0)
1903 return codecvt_base::error;
1904 break;
1905 case 0xED:
1906 if ((c2 & 0xE0) != 0x80)
1907 return codecvt_base::error;
1908 break;
1909 default:
1910 if ((c2 & 0xC0) != 0x80)
1911 return codecvt_base::error;
1912 break;
1913 }
1914 if ((c3 & 0xC0) != 0x80)
1915 return codecvt_base::error;
1916 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1917 | ((c2 & 0x3F) << 6)
1918 | (c3 & 0x3F));
1919 if (t > Maxcode)
1920 return codecvt_base::error;
1921 *to_nxt = t;
1922 frm_nxt += 3;
1923 }
1924 else if (c1 < 0xF5)
1925 {
1926 if (frm_end-frm_nxt < 4)
1927 return codecvt_base::partial;
1928 uint8_t c2 = frm_nxt[1];
1929 uint8_t c3 = frm_nxt[2];
1930 uint8_t c4 = frm_nxt[3];
1931 switch (c1)
1932 {
1933 case 0xF0:
1934 if (!(0x90 <= c2 && c2 <= 0xBF))
1935 return codecvt_base::error;
1936 break;
1937 case 0xF4:
1938 if ((c2 & 0xF0) != 0x80)
1939 return codecvt_base::error;
1940 break;
1941 default:
1942 if ((c2 & 0xC0) != 0x80)
1943 return codecvt_base::error;
1944 break;
1945 }
1946 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1947 return codecvt_base::error;
1948 if (to_end-to_nxt < 2)
1949 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00001950 if ((((c1 & 7UL) << 18) +
1951 ((c2 & 0x3FUL) << 12) +
1952 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00001953 return codecvt_base::error;
1954 *to_nxt = static_cast<uint16_t>(
1955 0xD800
1956 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1957 | ((c2 & 0x0F) << 2)
1958 | ((c3 & 0x30) >> 4));
1959 *++to_nxt = static_cast<uint16_t>(
1960 0xDC00
1961 | ((c3 & 0x0F) << 6)
1962 | (c4 & 0x3F));
1963 frm_nxt += 4;
1964 }
1965 else
1966 {
1967 return codecvt_base::error;
1968 }
1969 }
1970 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1971}
1972
1973static
1974codecvt_base::result
1975utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1976 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1977 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1978{
1979 frm_nxt = frm;
1980 to_nxt = to;
1981 if (mode & consume_header)
1982 {
1983 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1984 frm_nxt[2] == 0xBF)
1985 frm_nxt += 3;
1986 }
1987 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1988 {
1989 uint8_t c1 = *frm_nxt;
1990 if (c1 > Maxcode)
1991 return codecvt_base::error;
1992 if (c1 < 0x80)
1993 {
1994 *to_nxt = static_cast<uint32_t>(c1);
1995 ++frm_nxt;
1996 }
1997 else if (c1 < 0xC2)
1998 {
1999 return codecvt_base::error;
2000 }
2001 else if (c1 < 0xE0)
2002 {
2003 if (frm_end-frm_nxt < 2)
2004 return codecvt_base::partial;
2005 uint8_t c2 = frm_nxt[1];
2006 if ((c2 & 0xC0) != 0x80)
2007 return codecvt_base::error;
2008 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2009 if (t > Maxcode)
2010 return codecvt_base::error;
2011 *to_nxt = static_cast<uint32_t>(t);
2012 frm_nxt += 2;
2013 }
2014 else if (c1 < 0xF0)
2015 {
2016 if (frm_end-frm_nxt < 3)
2017 return codecvt_base::partial;
2018 uint8_t c2 = frm_nxt[1];
2019 uint8_t c3 = frm_nxt[2];
2020 switch (c1)
2021 {
2022 case 0xE0:
2023 if ((c2 & 0xE0) != 0xA0)
2024 return codecvt_base::error;
2025 break;
2026 case 0xED:
2027 if ((c2 & 0xE0) != 0x80)
2028 return codecvt_base::error;
2029 break;
2030 default:
2031 if ((c2 & 0xC0) != 0x80)
2032 return codecvt_base::error;
2033 break;
2034 }
2035 if ((c3 & 0xC0) != 0x80)
2036 return codecvt_base::error;
2037 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2038 | ((c2 & 0x3F) << 6)
2039 | (c3 & 0x3F));
2040 if (t > Maxcode)
2041 return codecvt_base::error;
2042 *to_nxt = static_cast<uint32_t>(t);
2043 frm_nxt += 3;
2044 }
2045 else if (c1 < 0xF5)
2046 {
2047 if (frm_end-frm_nxt < 4)
2048 return codecvt_base::partial;
2049 uint8_t c2 = frm_nxt[1];
2050 uint8_t c3 = frm_nxt[2];
2051 uint8_t c4 = frm_nxt[3];
2052 switch (c1)
2053 {
2054 case 0xF0:
2055 if (!(0x90 <= c2 && c2 <= 0xBF))
2056 return codecvt_base::error;
2057 break;
2058 case 0xF4:
2059 if ((c2 & 0xF0) != 0x80)
2060 return codecvt_base::error;
2061 break;
2062 default:
2063 if ((c2 & 0xC0) != 0x80)
2064 return codecvt_base::error;
2065 break;
2066 }
2067 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2068 return codecvt_base::error;
2069 if (to_end-to_nxt < 2)
2070 return codecvt_base::partial;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002071 if ((((c1 & 7UL) << 18) +
2072 ((c2 & 0x3FUL) << 12) +
2073 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002074 return codecvt_base::error;
2075 *to_nxt = static_cast<uint32_t>(
2076 0xD800
2077 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2078 | ((c2 & 0x0F) << 2)
2079 | ((c3 & 0x30) >> 4));
2080 *++to_nxt = static_cast<uint32_t>(
2081 0xDC00
2082 | ((c3 & 0x0F) << 6)
2083 | (c4 & 0x3F));
2084 frm_nxt += 4;
2085 }
2086 else
2087 {
2088 return codecvt_base::error;
2089 }
2090 }
2091 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2092}
2093
2094static
2095int
2096utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2097 size_t mx, unsigned long Maxcode = 0x10FFFF,
2098 codecvt_mode mode = codecvt_mode(0))
2099{
2100 const uint8_t* frm_nxt = frm;
2101 if (mode & consume_header)
2102 {
2103 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2104 frm_nxt[2] == 0xBF)
2105 frm_nxt += 3;
2106 }
2107 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2108 {
2109 uint8_t c1 = *frm_nxt;
2110 if (c1 > Maxcode)
2111 break;
2112 if (c1 < 0x80)
2113 {
2114 ++frm_nxt;
2115 }
2116 else if (c1 < 0xC2)
2117 {
2118 break;
2119 }
2120 else if (c1 < 0xE0)
2121 {
2122 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2123 break;
2124 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2125 if (t > Maxcode)
2126 break;
2127 frm_nxt += 2;
2128 }
2129 else if (c1 < 0xF0)
2130 {
2131 if (frm_end-frm_nxt < 3)
2132 break;
2133 uint8_t c2 = frm_nxt[1];
2134 uint8_t c3 = frm_nxt[2];
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002135 switch (c1)
2136 {
2137 case 0xE0:
2138 if ((c2 & 0xE0) != 0xA0)
2139 return static_cast<int>(frm_nxt - frm);
2140 break;
2141 case 0xED:
2142 if ((c2 & 0xE0) != 0x80)
2143 return static_cast<int>(frm_nxt - frm);
2144 break;
2145 default:
2146 if ((c2 & 0xC0) != 0x80)
2147 return static_cast<int>(frm_nxt - frm);
2148 break;
2149 }
2150 if ((c3 & 0xC0) != 0x80)
2151 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002152 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002153 break;
2154 frm_nxt += 3;
2155 }
2156 else if (c1 < 0xF5)
2157 {
2158 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2159 break;
2160 uint8_t c2 = frm_nxt[1];
2161 uint8_t c3 = frm_nxt[2];
2162 uint8_t c4 = frm_nxt[3];
2163 switch (c1)
2164 {
2165 case 0xF0:
2166 if (!(0x90 <= c2 && c2 <= 0xBF))
2167 return static_cast<int>(frm_nxt - frm);
2168 break;
2169 case 0xF4:
2170 if ((c2 & 0xF0) != 0x80)
2171 return static_cast<int>(frm_nxt - frm);
2172 break;
2173 default:
2174 if ((c2 & 0xC0) != 0x80)
2175 return static_cast<int>(frm_nxt - frm);
2176 break;
2177 }
2178 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2179 break;
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +00002180 if ((((c1 & 7UL) << 18) +
2181 ((c2 & 0x3FUL) << 12) +
2182 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002183 break;
2184 ++nchar16_t;
2185 frm_nxt += 4;
2186 }
2187 else
2188 {
2189 break;
2190 }
2191 }
2192 return static_cast<int>(frm_nxt - frm);
2193}
2194
2195static
2196codecvt_base::result
2197ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2198 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2199 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2200{
2201 frm_nxt = frm;
2202 to_nxt = to;
2203 if (mode & generate_header)
2204 {
2205 if (to_end-to_nxt < 3)
2206 return codecvt_base::partial;
2207 *to_nxt++ = static_cast<uint8_t>(0xEF);
2208 *to_nxt++ = static_cast<uint8_t>(0xBB);
2209 *to_nxt++ = static_cast<uint8_t>(0xBF);
2210 }
2211 for (; frm_nxt < frm_end; ++frm_nxt)
2212 {
2213 uint32_t wc = *frm_nxt;
2214 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2215 return codecvt_base::error;
2216 if (wc < 0x000080)
2217 {
2218 if (to_end-to_nxt < 1)
2219 return codecvt_base::partial;
2220 *to_nxt++ = static_cast<uint8_t>(wc);
2221 }
2222 else if (wc < 0x000800)
2223 {
2224 if (to_end-to_nxt < 2)
2225 return codecvt_base::partial;
2226 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2227 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2228 }
2229 else if (wc < 0x010000)
2230 {
2231 if (to_end-to_nxt < 3)
2232 return codecvt_base::partial;
2233 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2234 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2235 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2236 }
2237 else // if (wc < 0x110000)
2238 {
2239 if (to_end-to_nxt < 4)
2240 return codecvt_base::partial;
2241 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2242 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2243 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2244 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2245 }
2246 }
2247 return codecvt_base::ok;
2248}
2249
2250static
2251codecvt_base::result
2252utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2253 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2254 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2255{
2256 frm_nxt = frm;
2257 to_nxt = to;
2258 if (mode & consume_header)
2259 {
2260 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2261 frm_nxt[2] == 0xBF)
2262 frm_nxt += 3;
2263 }
2264 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2265 {
2266 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2267 if (c1 < 0x80)
2268 {
2269 if (c1 > Maxcode)
2270 return codecvt_base::error;
2271 *to_nxt = static_cast<uint32_t>(c1);
2272 ++frm_nxt;
2273 }
2274 else if (c1 < 0xC2)
2275 {
2276 return codecvt_base::error;
2277 }
2278 else if (c1 < 0xE0)
2279 {
2280 if (frm_end-frm_nxt < 2)
2281 return codecvt_base::partial;
2282 uint8_t c2 = frm_nxt[1];
2283 if ((c2 & 0xC0) != 0x80)
2284 return codecvt_base::error;
2285 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2286 | (c2 & 0x3F));
2287 if (t > Maxcode)
2288 return codecvt_base::error;
2289 *to_nxt = t;
2290 frm_nxt += 2;
2291 }
2292 else if (c1 < 0xF0)
2293 {
2294 if (frm_end-frm_nxt < 3)
2295 return codecvt_base::partial;
2296 uint8_t c2 = frm_nxt[1];
2297 uint8_t c3 = frm_nxt[2];
2298 switch (c1)
2299 {
2300 case 0xE0:
2301 if ((c2 & 0xE0) != 0xA0)
2302 return codecvt_base::error;
2303 break;
2304 case 0xED:
2305 if ((c2 & 0xE0) != 0x80)
2306 return codecvt_base::error;
2307 break;
2308 default:
2309 if ((c2 & 0xC0) != 0x80)
2310 return codecvt_base::error;
2311 break;
2312 }
2313 if ((c3 & 0xC0) != 0x80)
2314 return codecvt_base::error;
2315 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2316 | ((c2 & 0x3F) << 6)
2317 | (c3 & 0x3F));
2318 if (t > Maxcode)
2319 return codecvt_base::error;
2320 *to_nxt = t;
2321 frm_nxt += 3;
2322 }
2323 else if (c1 < 0xF5)
2324 {
2325 if (frm_end-frm_nxt < 4)
2326 return codecvt_base::partial;
2327 uint8_t c2 = frm_nxt[1];
2328 uint8_t c3 = frm_nxt[2];
2329 uint8_t c4 = frm_nxt[3];
2330 switch (c1)
2331 {
2332 case 0xF0:
2333 if (!(0x90 <= c2 && c2 <= 0xBF))
2334 return codecvt_base::error;
2335 break;
2336 case 0xF4:
2337 if ((c2 & 0xF0) != 0x80)
2338 return codecvt_base::error;
2339 break;
2340 default:
2341 if ((c2 & 0xC0) != 0x80)
2342 return codecvt_base::error;
2343 break;
2344 }
2345 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2346 return codecvt_base::error;
2347 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2348 | ((c2 & 0x3F) << 12)
2349 | ((c3 & 0x3F) << 6)
2350 | (c4 & 0x3F));
2351 if (t > Maxcode)
2352 return codecvt_base::error;
2353 *to_nxt = t;
2354 frm_nxt += 4;
2355 }
2356 else
2357 {
2358 return codecvt_base::error;
2359 }
2360 }
2361 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2362}
2363
2364static
2365int
2366utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2367 size_t mx, unsigned long Maxcode = 0x10FFFF,
2368 codecvt_mode mode = codecvt_mode(0))
2369{
2370 const uint8_t* frm_nxt = frm;
2371 if (mode & consume_header)
2372 {
2373 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2374 frm_nxt[2] == 0xBF)
2375 frm_nxt += 3;
2376 }
2377 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2378 {
2379 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2380 if (c1 < 0x80)
2381 {
2382 if (c1 > Maxcode)
2383 break;
2384 ++frm_nxt;
2385 }
2386 else if (c1 < 0xC2)
2387 {
2388 break;
2389 }
2390 else if (c1 < 0xE0)
2391 {
2392 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2393 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002394 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002395 break;
2396 frm_nxt += 2;
2397 }
2398 else if (c1 < 0xF0)
2399 {
2400 if (frm_end-frm_nxt < 3)
2401 break;
2402 uint8_t c2 = frm_nxt[1];
2403 uint8_t c3 = frm_nxt[2];
2404 switch (c1)
2405 {
2406 case 0xE0:
2407 if ((c2 & 0xE0) != 0xA0)
2408 return static_cast<int>(frm_nxt - frm);
2409 break;
2410 case 0xED:
2411 if ((c2 & 0xE0) != 0x80)
2412 return static_cast<int>(frm_nxt - frm);
2413 break;
2414 default:
2415 if ((c2 & 0xC0) != 0x80)
2416 return static_cast<int>(frm_nxt - frm);
2417 break;
2418 }
2419 if ((c3 & 0xC0) != 0x80)
2420 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002421 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002422 break;
2423 frm_nxt += 3;
2424 }
2425 else if (c1 < 0xF5)
2426 {
2427 if (frm_end-frm_nxt < 4)
2428 break;
2429 uint8_t c2 = frm_nxt[1];
2430 uint8_t c3 = frm_nxt[2];
2431 uint8_t c4 = frm_nxt[3];
2432 switch (c1)
2433 {
2434 case 0xF0:
2435 if (!(0x90 <= c2 && c2 <= 0xBF))
2436 return static_cast<int>(frm_nxt - frm);
2437 break;
2438 case 0xF4:
2439 if ((c2 & 0xF0) != 0x80)
2440 return static_cast<int>(frm_nxt - frm);
2441 break;
2442 default:
2443 if ((c2 & 0xC0) != 0x80)
2444 return static_cast<int>(frm_nxt - frm);
2445 break;
2446 }
2447 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2448 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002449 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2450 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002451 break;
2452 frm_nxt += 4;
2453 }
2454 else
2455 {
2456 break;
2457 }
2458 }
2459 return static_cast<int>(frm_nxt - frm);
2460}
2461
2462static
2463codecvt_base::result
2464ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2465 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2466 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2467{
2468 frm_nxt = frm;
2469 to_nxt = to;
2470 if (mode & generate_header)
2471 {
2472 if (to_end-to_nxt < 3)
2473 return codecvt_base::partial;
2474 *to_nxt++ = static_cast<uint8_t>(0xEF);
2475 *to_nxt++ = static_cast<uint8_t>(0xBB);
2476 *to_nxt++ = static_cast<uint8_t>(0xBF);
2477 }
2478 for (; frm_nxt < frm_end; ++frm_nxt)
2479 {
2480 uint16_t wc = *frm_nxt;
2481 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2482 return codecvt_base::error;
2483 if (wc < 0x0080)
2484 {
2485 if (to_end-to_nxt < 1)
2486 return codecvt_base::partial;
2487 *to_nxt++ = static_cast<uint8_t>(wc);
2488 }
2489 else if (wc < 0x0800)
2490 {
2491 if (to_end-to_nxt < 2)
2492 return codecvt_base::partial;
2493 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2494 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2495 }
2496 else // if (wc <= 0xFFFF)
2497 {
2498 if (to_end-to_nxt < 3)
2499 return codecvt_base::partial;
2500 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2501 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2502 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2503 }
2504 }
2505 return codecvt_base::ok;
2506}
2507
2508static
2509codecvt_base::result
2510utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2511 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2512 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2513{
2514 frm_nxt = frm;
2515 to_nxt = to;
2516 if (mode & consume_header)
2517 {
2518 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2519 frm_nxt[2] == 0xBF)
2520 frm_nxt += 3;
2521 }
2522 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2523 {
2524 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2525 if (c1 < 0x80)
2526 {
2527 if (c1 > Maxcode)
2528 return codecvt_base::error;
2529 *to_nxt = static_cast<uint16_t>(c1);
2530 ++frm_nxt;
2531 }
2532 else if (c1 < 0xC2)
2533 {
2534 return codecvt_base::error;
2535 }
2536 else if (c1 < 0xE0)
2537 {
2538 if (frm_end-frm_nxt < 2)
2539 return codecvt_base::partial;
2540 uint8_t c2 = frm_nxt[1];
2541 if ((c2 & 0xC0) != 0x80)
2542 return codecvt_base::error;
2543 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2544 | (c2 & 0x3F));
2545 if (t > Maxcode)
2546 return codecvt_base::error;
2547 *to_nxt = t;
2548 frm_nxt += 2;
2549 }
2550 else if (c1 < 0xF0)
2551 {
2552 if (frm_end-frm_nxt < 3)
2553 return codecvt_base::partial;
2554 uint8_t c2 = frm_nxt[1];
2555 uint8_t c3 = frm_nxt[2];
2556 switch (c1)
2557 {
2558 case 0xE0:
2559 if ((c2 & 0xE0) != 0xA0)
2560 return codecvt_base::error;
2561 break;
2562 case 0xED:
2563 if ((c2 & 0xE0) != 0x80)
2564 return codecvt_base::error;
2565 break;
2566 default:
2567 if ((c2 & 0xC0) != 0x80)
2568 return codecvt_base::error;
2569 break;
2570 }
2571 if ((c3 & 0xC0) != 0x80)
2572 return codecvt_base::error;
2573 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2574 | ((c2 & 0x3F) << 6)
2575 | (c3 & 0x3F));
2576 if (t > Maxcode)
2577 return codecvt_base::error;
2578 *to_nxt = t;
2579 frm_nxt += 3;
2580 }
2581 else
2582 {
2583 return codecvt_base::error;
2584 }
2585 }
2586 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2587}
2588
2589static
2590int
2591utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2592 size_t mx, unsigned long Maxcode = 0x10FFFF,
2593 codecvt_mode mode = codecvt_mode(0))
2594{
2595 const uint8_t* frm_nxt = frm;
2596 if (mode & consume_header)
2597 {
2598 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2599 frm_nxt[2] == 0xBF)
2600 frm_nxt += 3;
2601 }
2602 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2603 {
2604 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2605 if (c1 < 0x80)
2606 {
2607 if (c1 > Maxcode)
2608 break;
2609 ++frm_nxt;
2610 }
2611 else if (c1 < 0xC2)
2612 {
2613 break;
2614 }
2615 else if (c1 < 0xE0)
2616 {
2617 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2618 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002619 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002620 break;
2621 frm_nxt += 2;
2622 }
2623 else if (c1 < 0xF0)
2624 {
2625 if (frm_end-frm_nxt < 3)
2626 break;
2627 uint8_t c2 = frm_nxt[1];
2628 uint8_t c3 = frm_nxt[2];
2629 switch (c1)
2630 {
2631 case 0xE0:
2632 if ((c2 & 0xE0) != 0xA0)
2633 return static_cast<int>(frm_nxt - frm);
2634 break;
2635 case 0xED:
2636 if ((c2 & 0xE0) != 0x80)
2637 return static_cast<int>(frm_nxt - frm);
2638 break;
2639 default:
2640 if ((c2 & 0xC0) != 0x80)
2641 return static_cast<int>(frm_nxt - frm);
2642 break;
2643 }
2644 if ((c3 & 0xC0) != 0x80)
2645 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002646 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002647 break;
2648 frm_nxt += 3;
2649 }
2650 else
2651 {
2652 break;
2653 }
2654 }
2655 return static_cast<int>(frm_nxt - frm);
2656}
2657
2658static
2659codecvt_base::result
2660ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2661 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2662 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2663{
2664 frm_nxt = frm;
2665 to_nxt = to;
2666 if (mode & generate_header)
2667 {
2668 if (to_end-to_nxt < 2)
2669 return codecvt_base::partial;
2670 *to_nxt++ = static_cast<uint8_t>(0xFE);
2671 *to_nxt++ = static_cast<uint8_t>(0xFF);
2672 }
2673 for (; frm_nxt < frm_end; ++frm_nxt)
2674 {
2675 uint32_t wc = *frm_nxt;
2676 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2677 return codecvt_base::error;
2678 if (wc < 0x010000)
2679 {
2680 if (to_end-to_nxt < 2)
2681 return codecvt_base::partial;
2682 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2683 *to_nxt++ = static_cast<uint8_t>(wc);
2684 }
2685 else
2686 {
2687 if (to_end-to_nxt < 4)
2688 return codecvt_base::partial;
2689 uint16_t t = static_cast<uint16_t>(
2690 0xD800
2691 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2692 | ((wc & 0x00FC00) >> 10));
2693 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2694 *to_nxt++ = static_cast<uint8_t>(t);
2695 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2696 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2697 *to_nxt++ = static_cast<uint8_t>(t);
2698 }
2699 }
2700 return codecvt_base::ok;
2701}
2702
2703static
2704codecvt_base::result
2705utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2706 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2707 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2708{
2709 frm_nxt = frm;
2710 to_nxt = to;
2711 if (mode & consume_header)
2712 {
2713 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2714 frm_nxt += 2;
2715 }
2716 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2717 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002718 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002719 if ((c1 & 0xFC00) == 0xDC00)
2720 return codecvt_base::error;
2721 if ((c1 & 0xFC00) != 0xD800)
2722 {
2723 if (c1 > Maxcode)
2724 return codecvt_base::error;
2725 *to_nxt = static_cast<uint32_t>(c1);
2726 frm_nxt += 2;
2727 }
2728 else
2729 {
2730 if (frm_end-frm_nxt < 4)
2731 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002732 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002733 if ((c2 & 0xFC00) != 0xDC00)
2734 return codecvt_base::error;
2735 uint32_t t = static_cast<uint32_t>(
2736 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2737 | ((c1 & 0x003F) << 10)
2738 | (c2 & 0x03FF));
2739 if (t > Maxcode)
2740 return codecvt_base::error;
2741 *to_nxt = t;
2742 frm_nxt += 4;
2743 }
2744 }
2745 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2746}
2747
2748static
2749int
2750utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2751 size_t mx, unsigned long Maxcode = 0x10FFFF,
2752 codecvt_mode mode = codecvt_mode(0))
2753{
2754 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002755 if (mode & consume_header)
2756 {
2757 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2758 frm_nxt += 2;
2759 }
2760 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2761 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002762 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002763 if ((c1 & 0xFC00) == 0xDC00)
2764 break;
2765 if ((c1 & 0xFC00) != 0xD800)
2766 {
2767 if (c1 > Maxcode)
2768 break;
2769 frm_nxt += 2;
2770 }
2771 else
2772 {
2773 if (frm_end-frm_nxt < 4)
2774 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002775 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002776 if ((c2 & 0xFC00) != 0xDC00)
2777 break;
2778 uint32_t t = static_cast<uint32_t>(
2779 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2780 | ((c1 & 0x003F) << 10)
2781 | (c2 & 0x03FF));
2782 if (t > Maxcode)
2783 break;
2784 frm_nxt += 4;
2785 }
2786 }
2787 return static_cast<int>(frm_nxt - frm);
2788}
2789
2790static
2791codecvt_base::result
2792ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2793 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2794 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2795{
2796 frm_nxt = frm;
2797 to_nxt = to;
2798 if (mode & generate_header)
2799 {
2800 if (to_end-to_nxt < 2)
2801 return codecvt_base::partial;
2802 *to_nxt++ = static_cast<uint8_t>(0xFF);
2803 *to_nxt++ = static_cast<uint8_t>(0xFE);
2804 }
2805 for (; frm_nxt < frm_end; ++frm_nxt)
2806 {
2807 uint32_t wc = *frm_nxt;
2808 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2809 return codecvt_base::error;
2810 if (wc < 0x010000)
2811 {
2812 if (to_end-to_nxt < 2)
2813 return codecvt_base::partial;
2814 *to_nxt++ = static_cast<uint8_t>(wc);
2815 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2816 }
2817 else
2818 {
2819 if (to_end-to_nxt < 4)
2820 return codecvt_base::partial;
2821 uint16_t t = static_cast<uint16_t>(
2822 0xD800
2823 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2824 | ((wc & 0x00FC00) >> 10));
2825 *to_nxt++ = static_cast<uint8_t>(t);
2826 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2827 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2828 *to_nxt++ = static_cast<uint8_t>(t);
2829 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2830 }
2831 }
2832 return codecvt_base::ok;
2833}
2834
2835static
2836codecvt_base::result
2837utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2838 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2839 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2840{
2841 frm_nxt = frm;
2842 to_nxt = to;
2843 if (mode & consume_header)
2844 {
2845 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2846 frm_nxt += 2;
2847 }
2848 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2849 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002850 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002851 if ((c1 & 0xFC00) == 0xDC00)
2852 return codecvt_base::error;
2853 if ((c1 & 0xFC00) != 0xD800)
2854 {
2855 if (c1 > Maxcode)
2856 return codecvt_base::error;
2857 *to_nxt = static_cast<uint32_t>(c1);
2858 frm_nxt += 2;
2859 }
2860 else
2861 {
2862 if (frm_end-frm_nxt < 4)
2863 return codecvt_base::partial;
Howard Hinnant28b24882011-12-01 20:21:04 +00002864 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002865 if ((c2 & 0xFC00) != 0xDC00)
2866 return codecvt_base::error;
2867 uint32_t t = static_cast<uint32_t>(
2868 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2869 | ((c1 & 0x003F) << 10)
2870 | (c2 & 0x03FF));
2871 if (t > Maxcode)
2872 return codecvt_base::error;
2873 *to_nxt = t;
2874 frm_nxt += 4;
2875 }
2876 }
2877 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2878}
2879
2880static
2881int
2882utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2883 size_t mx, unsigned long Maxcode = 0x10FFFF,
2884 codecvt_mode mode = codecvt_mode(0))
2885{
2886 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002887 if (mode & consume_header)
2888 {
2889 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2890 frm_nxt += 2;
2891 }
2892 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2893 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002894 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002895 if ((c1 & 0xFC00) == 0xDC00)
2896 break;
2897 if ((c1 & 0xFC00) != 0xD800)
2898 {
2899 if (c1 > Maxcode)
2900 break;
2901 frm_nxt += 2;
2902 }
2903 else
2904 {
2905 if (frm_end-frm_nxt < 4)
2906 break;
Howard Hinnant28b24882011-12-01 20:21:04 +00002907 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002908 if ((c2 & 0xFC00) != 0xDC00)
2909 break;
2910 uint32_t t = static_cast<uint32_t>(
2911 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2912 | ((c1 & 0x003F) << 10)
2913 | (c2 & 0x03FF));
2914 if (t > Maxcode)
2915 break;
2916 frm_nxt += 4;
2917 }
2918 }
2919 return static_cast<int>(frm_nxt - frm);
2920}
2921
2922static
2923codecvt_base::result
2924ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2925 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2926 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2927{
2928 frm_nxt = frm;
2929 to_nxt = to;
2930 if (mode & generate_header)
2931 {
2932 if (to_end-to_nxt < 2)
2933 return codecvt_base::partial;
2934 *to_nxt++ = static_cast<uint8_t>(0xFE);
2935 *to_nxt++ = static_cast<uint8_t>(0xFF);
2936 }
2937 for (; frm_nxt < frm_end; ++frm_nxt)
2938 {
2939 uint16_t wc = *frm_nxt;
2940 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2941 return codecvt_base::error;
2942 if (to_end-to_nxt < 2)
2943 return codecvt_base::partial;
2944 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2945 *to_nxt++ = static_cast<uint8_t>(wc);
2946 }
2947 return codecvt_base::ok;
2948}
2949
2950static
2951codecvt_base::result
2952utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2953 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2954 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2955{
2956 frm_nxt = frm;
2957 to_nxt = to;
2958 if (mode & consume_header)
2959 {
2960 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2961 frm_nxt += 2;
2962 }
2963 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2964 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002965 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002966 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2967 return codecvt_base::error;
2968 *to_nxt = c1;
2969 frm_nxt += 2;
2970 }
2971 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2972}
2973
2974static
2975int
2976utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2977 size_t mx, unsigned long Maxcode = 0x10FFFF,
2978 codecvt_mode mode = codecvt_mode(0))
2979{
2980 const uint8_t* frm_nxt = frm;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002981 if (mode & consume_header)
2982 {
2983 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2984 frm_nxt += 2;
2985 }
2986 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2987 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002988 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00002989 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2990 break;
2991 frm_nxt += 2;
2992 }
2993 return static_cast<int>(frm_nxt - frm);
2994}
2995
2996static
2997codecvt_base::result
2998ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2999 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3000 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3001{
3002 frm_nxt = frm;
3003 to_nxt = to;
3004 if (mode & generate_header)
3005 {
3006 if (to_end-to_nxt < 2)
3007 return codecvt_base::partial;
3008 *to_nxt++ = static_cast<uint8_t>(0xFF);
3009 *to_nxt++ = static_cast<uint8_t>(0xFE);
3010 }
3011 for (; frm_nxt < frm_end; ++frm_nxt)
3012 {
3013 uint16_t wc = *frm_nxt;
3014 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3015 return codecvt_base::error;
3016 if (to_end-to_nxt < 2)
3017 return codecvt_base::partial;
3018 *to_nxt++ = static_cast<uint8_t>(wc);
3019 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3020 }
3021 return codecvt_base::ok;
3022}
3023
3024static
3025codecvt_base::result
3026utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3027 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3028 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3029{
3030 frm_nxt = frm;
3031 to_nxt = to;
3032 if (mode & consume_header)
3033 {
3034 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3035 frm_nxt += 2;
3036 }
3037 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3038 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003039 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003040 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3041 return codecvt_base::error;
3042 *to_nxt = c1;
3043 frm_nxt += 2;
3044 }
3045 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3046}
3047
3048static
3049int
3050utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3051 size_t mx, unsigned long Maxcode = 0x10FFFF,
3052 codecvt_mode mode = codecvt_mode(0))
3053{
3054 const uint8_t* frm_nxt = frm;
3055 frm_nxt = frm;
3056 if (mode & consume_header)
3057 {
3058 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3059 frm_nxt += 2;
3060 }
3061 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3062 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003063 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003064 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3065 break;
3066 frm_nxt += 2;
3067 }
3068 return static_cast<int>(frm_nxt - frm);
3069}
3070
Howard Hinnantc51e1022010-05-11 19:42:16 +00003071// template <> class codecvt<char16_t, char, mbstate_t>
3072
Howard Hinnantffb308e2010-08-22 00:03:27 +00003073locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003074
3075codecvt<char16_t, char, mbstate_t>::~codecvt()
3076{
3077}
3078
3079codecvt<char16_t, char, mbstate_t>::result
3080codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003081 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003082 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3083{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003084 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3085 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3086 const uint16_t* _frm_nxt = _frm;
3087 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3088 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3089 uint8_t* _to_nxt = _to;
3090 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3091 frm_nxt = frm + (_frm_nxt - _frm);
3092 to_nxt = to + (_to_nxt - _to);
3093 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003094}
3095
3096codecvt<char16_t, char, mbstate_t>::result
3097codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003098 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003099 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3100{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003101 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3102 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3103 const uint8_t* _frm_nxt = _frm;
3104 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3105 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3106 uint16_t* _to_nxt = _to;
3107 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3108 frm_nxt = frm + (_frm_nxt - _frm);
3109 to_nxt = to + (_to_nxt - _to);
3110 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003111}
3112
3113codecvt<char16_t, char, mbstate_t>::result
3114codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3115 extern_type* to, extern_type*, extern_type*& to_nxt) const
3116{
3117 to_nxt = to;
3118 return noconv;
3119}
3120
3121int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003122codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003123{
3124 return 0;
3125}
3126
3127bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003128codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003129{
3130 return false;
3131}
3132
3133int
3134codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3135 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3136{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003137 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3138 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3139 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003140}
3141
3142int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003143codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003144{
3145 return 4;
3146}
3147
3148// template <> class codecvt<char32_t, char, mbstate_t>
3149
Howard Hinnantffb308e2010-08-22 00:03:27 +00003150locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003151
3152codecvt<char32_t, char, mbstate_t>::~codecvt()
3153{
3154}
3155
3156codecvt<char32_t, char, mbstate_t>::result
3157codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003158 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003159 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3160{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003161 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3162 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3163 const uint32_t* _frm_nxt = _frm;
3164 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3165 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3166 uint8_t* _to_nxt = _to;
3167 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3168 frm_nxt = frm + (_frm_nxt - _frm);
3169 to_nxt = to + (_to_nxt - _to);
3170 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003171}
3172
3173codecvt<char32_t, char, mbstate_t>::result
3174codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnantffb308e2010-08-22 00:03:27 +00003175 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003176 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3177{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003178 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3179 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3180 const uint8_t* _frm_nxt = _frm;
3181 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3182 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3183 uint32_t* _to_nxt = _to;
3184 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3185 frm_nxt = frm + (_frm_nxt - _frm);
3186 to_nxt = to + (_to_nxt - _to);
3187 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003188}
3189
3190codecvt<char32_t, char, mbstate_t>::result
3191codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3192 extern_type* to, extern_type*, extern_type*& to_nxt) const
3193{
3194 to_nxt = to;
3195 return noconv;
3196}
3197
3198int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003199codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003200{
3201 return 0;
3202}
3203
3204bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003205codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003206{
3207 return false;
3208}
3209
3210int
3211codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3212 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3213{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003214 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3215 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3216 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003217}
3218
3219int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003220codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003221{
3222 return 4;
3223}
3224
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003225// __codecvt_utf8<wchar_t>
Howard Hinnantc51e1022010-05-11 19:42:16 +00003226
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003227__codecvt_utf8<wchar_t>::result
3228__codecvt_utf8<wchar_t>::do_out(state_type&,
3229 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003230 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3231{
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003232#if _WIN32
3233 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3234 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3235 const uint16_t* _frm_nxt = _frm;
3236#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003237 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3238 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3239 const uint32_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003240#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003241 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3242 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3243 uint8_t* _to_nxt = _to;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003244#if _WIN32
3245 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3246 _Maxcode_, _Mode_);
3247#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003248 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3249 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003250#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003251 frm_nxt = frm + (_frm_nxt - _frm);
3252 to_nxt = to + (_to_nxt - _to);
3253 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003254}
3255
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003256__codecvt_utf8<wchar_t>::result
3257__codecvt_utf8<wchar_t>::do_in(state_type&,
3258 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003259 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3260{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003261 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3262 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3263 const uint8_t* _frm_nxt = _frm;
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003264#if _WIN32
3265 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3266 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3267 uint16_t* _to_nxt = _to;
3268 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3269 _Maxcode_, _Mode_);
3270#else
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003271 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3272 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3273 uint32_t* _to_nxt = _to;
3274 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3275 _Maxcode_, _Mode_);
Howard Hinnant9e29a9f2013-07-08 19:03:07 +00003276#endif
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003277 frm_nxt = frm + (_frm_nxt - _frm);
3278 to_nxt = to + (_to_nxt - _to);
3279 return r;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003280}
3281
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003282__codecvt_utf8<wchar_t>::result
3283__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003284 extern_type* to, extern_type*, extern_type*& to_nxt) const
3285{
3286 to_nxt = to;
3287 return noconv;
3288}
3289
3290int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003291__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003292{
3293 return 0;
3294}
3295
3296bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003297__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003298{
3299 return false;
3300}
3301
3302int
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003303__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00003304 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3305{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003306 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3307 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3308 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003309}
3310
3311int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003312__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +00003313{
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003314 if (_Mode_ & consume_header)
3315 return 7;
3316 return 4;
3317}
3318
3319// __codecvt_utf8<char16_t>
3320
3321__codecvt_utf8<char16_t>::result
3322__codecvt_utf8<char16_t>::do_out(state_type&,
3323 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3324 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3325{
3326 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3327 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3328 const uint16_t* _frm_nxt = _frm;
3329 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;
3332 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3333 _Maxcode_, _Mode_);
3334 frm_nxt = frm + (_frm_nxt - _frm);
3335 to_nxt = to + (_to_nxt - _to);
3336 return r;
3337}
3338
3339__codecvt_utf8<char16_t>::result
3340__codecvt_utf8<char16_t>::do_in(state_type&,
3341 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3342 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3343{
3344 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3345 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3346 const uint8_t* _frm_nxt = _frm;
3347 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3348 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3349 uint16_t* _to_nxt = _to;
3350 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3351 _Maxcode_, _Mode_);
3352 frm_nxt = frm + (_frm_nxt - _frm);
3353 to_nxt = to + (_to_nxt - _to);
3354 return r;
3355}
3356
3357__codecvt_utf8<char16_t>::result
3358__codecvt_utf8<char16_t>::do_unshift(state_type&,
3359 extern_type* to, extern_type*, extern_type*& to_nxt) const
3360{
3361 to_nxt = to;
3362 return noconv;
3363}
3364
3365int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003366__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003367{
3368 return 0;
3369}
3370
3371bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003372__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003373{
3374 return false;
3375}
3376
3377int
3378__codecvt_utf8<char16_t>::do_length(state_type&,
3379 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3380{
3381 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3382 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3383 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3384}
3385
3386int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003387__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003388{
3389 if (_Mode_ & consume_header)
3390 return 6;
3391 return 3;
3392}
3393
3394// __codecvt_utf8<char32_t>
3395
3396__codecvt_utf8<char32_t>::result
3397__codecvt_utf8<char32_t>::do_out(state_type&,
3398 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3399 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3400{
3401 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3402 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3403 const uint32_t* _frm_nxt = _frm;
3404 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3405 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3406 uint8_t* _to_nxt = _to;
3407 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3408 _Maxcode_, _Mode_);
3409 frm_nxt = frm + (_frm_nxt - _frm);
3410 to_nxt = to + (_to_nxt - _to);
3411 return r;
3412}
3413
3414__codecvt_utf8<char32_t>::result
3415__codecvt_utf8<char32_t>::do_in(state_type&,
3416 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3417 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3418{
3419 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3420 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3421 const uint8_t* _frm_nxt = _frm;
3422 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3423 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3424 uint32_t* _to_nxt = _to;
3425 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3426 _Maxcode_, _Mode_);
3427 frm_nxt = frm + (_frm_nxt - _frm);
3428 to_nxt = to + (_to_nxt - _to);
3429 return r;
3430}
3431
3432__codecvt_utf8<char32_t>::result
3433__codecvt_utf8<char32_t>::do_unshift(state_type&,
3434 extern_type* to, extern_type*, extern_type*& to_nxt) const
3435{
3436 to_nxt = to;
3437 return noconv;
3438}
3439
3440int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003441__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003442{
3443 return 0;
3444}
3445
3446bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003447__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003448{
3449 return false;
3450}
3451
3452int
3453__codecvt_utf8<char32_t>::do_length(state_type&,
3454 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3455{
3456 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3457 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3458 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3459}
3460
3461int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003462__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003463{
3464 if (_Mode_ & consume_header)
3465 return 7;
3466 return 4;
3467}
3468
3469// __codecvt_utf16<wchar_t, false>
3470
3471__codecvt_utf16<wchar_t, false>::result
3472__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3473 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3474 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3475{
3476 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3477 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3478 const uint32_t* _frm_nxt = _frm;
3479 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3480 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3481 uint8_t* _to_nxt = _to;
3482 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3483 _Maxcode_, _Mode_);
3484 frm_nxt = frm + (_frm_nxt - _frm);
3485 to_nxt = to + (_to_nxt - _to);
3486 return r;
3487}
3488
3489__codecvt_utf16<wchar_t, false>::result
3490__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3491 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3492 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3493{
3494 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3495 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3496 const uint8_t* _frm_nxt = _frm;
3497 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3498 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3499 uint32_t* _to_nxt = _to;
3500 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3501 _Maxcode_, _Mode_);
3502 frm_nxt = frm + (_frm_nxt - _frm);
3503 to_nxt = to + (_to_nxt - _to);
3504 return r;
3505}
3506
3507__codecvt_utf16<wchar_t, false>::result
3508__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3509 extern_type* to, extern_type*, extern_type*& to_nxt) const
3510{
3511 to_nxt = to;
3512 return noconv;
3513}
3514
3515int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003516__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003517{
3518 return 0;
3519}
3520
3521bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003522__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003523{
3524 return false;
3525}
3526
3527int
3528__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3529 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3530{
3531 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3532 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3533 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3534}
3535
3536int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003537__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003538{
3539 if (_Mode_ & consume_header)
3540 return 6;
3541 return 4;
3542}
3543
3544// __codecvt_utf16<wchar_t, true>
3545
3546__codecvt_utf16<wchar_t, true>::result
3547__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3548 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3549 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3550{
3551 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3552 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3553 const uint32_t* _frm_nxt = _frm;
3554 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3555 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3556 uint8_t* _to_nxt = _to;
3557 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3558 _Maxcode_, _Mode_);
3559 frm_nxt = frm + (_frm_nxt - _frm);
3560 to_nxt = to + (_to_nxt - _to);
3561 return r;
3562}
3563
3564__codecvt_utf16<wchar_t, true>::result
3565__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3566 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3567 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3568{
3569 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3570 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3571 const uint8_t* _frm_nxt = _frm;
3572 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3573 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3574 uint32_t* _to_nxt = _to;
3575 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3576 _Maxcode_, _Mode_);
3577 frm_nxt = frm + (_frm_nxt - _frm);
3578 to_nxt = to + (_to_nxt - _to);
3579 return r;
3580}
3581
3582__codecvt_utf16<wchar_t, true>::result
3583__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3584 extern_type* to, extern_type*, extern_type*& to_nxt) const
3585{
3586 to_nxt = to;
3587 return noconv;
3588}
3589
3590int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003591__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003592{
3593 return 0;
3594}
3595
3596bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003597__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003598{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003599 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003600}
3601
3602int
3603__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3604 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3605{
3606 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3607 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3608 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3609}
3610
3611int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003612__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003613{
3614 if (_Mode_ & consume_header)
3615 return 6;
3616 return 4;
3617}
3618
3619// __codecvt_utf16<char16_t, false>
3620
3621__codecvt_utf16<char16_t, false>::result
3622__codecvt_utf16<char16_t, false>::do_out(state_type&,
3623 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3624 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3625{
3626 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3627 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3628 const uint16_t* _frm_nxt = _frm;
3629 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3630 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3631 uint8_t* _to_nxt = _to;
3632 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3633 _Maxcode_, _Mode_);
3634 frm_nxt = frm + (_frm_nxt - _frm);
3635 to_nxt = to + (_to_nxt - _to);
3636 return r;
3637}
3638
3639__codecvt_utf16<char16_t, false>::result
3640__codecvt_utf16<char16_t, false>::do_in(state_type&,
3641 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3642 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3643{
3644 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3645 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3646 const uint8_t* _frm_nxt = _frm;
3647 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3648 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3649 uint16_t* _to_nxt = _to;
3650 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3651 _Maxcode_, _Mode_);
3652 frm_nxt = frm + (_frm_nxt - _frm);
3653 to_nxt = to + (_to_nxt - _to);
3654 return r;
3655}
3656
3657__codecvt_utf16<char16_t, false>::result
3658__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3659 extern_type* to, extern_type*, extern_type*& to_nxt) const
3660{
3661 to_nxt = to;
3662 return noconv;
3663}
3664
3665int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003666__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003667{
3668 return 0;
3669}
3670
3671bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003672__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003673{
3674 return false;
3675}
3676
3677int
3678__codecvt_utf16<char16_t, false>::do_length(state_type&,
3679 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3680{
3681 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3682 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3683 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3684}
3685
3686int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003687__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003688{
3689 if (_Mode_ & consume_header)
3690 return 4;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003691 return 2;
3692}
3693
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003694// __codecvt_utf16<char16_t, true>
3695
3696__codecvt_utf16<char16_t, true>::result
3697__codecvt_utf16<char16_t, true>::do_out(state_type&,
3698 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3699 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3700{
3701 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3702 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3703 const uint16_t* _frm_nxt = _frm;
3704 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3705 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3706 uint8_t* _to_nxt = _to;
3707 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3708 _Maxcode_, _Mode_);
3709 frm_nxt = frm + (_frm_nxt - _frm);
3710 to_nxt = to + (_to_nxt - _to);
3711 return r;
3712}
3713
3714__codecvt_utf16<char16_t, true>::result
3715__codecvt_utf16<char16_t, true>::do_in(state_type&,
3716 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3717 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3718{
3719 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3720 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3721 const uint8_t* _frm_nxt = _frm;
3722 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3723 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3724 uint16_t* _to_nxt = _to;
3725 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3726 _Maxcode_, _Mode_);
3727 frm_nxt = frm + (_frm_nxt - _frm);
3728 to_nxt = to + (_to_nxt - _to);
3729 return r;
3730}
3731
3732__codecvt_utf16<char16_t, true>::result
3733__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3734 extern_type* to, extern_type*, extern_type*& to_nxt) const
3735{
3736 to_nxt = to;
3737 return noconv;
3738}
3739
3740int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003741__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003742{
3743 return 0;
3744}
3745
3746bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003747__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003748{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003749 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003750}
3751
3752int
3753__codecvt_utf16<char16_t, true>::do_length(state_type&,
3754 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3755{
3756 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3757 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3758 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3759}
3760
3761int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003762__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003763{
3764 if (_Mode_ & consume_header)
3765 return 4;
3766 return 2;
3767}
3768
3769// __codecvt_utf16<char32_t, false>
3770
3771__codecvt_utf16<char32_t, false>::result
3772__codecvt_utf16<char32_t, false>::do_out(state_type&,
3773 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3774 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3775{
3776 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3777 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3778 const uint32_t* _frm_nxt = _frm;
3779 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3780 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3781 uint8_t* _to_nxt = _to;
3782 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3783 _Maxcode_, _Mode_);
3784 frm_nxt = frm + (_frm_nxt - _frm);
3785 to_nxt = to + (_to_nxt - _to);
3786 return r;
3787}
3788
3789__codecvt_utf16<char32_t, false>::result
3790__codecvt_utf16<char32_t, false>::do_in(state_type&,
3791 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3792 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3793{
3794 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3795 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3796 const uint8_t* _frm_nxt = _frm;
3797 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3798 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3799 uint32_t* _to_nxt = _to;
3800 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3801 _Maxcode_, _Mode_);
3802 frm_nxt = frm + (_frm_nxt - _frm);
3803 to_nxt = to + (_to_nxt - _to);
3804 return r;
3805}
3806
3807__codecvt_utf16<char32_t, false>::result
3808__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3809 extern_type* to, extern_type*, extern_type*& to_nxt) const
3810{
3811 to_nxt = to;
3812 return noconv;
3813}
3814
3815int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003816__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003817{
3818 return 0;
3819}
3820
3821bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003822__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003823{
3824 return false;
3825}
3826
3827int
3828__codecvt_utf16<char32_t, false>::do_length(state_type&,
3829 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3830{
3831 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3832 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3833 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3834}
3835
3836int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003837__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003838{
3839 if (_Mode_ & consume_header)
3840 return 6;
3841 return 4;
3842}
3843
3844// __codecvt_utf16<char32_t, true>
3845
3846__codecvt_utf16<char32_t, true>::result
3847__codecvt_utf16<char32_t, true>::do_out(state_type&,
3848 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3849 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3850{
3851 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3852 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3853 const uint32_t* _frm_nxt = _frm;
3854 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3855 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3856 uint8_t* _to_nxt = _to;
3857 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3858 _Maxcode_, _Mode_);
3859 frm_nxt = frm + (_frm_nxt - _frm);
3860 to_nxt = to + (_to_nxt - _to);
3861 return r;
3862}
3863
3864__codecvt_utf16<char32_t, true>::result
3865__codecvt_utf16<char32_t, true>::do_in(state_type&,
3866 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3867 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3868{
3869 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3870 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3871 const uint8_t* _frm_nxt = _frm;
3872 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3873 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3874 uint32_t* _to_nxt = _to;
3875 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3876 _Maxcode_, _Mode_);
3877 frm_nxt = frm + (_frm_nxt - _frm);
3878 to_nxt = to + (_to_nxt - _to);
3879 return r;
3880}
3881
3882__codecvt_utf16<char32_t, true>::result
3883__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3884 extern_type* to, extern_type*, extern_type*& to_nxt) const
3885{
3886 to_nxt = to;
3887 return noconv;
3888}
3889
3890int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003891__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003892{
3893 return 0;
3894}
3895
3896bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003897__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003898{
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003899 return false;
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003900}
3901
3902int
3903__codecvt_utf16<char32_t, true>::do_length(state_type&,
3904 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3905{
3906 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3907 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3908 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3909}
3910
3911int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003912__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003913{
3914 if (_Mode_ & consume_header)
3915 return 6;
3916 return 4;
3917}
3918
3919// __codecvt_utf8_utf16<wchar_t>
3920
3921__codecvt_utf8_utf16<wchar_t>::result
3922__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3923 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3924 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3925{
3926 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3927 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3928 const uint32_t* _frm_nxt = _frm;
3929 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3930 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3931 uint8_t* _to_nxt = _to;
3932 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3933 _Maxcode_, _Mode_);
3934 frm_nxt = frm + (_frm_nxt - _frm);
3935 to_nxt = to + (_to_nxt - _to);
3936 return r;
3937}
3938
3939__codecvt_utf8_utf16<wchar_t>::result
3940__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3941 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3942 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3943{
3944 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3945 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3946 const uint8_t* _frm_nxt = _frm;
3947 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3948 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3949 uint32_t* _to_nxt = _to;
3950 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3951 _Maxcode_, _Mode_);
3952 frm_nxt = frm + (_frm_nxt - _frm);
3953 to_nxt = to + (_to_nxt - _to);
3954 return r;
3955}
3956
3957__codecvt_utf8_utf16<wchar_t>::result
3958__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3959 extern_type* to, extern_type*, extern_type*& to_nxt) const
3960{
3961 to_nxt = to;
3962 return noconv;
3963}
3964
3965int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003966__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003967{
3968 return 0;
3969}
3970
3971bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003972__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003973{
3974 return false;
3975}
3976
3977int
3978__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3979 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3980{
3981 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3982 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3983 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3984}
3985
3986int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00003987__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00003988{
3989 if (_Mode_ & consume_header)
3990 return 7;
3991 return 4;
3992}
3993
3994// __codecvt_utf8_utf16<char16_t>
3995
3996__codecvt_utf8_utf16<char16_t>::result
3997__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3998 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3999 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4000{
4001 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4002 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4003 const uint16_t* _frm_nxt = _frm;
4004 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4005 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4006 uint8_t* _to_nxt = _to;
4007 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4008 _Maxcode_, _Mode_);
4009 frm_nxt = frm + (_frm_nxt - _frm);
4010 to_nxt = to + (_to_nxt - _to);
4011 return r;
4012}
4013
4014__codecvt_utf8_utf16<char16_t>::result
4015__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4016 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4017 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4018{
4019 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4020 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4021 const uint8_t* _frm_nxt = _frm;
4022 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4023 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4024 uint16_t* _to_nxt = _to;
4025 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4026 _Maxcode_, _Mode_);
4027 frm_nxt = frm + (_frm_nxt - _frm);
4028 to_nxt = to + (_to_nxt - _to);
4029 return r;
4030}
4031
4032__codecvt_utf8_utf16<char16_t>::result
4033__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4034 extern_type* to, extern_type*, extern_type*& to_nxt) const
4035{
4036 to_nxt = to;
4037 return noconv;
4038}
4039
4040int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004041__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004042{
4043 return 0;
4044}
4045
4046bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004047__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004048{
4049 return false;
4050}
4051
4052int
4053__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4054 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4055{
4056 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4057 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4058 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4059}
4060
4061int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004062__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004063{
4064 if (_Mode_ & consume_header)
4065 return 7;
4066 return 4;
4067}
4068
4069// __codecvt_utf8_utf16<char32_t>
4070
4071__codecvt_utf8_utf16<char32_t>::result
4072__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4073 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4074 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4075{
4076 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4077 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4078 const uint32_t* _frm_nxt = _frm;
4079 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4080 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4081 uint8_t* _to_nxt = _to;
4082 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4083 _Maxcode_, _Mode_);
4084 frm_nxt = frm + (_frm_nxt - _frm);
4085 to_nxt = to + (_to_nxt - _to);
4086 return r;
4087}
4088
4089__codecvt_utf8_utf16<char32_t>::result
4090__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4091 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4092 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4093{
4094 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4095 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4096 const uint8_t* _frm_nxt = _frm;
4097 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4098 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4099 uint32_t* _to_nxt = _to;
4100 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4101 _Maxcode_, _Mode_);
4102 frm_nxt = frm + (_frm_nxt - _frm);
4103 to_nxt = to + (_to_nxt - _to);
4104 return r;
4105}
4106
4107__codecvt_utf8_utf16<char32_t>::result
4108__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4109 extern_type* to, extern_type*, extern_type*& to_nxt) const
4110{
4111 to_nxt = to;
4112 return noconv;
4113}
4114
4115int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004116__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004117{
4118 return 0;
4119}
4120
4121bool
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004122__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004123{
4124 return false;
4125}
4126
4127int
4128__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4129 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4130{
4131 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4132 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4133 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4134}
4135
4136int
Howard Hinnant7c9e5732011-05-31 15:34:58 +00004137__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant7282c5a2010-05-30 21:39:41 +00004138{
4139 if (_Mode_ & consume_header)
4140 return 7;
4141 return 4;
4142}
4143
Howard Hinnantc51e1022010-05-11 19:42:16 +00004144// __narrow_to_utf8<16>
4145
4146__narrow_to_utf8<16>::~__narrow_to_utf8()
4147{
4148}
4149
4150// __narrow_to_utf8<32>
4151
4152__narrow_to_utf8<32>::~__narrow_to_utf8()
4153{
4154}
4155
4156// __widen_from_utf8<16>
4157
4158__widen_from_utf8<16>::~__widen_from_utf8()
4159{
4160}
4161
4162// __widen_from_utf8<32>
4163
4164__widen_from_utf8<32>::~__widen_from_utf8()
4165{
4166}
4167
4168// numpunct<char> && numpunct<wchar_t>
4169
4170locale::id numpunct< char >::id;
4171locale::id numpunct<wchar_t>::id;
4172
4173numpunct<char>::numpunct(size_t refs)
4174 : locale::facet(refs),
4175 __decimal_point_('.'),
4176 __thousands_sep_(',')
4177{
4178}
4179
4180numpunct<wchar_t>::numpunct(size_t refs)
4181 : locale::facet(refs),
4182 __decimal_point_(L'.'),
4183 __thousands_sep_(L',')
4184{
4185}
4186
4187numpunct<char>::~numpunct()
4188{
4189}
4190
4191numpunct<wchar_t>::~numpunct()
4192{
4193}
4194
4195 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4196wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4197
4198 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4199wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4200
4201string numpunct< char >::do_grouping() const {return __grouping_;}
4202string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4203
4204 string numpunct< char >::do_truename() const {return "true";}
4205wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4206
4207 string numpunct< char >::do_falsename() const {return "false";}
4208wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4209
4210// numpunct_byname<char>
4211
4212numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4213 : numpunct<char>(refs)
4214{
4215 __init(nm);
4216}
4217
4218numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4219 : numpunct<char>(refs)
4220{
4221 __init(nm.c_str());
4222}
4223
4224numpunct_byname<char>::~numpunct_byname()
4225{
4226}
4227
4228void
4229numpunct_byname<char>::__init(const char* nm)
4230{
4231 if (strcmp(nm, "C") != 0)
4232 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004233 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004234#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004235 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004236 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4237 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004238#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004239#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004240 lconv* lc = localeconv_l(loc.get());
4241#else
4242 lconv* lc = __localeconv_l(loc.get());
4243#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004244 if (*lc->decimal_point)
4245 __decimal_point_ = *lc->decimal_point;
4246 if (*lc->thousands_sep)
4247 __thousands_sep_ = *lc->thousands_sep;
4248 __grouping_ = lc->grouping;
Alexis Hunt920b4a22011-07-07 22:45:07 +00004249 // localization for truename and falsename is not available
Howard Hinnantc51e1022010-05-11 19:42:16 +00004250 }
4251}
4252
4253// numpunct_byname<wchar_t>
4254
4255numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4256 : numpunct<wchar_t>(refs)
4257{
4258 __init(nm);
4259}
4260
4261numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4262 : numpunct<wchar_t>(refs)
4263{
4264 __init(nm.c_str());
4265}
4266
4267numpunct_byname<wchar_t>::~numpunct_byname()
4268{
4269}
4270
4271void
4272numpunct_byname<wchar_t>::__init(const char* nm)
4273{
4274 if (strcmp(nm, "C") != 0)
4275 {
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004276 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00004277#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00004278 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004279 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4280 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004281#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004282#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004283 lconv* lc = localeconv_l(loc.get());
4284#else
4285 lconv* lc = __localeconv_l(loc.get());
4286#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00004287 if (*lc->decimal_point)
4288 __decimal_point_ = *lc->decimal_point;
4289 if (*lc->thousands_sep)
4290 __thousands_sep_ = *lc->thousands_sep;
4291 __grouping_ = lc->grouping;
4292 // locallization for truename and falsename is not available
4293 }
4294}
4295
4296// num_get helpers
4297
4298int
4299__num_get_base::__get_base(ios_base& iob)
4300{
4301 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4302 if (__basefield == ios_base::oct)
4303 return 8;
4304 else if (__basefield == ios_base::hex)
4305 return 16;
4306 else if (__basefield == 0)
4307 return 0;
4308 return 10;
4309}
4310
4311const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4312
4313void
4314__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4315 ios_base::iostate& __err)
4316{
4317 if (__grouping.size() != 0)
4318 {
4319 reverse(__g, __g_end);
4320 const char* __ig = __grouping.data();
4321 const char* __eg = __ig + __grouping.size();
4322 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4323 {
4324 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4325 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004326 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004327 {
4328 __err = ios_base::failbit;
4329 return;
4330 }
4331 }
4332 if (__eg - __ig > 1)
4333 ++__ig;
4334 }
4335 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4336 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004337 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00004338 __err = ios_base::failbit;
4339 }
4340 }
4341}
4342
4343void
4344__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4345 ios_base::fmtflags __flags)
4346{
4347 if (__flags & ios_base::showpos)
4348 *__fmtp++ = '+';
4349 if (__flags & ios_base::showbase)
4350 *__fmtp++ = '#';
4351 while(*__len)
4352 *__fmtp++ = *__len++;
4353 if ((__flags & ios_base::basefield) == ios_base::oct)
4354 *__fmtp = 'o';
4355 else if ((__flags & ios_base::basefield) == ios_base::hex)
4356 {
4357 if (__flags & ios_base::uppercase)
4358 *__fmtp = 'X';
4359 else
4360 *__fmtp = 'x';
4361 }
4362 else if (__signd)
4363 *__fmtp = 'd';
4364 else
4365 *__fmtp = 'u';
4366}
4367
4368bool
4369__num_put_base::__format_float(char* __fmtp, const char* __len,
4370 ios_base::fmtflags __flags)
4371{
4372 bool specify_precision = true;
4373 if (__flags & ios_base::showpos)
4374 *__fmtp++ = '+';
4375 if (__flags & ios_base::showpoint)
4376 *__fmtp++ = '#';
4377 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowd920eea2013-10-21 15:07:28 +00004378 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004379 if (floatfield == (ios_base::fixed | ios_base::scientific))
4380 specify_precision = false;
4381 else
4382 {
4383 *__fmtp++ = '.';
4384 *__fmtp++ = '*';
4385 }
4386 while(*__len)
4387 *__fmtp++ = *__len++;
4388 if (floatfield == ios_base::fixed)
4389 {
4390 if (uppercase)
4391 *__fmtp = 'F';
4392 else
4393 *__fmtp = 'f';
4394 }
4395 else if (floatfield == ios_base::scientific)
4396 {
4397 if (uppercase)
4398 *__fmtp = 'E';
4399 else
4400 *__fmtp = 'e';
4401 }
4402 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4403 {
4404 if (uppercase)
4405 *__fmtp = 'A';
4406 else
4407 *__fmtp = 'a';
4408 }
4409 else
4410 {
4411 if (uppercase)
4412 *__fmtp = 'G';
4413 else
4414 *__fmtp = 'g';
4415 }
4416 return specify_precision;
4417}
4418
4419char*
4420__num_put_base::__identify_padding(char* __nb, char* __ne,
4421 const ios_base& __iob)
4422{
4423 switch (__iob.flags() & ios_base::adjustfield)
4424 {
4425 case ios_base::internal:
4426 if (__nb[0] == '-' || __nb[0] == '+')
4427 return __nb+1;
4428 if (__ne - __nb >= 2 && __nb[0] == '0'
4429 && (__nb[1] == 'x' || __nb[1] == 'X'))
4430 return __nb+2;
4431 break;
4432 case ios_base::left:
4433 return __ne;
4434 case ios_base::right:
4435 default:
4436 break;
4437 }
4438 return __nb;
4439}
4440
4441// time_get
4442
4443static
4444string*
4445init_weeks()
4446{
4447 static string weeks[14];
4448 weeks[0] = "Sunday";
4449 weeks[1] = "Monday";
4450 weeks[2] = "Tuesday";
4451 weeks[3] = "Wednesday";
4452 weeks[4] = "Thursday";
4453 weeks[5] = "Friday";
4454 weeks[6] = "Saturday";
4455 weeks[7] = "Sun";
4456 weeks[8] = "Mon";
4457 weeks[9] = "Tue";
4458 weeks[10] = "Wed";
4459 weeks[11] = "Thu";
4460 weeks[12] = "Fri";
4461 weeks[13] = "Sat";
4462 return weeks;
4463}
4464
4465static
4466wstring*
4467init_wweeks()
4468{
4469 static wstring weeks[14];
4470 weeks[0] = L"Sunday";
4471 weeks[1] = L"Monday";
4472 weeks[2] = L"Tuesday";
4473 weeks[3] = L"Wednesday";
4474 weeks[4] = L"Thursday";
4475 weeks[5] = L"Friday";
4476 weeks[6] = L"Saturday";
4477 weeks[7] = L"Sun";
4478 weeks[8] = L"Mon";
4479 weeks[9] = L"Tue";
4480 weeks[10] = L"Wed";
4481 weeks[11] = L"Thu";
4482 weeks[12] = L"Fri";
4483 weeks[13] = L"Sat";
4484 return weeks;
4485}
4486
4487template <>
4488const string*
4489__time_get_c_storage<char>::__weeks() const
4490{
4491 static const string* weeks = init_weeks();
4492 return weeks;
4493}
4494
4495template <>
4496const wstring*
4497__time_get_c_storage<wchar_t>::__weeks() const
4498{
4499 static const wstring* weeks = init_wweeks();
4500 return weeks;
4501}
4502
4503static
4504string*
4505init_months()
4506{
4507 static string months[24];
4508 months[0] = "January";
4509 months[1] = "February";
4510 months[2] = "March";
4511 months[3] = "April";
4512 months[4] = "May";
4513 months[5] = "June";
4514 months[6] = "July";
4515 months[7] = "August";
4516 months[8] = "September";
4517 months[9] = "October";
4518 months[10] = "November";
4519 months[11] = "December";
4520 months[12] = "Jan";
4521 months[13] = "Feb";
4522 months[14] = "Mar";
4523 months[15] = "Apr";
4524 months[16] = "May";
4525 months[17] = "Jun";
4526 months[18] = "Jul";
4527 months[19] = "Aug";
4528 months[20] = "Sep";
4529 months[21] = "Oct";
4530 months[22] = "Nov";
4531 months[23] = "Dec";
4532 return months;
4533}
4534
4535static
4536wstring*
4537init_wmonths()
4538{
4539 static wstring months[24];
4540 months[0] = L"January";
4541 months[1] = L"February";
4542 months[2] = L"March";
4543 months[3] = L"April";
4544 months[4] = L"May";
4545 months[5] = L"June";
4546 months[6] = L"July";
4547 months[7] = L"August";
4548 months[8] = L"September";
4549 months[9] = L"October";
4550 months[10] = L"November";
4551 months[11] = L"December";
4552 months[12] = L"Jan";
4553 months[13] = L"Feb";
4554 months[14] = L"Mar";
4555 months[15] = L"Apr";
4556 months[16] = L"May";
4557 months[17] = L"Jun";
4558 months[18] = L"Jul";
4559 months[19] = L"Aug";
4560 months[20] = L"Sep";
4561 months[21] = L"Oct";
4562 months[22] = L"Nov";
4563 months[23] = L"Dec";
4564 return months;
4565}
4566
4567template <>
4568const string*
4569__time_get_c_storage<char>::__months() const
4570{
4571 static const string* months = init_months();
4572 return months;
4573}
4574
4575template <>
4576const wstring*
4577__time_get_c_storage<wchar_t>::__months() const
4578{
4579 static const wstring* months = init_wmonths();
4580 return months;
4581}
4582
4583static
4584string*
4585init_am_pm()
4586{
4587 static string am_pm[24];
4588 am_pm[0] = "AM";
4589 am_pm[1] = "PM";
4590 return am_pm;
4591}
4592
4593static
4594wstring*
4595init_wam_pm()
4596{
4597 static wstring am_pm[24];
4598 am_pm[0] = L"AM";
4599 am_pm[1] = L"PM";
4600 return am_pm;
4601}
4602
4603template <>
4604const string*
4605__time_get_c_storage<char>::__am_pm() const
4606{
4607 static const string* am_pm = init_am_pm();
4608 return am_pm;
4609}
4610
4611template <>
4612const wstring*
4613__time_get_c_storage<wchar_t>::__am_pm() const
4614{
4615 static const wstring* am_pm = init_wam_pm();
4616 return am_pm;
4617}
4618
4619template <>
4620const string&
4621__time_get_c_storage<char>::__x() const
4622{
4623 static string s("%m/%d/%y");
4624 return s;
4625}
4626
4627template <>
4628const wstring&
4629__time_get_c_storage<wchar_t>::__x() const
4630{
4631 static wstring s(L"%m/%d/%y");
4632 return s;
4633}
4634
4635template <>
4636const string&
4637__time_get_c_storage<char>::__X() const
4638{
4639 static string s("%H:%M:%S");
4640 return s;
4641}
4642
4643template <>
4644const wstring&
4645__time_get_c_storage<wchar_t>::__X() const
4646{
4647 static wstring s(L"%H:%M:%S");
4648 return s;
4649}
4650
4651template <>
4652const string&
4653__time_get_c_storage<char>::__c() const
4654{
4655 static string s("%a %b %d %H:%M:%S %Y");
4656 return s;
4657}
4658
4659template <>
4660const wstring&
4661__time_get_c_storage<wchar_t>::__c() const
4662{
4663 static wstring s(L"%a %b %d %H:%M:%S %Y");
4664 return s;
4665}
4666
4667template <>
4668const string&
4669__time_get_c_storage<char>::__r() const
4670{
4671 static string s("%I:%M:%S %p");
4672 return s;
4673}
4674
4675template <>
4676const wstring&
4677__time_get_c_storage<wchar_t>::__r() const
4678{
4679 static wstring s(L"%I:%M:%S %p");
4680 return s;
4681}
4682
4683// time_get_byname
4684
4685__time_get::__time_get(const char* nm)
4686 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4687{
Howard Hinnant72f73582010-08-11 17:04:31 +00004688#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004689 if (__loc_ == 0)
4690 throw runtime_error("time_get_byname"
4691 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00004692#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004693}
4694
4695__time_get::__time_get(const string& nm)
4696 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4697{
Howard Hinnant72f73582010-08-11 17:04:31 +00004698#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004699 if (__loc_ == 0)
4700 throw runtime_error("time_get_byname"
4701 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00004702#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00004703}
4704
4705__time_get::~__time_get()
4706{
4707 freelocale(__loc_);
4708}
Marshall Clowd920eea2013-10-21 15:07:28 +00004709#if defined(__clang__)
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004710#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004711#endif
4712#if defined(__GNUG__)
Howard Hinnanta80f1ec2012-12-28 18:15:01 +00004713#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowd920eea2013-10-21 15:07:28 +00004714#endif
Howard Hinnant3a4f7c92012-02-20 16:51:43 +00004715
Howard Hinnantc51e1022010-05-11 19:42:16 +00004716template <>
4717string
4718__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4719{
Howard Hinnant990207c2012-02-19 14:55:32 +00004720 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004721 t.tm_sec = 59;
4722 t.tm_min = 55;
4723 t.tm_hour = 23;
4724 t.tm_mday = 31;
4725 t.tm_mon = 11;
4726 t.tm_year = 161;
4727 t.tm_wday = 6;
4728 t.tm_yday = 364;
4729 t.tm_isdst = -1;
4730 char buf[100];
4731 char f[3] = {0};
4732 f[0] = '%';
4733 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004734 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004735 char* bb = buf;
4736 char* be = buf + n;
4737 string result;
4738 while (bb != be)
4739 {
4740 if (ct.is(ctype_base::space, *bb))
4741 {
4742 result.push_back(' ');
4743 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4744 ;
4745 continue;
4746 }
4747 char* w = bb;
4748 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004749 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004750 ct, err, false)
4751 - this->__weeks_;
4752 if (i < 14)
4753 {
4754 result.push_back('%');
4755 if (i < 7)
4756 result.push_back('A');
4757 else
4758 result.push_back('a');
4759 bb = w;
4760 continue;
4761 }
4762 w = bb;
4763 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4764 ct, err, false)
4765 - this->__months_;
4766 if (i < 24)
4767 {
4768 result.push_back('%');
4769 if (i < 12)
4770 result.push_back('B');
4771 else
4772 result.push_back('b');
4773 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4774 result.back() = 'm';
4775 bb = w;
4776 continue;
4777 }
4778 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4779 {
4780 w = bb;
4781 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4782 ct, err, false) - this->__am_pm_;
4783 if (i < 2)
4784 {
4785 result.push_back('%');
4786 result.push_back('p');
4787 bb = w;
4788 continue;
4789 }
4790 }
4791 w = bb;
4792 if (ct.is(ctype_base::digit, *bb))
4793 {
4794 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4795 {
4796 case 6:
4797 result.push_back('%');
4798 result.push_back('w');
4799 break;
4800 case 7:
4801 result.push_back('%');
4802 result.push_back('u');
4803 break;
4804 case 11:
4805 result.push_back('%');
4806 result.push_back('I');
4807 break;
4808 case 12:
4809 result.push_back('%');
4810 result.push_back('m');
4811 break;
4812 case 23:
4813 result.push_back('%');
4814 result.push_back('H');
4815 break;
4816 case 31:
4817 result.push_back('%');
4818 result.push_back('d');
4819 break;
4820 case 55:
4821 result.push_back('%');
4822 result.push_back('M');
4823 break;
4824 case 59:
4825 result.push_back('%');
4826 result.push_back('S');
4827 break;
4828 case 61:
4829 result.push_back('%');
4830 result.push_back('y');
4831 break;
4832 case 364:
4833 result.push_back('%');
4834 result.push_back('j');
4835 break;
4836 case 2061:
4837 result.push_back('%');
4838 result.push_back('Y');
4839 break;
4840 default:
4841 for (; w != bb; ++w)
4842 result.push_back(*w);
4843 break;
4844 }
4845 continue;
4846 }
4847 if (*bb == '%')
4848 {
4849 result.push_back('%');
4850 result.push_back('%');
4851 ++bb;
4852 continue;
4853 }
4854 result.push_back(*bb);
4855 ++bb;
4856 }
4857 return result;
4858}
4859
Marshall Clowd920eea2013-10-21 15:07:28 +00004860#if defined(__clang__)
Howard Hinnant28b24882011-12-01 20:21:04 +00004861#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowd920eea2013-10-21 15:07:28 +00004862#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004863
Howard Hinnantc51e1022010-05-11 19:42:16 +00004864template <>
4865wstring
4866__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4867{
Howard Hinnant990207c2012-02-19 14:55:32 +00004868 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00004869 t.tm_sec = 59;
4870 t.tm_min = 55;
4871 t.tm_hour = 23;
4872 t.tm_mday = 31;
4873 t.tm_mon = 11;
4874 t.tm_year = 161;
4875 t.tm_wday = 6;
4876 t.tm_yday = 364;
4877 t.tm_isdst = -1;
4878 char buf[100];
4879 char f[3] = {0};
4880 f[0] = '%';
4881 f[1] = fmt;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004882 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00004883 wchar_t wbuf[100];
4884 wchar_t* wbb = wbuf;
4885 mbstate_t mb = {0};
4886 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00004887#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004888 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004889#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00004890 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00004891#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00004892 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00004893 __throw_runtime_error("locale not supported");
Howard Hinnant28b24882011-12-01 20:21:04 +00004894 wchar_t* wbe = wbb + j;
Howard Hinnantc51e1022010-05-11 19:42:16 +00004895 wstring result;
4896 while (wbb != wbe)
4897 {
4898 if (ct.is(ctype_base::space, *wbb))
4899 {
4900 result.push_back(L' ');
4901 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4902 ;
4903 continue;
4904 }
4905 wchar_t* w = wbb;
4906 ios_base::iostate err = ios_base::goodbit;
Howard Hinnant28b24882011-12-01 20:21:04 +00004907 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantc51e1022010-05-11 19:42:16 +00004908 ct, err, false)
4909 - this->__weeks_;
4910 if (i < 14)
4911 {
4912 result.push_back(L'%');
4913 if (i < 7)
4914 result.push_back(L'A');
4915 else
4916 result.push_back(L'a');
4917 wbb = w;
4918 continue;
4919 }
4920 w = wbb;
4921 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4922 ct, err, false)
4923 - this->__months_;
4924 if (i < 24)
4925 {
4926 result.push_back(L'%');
4927 if (i < 12)
4928 result.push_back(L'B');
4929 else
4930 result.push_back(L'b');
4931 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4932 result.back() = L'm';
4933 wbb = w;
4934 continue;
4935 }
4936 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4937 {
4938 w = wbb;
4939 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4940 ct, err, false) - this->__am_pm_;
4941 if (i < 2)
4942 {
4943 result.push_back(L'%');
4944 result.push_back(L'p');
4945 wbb = w;
4946 continue;
4947 }
4948 }
4949 w = wbb;
4950 if (ct.is(ctype_base::digit, *wbb))
4951 {
4952 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4953 {
4954 case 6:
4955 result.push_back(L'%');
4956 result.push_back(L'w');
4957 break;
4958 case 7:
4959 result.push_back(L'%');
4960 result.push_back(L'u');
4961 break;
4962 case 11:
4963 result.push_back(L'%');
4964 result.push_back(L'I');
4965 break;
4966 case 12:
4967 result.push_back(L'%');
4968 result.push_back(L'm');
4969 break;
4970 case 23:
4971 result.push_back(L'%');
4972 result.push_back(L'H');
4973 break;
4974 case 31:
4975 result.push_back(L'%');
4976 result.push_back(L'd');
4977 break;
4978 case 55:
4979 result.push_back(L'%');
4980 result.push_back(L'M');
4981 break;
4982 case 59:
4983 result.push_back(L'%');
4984 result.push_back(L'S');
4985 break;
4986 case 61:
4987 result.push_back(L'%');
4988 result.push_back(L'y');
4989 break;
4990 case 364:
4991 result.push_back(L'%');
4992 result.push_back(L'j');
4993 break;
4994 case 2061:
4995 result.push_back(L'%');
4996 result.push_back(L'Y');
4997 break;
4998 default:
4999 for (; w != wbb; ++w)
5000 result.push_back(*w);
5001 break;
5002 }
5003 continue;
5004 }
5005 if (ct.narrow(*wbb, 0) == '%')
5006 {
5007 result.push_back(L'%');
5008 result.push_back(L'%');
5009 ++wbb;
5010 continue;
5011 }
5012 result.push_back(*wbb);
5013 ++wbb;
5014 }
5015 return result;
5016}
5017
5018template <>
5019void
5020__time_get_storage<char>::init(const ctype<char>& ct)
5021{
Howard Hinnant1796ab12012-08-02 18:44:17 +00005022 tm t = {0};
Howard Hinnantc51e1022010-05-11 19:42:16 +00005023 char buf[100];
5024 // __weeks_
5025 for (int i = 0; i < 7; ++i)
5026 {
5027 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005028 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005029 __weeks_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005030 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005031 __weeks_[i+7] = buf;
5032 }
5033 // __months_
5034 for (int i = 0; i < 12; ++i)
5035 {
5036 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005037 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005038 __months_[i] = buf;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005039 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005040 __months_[i+12] = buf;
5041 }
5042 // __am_pm_
5043 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005044 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005045 __am_pm_[0] = buf;
5046 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005047 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005048 __am_pm_[1] = buf;
5049 __c_ = __analyze('c', ct);
5050 __r_ = __analyze('r', ct);
5051 __x_ = __analyze('x', ct);
5052 __X_ = __analyze('X', ct);
5053}
5054
5055template <>
5056void
5057__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5058{
5059 tm t = {0};
5060 char buf[100];
Howard Hinnantc51e1022010-05-11 19:42:16 +00005061 wchar_t wbuf[100];
5062 wchar_t* wbe;
5063 mbstate_t mb = {0};
5064 // __weeks_
5065 for (int i = 0; i < 7; ++i)
5066 {
5067 t.tm_wday = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005068 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005069 mb = mbstate_t();
5070 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005071#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005072 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005073#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005074 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005075#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005076 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005077 __throw_runtime_error("locale not supported");
5078 wbe = wbuf + j;
5079 __weeks_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005080 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005081 mb = mbstate_t();
5082 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005083#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005084 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005085#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005086 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005087#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005088 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005089 __throw_runtime_error("locale not supported");
5090 wbe = wbuf + j;
5091 __weeks_[i+7].assign(wbuf, wbe);
5092 }
5093 // __months_
5094 for (int i = 0; i < 12; ++i)
5095 {
5096 t.tm_mon = i;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005097 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005098 mb = mbstate_t();
5099 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005100#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005101 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005102#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005103 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005104#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005105 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005106 __throw_runtime_error("locale not supported");
5107 wbe = wbuf + j;
5108 __months_[i].assign(wbuf, wbe);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005109 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005110 mb = mbstate_t();
5111 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005112#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005113 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005114#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005115 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005116#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005117 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005118 __throw_runtime_error("locale not supported");
5119 wbe = wbuf + j;
5120 __months_[i+12].assign(wbuf, wbe);
5121 }
5122 // __am_pm_
5123 t.tm_hour = 1;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005124 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005125 mb = mbstate_t();
5126 const char* bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005127#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005128 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005129#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005130 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005131#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005132 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005133 __throw_runtime_error("locale not supported");
5134 wbe = wbuf + j;
5135 __am_pm_[0].assign(wbuf, wbe);
5136 t.tm_hour = 13;
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005137 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005138 mb = mbstate_t();
5139 bb = buf;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005140#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005141 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005142#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005143 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005144#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005145 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005146 __throw_runtime_error("locale not supported");
5147 wbe = wbuf + j;
5148 __am_pm_[1].assign(wbuf, wbe);
5149 __c_ = __analyze('c', ct);
5150 __r_ = __analyze('r', ct);
5151 __x_ = __analyze('x', ct);
5152 __X_ = __analyze('X', ct);
5153}
5154
5155template <class CharT>
5156struct _LIBCPP_HIDDEN __time_get_temp
5157 : public ctype_byname<CharT>
5158{
5159 explicit __time_get_temp(const char* nm)
5160 : ctype_byname<CharT>(nm, 1) {}
5161 explicit __time_get_temp(const string& nm)
5162 : ctype_byname<CharT>(nm, 1) {}
5163};
5164
5165template <>
5166__time_get_storage<char>::__time_get_storage(const char* __nm)
5167 : __time_get(__nm)
5168{
5169 const __time_get_temp<char> ct(__nm);
5170 init(ct);
5171}
5172
5173template <>
5174__time_get_storage<char>::__time_get_storage(const string& __nm)
5175 : __time_get(__nm)
5176{
5177 const __time_get_temp<char> ct(__nm);
5178 init(ct);
5179}
5180
5181template <>
5182__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5183 : __time_get(__nm)
5184{
5185 const __time_get_temp<wchar_t> ct(__nm);
5186 init(ct);
5187}
5188
5189template <>
5190__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5191 : __time_get(__nm)
5192{
5193 const __time_get_temp<wchar_t> ct(__nm);
5194 init(ct);
5195}
5196
5197template <>
5198time_base::dateorder
5199__time_get_storage<char>::__do_date_order() const
5200{
5201 unsigned i;
5202 for (i = 0; i < __x_.size(); ++i)
5203 if (__x_[i] == '%')
5204 break;
5205 ++i;
5206 switch (__x_[i])
5207 {
5208 case 'y':
5209 case 'Y':
5210 for (++i; i < __x_.size(); ++i)
5211 if (__x_[i] == '%')
5212 break;
5213 if (i == __x_.size())
5214 break;
5215 ++i;
5216 switch (__x_[i])
5217 {
5218 case 'm':
5219 for (++i; i < __x_.size(); ++i)
5220 if (__x_[i] == '%')
5221 break;
5222 if (i == __x_.size())
5223 break;
5224 ++i;
5225 if (__x_[i] == 'd')
5226 return time_base::ymd;
5227 break;
5228 case 'd':
5229 for (++i; i < __x_.size(); ++i)
5230 if (__x_[i] == '%')
5231 break;
5232 if (i == __x_.size())
5233 break;
5234 ++i;
5235 if (__x_[i] == 'm')
5236 return time_base::ydm;
5237 break;
5238 }
5239 break;
5240 case 'm':
5241 for (++i; i < __x_.size(); ++i)
5242 if (__x_[i] == '%')
5243 break;
5244 if (i == __x_.size())
5245 break;
5246 ++i;
5247 if (__x_[i] == 'd')
5248 {
5249 for (++i; i < __x_.size(); ++i)
5250 if (__x_[i] == '%')
5251 break;
5252 if (i == __x_.size())
5253 break;
5254 ++i;
5255 if (__x_[i] == 'y' || __x_[i] == 'Y')
5256 return time_base::mdy;
5257 break;
5258 }
5259 break;
5260 case 'd':
5261 for (++i; i < __x_.size(); ++i)
5262 if (__x_[i] == '%')
5263 break;
5264 if (i == __x_.size())
5265 break;
5266 ++i;
5267 if (__x_[i] == 'm')
5268 {
5269 for (++i; i < __x_.size(); ++i)
5270 if (__x_[i] == '%')
5271 break;
5272 if (i == __x_.size())
5273 break;
5274 ++i;
5275 if (__x_[i] == 'y' || __x_[i] == 'Y')
5276 return time_base::dmy;
5277 break;
5278 }
5279 break;
5280 }
5281 return time_base::no_order;
5282}
5283
5284template <>
5285time_base::dateorder
5286__time_get_storage<wchar_t>::__do_date_order() const
5287{
5288 unsigned i;
5289 for (i = 0; i < __x_.size(); ++i)
5290 if (__x_[i] == L'%')
5291 break;
5292 ++i;
5293 switch (__x_[i])
5294 {
5295 case L'y':
5296 case L'Y':
5297 for (++i; i < __x_.size(); ++i)
5298 if (__x_[i] == L'%')
5299 break;
5300 if (i == __x_.size())
5301 break;
5302 ++i;
5303 switch (__x_[i])
5304 {
5305 case L'm':
5306 for (++i; i < __x_.size(); ++i)
5307 if (__x_[i] == L'%')
5308 break;
5309 if (i == __x_.size())
5310 break;
5311 ++i;
5312 if (__x_[i] == L'd')
5313 return time_base::ymd;
5314 break;
5315 case L'd':
5316 for (++i; i < __x_.size(); ++i)
5317 if (__x_[i] == L'%')
5318 break;
5319 if (i == __x_.size())
5320 break;
5321 ++i;
5322 if (__x_[i] == L'm')
5323 return time_base::ydm;
5324 break;
5325 }
5326 break;
5327 case L'm':
5328 for (++i; i < __x_.size(); ++i)
5329 if (__x_[i] == L'%')
5330 break;
5331 if (i == __x_.size())
5332 break;
5333 ++i;
5334 if (__x_[i] == L'd')
5335 {
5336 for (++i; i < __x_.size(); ++i)
5337 if (__x_[i] == L'%')
5338 break;
5339 if (i == __x_.size())
5340 break;
5341 ++i;
5342 if (__x_[i] == L'y' || __x_[i] == L'Y')
5343 return time_base::mdy;
5344 break;
5345 }
5346 break;
5347 case L'd':
5348 for (++i; i < __x_.size(); ++i)
5349 if (__x_[i] == L'%')
5350 break;
5351 if (i == __x_.size())
5352 break;
5353 ++i;
5354 if (__x_[i] == L'm')
5355 {
5356 for (++i; i < __x_.size(); ++i)
5357 if (__x_[i] == L'%')
5358 break;
5359 if (i == __x_.size())
5360 break;
5361 ++i;
5362 if (__x_[i] == L'y' || __x_[i] == L'Y')
5363 return time_base::dmy;
5364 break;
5365 }
5366 break;
5367 }
5368 return time_base::no_order;
5369}
5370
5371// time_put
5372
5373__time_put::__time_put(const char* nm)
5374 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5375{
Howard Hinnant72f73582010-08-11 17:04:31 +00005376#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005377 if (__loc_ == 0)
5378 throw runtime_error("time_put_byname"
5379 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005380#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005381}
5382
5383__time_put::__time_put(const string& nm)
5384 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5385{
Howard Hinnant72f73582010-08-11 17:04:31 +00005386#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005387 if (__loc_ == 0)
5388 throw runtime_error("time_put_byname"
5389 " failed to construct for " + nm);
Howard Hinnantffb308e2010-08-22 00:03:27 +00005390#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00005391}
5392
5393__time_put::~__time_put()
5394{
Joerg Sonnenbergere039efb2013-07-02 19:46:18 +00005395 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005396 freelocale(__loc_);
5397}
5398
5399void
5400__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5401 char __fmt, char __mod) const
5402{
5403 char fmt[] = {'%', __fmt, __mod, 0};
5404 if (__mod != 0)
5405 swap(fmt[1], fmt[2]);
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005406 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantc51e1022010-05-11 19:42:16 +00005407 __ne = __nb + n;
5408}
5409
5410void
5411__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5412 char __fmt, char __mod) const
5413{
5414 char __nar[100];
5415 char* __ne = __nar + 100;
5416 __do_put(__nar, __ne, __tm, __fmt, __mod);
5417 mbstate_t mb = {0};
5418 const char* __nb = __nar;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005419#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005420 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005421#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005422 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005423#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005424 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005425 __throw_runtime_error("locale not supported");
5426 __we = __wb + j;
5427}
5428
5429// moneypunct_byname
5430
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005431template <class charT>
Howard Hinnantc51e1022010-05-11 19:42:16 +00005432static
5433void
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005434__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5435 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5436 charT space_char)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005437{
5438 const char sign = static_cast<char>(money_base::sign);
5439 const char space = static_cast<char>(money_base::space);
5440 const char none = static_cast<char>(money_base::none);
5441 const char symbol = static_cast<char>(money_base::symbol);
5442 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005443 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5444
5445 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5446 // function'. "Space between sign and symbol or value" means that
5447 // if the sign is adjacent to the symbol, there's a space between
5448 // them, and otherwise there's a space between the sign and value.
5449 //
5450 // C11's localeconv specifies that the fourth character of an
5451 // international curr_symbol is used to separate the sign and
5452 // value when sep_by_space says to do so. C++ can't represent
5453 // that, so we just use a space. When sep_by_space says to
5454 // separate the symbol and value-or-sign with a space, we rearrange the
5455 // curr_symbol to put its spacing character on the correct side of
5456 // the symbol.
5457 //
5458 // We also need to avoid adding an extra space between the sign
5459 // and value when the currency symbol is suppressed (by not
5460 // setting showbase). We match glibc's strfmon by interpreting
5461 // sep_by_space==1 as "omit the space when the currency symbol is
5462 // absent".
5463 //
5464 // Users who want to get this right should use ICU instead.
5465
Howard Hinnantc51e1022010-05-11 19:42:16 +00005466 switch (cs_precedes)
5467 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005468 case 0: // value before curr_symbol
5469 if (symbol_contains_sep) {
5470 // Move the separator to before the symbol, to place it
5471 // between the value and symbol.
5472 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5473 __curr_symbol_.end());
5474 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005475 switch (sign_posn)
5476 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005477 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005478 pat.field[0] = sign;
5479 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005480 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005481 pat.field[3] = symbol;
5482 switch (sep_by_space)
5483 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005484 case 0: // No space separates the currency symbol and value.
5485 // This case may have changed between C99 and C11;
5486 // assume the currency symbol matches the intention.
5487 case 2: // Space between sign and currency or value.
5488 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005489 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005490 case 1: // Space between currency-and-sign or currency and value.
5491 if (!symbol_contains_sep) {
5492 // We insert the space into the symbol instead of
5493 // setting pat.field[2]=space so that when
5494 // showbase is not set, the space goes away too.
5495 __curr_symbol_.insert(0, 1, space_char);
5496 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005497 return;
5498 default:
5499 break;
5500 }
5501 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005502 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005503 pat.field[0] = sign;
5504 pat.field[3] = symbol;
5505 switch (sep_by_space)
5506 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005507 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005508 pat.field[1] = value;
5509 pat.field[2] = none;
5510 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005511 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005512 pat.field[1] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005513 pat.field[2] = none;
5514 if (!symbol_contains_sep) {
5515 // We insert the space into the symbol instead of
5516 // setting pat.field[2]=space so that when
5517 // showbase is not set, the space goes away too.
5518 __curr_symbol_.insert(0, 1, space_char);
5519 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005520 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005521 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005522 pat.field[1] = space;
5523 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005524 if (symbol_contains_sep) {
5525 // Remove the separator from the symbol, since it
5526 // has already appeared after the sign.
5527 __curr_symbol_.erase(__curr_symbol_.begin());
5528 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005529 return;
5530 default:
5531 break;
5532 }
5533 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005534 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005535 pat.field[0] = value;
5536 pat.field[3] = sign;
5537 switch (sep_by_space)
5538 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005539 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005540 pat.field[1] = none;
5541 pat.field[2] = symbol;
5542 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005543 case 1: // Space between currency-and-sign or currency and value.
5544 if (!symbol_contains_sep) {
5545 // We insert the space into the symbol instead of
5546 // setting pat.field[1]=space so that when
5547 // showbase is not set, the space goes away too.
5548 __curr_symbol_.insert(0, 1, space_char);
5549 }
5550 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005551 pat.field[2] = symbol;
5552 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005553 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005554 pat.field[1] = symbol;
5555 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005556 if (symbol_contains_sep) {
5557 // Remove the separator from the symbol, since it
5558 // should not be removed if showbase is absent.
5559 __curr_symbol_.erase(__curr_symbol_.begin());
5560 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005561 return;
5562 default:
5563 break;
5564 }
5565 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005566 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005567 pat.field[0] = value;
5568 pat.field[3] = symbol;
5569 switch (sep_by_space)
5570 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005571 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005572 pat.field[1] = none;
5573 pat.field[2] = sign;
5574 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005575 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005576 pat.field[1] = space;
5577 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005578 if (symbol_contains_sep) {
5579 // Remove the separator from the symbol, since it
5580 // has already appeared before the sign.
5581 __curr_symbol_.erase(__curr_symbol_.begin());
5582 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005583 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005584 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005585 pat.field[1] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005586 pat.field[2] = none;
5587 if (!symbol_contains_sep) {
5588 // We insert the space into the symbol instead of
5589 // setting pat.field[2]=space so that when
5590 // showbase is not set, the space goes away too.
5591 __curr_symbol_.insert(0, 1, space_char);
5592 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005593 return;
5594 default:
5595 break;
5596 }
5597 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005598 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005599 pat.field[0] = value;
5600 pat.field[3] = sign;
5601 switch (sep_by_space)
5602 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005603 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005604 pat.field[1] = none;
5605 pat.field[2] = symbol;
5606 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005607 case 1: // Space between currency-and-sign or currency and value.
5608 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005609 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005610 if (!symbol_contains_sep) {
5611 // We insert the space into the symbol instead of
5612 // setting pat.field[1]=space so that when
5613 // showbase is not set, the space goes away too.
5614 __curr_symbol_.insert(0, 1, space_char);
5615 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005616 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005617 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005618 pat.field[1] = symbol;
5619 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005620 if (symbol_contains_sep) {
5621 // Remove the separator from the symbol, since it
5622 // should not disappear when showbase is absent.
5623 __curr_symbol_.erase(__curr_symbol_.begin());
5624 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005625 return;
5626 default:
5627 break;
5628 }
5629 break;
5630 default:
5631 break;
5632 }
5633 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005634 case 1: // curr_symbol before value
Howard Hinnantc51e1022010-05-11 19:42:16 +00005635 switch (sign_posn)
5636 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005637 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005638 pat.field[0] = sign;
5639 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005640 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005641 pat.field[3] = value;
5642 switch (sep_by_space)
5643 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005644 case 0: // No space separates the currency symbol and value.
5645 // This case may have changed between C99 and C11;
5646 // assume the currency symbol matches the intention.
5647 case 2: // Space between sign and currency or value.
5648 // The "sign" is two parentheses, so no space here either.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005649 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005650 case 1: // Space between currency-and-sign or currency and value.
5651 if (!symbol_contains_sep) {
5652 // We insert the space into the symbol instead of
5653 // setting pat.field[2]=space so that when
5654 // showbase is not set, the space goes away too.
5655 __curr_symbol_.insert(0, 1, space_char);
5656 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005657 return;
5658 default:
5659 break;
5660 }
5661 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005662 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005663 pat.field[0] = sign;
5664 pat.field[3] = value;
5665 switch (sep_by_space)
5666 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005667 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005668 pat.field[1] = symbol;
5669 pat.field[2] = none;
5670 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005671 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005672 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005673 pat.field[2] = none;
5674 if (!symbol_contains_sep) {
5675 // We insert the space into the symbol instead of
5676 // setting pat.field[2]=space so that when
5677 // showbase is not set, the space goes away too.
5678 __curr_symbol_.push_back(space_char);
5679 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005680 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005681 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005682 pat.field[1] = space;
5683 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005684 if (symbol_contains_sep) {
5685 // Remove the separator from the symbol, since it
5686 // has already appeared after the sign.
5687 __curr_symbol_.pop_back();
5688 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005689 return;
5690 default:
5691 break;
5692 }
5693 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005694 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005695 pat.field[0] = symbol;
5696 pat.field[3] = sign;
5697 switch (sep_by_space)
5698 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005699 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005700 pat.field[1] = none;
5701 pat.field[2] = value;
5702 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005703 case 1: // Space between currency-and-sign or currency and value.
5704 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005705 pat.field[2] = value;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005706 if (!symbol_contains_sep) {
5707 // We insert the space into the symbol instead of
5708 // setting pat.field[1]=space so that when
5709 // showbase is not set, the space goes away too.
5710 __curr_symbol_.push_back(space_char);
5711 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005712 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005713 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005714 pat.field[1] = value;
5715 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005716 if (symbol_contains_sep) {
5717 // Remove the separator from the symbol, since it
5718 // will appear before the sign.
5719 __curr_symbol_.pop_back();
5720 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005721 return;
5722 default:
5723 break;
5724 }
5725 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005726 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005727 pat.field[0] = sign;
5728 pat.field[3] = value;
5729 switch (sep_by_space)
5730 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005731 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005732 pat.field[1] = symbol;
5733 pat.field[2] = none;
5734 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005735 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005736 pat.field[1] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005737 pat.field[2] = none;
5738 if (!symbol_contains_sep) {
5739 // We insert the space into the symbol instead of
5740 // setting pat.field[2]=space so that when
5741 // showbase is not set, the space goes away too.
5742 __curr_symbol_.push_back(space_char);
5743 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005744 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005745 case 2: // Space between sign and currency or value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005746 pat.field[1] = space;
5747 pat.field[2] = symbol;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005748 if (symbol_contains_sep) {
5749 // Remove the separator from the symbol, since it
5750 // has already appeared after the sign.
5751 __curr_symbol_.pop_back();
5752 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005753 return;
5754 default:
5755 break;
5756 }
5757 break;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005758 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005759 pat.field[0] = symbol;
5760 pat.field[3] = value;
5761 switch (sep_by_space)
5762 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005763 case 0: // No space separates the currency symbol and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005764 pat.field[1] = sign;
5765 pat.field[2] = none;
5766 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005767 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantc51e1022010-05-11 19:42:16 +00005768 pat.field[1] = sign;
5769 pat.field[2] = space;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005770 if (symbol_contains_sep) {
5771 // Remove the separator from the symbol, since it
5772 // should not disappear when showbase is absent.
5773 __curr_symbol_.pop_back();
5774 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005775 return;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005776 case 2: // Space between sign and currency or value.
5777 pat.field[1] = none;
Howard Hinnantc51e1022010-05-11 19:42:16 +00005778 pat.field[2] = sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005779 if (!symbol_contains_sep) {
5780 // We insert the space into the symbol instead of
5781 // setting pat.field[1]=space so that when
5782 // showbase is not set, the space goes away too.
5783 __curr_symbol_.push_back(space_char);
5784 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00005785 return;
5786 default:
5787 break;
5788 }
5789 break;
5790 default:
5791 break;
5792 }
5793 break;
5794 default:
5795 break;
5796 }
5797 pat.field[0] = symbol;
5798 pat.field[1] = sign;
5799 pat.field[2] = none;
5800 pat.field[3] = value;
5801}
5802
5803template<>
5804void
5805moneypunct_byname<char, false>::init(const char* nm)
5806{
5807 typedef moneypunct<char, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005808 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005809#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005810 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005811 throw runtime_error("moneypunct_byname"
5812 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005813#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005814#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005815 lconv* lc = localeconv_l(loc.get());
5816#else
5817 lconv* lc = __localeconv_l(loc.get());
5818#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005819 if (*lc->mon_decimal_point)
5820 __decimal_point_ = *lc->mon_decimal_point;
5821 else
5822 __decimal_point_ = base::do_decimal_point();
5823 if (*lc->mon_thousands_sep)
5824 __thousands_sep_ = *lc->mon_thousands_sep;
5825 else
5826 __thousands_sep_ = base::do_thousands_sep();
5827 __grouping_ = lc->mon_grouping;
5828 __curr_symbol_ = lc->currency_symbol;
5829 if (lc->frac_digits != CHAR_MAX)
5830 __frac_digits_ = lc->frac_digits;
5831 else
5832 __frac_digits_ = base::do_frac_digits();
5833 if (lc->p_sign_posn == 0)
5834 __positive_sign_ = "()";
5835 else
5836 __positive_sign_ = lc->positive_sign;
5837 if (lc->n_sign_posn == 0)
5838 __negative_sign_ = "()";
5839 else
5840 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005841 // Assume the positive and negative formats will want spaces in
5842 // the same places in curr_symbol since there's no way to
5843 // represent anything else.
5844 string_type __dummy_curr_symbol = __curr_symbol_;
5845 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5846 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5847 __init_pat(__neg_format_, __curr_symbol_, false,
5848 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005849}
5850
5851template<>
5852void
5853moneypunct_byname<char, true>::init(const char* nm)
5854{
5855 typedef moneypunct<char, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005856 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005857#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005858 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005859 throw runtime_error("moneypunct_byname"
5860 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005861#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005862#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005863 lconv* lc = localeconv_l(loc.get());
5864#else
5865 lconv* lc = __localeconv_l(loc.get());
5866#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005867 if (*lc->mon_decimal_point)
5868 __decimal_point_ = *lc->mon_decimal_point;
5869 else
5870 __decimal_point_ = base::do_decimal_point();
5871 if (*lc->mon_thousands_sep)
5872 __thousands_sep_ = *lc->mon_thousands_sep;
5873 else
5874 __thousands_sep_ = base::do_thousands_sep();
5875 __grouping_ = lc->mon_grouping;
5876 __curr_symbol_ = lc->int_curr_symbol;
5877 if (lc->int_frac_digits != CHAR_MAX)
5878 __frac_digits_ = lc->int_frac_digits;
5879 else
5880 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00005881#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005882 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005883#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005884 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005885#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005886 __positive_sign_ = "()";
5887 else
5888 __positive_sign_ = lc->positive_sign;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005889#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00005890 if(lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005891#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005892 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005893#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005894 __negative_sign_ = "()";
5895 else
5896 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005897 // Assume the positive and negative formats will want spaces in
5898 // the same places in curr_symbol since there's no way to
5899 // represent anything else.
5900 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00005901#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005902 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5903 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5904 __init_pat(__neg_format_, __curr_symbol_, true,
5905 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005906#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005907 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5908 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5909 lc->int_p_sign_posn, ' ');
5910 __init_pat(__neg_format_, __curr_symbol_, true,
5911 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5912 lc->int_n_sign_posn, ' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00005913#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00005914}
5915
5916template<>
5917void
5918moneypunct_byname<wchar_t, false>::init(const char* nm)
5919{
5920 typedef moneypunct<wchar_t, false> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005921 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00005922#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00005923 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00005924 throw runtime_error("moneypunct_byname"
5925 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00005926#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005927#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005928 lconv* lc = localeconv_l(loc.get());
5929#else
5930 lconv* lc = __localeconv_l(loc.get());
5931#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00005932 if (*lc->mon_decimal_point)
5933 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5934 else
5935 __decimal_point_ = base::do_decimal_point();
5936 if (*lc->mon_thousands_sep)
5937 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5938 else
5939 __thousands_sep_ = base::do_thousands_sep();
5940 __grouping_ = lc->mon_grouping;
5941 wchar_t wbuf[100];
5942 mbstate_t mb = {0};
5943 const char* bb = lc->currency_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005944#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005945 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005946#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005947 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005948#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005949 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005950 __throw_runtime_error("locale not supported");
5951 wchar_t* wbe = wbuf + j;
5952 __curr_symbol_.assign(wbuf, wbe);
5953 if (lc->frac_digits != CHAR_MAX)
5954 __frac_digits_ = lc->frac_digits;
5955 else
5956 __frac_digits_ = base::do_frac_digits();
5957 if (lc->p_sign_posn == 0)
5958 __positive_sign_ = L"()";
5959 else
5960 {
5961 mb = mbstate_t();
5962 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005963#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005964 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005965#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005966 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005967#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005968 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005969 __throw_runtime_error("locale not supported");
5970 wbe = wbuf + j;
5971 __positive_sign_.assign(wbuf, wbe);
5972 }
5973 if (lc->n_sign_posn == 0)
5974 __negative_sign_ = L"()";
5975 else
5976 {
5977 mb = mbstate_t();
5978 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00005979#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005980 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005981#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00005982 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00005983#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00005984 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00005985 __throw_runtime_error("locale not supported");
5986 wbe = wbuf + j;
5987 __negative_sign_.assign(wbuf, wbe);
5988 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00005989 // Assume the positive and negative formats will want spaces in
5990 // the same places in curr_symbol since there's no way to
5991 // represent anything else.
5992 string_type __dummy_curr_symbol = __curr_symbol_;
5993 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5994 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5995 __init_pat(__neg_format_, __curr_symbol_, false,
5996 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantc51e1022010-05-11 19:42:16 +00005997}
5998
5999template<>
6000void
6001moneypunct_byname<wchar_t, true>::init(const char* nm)
6002{
6003 typedef moneypunct<wchar_t, true> base;
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006004 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnant72f73582010-08-11 17:04:31 +00006005#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant03de6f92012-03-07 20:37:43 +00006006 if (loc == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00006007 throw runtime_error("moneypunct_byname"
6008 " failed to construct for " + string(nm));
Howard Hinnantffb308e2010-08-22 00:03:27 +00006009#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006010#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006011 lconv* lc = localeconv_l(loc.get());
6012#else
6013 lconv* lc = __localeconv_l(loc.get());
6014#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006015 if (*lc->mon_decimal_point)
6016 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6017 else
6018 __decimal_point_ = base::do_decimal_point();
6019 if (*lc->mon_thousands_sep)
6020 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6021 else
6022 __thousands_sep_ = base::do_thousands_sep();
6023 __grouping_ = lc->mon_grouping;
6024 wchar_t wbuf[100];
6025 mbstate_t mb = {0};
6026 const char* bb = lc->int_curr_symbol;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006027#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006028 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006029#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006030 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006031#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006032 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006033 __throw_runtime_error("locale not supported");
6034 wchar_t* wbe = wbuf + j;
6035 __curr_symbol_.assign(wbuf, wbe);
6036 if (lc->int_frac_digits != CHAR_MAX)
6037 __frac_digits_ = lc->int_frac_digits;
6038 else
6039 __frac_digits_ = base::do_frac_digits();
Howard Hinnant8ad70912013-09-17 01:34:47 +00006040#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006041 if (lc->p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006042#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006043 if (lc->int_p_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006044#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006045 __positive_sign_ = L"()";
6046 else
6047 {
6048 mb = mbstate_t();
6049 bb = lc->positive_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006050#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006051 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006052#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006053 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006054#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006055 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006056 __throw_runtime_error("locale not supported");
6057 wbe = wbuf + j;
6058 __positive_sign_.assign(wbuf, wbe);
6059 }
Howard Hinnant8ad70912013-09-17 01:34:47 +00006060#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnanteb505f62011-09-23 16:11:27 +00006061 if (lc->n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006062#else // _LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006063 if (lc->int_n_sign_posn == 0)
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006064#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006065 __negative_sign_ = L"()";
6066 else
6067 {
6068 mb = mbstate_t();
6069 bb = lc->negative_sign;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00006070#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006071 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006072#else
Howard Hinnant3d2417c2012-12-27 21:17:53 +00006073 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00006074#endif
Howard Hinnant28b24882011-12-01 20:21:04 +00006075 if (j == size_t(-1))
Howard Hinnantc51e1022010-05-11 19:42:16 +00006076 __throw_runtime_error("locale not supported");
6077 wbe = wbuf + j;
6078 __negative_sign_.assign(wbuf, wbe);
6079 }
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006080 // Assume the positive and negative formats will want spaces in
6081 // the same places in curr_symbol since there's no way to
6082 // represent anything else.
6083 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant8ad70912013-09-17 01:34:47 +00006084#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006085 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6086 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6087 __init_pat(__neg_format_, __curr_symbol_, true,
6088 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006089#else // _LIBCPP_MSVCRT
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00006090 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6091 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6092 lc->int_p_sign_posn, L' ');
6093 __init_pat(__neg_format_, __curr_symbol_, true,
6094 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6095 lc->int_n_sign_posn, L' ');
Howard Hinnant13d8bc12013-08-01 18:17:34 +00006096#endif // !_LIBCPP_MSVCRT
Howard Hinnantc51e1022010-05-11 19:42:16 +00006097}
6098
6099void __do_nothing(void*) {}
6100
6101void __throw_runtime_error(const char* msg)
6102{
Howard Hinnant72f73582010-08-11 17:04:31 +00006103#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantc51e1022010-05-11 19:42:16 +00006104 throw runtime_error(msg);
Howard Hinnant417bc432013-03-28 18:56:26 +00006105#else
6106 (void)msg;
Howard Hinnant72f73582010-08-11 17:04:31 +00006107#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00006108}
6109
6110template class collate<char>;
6111template class collate<wchar_t>;
6112
6113template class num_get<char>;
6114template class num_get<wchar_t>;
6115
Howard Hinnant28b24882011-12-01 20:21:04 +00006116template struct __num_get<char>;
6117template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006118
6119template class num_put<char>;
6120template class num_put<wchar_t>;
6121
Howard Hinnant28b24882011-12-01 20:21:04 +00006122template struct __num_put<char>;
6123template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00006124
6125template class time_get<char>;
6126template class time_get<wchar_t>;
6127
6128template class time_get_byname<char>;
6129template class time_get_byname<wchar_t>;
6130
6131template class time_put<char>;
6132template class time_put<wchar_t>;
6133
6134template class time_put_byname<char>;
6135template class time_put_byname<wchar_t>;
6136
6137template class moneypunct<char, false>;
6138template class moneypunct<char, true>;
6139template class moneypunct<wchar_t, false>;
6140template class moneypunct<wchar_t, true>;
6141
6142template class moneypunct_byname<char, false>;
6143template class moneypunct_byname<char, true>;
6144template class moneypunct_byname<wchar_t, false>;
6145template class moneypunct_byname<wchar_t, true>;
6146
6147template class money_get<char>;
6148template class money_get<wchar_t>;
6149
6150template class __money_get<char>;
6151template class __money_get<wchar_t>;
6152
6153template class money_put<char>;
6154template class money_put<wchar_t>;
6155
6156template class __money_put<char>;
6157template class __money_put<wchar_t>;
6158
6159template class messages<char>;
6160template class messages<wchar_t>;
6161
6162template class messages_byname<char>;
6163template class messages_byname<wchar_t>;
6164
6165template class codecvt_byname<char, char, mbstate_t>;
6166template class codecvt_byname<wchar_t, char, mbstate_t>;
6167template class codecvt_byname<char16_t, char, mbstate_t>;
6168template class codecvt_byname<char32_t, char, mbstate_t>;
6169
6170template class __vector_base_common<true>;
6171
6172_LIBCPP_END_NAMESPACE_STD