blob: dafe14e8cdad6b5e1d274bce7601884ccec0c48d [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-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 Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
David Chisnall997e4542012-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 Hinnantbc8d3f92010-05-11 19:42:16 +000016#include "string"
17#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000018#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000019#include "vector"
20#include "algorithm"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000021#include "typeinfo"
Howard Hinnantb87922c2013-07-28 18:20:00 +000022#ifndef _LIBCPP_NO_EXCEPTIONS
23# include "type_traits"
24#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000025#include "clocale"
26#include "cstring"
27#include "cwctype"
28#include "__sso_allocator"
Howard Hinnantef5aa932013-09-17 01:34:47 +000029#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant14fa9f92011-09-29 20:33:10 +000030#include <support/win32/locale_win32.h>
Marshall Clowa6439262014-07-10 15:20:28 +000031#elif !defined(__ANDROID__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000032#include <langinfo.h>
Marshall Clowa6439262014-07-10 15:20:28 +000033#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000034#include <stdlib.h>
Howard Hinnanted14a762013-07-23 16:05:56 +000035#include <stdio.h>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036
Marshall Clow9ae96d02013-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 Clowa3645132013-10-21 15:07:28 +000039#if defined(__clang__)
Marshall Clow9ae96d02013-02-07 17:20:56 +000040#pragma clang diagnostic ignored "-Wsign-conversion"
Marshall Clowa3645132013-10-21 15:07:28 +000041#endif
Marshall Clow9ae96d02013-02-07 17:20:56 +000042
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000043_LIBCPP_BEGIN_NAMESPACE_STD
44
Howard Hinnant866569b2011-09-28 23:39:33 +000045#ifdef __cloc_defined
Sean Hunt62a6ac32011-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.
Sean Hunt62a6ac32011-07-09 00:56:23 +000050 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
51 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000052}
Howard Hinnant866569b2011-09-28 23:39:33 +000053#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000054
Howard Hinnantbc8d3f92010-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 Sonnenberger4c6acb52014-01-04 17:43:00 +000069 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-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 Sonnenberger4c6acb52014-01-04 17:43:00 +000079 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-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 Sonnenberger4c6acb52014-01-04 17:43:00 +000089 return *reinterpret_cast<T*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000090}
91
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000092template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000093inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000094_LIBCPP_CONSTEXPR
95size_t
96countof(const T (&)[N])
97{
98 return N;
99}
100
101template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +0000102inline
Howard Hinnantbf68bdc2012-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000110}
111
Howard Hinnant51437222013-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 Hinnant0a69fa12012-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 Clowa3645132013-10-21 15:07:28 +0000126#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000127#pragma clang diagnostic push
128#pragma clang diagnostic ignored "-Wpadded"
Marshall Clowa3645132013-10-21 15:07:28 +0000129#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000130
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131class _LIBCPP_HIDDEN locale::__imp
132 : public facet
133{
134 enum {N = 28};
Marshall Clowa3645132013-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000141 vector<facet*, __sso_allocator<facet*, N> > facets_;
Marshall Clowa3645132013-10-21 15:07:28 +0000142#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000143 string name_;
Howard Hinnantbc8d3f92010-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 Hinnantec3773c2011-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 Hinnantbc8d3f92010-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 Clowa3645132013-10-21 15:07:28 +0000166#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000167#pragma clang diagnostic pop
Marshall Clowa3645132013-10-21 15:07:28 +0000168#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +0000169
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000170locale::__imp::__imp(size_t refs)
171 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000172 facets_(N),
173 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000174{
175 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000176 install(&make<_VSTD::collate<char> >(1u));
177 install(&make<_VSTD::collate<wchar_t> >(1u));
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000178 install(&make<_VSTD::ctype<char> >(nullptr, false, 1u));
Howard Hinnantec3773c2011-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000204}
205
206locale::__imp::__imp(const string& name, size_t refs)
207 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000208 facets_(N),
209 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000210{
Howard Hinnantd4444702010-08-11 17:04:31 +0000211#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000212 try
213 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000214#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000239#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000248#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000249}
250
Howard Hinnant21772ec2012-12-28 18:15:01 +0000251// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000252// copy constructor` warning emitted by GCC
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000253#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000254#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000255#pragma GCC diagnostic ignored "-Wextra"
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000256#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000257
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000258locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000259 : facets_(max<size_t>(N, other.facets_.size())),
260 name_(other.name_)
Howard Hinnantbc8d3f92010-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 Sonnenbergere58bc122013-05-02 19:34:26 +0000268#if defined(__clang__) || _GNUC_VER >= 406
Howard Hinnant5f767b72012-12-27 23:24:31 +0000269#pragma GCC diagnostic pop
Joerg Sonnenbergere58bc122013-05-02 19:34:26 +0000270#endif
Howard Hinnant5f767b72012-12-27 23:24:31 +0000271
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000272locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000273 : facets_(N),
274 name_("*")
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000280#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000281 try
282 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000283#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000322#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000331#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantec3773c2011-12-01 20:21:04 +0000344 : facets_(N),
345 name_("*")
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000351#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000352 try
353 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000354#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000355 if (c & locale::collate)
356 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000357 install_from<_VSTD::collate<char> >(one);
358 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000359 }
360 if (c & locale::ctype)
361 {
Howard Hinnant0949eed2011-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 Hinnantbc8d3f92010-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 Hinnant0949eed2011-06-30 21:18:19 +0000398 install_from<_VSTD::messages<char> >(one);
399 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000400 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000401#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000410#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000411}
412
413locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000414 : facets_(max<size_t>(N, other.facets_.size()+1)),
415 name_("*")
Howard Hinnantbc8d3f92010-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 Hinnantec3773c2011-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000443}
444
445const locale::facet*
446locale::__imp::use_facet(long id) const
447{
Howard Hinnantd4444702010-08-11 17:04:31 +0000448#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000449 if (!has_facet(id))
450 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000451#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000452 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-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 Sonnenberger4c6acb52014-01-04 17:43:00 +0000462 locale* c = reinterpret_cast<locale*>(&buf);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000463 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000479 ::new (&buf) locale(locale::classic());
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000480 return *reinterpret_cast<locale*>(&buf);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000481}
482
483locale&
484locale::__global()
485{
486 static locale& g = __imp::make_global();
487 return g;
488}
489
Howard Hinnantc9834542011-05-31 15:34:58 +0000490locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000491 : __locale_(__global().__locale_)
492{
493 __locale_->__add_shared();
494}
495
Howard Hinnantc9834542011-05-31 15:34:58 +0000496locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000497 : __locale_(l.__locale_)
498{
499 __locale_->__add_shared();
500}
501
Howard Hinnantc9834542011-05-31 15:34:58 +0000502locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000503{
504 __locale_->__release_shared();
505}
506
507const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000508locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000517#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000518 : __locale_(name ? new __imp(name)
519 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000520#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000521 : __locale_(new __imp(name))
522#endif
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000534#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000535 : __locale_(name ? new __imp(*other.__locale_, name, c)
536 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000537#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000538 : __locale_(new __imp(*other.__locale_, name, c))
539#endif
Howard Hinnantbc8d3f92010-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 Hinnant1694d232011-05-28 14:41:13 +0000609locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-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 Hinnantadff4892010-05-24 17:49:41 +0000647 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000656#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000660#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000667#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000671#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000708#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000712#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnantd4444702010-08-11 17:04:31 +0000719#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant16e6e1d2010-08-22 00:03:27 +0000723#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-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 Hinnant0a69fa12012-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 Hinnantbc8d3f92010-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 Clowa3645132013-10-21 15:07:28 +0000778 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantbc8d3f92010-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)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000785 *vec = static_cast<mask>(isascii(*low) ?
786 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-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)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000794 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-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)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000803 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-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 Hinnant3c466fc2011-09-29 13:33:15 +0000811#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
812 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000813#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000814 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000815#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000816 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000817#endif
Howard Hinnantbc8d3f92010-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 Hinnant3c466fc2011-09-29 13:33:15 +0000824#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
825 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000826#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000827 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
828 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000829#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000830 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000831#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000832 return low;
833}
834
835wchar_t
836ctype<wchar_t>::do_tolower(char_type c) const
837{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000838#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
839 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000840#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000841 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000842#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000843 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000844#endif
Howard Hinnantbc8d3f92010-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 Hinnant3c466fc2011-09-29 13:33:15 +0000851#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
852 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000853#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000854 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
855 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000856#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000857 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000858#endif
Howard Hinnantbc8d3f92010-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 Hinnantec3773c2011-12-01 20:21:04 +0000889 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-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{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000904 if (__tab_ == 0)
905 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-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 Hinnant3c466fc2011-09-29 13:33:15 +0000917#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000918 return isascii(c) ?
919 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000920#elif defined(__NetBSD__)
921 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000922#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000923 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000924 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000925#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000926 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000927#endif
Howard Hinnantbc8d3f92010-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 Hinnant3c466fc2011-09-29 13:33:15 +0000934#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000935 *low = isascii(*low) ?
936 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000937#elif defined(__NetBSD__)
938 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000939#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000940 *low = isascii(*low) ?
941 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000942#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000943 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000944#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000945 return low;
946}
947
948char
949ctype<char>::do_tolower(char_type c) const
950{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000951#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000952 return isascii(c) ?
953 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000954#elif defined(__NetBSD__)
955 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000956#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000957 return isascii(c) ?
958 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000959#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000960 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000961#endif
Howard Hinnantbc8d3f92010-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 Hinnant3c466fc2011-09-29 13:33:15 +0000968#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000969 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000970#elif defined(__NetBSD__)
971 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000972#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000973 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000974#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000975 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000976#endif
Howard Hinnantbc8d3f92010-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 Clow2ccffef2013-11-19 18:05:03 +00001013#ifdef __EMSCRIPTEN__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001014extern "C" const unsigned short ** __ctype_b_loc();
1015extern "C" const int ** __ctype_tolower_loc();
1016extern "C" const int ** __ctype_toupper_loc();
1017#endif
1018
Marshall Clowe917d802015-03-04 16:50:02 +00001019#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clow8291a762015-03-04 16:10:14 +00001020const ctype<char>::mask*
1021ctype<char>::classic_table() _NOEXCEPT
1022{
1023 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1024 cntrl, cntrl,
1025 cntrl, cntrl,
1026 cntrl, cntrl,
1027 cntrl, cntrl,
1028 cntrl, cntrl | space | blank,
1029 cntrl | space, cntrl | space,
1030 cntrl | space, cntrl | space,
1031 cntrl, cntrl,
1032 cntrl, cntrl,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl,
1040 space | blank | print, punct | print,
1041 punct | print, punct | print,
1042 punct | print, punct | print,
1043 punct | print, punct | print,
1044 punct | print, punct | print,
1045 punct | print, punct | print,
1046 punct | print, punct | print,
1047 punct | print, punct | print,
1048 digit | print | xdigit, digit | print | xdigit,
1049 digit | print | xdigit, digit | print | xdigit,
1050 digit | print | xdigit, digit | print | xdigit,
1051 digit | print | xdigit, digit | print | xdigit,
1052 digit | print | xdigit, digit | print | xdigit,
1053 punct | print, punct | print,
1054 punct | print, punct | print,
1055 punct | print, punct | print,
1056 punct | print, upper | xdigit | print | alpha,
1057 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1058 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1059 upper | xdigit | print | alpha, upper | print | alpha,
1060 upper | print | alpha, upper | print | alpha,
1061 upper | print | alpha, upper | print | alpha,
1062 upper | print | alpha, upper | print | alpha,
1063 upper | print | alpha, upper | print | alpha,
1064 upper | print | alpha, upper | print | alpha,
1065 upper | print | alpha, upper | print | alpha,
1066 upper | print | alpha, upper | print | alpha,
1067 upper | print | alpha, upper | print | alpha,
1068 upper | print | alpha, upper | print | alpha,
1069 upper | print | alpha, punct | print,
1070 punct | print, punct | print,
1071 punct | print, punct | print,
1072 punct | print, lower | xdigit | print | alpha,
1073 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1074 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1075 lower | xdigit | print | alpha, lower | print | alpha,
1076 lower | print | alpha, lower | print | alpha,
1077 lower | print | alpha, lower | print | alpha,
1078 lower | print | alpha, lower | print | alpha,
1079 lower | print | alpha, lower | print | alpha,
1080 lower | print | alpha, lower | print | alpha,
1081 lower | print | alpha, lower | print | alpha,
1082 lower | print | alpha, lower | print | alpha,
1083 lower | print | alpha, lower | print | alpha,
1084 lower | print | alpha, lower | print | alpha,
1085 lower | print | alpha, punct | print,
1086 punct | print, punct | print,
1087 punct | print, cntrl,
1088 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1089 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1090 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1091 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1092 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1093 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1094 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1095 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1096 };
1097 return builtin_table;
1098}
1099#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001100const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001101ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001102{
David Chisnallc512df12011-09-21 08:39:44 +00001103#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001104 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001105#elif defined(__NetBSD__)
1106 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001107#elif defined(__GLIBC__)
1108 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001109#elif __sun__
1110 return __ctype_mask;
Howard Hinnantef5aa932013-09-17 01:34:47 +00001111#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001112 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001113// This is assumed to be safe, which is a nonsense assumption because we're
1114// going to end up dereferencing it later...
Marshall Clow2ccffef2013-11-19 18:05:03 +00001115#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001116 return *__ctype_b_loc();
JF Bastiena14f7cb2015-02-25 22:16:46 +00001117#elif defined(_NEWLIB_VERSION)
1118 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1119 return _ctype_ + 1;
Howard Hinnant7f764502013-08-14 18:00:20 +00001120#elif defined(_AIX)
Marshall Clow016d4e82013-11-19 19:16:03 +00001121 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001122#else
David Chisnall997e4542012-02-29 13:05:08 +00001123 // Platform not supported: abort so the person doing the port knows what to
1124 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001125# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001126 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001127 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001128 return NULL;
1129#endif
1130}
Marshall Clow8291a762015-03-04 16:10:14 +00001131#endif
Sean Hunt62a6ac32011-07-09 00:56:23 +00001132
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001133#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001134const int*
1135ctype<char>::__classic_lower_table() _NOEXCEPT
1136{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001137 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001138}
1139
1140const int*
1141ctype<char>::__classic_upper_table() _NOEXCEPT
1142{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001143 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001144}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001145#elif __NetBSD__
1146const short*
1147ctype<char>::__classic_lower_table() _NOEXCEPT
1148{
1149 return _C_tolower_tab_ + 1;
1150}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001151
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001152const short*
1153ctype<char>::__classic_upper_table() _NOEXCEPT
1154{
1155 return _C_toupper_tab_ + 1;
1156}
1157
Marshall Clow2ccffef2013-11-19 18:05:03 +00001158#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001159const int*
1160ctype<char>::__classic_lower_table() _NOEXCEPT
1161{
1162 return *__ctype_tolower_loc();
1163}
1164
1165const int*
1166ctype<char>::__classic_upper_table() _NOEXCEPT
1167{
1168 return *__ctype_toupper_loc();
1169}
Marshall Clow2ccffef2013-11-19 18:05:03 +00001170#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001171
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172// template <> class ctype_byname<char>
1173
1174ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1175 : ctype<char>(0, false, refs),
1176 __l(newlocale(LC_ALL_MASK, name, 0))
1177{
Howard Hinnantd4444702010-08-11 17:04:31 +00001178#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001179 if (__l == 0)
1180 throw runtime_error("ctype_byname<char>::ctype_byname"
1181 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001182#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001183}
1184
1185ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1186 : ctype<char>(0, false, refs),
1187 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1188{
Howard Hinnantd4444702010-08-11 17:04:31 +00001189#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001190 if (__l == 0)
1191 throw runtime_error("ctype_byname<char>::ctype_byname"
1192 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001193#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001194}
1195
1196ctype_byname<char>::~ctype_byname()
1197{
1198 freelocale(__l);
1199}
1200
1201char
1202ctype_byname<char>::do_toupper(char_type c) const
1203{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001204 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001205}
1206
1207const char*
1208ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1209{
1210 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001211 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 return low;
1213}
1214
1215char
1216ctype_byname<char>::do_tolower(char_type c) const
1217{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001218 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001219}
1220
1221const char*
1222ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1223{
1224 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001225 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001226 return low;
1227}
1228
1229// template <> class ctype_byname<wchar_t>
1230
1231ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1232 : ctype<wchar_t>(refs),
1233 __l(newlocale(LC_ALL_MASK, name, 0))
1234{
Howard Hinnantd4444702010-08-11 17:04:31 +00001235#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001236 if (__l == 0)
1237 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1238 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001239#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240}
1241
1242ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1243 : ctype<wchar_t>(refs),
1244 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1245{
Howard Hinnantd4444702010-08-11 17:04:31 +00001246#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001247 if (__l == 0)
1248 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1249 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001250#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001251}
1252
1253ctype_byname<wchar_t>::~ctype_byname()
1254{
1255 freelocale(__l);
1256}
1257
1258bool
1259ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1260{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001261#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001262 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001263#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001264 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001265 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001266 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1267 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1268 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1269 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1270 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1271 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1272 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1273 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1274 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1275 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001276 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001277#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001278}
1279
1280const wchar_t*
1281ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1282{
1283 for (; low != high; ++low, ++vec)
1284 {
1285 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001286 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001287 else
1288 {
1289 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001290 wint_t ch = static_cast<wint_t>(*low);
1291 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001292 *vec |= space;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001293#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clow88c31902013-02-07 14:22:51 +00001294 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001295 *vec |= print;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001296#endif
Marshall Clow88c31902013-02-07 14:22:51 +00001297 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001298 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001299 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001300 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001301 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001302 *vec |= lower;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001303#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clow88c31902013-02-07 14:22:51 +00001304 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001305 *vec |= alpha;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001306#endif
Marshall Clow88c31902013-02-07 14:22:51 +00001307 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001308 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001309 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001310 *vec |= punct;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001311#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clow88c31902013-02-07 14:22:51 +00001312 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001313 *vec |= xdigit;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001314#endif
Jonathan Roelofsf77031d2015-03-13 15:09:42 +00001315#if !defined(__sun__)
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001316 if (iswblank_l(ch, __l))
1317 *vec |= blank;
Jonathan Roelofsf77031d2015-03-13 15:09:42 +00001318#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319 }
1320 }
1321 return low;
1322}
1323
1324const wchar_t*
1325ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1326{
1327 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001328 {
1329#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001330 if (iswctype_l(*low, m, __l))
1331 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001332#else
Marshall Clow88c31902013-02-07 14:22:51 +00001333 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001334 if ((m & space) == space && iswspace_l(ch, __l)) break;
1335 if ((m & print) == print && iswprint_l(ch, __l)) break;
1336 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1337 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1338 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1339 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1340 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1341 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1342 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1343 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001344#endif
1345 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001346 return low;
1347}
1348
1349const wchar_t*
1350ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1351{
1352 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001353 {
1354#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001355 if (!iswctype_l(*low, m, __l))
1356 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001357#else
Marshall Clow88c31902013-02-07 14:22:51 +00001358 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001359 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1360 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1361 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1362 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1363 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1364 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1365 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1366 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1367 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1368 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001369 break;
1370#endif
1371 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001372 return low;
1373}
1374
1375wchar_t
1376ctype_byname<wchar_t>::do_toupper(char_type c) const
1377{
1378 return towupper_l(c, __l);
1379}
1380
1381const wchar_t*
1382ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1383{
1384 for (; low != high; ++low)
1385 *low = towupper_l(*low, __l);
1386 return low;
1387}
1388
1389wchar_t
1390ctype_byname<wchar_t>::do_tolower(char_type c) const
1391{
1392 return towlower_l(c, __l);
1393}
1394
1395const wchar_t*
1396ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1397{
1398 for (; low != high; ++low)
1399 *low = towlower_l(*low, __l);
1400 return low;
1401}
1402
1403wchar_t
1404ctype_byname<wchar_t>::do_widen(char c) const
1405{
Howard Hinnant866569b2011-09-28 23:39:33 +00001406#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001407 return btowc_l(c, __l);
1408#else
1409 return __btowc_l(c, __l);
1410#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001411}
1412
1413const char*
1414ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1415{
1416 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001417#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001418 *dest = btowc_l(*low, __l);
1419#else
1420 *dest = __btowc_l(*low, __l);
1421#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001422 return low;
1423}
1424
1425char
1426ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1427{
Howard Hinnant866569b2011-09-28 23:39:33 +00001428#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001429 int r = wctob_l(c, __l);
1430#else
1431 int r = __wctob_l(c, __l);
1432#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001433 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001434}
1435
1436const wchar_t*
1437ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1438{
1439 for (; low != high; ++low, ++dest)
1440 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001441#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001442 int r = wctob_l(*low, __l);
1443#else
1444 int r = __wctob_l(*low, __l);
1445#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001446 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001447 }
1448 return low;
1449}
1450
1451// template <> class codecvt<char, char, mbstate_t>
1452
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001453locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001454
1455codecvt<char, char, mbstate_t>::~codecvt()
1456{
1457}
1458
1459codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001460codecvt<char, char, mbstate_t>::do_out(state_type&,
1461 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001462 extern_type* to, extern_type*, extern_type*& to_nxt) const
1463{
1464 frm_nxt = frm;
1465 to_nxt = to;
1466 return noconv;
1467}
1468
1469codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001470codecvt<char, char, mbstate_t>::do_in(state_type&,
1471 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472 intern_type* to, intern_type*, intern_type*& to_nxt) const
1473{
1474 frm_nxt = frm;
1475 to_nxt = to;
1476 return noconv;
1477}
1478
1479codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001480codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001481 extern_type* to, extern_type*, extern_type*& to_nxt) const
1482{
1483 to_nxt = to;
1484 return noconv;
1485}
1486
1487int
Howard Hinnantc9834542011-05-31 15:34:58 +00001488codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001489{
1490 return 1;
1491}
1492
1493bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001494codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001495{
1496 return true;
1497}
1498
1499int
1500codecvt<char, char, mbstate_t>::do_length(state_type&,
1501 const extern_type* frm, const extern_type* end, size_t mx) const
1502{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001503 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001504}
1505
1506int
Howard Hinnantc9834542011-05-31 15:34:58 +00001507codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508{
1509 return 1;
1510}
1511
1512// template <> class codecvt<wchar_t, char, mbstate_t>
1513
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001514locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001515
1516codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1517 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001518 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001519{
1520}
1521
1522codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1523 : locale::facet(refs),
1524 __l(newlocale(LC_ALL_MASK, nm, 0))
1525{
Howard Hinnantd4444702010-08-11 17:04:31 +00001526#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001527 if (__l == 0)
1528 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1529 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001530#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001531}
1532
1533codecvt<wchar_t, char, mbstate_t>::~codecvt()
1534{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001535 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001536 freelocale(__l);
1537}
1538
1539codecvt<wchar_t, char, mbstate_t>::result
1540codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001541 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001542 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1543{
1544 // look for first internal null in frm
1545 const intern_type* fend = frm;
1546 for (; fend != frm_end; ++fend)
1547 if (*fend == 0)
1548 break;
1549 // loop over all null-terminated sequences in frm
1550 to_nxt = to;
1551 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1552 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001553 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001554 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001555#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001556 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1557 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001558#else
1559 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1560#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001561 if (n == size_t(-1))
1562 {
1563 // need to recover to_nxt
1564 for (to_nxt = to; frm != frm_nxt; ++frm)
1565 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001566#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001567 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1568#else
1569 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1570#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001571 if (n == size_t(-1))
1572 break;
1573 to_nxt += n;
1574 }
1575 frm_nxt = frm;
1576 return error;
1577 }
1578 if (n == 0)
1579 return partial;
1580 to_nxt += n;
1581 if (to_nxt == to_end)
1582 break;
1583 if (fend != frm_end) // set up next null terminated sequence
1584 {
1585 // Try to write the terminating null
1586 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001587#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001588 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1589#else
1590 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1591#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001592 if (n == size_t(-1)) // on error
1593 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001594 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001595 return partial;
1596 for (extern_type* p = tmp; n; --n) // write it
1597 *to_nxt++ = *p++;
1598 ++frm_nxt;
1599 // look for next null in frm
1600 for (fend = frm_nxt; fend != frm_end; ++fend)
1601 if (*fend == 0)
1602 break;
1603 }
1604 }
1605 return frm_nxt == frm_end ? ok : partial;
1606}
1607
1608codecvt<wchar_t, char, mbstate_t>::result
1609codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001610 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001611 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1612{
1613 // look for first internal null in frm
1614 const extern_type* fend = frm;
1615 for (; fend != frm_end; ++fend)
1616 if (*fend == 0)
1617 break;
1618 // loop over all null-terminated sequences in frm
1619 to_nxt = to;
1620 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1621 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001622 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001623 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001624#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001625 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1626 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001627#else
1628 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1629#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001630 if (n == size_t(-1))
1631 {
1632 // need to recover to_nxt
1633 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1634 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001635#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001636 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1637 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001638#else
1639 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1640#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001641 switch (n)
1642 {
1643 case 0:
1644 ++frm;
1645 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001646 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001647 frm_nxt = frm;
1648 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001649 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001650 frm_nxt = frm;
1651 return partial;
1652 default:
1653 frm += n;
1654 break;
1655 }
1656 }
1657 frm_nxt = frm;
1658 return frm_nxt == frm_end ? ok : partial;
1659 }
Joerg Sonnenberger64c62482015-06-05 15:54:26 +00001660 if (n == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001661 return error;
1662 to_nxt += n;
1663 if (to_nxt == to_end)
1664 break;
1665 if (fend != frm_end) // set up next null terminated sequence
1666 {
1667 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001668#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001669 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1670#else
1671 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1672#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001673 if (n != 0) // on error
1674 return error;
1675 ++to_nxt;
1676 ++frm_nxt;
1677 // look for next null in frm
1678 for (fend = frm_nxt; fend != frm_end; ++fend)
1679 if (*fend == 0)
1680 break;
1681 }
1682 }
1683 return frm_nxt == frm_end ? ok : partial;
1684}
1685
1686codecvt<wchar_t, char, mbstate_t>::result
1687codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1688 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1689{
1690 to_nxt = to;
1691 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001692#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001693 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1694#else
1695 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1696#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001697 if (n == size_t(-1) || n == 0) // on error
1698 return error;
1699 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001700 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001701 return partial;
1702 for (extern_type* p = tmp; n; --n) // write it
1703 *to_nxt++ = *p++;
1704 return ok;
1705}
1706
1707int
Howard Hinnantc9834542011-05-31 15:34:58 +00001708codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001709{
Howard Hinnant866569b2011-09-28 23:39:33 +00001710#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001711 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001712#else
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001713 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) == 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001714#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001715 {
1716 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001717#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001718 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1719#else
1720 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1721#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001722 return 1; // which take more than 1 char to form a wchar_t
1723 return 0;
1724 }
1725 return -1;
1726}
1727
1728bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001729codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001730{
1731 return false;
1732}
1733
1734int
1735codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1736 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1737{
1738 int nbytes = 0;
1739 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1740 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001741#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001742 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001743#else
1744 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1745#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001746 switch (n)
1747 {
1748 case 0:
1749 ++nbytes;
1750 ++frm;
1751 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001752 case size_t(-1):
1753 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001754 return nbytes;
1755 default:
1756 nbytes += n;
1757 frm += n;
1758 break;
1759 }
1760 }
1761 return nbytes;
1762}
1763
1764int
Howard Hinnantc9834542011-05-31 15:34:58 +00001765codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001766{
Howard Hinnant866569b2011-09-28 23:39:33 +00001767#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001768 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001769#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001770 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001771#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001772}
1773
1774// Valid UTF ranges
1775// UTF-32 UTF-16 UTF-8 # of code points
1776// first second first second third fourth
1777// 000000 - 00007F 0000 - 007F 00 - 7F 127
1778// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1779// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1780// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1781// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1782// 00D800 - 00DFFF invalid
1783// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1784// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1785// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1786// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1787
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001788static
1789codecvt_base::result
1790utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1791 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1792 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1793{
1794 frm_nxt = frm;
1795 to_nxt = to;
1796 if (mode & generate_header)
1797 {
1798 if (to_end-to_nxt < 3)
1799 return codecvt_base::partial;
1800 *to_nxt++ = static_cast<uint8_t>(0xEF);
1801 *to_nxt++ = static_cast<uint8_t>(0xBB);
1802 *to_nxt++ = static_cast<uint8_t>(0xBF);
1803 }
1804 for (; frm_nxt < frm_end; ++frm_nxt)
1805 {
1806 uint16_t wc1 = *frm_nxt;
1807 if (wc1 > Maxcode)
1808 return codecvt_base::error;
1809 if (wc1 < 0x0080)
1810 {
1811 if (to_end-to_nxt < 1)
1812 return codecvt_base::partial;
1813 *to_nxt++ = static_cast<uint8_t>(wc1);
1814 }
1815 else if (wc1 < 0x0800)
1816 {
1817 if (to_end-to_nxt < 2)
1818 return codecvt_base::partial;
1819 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1820 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1821 }
1822 else if (wc1 < 0xD800)
1823 {
1824 if (to_end-to_nxt < 3)
1825 return codecvt_base::partial;
1826 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1827 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1828 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1829 }
1830 else if (wc1 < 0xDC00)
1831 {
1832 if (frm_end-frm_nxt < 2)
1833 return codecvt_base::partial;
1834 uint16_t wc2 = frm_nxt[1];
1835 if ((wc2 & 0xFC00) != 0xDC00)
1836 return codecvt_base::error;
1837 if (to_end-to_nxt < 4)
1838 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001839 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1840 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001841 return codecvt_base::error;
1842 ++frm_nxt;
1843 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1844 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1845 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1846 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1847 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1848 }
1849 else if (wc1 < 0xE000)
1850 {
1851 return codecvt_base::error;
1852 }
1853 else
1854 {
1855 if (to_end-to_nxt < 3)
1856 return codecvt_base::partial;
1857 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1858 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1859 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1860 }
1861 }
1862 return codecvt_base::ok;
1863}
1864
1865static
1866codecvt_base::result
1867utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1868 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1869 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1870{
1871 frm_nxt = frm;
1872 to_nxt = to;
1873 if (mode & generate_header)
1874 {
1875 if (to_end-to_nxt < 3)
1876 return codecvt_base::partial;
1877 *to_nxt++ = static_cast<uint8_t>(0xEF);
1878 *to_nxt++ = static_cast<uint8_t>(0xBB);
1879 *to_nxt++ = static_cast<uint8_t>(0xBF);
1880 }
1881 for (; frm_nxt < frm_end; ++frm_nxt)
1882 {
1883 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1884 if (wc1 > Maxcode)
1885 return codecvt_base::error;
1886 if (wc1 < 0x0080)
1887 {
1888 if (to_end-to_nxt < 1)
1889 return codecvt_base::partial;
1890 *to_nxt++ = static_cast<uint8_t>(wc1);
1891 }
1892 else if (wc1 < 0x0800)
1893 {
1894 if (to_end-to_nxt < 2)
1895 return codecvt_base::partial;
1896 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1897 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1898 }
1899 else if (wc1 < 0xD800)
1900 {
1901 if (to_end-to_nxt < 3)
1902 return codecvt_base::partial;
1903 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1904 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1905 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1906 }
1907 else if (wc1 < 0xDC00)
1908 {
1909 if (frm_end-frm_nxt < 2)
1910 return codecvt_base::partial;
1911 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1912 if ((wc2 & 0xFC00) != 0xDC00)
1913 return codecvt_base::error;
1914 if (to_end-to_nxt < 4)
1915 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001916 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1917 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001918 return codecvt_base::error;
1919 ++frm_nxt;
1920 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1921 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1922 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1923 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1924 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1925 }
1926 else if (wc1 < 0xE000)
1927 {
1928 return codecvt_base::error;
1929 }
1930 else
1931 {
1932 if (to_end-to_nxt < 3)
1933 return codecvt_base::partial;
1934 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1935 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1936 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1937 }
1938 }
1939 return codecvt_base::ok;
1940}
1941
1942static
1943codecvt_base::result
1944utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1945 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1946 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1947{
1948 frm_nxt = frm;
1949 to_nxt = to;
1950 if (mode & consume_header)
1951 {
1952 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1953 frm_nxt[2] == 0xBF)
1954 frm_nxt += 3;
1955 }
1956 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1957 {
1958 uint8_t c1 = *frm_nxt;
1959 if (c1 > Maxcode)
1960 return codecvt_base::error;
1961 if (c1 < 0x80)
1962 {
1963 *to_nxt = static_cast<uint16_t>(c1);
1964 ++frm_nxt;
1965 }
1966 else if (c1 < 0xC2)
1967 {
1968 return codecvt_base::error;
1969 }
1970 else if (c1 < 0xE0)
1971 {
1972 if (frm_end-frm_nxt < 2)
1973 return codecvt_base::partial;
1974 uint8_t c2 = frm_nxt[1];
1975 if ((c2 & 0xC0) != 0x80)
1976 return codecvt_base::error;
1977 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1978 if (t > Maxcode)
1979 return codecvt_base::error;
1980 *to_nxt = t;
1981 frm_nxt += 2;
1982 }
1983 else if (c1 < 0xF0)
1984 {
1985 if (frm_end-frm_nxt < 3)
1986 return codecvt_base::partial;
1987 uint8_t c2 = frm_nxt[1];
1988 uint8_t c3 = frm_nxt[2];
1989 switch (c1)
1990 {
1991 case 0xE0:
1992 if ((c2 & 0xE0) != 0xA0)
1993 return codecvt_base::error;
1994 break;
1995 case 0xED:
1996 if ((c2 & 0xE0) != 0x80)
1997 return codecvt_base::error;
1998 break;
1999 default:
2000 if ((c2 & 0xC0) != 0x80)
2001 return codecvt_base::error;
2002 break;
2003 }
2004 if ((c3 & 0xC0) != 0x80)
2005 return codecvt_base::error;
2006 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2007 | ((c2 & 0x3F) << 6)
2008 | (c3 & 0x3F));
2009 if (t > Maxcode)
2010 return codecvt_base::error;
2011 *to_nxt = t;
2012 frm_nxt += 3;
2013 }
2014 else if (c1 < 0xF5)
2015 {
2016 if (frm_end-frm_nxt < 4)
2017 return codecvt_base::partial;
2018 uint8_t c2 = frm_nxt[1];
2019 uint8_t c3 = frm_nxt[2];
2020 uint8_t c4 = frm_nxt[3];
2021 switch (c1)
2022 {
2023 case 0xF0:
2024 if (!(0x90 <= c2 && c2 <= 0xBF))
2025 return codecvt_base::error;
2026 break;
2027 case 0xF4:
2028 if ((c2 & 0xF0) != 0x80)
2029 return codecvt_base::error;
2030 break;
2031 default:
2032 if ((c2 & 0xC0) != 0x80)
2033 return codecvt_base::error;
2034 break;
2035 }
2036 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2037 return codecvt_base::error;
2038 if (to_end-to_nxt < 2)
2039 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002040 if ((((c1 & 7UL) << 18) +
2041 ((c2 & 0x3FUL) << 12) +
2042 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002043 return codecvt_base::error;
2044 *to_nxt = static_cast<uint16_t>(
2045 0xD800
2046 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2047 | ((c2 & 0x0F) << 2)
2048 | ((c3 & 0x30) >> 4));
2049 *++to_nxt = static_cast<uint16_t>(
2050 0xDC00
2051 | ((c3 & 0x0F) << 6)
2052 | (c4 & 0x3F));
2053 frm_nxt += 4;
2054 }
2055 else
2056 {
2057 return codecvt_base::error;
2058 }
2059 }
2060 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2061}
2062
2063static
2064codecvt_base::result
2065utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2066 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2067 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2068{
2069 frm_nxt = frm;
2070 to_nxt = to;
2071 if (mode & consume_header)
2072 {
2073 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2074 frm_nxt[2] == 0xBF)
2075 frm_nxt += 3;
2076 }
2077 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2078 {
2079 uint8_t c1 = *frm_nxt;
2080 if (c1 > Maxcode)
2081 return codecvt_base::error;
2082 if (c1 < 0x80)
2083 {
2084 *to_nxt = static_cast<uint32_t>(c1);
2085 ++frm_nxt;
2086 }
2087 else if (c1 < 0xC2)
2088 {
2089 return codecvt_base::error;
2090 }
2091 else if (c1 < 0xE0)
2092 {
2093 if (frm_end-frm_nxt < 2)
2094 return codecvt_base::partial;
2095 uint8_t c2 = frm_nxt[1];
2096 if ((c2 & 0xC0) != 0x80)
2097 return codecvt_base::error;
2098 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2099 if (t > Maxcode)
2100 return codecvt_base::error;
2101 *to_nxt = static_cast<uint32_t>(t);
2102 frm_nxt += 2;
2103 }
2104 else if (c1 < 0xF0)
2105 {
2106 if (frm_end-frm_nxt < 3)
2107 return codecvt_base::partial;
2108 uint8_t c2 = frm_nxt[1];
2109 uint8_t c3 = frm_nxt[2];
2110 switch (c1)
2111 {
2112 case 0xE0:
2113 if ((c2 & 0xE0) != 0xA0)
2114 return codecvt_base::error;
2115 break;
2116 case 0xED:
2117 if ((c2 & 0xE0) != 0x80)
2118 return codecvt_base::error;
2119 break;
2120 default:
2121 if ((c2 & 0xC0) != 0x80)
2122 return codecvt_base::error;
2123 break;
2124 }
2125 if ((c3 & 0xC0) != 0x80)
2126 return codecvt_base::error;
2127 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2128 | ((c2 & 0x3F) << 6)
2129 | (c3 & 0x3F));
2130 if (t > Maxcode)
2131 return codecvt_base::error;
2132 *to_nxt = static_cast<uint32_t>(t);
2133 frm_nxt += 3;
2134 }
2135 else if (c1 < 0xF5)
2136 {
2137 if (frm_end-frm_nxt < 4)
2138 return codecvt_base::partial;
2139 uint8_t c2 = frm_nxt[1];
2140 uint8_t c3 = frm_nxt[2];
2141 uint8_t c4 = frm_nxt[3];
2142 switch (c1)
2143 {
2144 case 0xF0:
2145 if (!(0x90 <= c2 && c2 <= 0xBF))
2146 return codecvt_base::error;
2147 break;
2148 case 0xF4:
2149 if ((c2 & 0xF0) != 0x80)
2150 return codecvt_base::error;
2151 break;
2152 default:
2153 if ((c2 & 0xC0) != 0x80)
2154 return codecvt_base::error;
2155 break;
2156 }
2157 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2158 return codecvt_base::error;
2159 if (to_end-to_nxt < 2)
2160 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002161 if ((((c1 & 7UL) << 18) +
2162 ((c2 & 0x3FUL) << 12) +
2163 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002164 return codecvt_base::error;
2165 *to_nxt = static_cast<uint32_t>(
2166 0xD800
2167 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2168 | ((c2 & 0x0F) << 2)
2169 | ((c3 & 0x30) >> 4));
2170 *++to_nxt = static_cast<uint32_t>(
2171 0xDC00
2172 | ((c3 & 0x0F) << 6)
2173 | (c4 & 0x3F));
2174 frm_nxt += 4;
2175 }
2176 else
2177 {
2178 return codecvt_base::error;
2179 }
2180 }
2181 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2182}
2183
2184static
2185int
2186utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2187 size_t mx, unsigned long Maxcode = 0x10FFFF,
2188 codecvt_mode mode = codecvt_mode(0))
2189{
2190 const uint8_t* frm_nxt = frm;
2191 if (mode & consume_header)
2192 {
2193 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2194 frm_nxt[2] == 0xBF)
2195 frm_nxt += 3;
2196 }
2197 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2198 {
2199 uint8_t c1 = *frm_nxt;
2200 if (c1 > Maxcode)
2201 break;
2202 if (c1 < 0x80)
2203 {
2204 ++frm_nxt;
2205 }
2206 else if (c1 < 0xC2)
2207 {
2208 break;
2209 }
2210 else if (c1 < 0xE0)
2211 {
2212 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2213 break;
2214 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2215 if (t > Maxcode)
2216 break;
2217 frm_nxt += 2;
2218 }
2219 else if (c1 < 0xF0)
2220 {
2221 if (frm_end-frm_nxt < 3)
2222 break;
2223 uint8_t c2 = frm_nxt[1];
2224 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002225 switch (c1)
2226 {
2227 case 0xE0:
2228 if ((c2 & 0xE0) != 0xA0)
2229 return static_cast<int>(frm_nxt - frm);
2230 break;
2231 case 0xED:
2232 if ((c2 & 0xE0) != 0x80)
2233 return static_cast<int>(frm_nxt - frm);
2234 break;
2235 default:
2236 if ((c2 & 0xC0) != 0x80)
2237 return static_cast<int>(frm_nxt - frm);
2238 break;
2239 }
2240 if ((c3 & 0xC0) != 0x80)
2241 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002242 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002243 break;
2244 frm_nxt += 3;
2245 }
2246 else if (c1 < 0xF5)
2247 {
2248 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2249 break;
2250 uint8_t c2 = frm_nxt[1];
2251 uint8_t c3 = frm_nxt[2];
2252 uint8_t c4 = frm_nxt[3];
2253 switch (c1)
2254 {
2255 case 0xF0:
2256 if (!(0x90 <= c2 && c2 <= 0xBF))
2257 return static_cast<int>(frm_nxt - frm);
2258 break;
2259 case 0xF4:
2260 if ((c2 & 0xF0) != 0x80)
2261 return static_cast<int>(frm_nxt - frm);
2262 break;
2263 default:
2264 if ((c2 & 0xC0) != 0x80)
2265 return static_cast<int>(frm_nxt - frm);
2266 break;
2267 }
2268 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2269 break;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002270 if ((((c1 & 7UL) << 18) +
2271 ((c2 & 0x3FUL) << 12) +
2272 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002273 break;
2274 ++nchar16_t;
2275 frm_nxt += 4;
2276 }
2277 else
2278 {
2279 break;
2280 }
2281 }
2282 return static_cast<int>(frm_nxt - frm);
2283}
2284
2285static
2286codecvt_base::result
2287ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2288 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2289 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2290{
2291 frm_nxt = frm;
2292 to_nxt = to;
2293 if (mode & generate_header)
2294 {
2295 if (to_end-to_nxt < 3)
2296 return codecvt_base::partial;
2297 *to_nxt++ = static_cast<uint8_t>(0xEF);
2298 *to_nxt++ = static_cast<uint8_t>(0xBB);
2299 *to_nxt++ = static_cast<uint8_t>(0xBF);
2300 }
2301 for (; frm_nxt < frm_end; ++frm_nxt)
2302 {
2303 uint32_t wc = *frm_nxt;
2304 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2305 return codecvt_base::error;
2306 if (wc < 0x000080)
2307 {
2308 if (to_end-to_nxt < 1)
2309 return codecvt_base::partial;
2310 *to_nxt++ = static_cast<uint8_t>(wc);
2311 }
2312 else if (wc < 0x000800)
2313 {
2314 if (to_end-to_nxt < 2)
2315 return codecvt_base::partial;
2316 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2317 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2318 }
2319 else if (wc < 0x010000)
2320 {
2321 if (to_end-to_nxt < 3)
2322 return codecvt_base::partial;
2323 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2324 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2325 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2326 }
2327 else // if (wc < 0x110000)
2328 {
2329 if (to_end-to_nxt < 4)
2330 return codecvt_base::partial;
2331 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2332 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2333 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2334 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2335 }
2336 }
2337 return codecvt_base::ok;
2338}
2339
2340static
2341codecvt_base::result
2342utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2343 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2344 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2345{
2346 frm_nxt = frm;
2347 to_nxt = to;
2348 if (mode & consume_header)
2349 {
2350 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2351 frm_nxt[2] == 0xBF)
2352 frm_nxt += 3;
2353 }
2354 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2355 {
2356 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2357 if (c1 < 0x80)
2358 {
2359 if (c1 > Maxcode)
2360 return codecvt_base::error;
2361 *to_nxt = static_cast<uint32_t>(c1);
2362 ++frm_nxt;
2363 }
2364 else if (c1 < 0xC2)
2365 {
2366 return codecvt_base::error;
2367 }
2368 else if (c1 < 0xE0)
2369 {
2370 if (frm_end-frm_nxt < 2)
2371 return codecvt_base::partial;
2372 uint8_t c2 = frm_nxt[1];
2373 if ((c2 & 0xC0) != 0x80)
2374 return codecvt_base::error;
2375 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2376 | (c2 & 0x3F));
2377 if (t > Maxcode)
2378 return codecvt_base::error;
2379 *to_nxt = t;
2380 frm_nxt += 2;
2381 }
2382 else if (c1 < 0xF0)
2383 {
2384 if (frm_end-frm_nxt < 3)
2385 return codecvt_base::partial;
2386 uint8_t c2 = frm_nxt[1];
2387 uint8_t c3 = frm_nxt[2];
2388 switch (c1)
2389 {
2390 case 0xE0:
2391 if ((c2 & 0xE0) != 0xA0)
2392 return codecvt_base::error;
2393 break;
2394 case 0xED:
2395 if ((c2 & 0xE0) != 0x80)
2396 return codecvt_base::error;
2397 break;
2398 default:
2399 if ((c2 & 0xC0) != 0x80)
2400 return codecvt_base::error;
2401 break;
2402 }
2403 if ((c3 & 0xC0) != 0x80)
2404 return codecvt_base::error;
2405 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2406 | ((c2 & 0x3F) << 6)
2407 | (c3 & 0x3F));
2408 if (t > Maxcode)
2409 return codecvt_base::error;
2410 *to_nxt = t;
2411 frm_nxt += 3;
2412 }
2413 else if (c1 < 0xF5)
2414 {
2415 if (frm_end-frm_nxt < 4)
2416 return codecvt_base::partial;
2417 uint8_t c2 = frm_nxt[1];
2418 uint8_t c3 = frm_nxt[2];
2419 uint8_t c4 = frm_nxt[3];
2420 switch (c1)
2421 {
2422 case 0xF0:
2423 if (!(0x90 <= c2 && c2 <= 0xBF))
2424 return codecvt_base::error;
2425 break;
2426 case 0xF4:
2427 if ((c2 & 0xF0) != 0x80)
2428 return codecvt_base::error;
2429 break;
2430 default:
2431 if ((c2 & 0xC0) != 0x80)
2432 return codecvt_base::error;
2433 break;
2434 }
2435 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2436 return codecvt_base::error;
2437 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2438 | ((c2 & 0x3F) << 12)
2439 | ((c3 & 0x3F) << 6)
2440 | (c4 & 0x3F));
2441 if (t > Maxcode)
2442 return codecvt_base::error;
2443 *to_nxt = t;
2444 frm_nxt += 4;
2445 }
2446 else
2447 {
2448 return codecvt_base::error;
2449 }
2450 }
2451 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2452}
2453
2454static
2455int
2456utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2457 size_t mx, unsigned long Maxcode = 0x10FFFF,
2458 codecvt_mode mode = codecvt_mode(0))
2459{
2460 const uint8_t* frm_nxt = frm;
2461 if (mode & consume_header)
2462 {
2463 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2464 frm_nxt[2] == 0xBF)
2465 frm_nxt += 3;
2466 }
2467 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2468 {
2469 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2470 if (c1 < 0x80)
2471 {
2472 if (c1 > Maxcode)
2473 break;
2474 ++frm_nxt;
2475 }
2476 else if (c1 < 0xC2)
2477 {
2478 break;
2479 }
2480 else if (c1 < 0xE0)
2481 {
2482 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2483 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002484 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002485 break;
2486 frm_nxt += 2;
2487 }
2488 else if (c1 < 0xF0)
2489 {
2490 if (frm_end-frm_nxt < 3)
2491 break;
2492 uint8_t c2 = frm_nxt[1];
2493 uint8_t c3 = frm_nxt[2];
2494 switch (c1)
2495 {
2496 case 0xE0:
2497 if ((c2 & 0xE0) != 0xA0)
2498 return static_cast<int>(frm_nxt - frm);
2499 break;
2500 case 0xED:
2501 if ((c2 & 0xE0) != 0x80)
2502 return static_cast<int>(frm_nxt - frm);
2503 break;
2504 default:
2505 if ((c2 & 0xC0) != 0x80)
2506 return static_cast<int>(frm_nxt - frm);
2507 break;
2508 }
2509 if ((c3 & 0xC0) != 0x80)
2510 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002511 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002512 break;
2513 frm_nxt += 3;
2514 }
2515 else if (c1 < 0xF5)
2516 {
2517 if (frm_end-frm_nxt < 4)
2518 break;
2519 uint8_t c2 = frm_nxt[1];
2520 uint8_t c3 = frm_nxt[2];
2521 uint8_t c4 = frm_nxt[3];
2522 switch (c1)
2523 {
2524 case 0xF0:
2525 if (!(0x90 <= c2 && c2 <= 0xBF))
2526 return static_cast<int>(frm_nxt - frm);
2527 break;
2528 case 0xF4:
2529 if ((c2 & 0xF0) != 0x80)
2530 return static_cast<int>(frm_nxt - frm);
2531 break;
2532 default:
2533 if ((c2 & 0xC0) != 0x80)
2534 return static_cast<int>(frm_nxt - frm);
2535 break;
2536 }
2537 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2538 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002539 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2540 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002541 break;
2542 frm_nxt += 4;
2543 }
2544 else
2545 {
2546 break;
2547 }
2548 }
2549 return static_cast<int>(frm_nxt - frm);
2550}
2551
2552static
2553codecvt_base::result
2554ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2555 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2556 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2557{
2558 frm_nxt = frm;
2559 to_nxt = to;
2560 if (mode & generate_header)
2561 {
2562 if (to_end-to_nxt < 3)
2563 return codecvt_base::partial;
2564 *to_nxt++ = static_cast<uint8_t>(0xEF);
2565 *to_nxt++ = static_cast<uint8_t>(0xBB);
2566 *to_nxt++ = static_cast<uint8_t>(0xBF);
2567 }
2568 for (; frm_nxt < frm_end; ++frm_nxt)
2569 {
2570 uint16_t wc = *frm_nxt;
2571 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2572 return codecvt_base::error;
2573 if (wc < 0x0080)
2574 {
2575 if (to_end-to_nxt < 1)
2576 return codecvt_base::partial;
2577 *to_nxt++ = static_cast<uint8_t>(wc);
2578 }
2579 else if (wc < 0x0800)
2580 {
2581 if (to_end-to_nxt < 2)
2582 return codecvt_base::partial;
2583 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2584 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2585 }
2586 else // if (wc <= 0xFFFF)
2587 {
2588 if (to_end-to_nxt < 3)
2589 return codecvt_base::partial;
2590 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2591 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2592 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2593 }
2594 }
2595 return codecvt_base::ok;
2596}
2597
2598static
2599codecvt_base::result
2600utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2601 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2602 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2603{
2604 frm_nxt = frm;
2605 to_nxt = to;
2606 if (mode & consume_header)
2607 {
2608 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2609 frm_nxt[2] == 0xBF)
2610 frm_nxt += 3;
2611 }
2612 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2613 {
2614 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2615 if (c1 < 0x80)
2616 {
2617 if (c1 > Maxcode)
2618 return codecvt_base::error;
2619 *to_nxt = static_cast<uint16_t>(c1);
2620 ++frm_nxt;
2621 }
2622 else if (c1 < 0xC2)
2623 {
2624 return codecvt_base::error;
2625 }
2626 else if (c1 < 0xE0)
2627 {
2628 if (frm_end-frm_nxt < 2)
2629 return codecvt_base::partial;
2630 uint8_t c2 = frm_nxt[1];
2631 if ((c2 & 0xC0) != 0x80)
2632 return codecvt_base::error;
2633 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2634 | (c2 & 0x3F));
2635 if (t > Maxcode)
2636 return codecvt_base::error;
2637 *to_nxt = t;
2638 frm_nxt += 2;
2639 }
2640 else if (c1 < 0xF0)
2641 {
2642 if (frm_end-frm_nxt < 3)
2643 return codecvt_base::partial;
2644 uint8_t c2 = frm_nxt[1];
2645 uint8_t c3 = frm_nxt[2];
2646 switch (c1)
2647 {
2648 case 0xE0:
2649 if ((c2 & 0xE0) != 0xA0)
2650 return codecvt_base::error;
2651 break;
2652 case 0xED:
2653 if ((c2 & 0xE0) != 0x80)
2654 return codecvt_base::error;
2655 break;
2656 default:
2657 if ((c2 & 0xC0) != 0x80)
2658 return codecvt_base::error;
2659 break;
2660 }
2661 if ((c3 & 0xC0) != 0x80)
2662 return codecvt_base::error;
2663 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2664 | ((c2 & 0x3F) << 6)
2665 | (c3 & 0x3F));
2666 if (t > Maxcode)
2667 return codecvt_base::error;
2668 *to_nxt = t;
2669 frm_nxt += 3;
2670 }
2671 else
2672 {
2673 return codecvt_base::error;
2674 }
2675 }
2676 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2677}
2678
2679static
2680int
2681utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2682 size_t mx, unsigned long Maxcode = 0x10FFFF,
2683 codecvt_mode mode = codecvt_mode(0))
2684{
2685 const uint8_t* frm_nxt = frm;
2686 if (mode & consume_header)
2687 {
2688 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2689 frm_nxt[2] == 0xBF)
2690 frm_nxt += 3;
2691 }
2692 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2693 {
2694 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2695 if (c1 < 0x80)
2696 {
2697 if (c1 > Maxcode)
2698 break;
2699 ++frm_nxt;
2700 }
2701 else if (c1 < 0xC2)
2702 {
2703 break;
2704 }
2705 else if (c1 < 0xE0)
2706 {
2707 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2708 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002709 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002710 break;
2711 frm_nxt += 2;
2712 }
2713 else if (c1 < 0xF0)
2714 {
2715 if (frm_end-frm_nxt < 3)
2716 break;
2717 uint8_t c2 = frm_nxt[1];
2718 uint8_t c3 = frm_nxt[2];
2719 switch (c1)
2720 {
2721 case 0xE0:
2722 if ((c2 & 0xE0) != 0xA0)
2723 return static_cast<int>(frm_nxt - frm);
2724 break;
2725 case 0xED:
2726 if ((c2 & 0xE0) != 0x80)
2727 return static_cast<int>(frm_nxt - frm);
2728 break;
2729 default:
2730 if ((c2 & 0xC0) != 0x80)
2731 return static_cast<int>(frm_nxt - frm);
2732 break;
2733 }
2734 if ((c3 & 0xC0) != 0x80)
2735 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002736 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002737 break;
2738 frm_nxt += 3;
2739 }
2740 else
2741 {
2742 break;
2743 }
2744 }
2745 return static_cast<int>(frm_nxt - frm);
2746}
2747
2748static
2749codecvt_base::result
2750ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2751 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2752 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2753{
2754 frm_nxt = frm;
2755 to_nxt = to;
2756 if (mode & generate_header)
2757 {
2758 if (to_end-to_nxt < 2)
2759 return codecvt_base::partial;
2760 *to_nxt++ = static_cast<uint8_t>(0xFE);
2761 *to_nxt++ = static_cast<uint8_t>(0xFF);
2762 }
2763 for (; frm_nxt < frm_end; ++frm_nxt)
2764 {
2765 uint32_t wc = *frm_nxt;
2766 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2767 return codecvt_base::error;
2768 if (wc < 0x010000)
2769 {
2770 if (to_end-to_nxt < 2)
2771 return codecvt_base::partial;
2772 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2773 *to_nxt++ = static_cast<uint8_t>(wc);
2774 }
2775 else
2776 {
2777 if (to_end-to_nxt < 4)
2778 return codecvt_base::partial;
2779 uint16_t t = static_cast<uint16_t>(
2780 0xD800
2781 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2782 | ((wc & 0x00FC00) >> 10));
2783 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2784 *to_nxt++ = static_cast<uint8_t>(t);
2785 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2786 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2787 *to_nxt++ = static_cast<uint8_t>(t);
2788 }
2789 }
2790 return codecvt_base::ok;
2791}
2792
2793static
2794codecvt_base::result
2795utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2796 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2797 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2798{
2799 frm_nxt = frm;
2800 to_nxt = to;
2801 if (mode & consume_header)
2802 {
2803 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2804 frm_nxt += 2;
2805 }
2806 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2807 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002808 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002809 if ((c1 & 0xFC00) == 0xDC00)
2810 return codecvt_base::error;
2811 if ((c1 & 0xFC00) != 0xD800)
2812 {
2813 if (c1 > Maxcode)
2814 return codecvt_base::error;
2815 *to_nxt = static_cast<uint32_t>(c1);
2816 frm_nxt += 2;
2817 }
2818 else
2819 {
2820 if (frm_end-frm_nxt < 4)
2821 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002822 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002823 if ((c2 & 0xFC00) != 0xDC00)
2824 return codecvt_base::error;
2825 uint32_t t = static_cast<uint32_t>(
2826 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2827 | ((c1 & 0x003F) << 10)
2828 | (c2 & 0x03FF));
2829 if (t > Maxcode)
2830 return codecvt_base::error;
2831 *to_nxt = t;
2832 frm_nxt += 4;
2833 }
2834 }
2835 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2836}
2837
2838static
2839int
2840utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2841 size_t mx, unsigned long Maxcode = 0x10FFFF,
2842 codecvt_mode mode = codecvt_mode(0))
2843{
2844 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002845 if (mode & consume_header)
2846 {
2847 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2848 frm_nxt += 2;
2849 }
2850 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2851 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002852 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002853 if ((c1 & 0xFC00) == 0xDC00)
2854 break;
2855 if ((c1 & 0xFC00) != 0xD800)
2856 {
2857 if (c1 > Maxcode)
2858 break;
2859 frm_nxt += 2;
2860 }
2861 else
2862 {
2863 if (frm_end-frm_nxt < 4)
2864 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002865 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002866 if ((c2 & 0xFC00) != 0xDC00)
2867 break;
2868 uint32_t t = static_cast<uint32_t>(
2869 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2870 | ((c1 & 0x003F) << 10)
2871 | (c2 & 0x03FF));
2872 if (t > Maxcode)
2873 break;
2874 frm_nxt += 4;
2875 }
2876 }
2877 return static_cast<int>(frm_nxt - frm);
2878}
2879
2880static
2881codecvt_base::result
2882ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2883 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2884 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2885{
2886 frm_nxt = frm;
2887 to_nxt = to;
2888 if (mode & generate_header)
2889 {
2890 if (to_end-to_nxt < 2)
2891 return codecvt_base::partial;
2892 *to_nxt++ = static_cast<uint8_t>(0xFF);
2893 *to_nxt++ = static_cast<uint8_t>(0xFE);
2894 }
2895 for (; frm_nxt < frm_end; ++frm_nxt)
2896 {
2897 uint32_t wc = *frm_nxt;
2898 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2899 return codecvt_base::error;
2900 if (wc < 0x010000)
2901 {
2902 if (to_end-to_nxt < 2)
2903 return codecvt_base::partial;
2904 *to_nxt++ = static_cast<uint8_t>(wc);
2905 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2906 }
2907 else
2908 {
2909 if (to_end-to_nxt < 4)
2910 return codecvt_base::partial;
2911 uint16_t t = static_cast<uint16_t>(
2912 0xD800
2913 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2914 | ((wc & 0x00FC00) >> 10));
2915 *to_nxt++ = static_cast<uint8_t>(t);
2916 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2917 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2918 *to_nxt++ = static_cast<uint8_t>(t);
2919 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2920 }
2921 }
2922 return codecvt_base::ok;
2923}
2924
2925static
2926codecvt_base::result
2927utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2928 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2929 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2930{
2931 frm_nxt = frm;
2932 to_nxt = to;
2933 if (mode & consume_header)
2934 {
2935 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2936 frm_nxt += 2;
2937 }
2938 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2939 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002940 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002941 if ((c1 & 0xFC00) == 0xDC00)
2942 return codecvt_base::error;
2943 if ((c1 & 0xFC00) != 0xD800)
2944 {
2945 if (c1 > Maxcode)
2946 return codecvt_base::error;
2947 *to_nxt = static_cast<uint32_t>(c1);
2948 frm_nxt += 2;
2949 }
2950 else
2951 {
2952 if (frm_end-frm_nxt < 4)
2953 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002954 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002955 if ((c2 & 0xFC00) != 0xDC00)
2956 return codecvt_base::error;
2957 uint32_t t = static_cast<uint32_t>(
2958 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2959 | ((c1 & 0x003F) << 10)
2960 | (c2 & 0x03FF));
2961 if (t > Maxcode)
2962 return codecvt_base::error;
2963 *to_nxt = t;
2964 frm_nxt += 4;
2965 }
2966 }
2967 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2968}
2969
2970static
2971int
2972utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2973 size_t mx, unsigned long Maxcode = 0x10FFFF,
2974 codecvt_mode mode = codecvt_mode(0))
2975{
2976 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002977 if (mode & consume_header)
2978 {
2979 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2980 frm_nxt += 2;
2981 }
2982 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2983 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002984 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002985 if ((c1 & 0xFC00) == 0xDC00)
2986 break;
2987 if ((c1 & 0xFC00) != 0xD800)
2988 {
2989 if (c1 > Maxcode)
2990 break;
2991 frm_nxt += 2;
2992 }
2993 else
2994 {
2995 if (frm_end-frm_nxt < 4)
2996 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002997 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002998 if ((c2 & 0xFC00) != 0xDC00)
2999 break;
3000 uint32_t t = static_cast<uint32_t>(
3001 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3002 | ((c1 & 0x003F) << 10)
3003 | (c2 & 0x03FF));
3004 if (t > Maxcode)
3005 break;
3006 frm_nxt += 4;
3007 }
3008 }
3009 return static_cast<int>(frm_nxt - frm);
3010}
3011
3012static
3013codecvt_base::result
3014ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3015 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3016 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3017{
3018 frm_nxt = frm;
3019 to_nxt = to;
3020 if (mode & generate_header)
3021 {
3022 if (to_end-to_nxt < 2)
3023 return codecvt_base::partial;
3024 *to_nxt++ = static_cast<uint8_t>(0xFE);
3025 *to_nxt++ = static_cast<uint8_t>(0xFF);
3026 }
3027 for (; frm_nxt < frm_end; ++frm_nxt)
3028 {
3029 uint16_t wc = *frm_nxt;
3030 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3031 return codecvt_base::error;
3032 if (to_end-to_nxt < 2)
3033 return codecvt_base::partial;
3034 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3035 *to_nxt++ = static_cast<uint8_t>(wc);
3036 }
3037 return codecvt_base::ok;
3038}
3039
3040static
3041codecvt_base::result
3042utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3043 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3044 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3045{
3046 frm_nxt = frm;
3047 to_nxt = to;
3048 if (mode & consume_header)
3049 {
3050 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3051 frm_nxt += 2;
3052 }
3053 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3054 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003055 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003056 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3057 return codecvt_base::error;
3058 *to_nxt = c1;
3059 frm_nxt += 2;
3060 }
3061 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3062}
3063
3064static
3065int
3066utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3067 size_t mx, unsigned long Maxcode = 0x10FFFF,
3068 codecvt_mode mode = codecvt_mode(0))
3069{
3070 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003071 if (mode & consume_header)
3072 {
3073 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3074 frm_nxt += 2;
3075 }
3076 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3077 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003078 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003079 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3080 break;
3081 frm_nxt += 2;
3082 }
3083 return static_cast<int>(frm_nxt - frm);
3084}
3085
3086static
3087codecvt_base::result
3088ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3089 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3090 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3091{
3092 frm_nxt = frm;
3093 to_nxt = to;
3094 if (mode & generate_header)
3095 {
3096 if (to_end-to_nxt < 2)
3097 return codecvt_base::partial;
3098 *to_nxt++ = static_cast<uint8_t>(0xFF);
3099 *to_nxt++ = static_cast<uint8_t>(0xFE);
3100 }
3101 for (; frm_nxt < frm_end; ++frm_nxt)
3102 {
3103 uint16_t wc = *frm_nxt;
3104 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3105 return codecvt_base::error;
3106 if (to_end-to_nxt < 2)
3107 return codecvt_base::partial;
3108 *to_nxt++ = static_cast<uint8_t>(wc);
3109 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3110 }
3111 return codecvt_base::ok;
3112}
3113
3114static
3115codecvt_base::result
3116utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3117 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3118 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3119{
3120 frm_nxt = frm;
3121 to_nxt = to;
3122 if (mode & consume_header)
3123 {
3124 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3125 frm_nxt += 2;
3126 }
3127 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3128 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003129 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003130 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3131 return codecvt_base::error;
3132 *to_nxt = c1;
3133 frm_nxt += 2;
3134 }
3135 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3136}
3137
3138static
3139int
3140utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3141 size_t mx, unsigned long Maxcode = 0x10FFFF,
3142 codecvt_mode mode = codecvt_mode(0))
3143{
3144 const uint8_t* frm_nxt = frm;
3145 frm_nxt = frm;
3146 if (mode & consume_header)
3147 {
3148 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3149 frm_nxt += 2;
3150 }
3151 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3152 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003153 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003154 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3155 break;
3156 frm_nxt += 2;
3157 }
3158 return static_cast<int>(frm_nxt - frm);
3159}
3160
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003161// template <> class codecvt<char16_t, char, mbstate_t>
3162
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003163locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003164
3165codecvt<char16_t, char, mbstate_t>::~codecvt()
3166{
3167}
3168
3169codecvt<char16_t, char, mbstate_t>::result
3170codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003171 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003172 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3173{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003174 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3175 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3176 const uint16_t* _frm_nxt = _frm;
3177 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3178 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3179 uint8_t* _to_nxt = _to;
3180 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3181 frm_nxt = frm + (_frm_nxt - _frm);
3182 to_nxt = to + (_to_nxt - _to);
3183 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003184}
3185
3186codecvt<char16_t, char, mbstate_t>::result
3187codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003188 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003189 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3190{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003191 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3192 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3193 const uint8_t* _frm_nxt = _frm;
3194 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3195 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3196 uint16_t* _to_nxt = _to;
3197 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3198 frm_nxt = frm + (_frm_nxt - _frm);
3199 to_nxt = to + (_to_nxt - _to);
3200 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003201}
3202
3203codecvt<char16_t, char, mbstate_t>::result
3204codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3205 extern_type* to, extern_type*, extern_type*& to_nxt) const
3206{
3207 to_nxt = to;
3208 return noconv;
3209}
3210
3211int
Howard Hinnantc9834542011-05-31 15:34:58 +00003212codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003213{
3214 return 0;
3215}
3216
3217bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003218codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003219{
3220 return false;
3221}
3222
3223int
3224codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3225 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3226{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003227 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3228 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3229 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003230}
3231
3232int
Howard Hinnantc9834542011-05-31 15:34:58 +00003233codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003234{
3235 return 4;
3236}
3237
3238// template <> class codecvt<char32_t, char, mbstate_t>
3239
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003240locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003241
3242codecvt<char32_t, char, mbstate_t>::~codecvt()
3243{
3244}
3245
3246codecvt<char32_t, char, mbstate_t>::result
3247codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003248 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003249 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3250{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003251 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3252 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3253 const uint32_t* _frm_nxt = _frm;
3254 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3255 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3256 uint8_t* _to_nxt = _to;
3257 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3258 frm_nxt = frm + (_frm_nxt - _frm);
3259 to_nxt = to + (_to_nxt - _to);
3260 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003261}
3262
3263codecvt<char32_t, char, mbstate_t>::result
3264codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003265 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003266 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3267{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003268 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3269 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3270 const uint8_t* _frm_nxt = _frm;
3271 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 frm_nxt = frm + (_frm_nxt - _frm);
3276 to_nxt = to + (_to_nxt - _to);
3277 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003278}
3279
3280codecvt<char32_t, char, mbstate_t>::result
3281codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3282 extern_type* to, extern_type*, extern_type*& to_nxt) const
3283{
3284 to_nxt = to;
3285 return noconv;
3286}
3287
3288int
Howard Hinnantc9834542011-05-31 15:34:58 +00003289codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003290{
3291 return 0;
3292}
3293
3294bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003295codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003296{
3297 return false;
3298}
3299
3300int
3301codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3302 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3303{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003304 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3305 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3306 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003307}
3308
3309int
Howard Hinnantc9834542011-05-31 15:34:58 +00003310codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003311{
3312 return 4;
3313}
3314
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003315// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003316
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003317__codecvt_utf8<wchar_t>::result
3318__codecvt_utf8<wchar_t>::do_out(state_type&,
3319 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003320 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3321{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003322#if _WIN32
3323 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3324 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3325 const uint16_t* _frm_nxt = _frm;
3326#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003327 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3328 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3329 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003330#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003331 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3332 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3333 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003334#if _WIN32
3335 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3336 _Maxcode_, _Mode_);
3337#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003338 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3339 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003340#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003341 frm_nxt = frm + (_frm_nxt - _frm);
3342 to_nxt = to + (_to_nxt - _to);
3343 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003344}
3345
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003346__codecvt_utf8<wchar_t>::result
3347__codecvt_utf8<wchar_t>::do_in(state_type&,
3348 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003349 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3350{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003351 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3352 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3353 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003354#if _WIN32
3355 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3356 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3357 uint16_t* _to_nxt = _to;
3358 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3359 _Maxcode_, _Mode_);
3360#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003361 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3362 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3363 uint32_t* _to_nxt = _to;
3364 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3365 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003366#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003367 frm_nxt = frm + (_frm_nxt - _frm);
3368 to_nxt = to + (_to_nxt - _to);
3369 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003370}
3371
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003372__codecvt_utf8<wchar_t>::result
3373__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003374 extern_type* to, extern_type*, extern_type*& to_nxt) const
3375{
3376 to_nxt = to;
3377 return noconv;
3378}
3379
3380int
Howard Hinnantc9834542011-05-31 15:34:58 +00003381__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003382{
3383 return 0;
3384}
3385
3386bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003387__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003388{
3389 return false;
3390}
3391
3392int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003393__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003394 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3395{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003396 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3397 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3398 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003399}
3400
3401int
Howard Hinnantc9834542011-05-31 15:34:58 +00003402__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003403{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003404 if (_Mode_ & consume_header)
3405 return 7;
3406 return 4;
3407}
3408
3409// __codecvt_utf8<char16_t>
3410
3411__codecvt_utf8<char16_t>::result
3412__codecvt_utf8<char16_t>::do_out(state_type&,
3413 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3414 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3415{
3416 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3417 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3418 const uint16_t* _frm_nxt = _frm;
3419 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3420 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3421 uint8_t* _to_nxt = _to;
3422 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3423 _Maxcode_, _Mode_);
3424 frm_nxt = frm + (_frm_nxt - _frm);
3425 to_nxt = to + (_to_nxt - _to);
3426 return r;
3427}
3428
3429__codecvt_utf8<char16_t>::result
3430__codecvt_utf8<char16_t>::do_in(state_type&,
3431 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3432 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3433{
3434 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3435 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3436 const uint8_t* _frm_nxt = _frm;
3437 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3438 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3439 uint16_t* _to_nxt = _to;
3440 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3441 _Maxcode_, _Mode_);
3442 frm_nxt = frm + (_frm_nxt - _frm);
3443 to_nxt = to + (_to_nxt - _to);
3444 return r;
3445}
3446
3447__codecvt_utf8<char16_t>::result
3448__codecvt_utf8<char16_t>::do_unshift(state_type&,
3449 extern_type* to, extern_type*, extern_type*& to_nxt) const
3450{
3451 to_nxt = to;
3452 return noconv;
3453}
3454
3455int
Howard Hinnantc9834542011-05-31 15:34:58 +00003456__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003457{
3458 return 0;
3459}
3460
3461bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003462__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003463{
3464 return false;
3465}
3466
3467int
3468__codecvt_utf8<char16_t>::do_length(state_type&,
3469 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3470{
3471 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3472 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3473 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3474}
3475
3476int
Howard Hinnantc9834542011-05-31 15:34:58 +00003477__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003478{
3479 if (_Mode_ & consume_header)
3480 return 6;
3481 return 3;
3482}
3483
3484// __codecvt_utf8<char32_t>
3485
3486__codecvt_utf8<char32_t>::result
3487__codecvt_utf8<char32_t>::do_out(state_type&,
3488 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3489 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3490{
3491 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3492 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3493 const uint32_t* _frm_nxt = _frm;
3494 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3495 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3496 uint8_t* _to_nxt = _to;
3497 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3498 _Maxcode_, _Mode_);
3499 frm_nxt = frm + (_frm_nxt - _frm);
3500 to_nxt = to + (_to_nxt - _to);
3501 return r;
3502}
3503
3504__codecvt_utf8<char32_t>::result
3505__codecvt_utf8<char32_t>::do_in(state_type&,
3506 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3507 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3508{
3509 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3510 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3511 const uint8_t* _frm_nxt = _frm;
3512 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3513 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3514 uint32_t* _to_nxt = _to;
3515 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3516 _Maxcode_, _Mode_);
3517 frm_nxt = frm + (_frm_nxt - _frm);
3518 to_nxt = to + (_to_nxt - _to);
3519 return r;
3520}
3521
3522__codecvt_utf8<char32_t>::result
3523__codecvt_utf8<char32_t>::do_unshift(state_type&,
3524 extern_type* to, extern_type*, extern_type*& to_nxt) const
3525{
3526 to_nxt = to;
3527 return noconv;
3528}
3529
3530int
Howard Hinnantc9834542011-05-31 15:34:58 +00003531__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003532{
3533 return 0;
3534}
3535
3536bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003537__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003538{
3539 return false;
3540}
3541
3542int
3543__codecvt_utf8<char32_t>::do_length(state_type&,
3544 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3545{
3546 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3547 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3548 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3549}
3550
3551int
Howard Hinnantc9834542011-05-31 15:34:58 +00003552__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003553{
3554 if (_Mode_ & consume_header)
3555 return 7;
3556 return 4;
3557}
3558
3559// __codecvt_utf16<wchar_t, false>
3560
3561__codecvt_utf16<wchar_t, false>::result
3562__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3563 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3564 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3565{
3566 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3567 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3568 const uint32_t* _frm_nxt = _frm;
3569 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3570 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3571 uint8_t* _to_nxt = _to;
3572 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3573 _Maxcode_, _Mode_);
3574 frm_nxt = frm + (_frm_nxt - _frm);
3575 to_nxt = to + (_to_nxt - _to);
3576 return r;
3577}
3578
3579__codecvt_utf16<wchar_t, false>::result
3580__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3581 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3582 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3583{
3584 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3585 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3586 const uint8_t* _frm_nxt = _frm;
3587 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3588 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3589 uint32_t* _to_nxt = _to;
3590 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3591 _Maxcode_, _Mode_);
3592 frm_nxt = frm + (_frm_nxt - _frm);
3593 to_nxt = to + (_to_nxt - _to);
3594 return r;
3595}
3596
3597__codecvt_utf16<wchar_t, false>::result
3598__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3599 extern_type* to, extern_type*, extern_type*& to_nxt) const
3600{
3601 to_nxt = to;
3602 return noconv;
3603}
3604
3605int
Howard Hinnantc9834542011-05-31 15:34:58 +00003606__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003607{
3608 return 0;
3609}
3610
3611bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003612__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003613{
3614 return false;
3615}
3616
3617int
3618__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3619 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3620{
3621 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3622 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3623 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3624}
3625
3626int
Howard Hinnantc9834542011-05-31 15:34:58 +00003627__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003628{
3629 if (_Mode_ & consume_header)
3630 return 6;
3631 return 4;
3632}
3633
3634// __codecvt_utf16<wchar_t, true>
3635
3636__codecvt_utf16<wchar_t, true>::result
3637__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3638 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3639 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3640{
3641 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3642 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3643 const uint32_t* _frm_nxt = _frm;
3644 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3645 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3646 uint8_t* _to_nxt = _to;
3647 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3648 _Maxcode_, _Mode_);
3649 frm_nxt = frm + (_frm_nxt - _frm);
3650 to_nxt = to + (_to_nxt - _to);
3651 return r;
3652}
3653
3654__codecvt_utf16<wchar_t, true>::result
3655__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3656 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3657 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3658{
3659 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3660 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3661 const uint8_t* _frm_nxt = _frm;
3662 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3663 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3664 uint32_t* _to_nxt = _to;
3665 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3666 _Maxcode_, _Mode_);
3667 frm_nxt = frm + (_frm_nxt - _frm);
3668 to_nxt = to + (_to_nxt - _to);
3669 return r;
3670}
3671
3672__codecvt_utf16<wchar_t, true>::result
3673__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3674 extern_type* to, extern_type*, extern_type*& to_nxt) const
3675{
3676 to_nxt = to;
3677 return noconv;
3678}
3679
3680int
Howard Hinnantc9834542011-05-31 15:34:58 +00003681__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003682{
3683 return 0;
3684}
3685
3686bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003687__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003688{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003689 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003690}
3691
3692int
3693__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3694 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3695{
3696 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3697 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3698 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3699}
3700
3701int
Howard Hinnantc9834542011-05-31 15:34:58 +00003702__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003703{
3704 if (_Mode_ & consume_header)
3705 return 6;
3706 return 4;
3707}
3708
3709// __codecvt_utf16<char16_t, false>
3710
3711__codecvt_utf16<char16_t, false>::result
3712__codecvt_utf16<char16_t, false>::do_out(state_type&,
3713 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3714 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3715{
3716 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3717 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3718 const uint16_t* _frm_nxt = _frm;
3719 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3720 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3721 uint8_t* _to_nxt = _to;
3722 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3723 _Maxcode_, _Mode_);
3724 frm_nxt = frm + (_frm_nxt - _frm);
3725 to_nxt = to + (_to_nxt - _to);
3726 return r;
3727}
3728
3729__codecvt_utf16<char16_t, false>::result
3730__codecvt_utf16<char16_t, false>::do_in(state_type&,
3731 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3732 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3733{
3734 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3735 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3736 const uint8_t* _frm_nxt = _frm;
3737 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3738 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3739 uint16_t* _to_nxt = _to;
3740 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3741 _Maxcode_, _Mode_);
3742 frm_nxt = frm + (_frm_nxt - _frm);
3743 to_nxt = to + (_to_nxt - _to);
3744 return r;
3745}
3746
3747__codecvt_utf16<char16_t, false>::result
3748__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3749 extern_type* to, extern_type*, extern_type*& to_nxt) const
3750{
3751 to_nxt = to;
3752 return noconv;
3753}
3754
3755int
Howard Hinnantc9834542011-05-31 15:34:58 +00003756__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003757{
3758 return 0;
3759}
3760
3761bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003762__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003763{
3764 return false;
3765}
3766
3767int
3768__codecvt_utf16<char16_t, false>::do_length(state_type&,
3769 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3770{
3771 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3772 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3773 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3774}
3775
3776int
Howard Hinnantc9834542011-05-31 15:34:58 +00003777__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003778{
3779 if (_Mode_ & consume_header)
3780 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003781 return 2;
3782}
3783
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003784// __codecvt_utf16<char16_t, true>
3785
3786__codecvt_utf16<char16_t, true>::result
3787__codecvt_utf16<char16_t, true>::do_out(state_type&,
3788 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3789 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3790{
3791 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3792 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3793 const uint16_t* _frm_nxt = _frm;
3794 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3795 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3796 uint8_t* _to_nxt = _to;
3797 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3798 _Maxcode_, _Mode_);
3799 frm_nxt = frm + (_frm_nxt - _frm);
3800 to_nxt = to + (_to_nxt - _to);
3801 return r;
3802}
3803
3804__codecvt_utf16<char16_t, true>::result
3805__codecvt_utf16<char16_t, true>::do_in(state_type&,
3806 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3807 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3808{
3809 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3810 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3811 const uint8_t* _frm_nxt = _frm;
3812 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3813 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3814 uint16_t* _to_nxt = _to;
3815 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3816 _Maxcode_, _Mode_);
3817 frm_nxt = frm + (_frm_nxt - _frm);
3818 to_nxt = to + (_to_nxt - _to);
3819 return r;
3820}
3821
3822__codecvt_utf16<char16_t, true>::result
3823__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3824 extern_type* to, extern_type*, extern_type*& to_nxt) const
3825{
3826 to_nxt = to;
3827 return noconv;
3828}
3829
3830int
Howard Hinnantc9834542011-05-31 15:34:58 +00003831__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003832{
3833 return 0;
3834}
3835
3836bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003837__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003838{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003839 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003840}
3841
3842int
3843__codecvt_utf16<char16_t, true>::do_length(state_type&,
3844 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3845{
3846 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3847 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3848 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3849}
3850
3851int
Howard Hinnantc9834542011-05-31 15:34:58 +00003852__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003853{
3854 if (_Mode_ & consume_header)
3855 return 4;
3856 return 2;
3857}
3858
3859// __codecvt_utf16<char32_t, false>
3860
3861__codecvt_utf16<char32_t, false>::result
3862__codecvt_utf16<char32_t, false>::do_out(state_type&,
3863 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3864 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3865{
3866 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3867 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3868 const uint32_t* _frm_nxt = _frm;
3869 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3870 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3871 uint8_t* _to_nxt = _to;
3872 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3873 _Maxcode_, _Mode_);
3874 frm_nxt = frm + (_frm_nxt - _frm);
3875 to_nxt = to + (_to_nxt - _to);
3876 return r;
3877}
3878
3879__codecvt_utf16<char32_t, false>::result
3880__codecvt_utf16<char32_t, false>::do_in(state_type&,
3881 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3882 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3883{
3884 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3885 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3886 const uint8_t* _frm_nxt = _frm;
3887 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3888 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3889 uint32_t* _to_nxt = _to;
3890 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3891 _Maxcode_, _Mode_);
3892 frm_nxt = frm + (_frm_nxt - _frm);
3893 to_nxt = to + (_to_nxt - _to);
3894 return r;
3895}
3896
3897__codecvt_utf16<char32_t, false>::result
3898__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3899 extern_type* to, extern_type*, extern_type*& to_nxt) const
3900{
3901 to_nxt = to;
3902 return noconv;
3903}
3904
3905int
Howard Hinnantc9834542011-05-31 15:34:58 +00003906__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003907{
3908 return 0;
3909}
3910
3911bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003912__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003913{
3914 return false;
3915}
3916
3917int
3918__codecvt_utf16<char32_t, false>::do_length(state_type&,
3919 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3920{
3921 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3922 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3923 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3924}
3925
3926int
Howard Hinnantc9834542011-05-31 15:34:58 +00003927__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003928{
3929 if (_Mode_ & consume_header)
3930 return 6;
3931 return 4;
3932}
3933
3934// __codecvt_utf16<char32_t, true>
3935
3936__codecvt_utf16<char32_t, true>::result
3937__codecvt_utf16<char32_t, true>::do_out(state_type&,
3938 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3939 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3940{
3941 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3942 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3943 const uint32_t* _frm_nxt = _frm;
3944 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3945 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3946 uint8_t* _to_nxt = _to;
3947 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3948 _Maxcode_, _Mode_);
3949 frm_nxt = frm + (_frm_nxt - _frm);
3950 to_nxt = to + (_to_nxt - _to);
3951 return r;
3952}
3953
3954__codecvt_utf16<char32_t, true>::result
3955__codecvt_utf16<char32_t, true>::do_in(state_type&,
3956 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3957 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3958{
3959 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3960 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3961 const uint8_t* _frm_nxt = _frm;
3962 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3963 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3964 uint32_t* _to_nxt = _to;
3965 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3966 _Maxcode_, _Mode_);
3967 frm_nxt = frm + (_frm_nxt - _frm);
3968 to_nxt = to + (_to_nxt - _to);
3969 return r;
3970}
3971
3972__codecvt_utf16<char32_t, true>::result
3973__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3974 extern_type* to, extern_type*, extern_type*& to_nxt) const
3975{
3976 to_nxt = to;
3977 return noconv;
3978}
3979
3980int
Howard Hinnantc9834542011-05-31 15:34:58 +00003981__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003982{
3983 return 0;
3984}
3985
3986bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003987__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003988{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003989 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003990}
3991
3992int
3993__codecvt_utf16<char32_t, true>::do_length(state_type&,
3994 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3995{
3996 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3997 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3998 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3999}
4000
4001int
Howard Hinnantc9834542011-05-31 15:34:58 +00004002__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004003{
4004 if (_Mode_ & consume_header)
4005 return 6;
4006 return 4;
4007}
4008
4009// __codecvt_utf8_utf16<wchar_t>
4010
4011__codecvt_utf8_utf16<wchar_t>::result
4012__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4013 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4014 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4015{
4016 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4017 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4018 const uint32_t* _frm_nxt = _frm;
4019 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4020 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4021 uint8_t* _to_nxt = _to;
4022 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4023 _Maxcode_, _Mode_);
4024 frm_nxt = frm + (_frm_nxt - _frm);
4025 to_nxt = to + (_to_nxt - _to);
4026 return r;
4027}
4028
4029__codecvt_utf8_utf16<wchar_t>::result
4030__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4031 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4032 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4033{
4034 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4035 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4036 const uint8_t* _frm_nxt = _frm;
4037 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4038 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4039 uint32_t* _to_nxt = _to;
4040 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4041 _Maxcode_, _Mode_);
4042 frm_nxt = frm + (_frm_nxt - _frm);
4043 to_nxt = to + (_to_nxt - _to);
4044 return r;
4045}
4046
4047__codecvt_utf8_utf16<wchar_t>::result
4048__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4049 extern_type* to, extern_type*, extern_type*& to_nxt) const
4050{
4051 to_nxt = to;
4052 return noconv;
4053}
4054
4055int
Howard Hinnantc9834542011-05-31 15:34:58 +00004056__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004057{
4058 return 0;
4059}
4060
4061bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004062__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004063{
4064 return false;
4065}
4066
4067int
4068__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4069 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4070{
4071 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4072 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4073 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4074}
4075
4076int
Howard Hinnantc9834542011-05-31 15:34:58 +00004077__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004078{
4079 if (_Mode_ & consume_header)
4080 return 7;
4081 return 4;
4082}
4083
4084// __codecvt_utf8_utf16<char16_t>
4085
4086__codecvt_utf8_utf16<char16_t>::result
4087__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4088 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4089 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4090{
4091 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4092 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4093 const uint16_t* _frm_nxt = _frm;
4094 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4095 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4096 uint8_t* _to_nxt = _to;
4097 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4098 _Maxcode_, _Mode_);
4099 frm_nxt = frm + (_frm_nxt - _frm);
4100 to_nxt = to + (_to_nxt - _to);
4101 return r;
4102}
4103
4104__codecvt_utf8_utf16<char16_t>::result
4105__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4106 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4107 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4108{
4109 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4110 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4111 const uint8_t* _frm_nxt = _frm;
4112 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4113 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4114 uint16_t* _to_nxt = _to;
4115 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4116 _Maxcode_, _Mode_);
4117 frm_nxt = frm + (_frm_nxt - _frm);
4118 to_nxt = to + (_to_nxt - _to);
4119 return r;
4120}
4121
4122__codecvt_utf8_utf16<char16_t>::result
4123__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4124 extern_type* to, extern_type*, extern_type*& to_nxt) const
4125{
4126 to_nxt = to;
4127 return noconv;
4128}
4129
4130int
Howard Hinnantc9834542011-05-31 15:34:58 +00004131__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004132{
4133 return 0;
4134}
4135
4136bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004137__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004138{
4139 return false;
4140}
4141
4142int
4143__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4144 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4145{
4146 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4147 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4148 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4149}
4150
4151int
Howard Hinnantc9834542011-05-31 15:34:58 +00004152__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004153{
4154 if (_Mode_ & consume_header)
4155 return 7;
4156 return 4;
4157}
4158
4159// __codecvt_utf8_utf16<char32_t>
4160
4161__codecvt_utf8_utf16<char32_t>::result
4162__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4163 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4164 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4165{
4166 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4167 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4168 const uint32_t* _frm_nxt = _frm;
4169 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4170 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4171 uint8_t* _to_nxt = _to;
4172 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4173 _Maxcode_, _Mode_);
4174 frm_nxt = frm + (_frm_nxt - _frm);
4175 to_nxt = to + (_to_nxt - _to);
4176 return r;
4177}
4178
4179__codecvt_utf8_utf16<char32_t>::result
4180__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4181 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4182 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4183{
4184 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4185 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4186 const uint8_t* _frm_nxt = _frm;
4187 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4188 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4189 uint32_t* _to_nxt = _to;
4190 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4191 _Maxcode_, _Mode_);
4192 frm_nxt = frm + (_frm_nxt - _frm);
4193 to_nxt = to + (_to_nxt - _to);
4194 return r;
4195}
4196
4197__codecvt_utf8_utf16<char32_t>::result
4198__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4199 extern_type* to, extern_type*, extern_type*& to_nxt) const
4200{
4201 to_nxt = to;
4202 return noconv;
4203}
4204
4205int
Howard Hinnantc9834542011-05-31 15:34:58 +00004206__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004207{
4208 return 0;
4209}
4210
4211bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004212__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004213{
4214 return false;
4215}
4216
4217int
4218__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4219 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4220{
4221 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4222 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4223 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4224}
4225
4226int
Howard Hinnantc9834542011-05-31 15:34:58 +00004227__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004228{
4229 if (_Mode_ & consume_header)
4230 return 7;
4231 return 4;
4232}
4233
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004234// __narrow_to_utf8<16>
4235
4236__narrow_to_utf8<16>::~__narrow_to_utf8()
4237{
4238}
4239
4240// __narrow_to_utf8<32>
4241
4242__narrow_to_utf8<32>::~__narrow_to_utf8()
4243{
4244}
4245
4246// __widen_from_utf8<16>
4247
4248__widen_from_utf8<16>::~__widen_from_utf8()
4249{
4250}
4251
4252// __widen_from_utf8<32>
4253
4254__widen_from_utf8<32>::~__widen_from_utf8()
4255{
4256}
4257
4258// numpunct<char> && numpunct<wchar_t>
4259
4260locale::id numpunct< char >::id;
4261locale::id numpunct<wchar_t>::id;
4262
4263numpunct<char>::numpunct(size_t refs)
4264 : locale::facet(refs),
4265 __decimal_point_('.'),
4266 __thousands_sep_(',')
4267{
4268}
4269
4270numpunct<wchar_t>::numpunct(size_t refs)
4271 : locale::facet(refs),
4272 __decimal_point_(L'.'),
4273 __thousands_sep_(L',')
4274{
4275}
4276
4277numpunct<char>::~numpunct()
4278{
4279}
4280
4281numpunct<wchar_t>::~numpunct()
4282{
4283}
4284
4285 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4286wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4287
4288 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4289wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4290
4291string numpunct< char >::do_grouping() const {return __grouping_;}
4292string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4293
4294 string numpunct< char >::do_truename() const {return "true";}
4295wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4296
4297 string numpunct< char >::do_falsename() const {return "false";}
4298wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4299
4300// numpunct_byname<char>
4301
4302numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4303 : numpunct<char>(refs)
4304{
4305 __init(nm);
4306}
4307
4308numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4309 : numpunct<char>(refs)
4310{
4311 __init(nm.c_str());
4312}
4313
4314numpunct_byname<char>::~numpunct_byname()
4315{
4316}
4317
4318void
4319numpunct_byname<char>::__init(const char* nm)
4320{
4321 if (strcmp(nm, "C") != 0)
4322 {
Sean Huntf3907e62011-07-15 05:40:33 +00004323 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004324#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004325 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004326 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4327 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004328#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004329#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004330 lconv* lc = localeconv_l(loc.get());
4331#else
4332 lconv* lc = __localeconv_l(loc.get());
4333#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004334 if (*lc->decimal_point)
4335 __decimal_point_ = *lc->decimal_point;
4336 if (*lc->thousands_sep)
4337 __thousands_sep_ = *lc->thousands_sep;
4338 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004339 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004340 }
4341}
4342
4343// numpunct_byname<wchar_t>
4344
4345numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4346 : numpunct<wchar_t>(refs)
4347{
4348 __init(nm);
4349}
4350
4351numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4352 : numpunct<wchar_t>(refs)
4353{
4354 __init(nm.c_str());
4355}
4356
4357numpunct_byname<wchar_t>::~numpunct_byname()
4358{
4359}
4360
4361void
4362numpunct_byname<wchar_t>::__init(const char* nm)
4363{
4364 if (strcmp(nm, "C") != 0)
4365 {
Sean Huntf3907e62011-07-15 05:40:33 +00004366 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004367#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004368 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004369 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4370 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004371#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004372#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004373 lconv* lc = localeconv_l(loc.get());
4374#else
4375 lconv* lc = __localeconv_l(loc.get());
4376#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004377 if (*lc->decimal_point)
4378 __decimal_point_ = *lc->decimal_point;
4379 if (*lc->thousands_sep)
4380 __thousands_sep_ = *lc->thousands_sep;
4381 __grouping_ = lc->grouping;
4382 // locallization for truename and falsename is not available
4383 }
4384}
4385
4386// num_get helpers
4387
4388int
4389__num_get_base::__get_base(ios_base& iob)
4390{
4391 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4392 if (__basefield == ios_base::oct)
4393 return 8;
4394 else if (__basefield == ios_base::hex)
4395 return 16;
4396 else if (__basefield == 0)
4397 return 0;
4398 return 10;
4399}
4400
4401const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4402
4403void
4404__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4405 ios_base::iostate& __err)
4406{
4407 if (__grouping.size() != 0)
4408 {
4409 reverse(__g, __g_end);
4410 const char* __ig = __grouping.data();
4411 const char* __eg = __ig + __grouping.size();
4412 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4413 {
4414 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4415 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004416 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004417 {
4418 __err = ios_base::failbit;
4419 return;
4420 }
4421 }
4422 if (__eg - __ig > 1)
4423 ++__ig;
4424 }
4425 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4426 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004427 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004428 __err = ios_base::failbit;
4429 }
4430 }
4431}
4432
4433void
4434__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4435 ios_base::fmtflags __flags)
4436{
4437 if (__flags & ios_base::showpos)
4438 *__fmtp++ = '+';
4439 if (__flags & ios_base::showbase)
4440 *__fmtp++ = '#';
4441 while(*__len)
4442 *__fmtp++ = *__len++;
4443 if ((__flags & ios_base::basefield) == ios_base::oct)
4444 *__fmtp = 'o';
4445 else if ((__flags & ios_base::basefield) == ios_base::hex)
4446 {
4447 if (__flags & ios_base::uppercase)
4448 *__fmtp = 'X';
4449 else
4450 *__fmtp = 'x';
4451 }
4452 else if (__signd)
4453 *__fmtp = 'd';
4454 else
4455 *__fmtp = 'u';
4456}
4457
4458bool
4459__num_put_base::__format_float(char* __fmtp, const char* __len,
4460 ios_base::fmtflags __flags)
4461{
4462 bool specify_precision = true;
4463 if (__flags & ios_base::showpos)
4464 *__fmtp++ = '+';
4465 if (__flags & ios_base::showpoint)
4466 *__fmtp++ = '#';
4467 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowa3645132013-10-21 15:07:28 +00004468 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004469 if (floatfield == (ios_base::fixed | ios_base::scientific))
4470 specify_precision = false;
4471 else
4472 {
4473 *__fmtp++ = '.';
4474 *__fmtp++ = '*';
4475 }
4476 while(*__len)
4477 *__fmtp++ = *__len++;
4478 if (floatfield == ios_base::fixed)
4479 {
4480 if (uppercase)
4481 *__fmtp = 'F';
4482 else
4483 *__fmtp = 'f';
4484 }
4485 else if (floatfield == ios_base::scientific)
4486 {
4487 if (uppercase)
4488 *__fmtp = 'E';
4489 else
4490 *__fmtp = 'e';
4491 }
4492 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4493 {
4494 if (uppercase)
4495 *__fmtp = 'A';
4496 else
4497 *__fmtp = 'a';
4498 }
4499 else
4500 {
4501 if (uppercase)
4502 *__fmtp = 'G';
4503 else
4504 *__fmtp = 'g';
4505 }
4506 return specify_precision;
4507}
4508
4509char*
4510__num_put_base::__identify_padding(char* __nb, char* __ne,
4511 const ios_base& __iob)
4512{
4513 switch (__iob.flags() & ios_base::adjustfield)
4514 {
4515 case ios_base::internal:
4516 if (__nb[0] == '-' || __nb[0] == '+')
4517 return __nb+1;
4518 if (__ne - __nb >= 2 && __nb[0] == '0'
4519 && (__nb[1] == 'x' || __nb[1] == 'X'))
4520 return __nb+2;
4521 break;
4522 case ios_base::left:
4523 return __ne;
4524 case ios_base::right:
4525 default:
4526 break;
4527 }
4528 return __nb;
4529}
4530
4531// time_get
4532
4533static
4534string*
4535init_weeks()
4536{
4537 static string weeks[14];
4538 weeks[0] = "Sunday";
4539 weeks[1] = "Monday";
4540 weeks[2] = "Tuesday";
4541 weeks[3] = "Wednesday";
4542 weeks[4] = "Thursday";
4543 weeks[5] = "Friday";
4544 weeks[6] = "Saturday";
4545 weeks[7] = "Sun";
4546 weeks[8] = "Mon";
4547 weeks[9] = "Tue";
4548 weeks[10] = "Wed";
4549 weeks[11] = "Thu";
4550 weeks[12] = "Fri";
4551 weeks[13] = "Sat";
4552 return weeks;
4553}
4554
4555static
4556wstring*
4557init_wweeks()
4558{
4559 static wstring weeks[14];
4560 weeks[0] = L"Sunday";
4561 weeks[1] = L"Monday";
4562 weeks[2] = L"Tuesday";
4563 weeks[3] = L"Wednesday";
4564 weeks[4] = L"Thursday";
4565 weeks[5] = L"Friday";
4566 weeks[6] = L"Saturday";
4567 weeks[7] = L"Sun";
4568 weeks[8] = L"Mon";
4569 weeks[9] = L"Tue";
4570 weeks[10] = L"Wed";
4571 weeks[11] = L"Thu";
4572 weeks[12] = L"Fri";
4573 weeks[13] = L"Sat";
4574 return weeks;
4575}
4576
4577template <>
4578const string*
4579__time_get_c_storage<char>::__weeks() const
4580{
4581 static const string* weeks = init_weeks();
4582 return weeks;
4583}
4584
4585template <>
4586const wstring*
4587__time_get_c_storage<wchar_t>::__weeks() const
4588{
4589 static const wstring* weeks = init_wweeks();
4590 return weeks;
4591}
4592
4593static
4594string*
4595init_months()
4596{
4597 static string months[24];
4598 months[0] = "January";
4599 months[1] = "February";
4600 months[2] = "March";
4601 months[3] = "April";
4602 months[4] = "May";
4603 months[5] = "June";
4604 months[6] = "July";
4605 months[7] = "August";
4606 months[8] = "September";
4607 months[9] = "October";
4608 months[10] = "November";
4609 months[11] = "December";
4610 months[12] = "Jan";
4611 months[13] = "Feb";
4612 months[14] = "Mar";
4613 months[15] = "Apr";
4614 months[16] = "May";
4615 months[17] = "Jun";
4616 months[18] = "Jul";
4617 months[19] = "Aug";
4618 months[20] = "Sep";
4619 months[21] = "Oct";
4620 months[22] = "Nov";
4621 months[23] = "Dec";
4622 return months;
4623}
4624
4625static
4626wstring*
4627init_wmonths()
4628{
4629 static wstring months[24];
4630 months[0] = L"January";
4631 months[1] = L"February";
4632 months[2] = L"March";
4633 months[3] = L"April";
4634 months[4] = L"May";
4635 months[5] = L"June";
4636 months[6] = L"July";
4637 months[7] = L"August";
4638 months[8] = L"September";
4639 months[9] = L"October";
4640 months[10] = L"November";
4641 months[11] = L"December";
4642 months[12] = L"Jan";
4643 months[13] = L"Feb";
4644 months[14] = L"Mar";
4645 months[15] = L"Apr";
4646 months[16] = L"May";
4647 months[17] = L"Jun";
4648 months[18] = L"Jul";
4649 months[19] = L"Aug";
4650 months[20] = L"Sep";
4651 months[21] = L"Oct";
4652 months[22] = L"Nov";
4653 months[23] = L"Dec";
4654 return months;
4655}
4656
4657template <>
4658const string*
4659__time_get_c_storage<char>::__months() const
4660{
4661 static const string* months = init_months();
4662 return months;
4663}
4664
4665template <>
4666const wstring*
4667__time_get_c_storage<wchar_t>::__months() const
4668{
4669 static const wstring* months = init_wmonths();
4670 return months;
4671}
4672
4673static
4674string*
4675init_am_pm()
4676{
4677 static string am_pm[24];
4678 am_pm[0] = "AM";
4679 am_pm[1] = "PM";
4680 return am_pm;
4681}
4682
4683static
4684wstring*
4685init_wam_pm()
4686{
4687 static wstring am_pm[24];
4688 am_pm[0] = L"AM";
4689 am_pm[1] = L"PM";
4690 return am_pm;
4691}
4692
4693template <>
4694const string*
4695__time_get_c_storage<char>::__am_pm() const
4696{
4697 static const string* am_pm = init_am_pm();
4698 return am_pm;
4699}
4700
4701template <>
4702const wstring*
4703__time_get_c_storage<wchar_t>::__am_pm() const
4704{
4705 static const wstring* am_pm = init_wam_pm();
4706 return am_pm;
4707}
4708
4709template <>
4710const string&
4711__time_get_c_storage<char>::__x() const
4712{
4713 static string s("%m/%d/%y");
4714 return s;
4715}
4716
4717template <>
4718const wstring&
4719__time_get_c_storage<wchar_t>::__x() const
4720{
4721 static wstring s(L"%m/%d/%y");
4722 return s;
4723}
4724
4725template <>
4726const string&
4727__time_get_c_storage<char>::__X() const
4728{
4729 static string s("%H:%M:%S");
4730 return s;
4731}
4732
4733template <>
4734const wstring&
4735__time_get_c_storage<wchar_t>::__X() const
4736{
4737 static wstring s(L"%H:%M:%S");
4738 return s;
4739}
4740
4741template <>
4742const string&
4743__time_get_c_storage<char>::__c() const
4744{
4745 static string s("%a %b %d %H:%M:%S %Y");
4746 return s;
4747}
4748
4749template <>
4750const wstring&
4751__time_get_c_storage<wchar_t>::__c() const
4752{
4753 static wstring s(L"%a %b %d %H:%M:%S %Y");
4754 return s;
4755}
4756
4757template <>
4758const string&
4759__time_get_c_storage<char>::__r() const
4760{
4761 static string s("%I:%M:%S %p");
4762 return s;
4763}
4764
4765template <>
4766const wstring&
4767__time_get_c_storage<wchar_t>::__r() const
4768{
4769 static wstring s(L"%I:%M:%S %p");
4770 return s;
4771}
4772
4773// time_get_byname
4774
4775__time_get::__time_get(const char* nm)
4776 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4777{
Howard Hinnantd4444702010-08-11 17:04:31 +00004778#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004779 if (__loc_ == 0)
4780 throw runtime_error("time_get_byname"
4781 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004782#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004783}
4784
4785__time_get::__time_get(const string& nm)
4786 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4787{
Howard Hinnantd4444702010-08-11 17:04:31 +00004788#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004789 if (__loc_ == 0)
4790 throw runtime_error("time_get_byname"
4791 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004792#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004793}
4794
4795__time_get::~__time_get()
4796{
4797 freelocale(__loc_);
4798}
Marshall Clowa3645132013-10-21 15:07:28 +00004799#if defined(__clang__)
Howard Hinnant335b1512012-02-20 16:51:43 +00004800#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004801#endif
4802#if defined(__GNUG__)
Howard Hinnant21772ec2012-12-28 18:15:01 +00004803#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004804#endif
Howard Hinnant335b1512012-02-20 16:51:43 +00004805
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004806template <>
4807string
4808__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4809{
Howard Hinnant3074a052012-02-19 14:55:32 +00004810 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004811 t.tm_sec = 59;
4812 t.tm_min = 55;
4813 t.tm_hour = 23;
4814 t.tm_mday = 31;
4815 t.tm_mon = 11;
4816 t.tm_year = 161;
4817 t.tm_wday = 6;
4818 t.tm_yday = 364;
4819 t.tm_isdst = -1;
4820 char buf[100];
4821 char f[3] = {0};
4822 f[0] = '%';
4823 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004824 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004825 char* bb = buf;
4826 char* be = buf + n;
4827 string result;
4828 while (bb != be)
4829 {
4830 if (ct.is(ctype_base::space, *bb))
4831 {
4832 result.push_back(' ');
4833 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4834 ;
4835 continue;
4836 }
4837 char* w = bb;
4838 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004839 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004840 ct, err, false)
4841 - this->__weeks_;
4842 if (i < 14)
4843 {
4844 result.push_back('%');
4845 if (i < 7)
4846 result.push_back('A');
4847 else
4848 result.push_back('a');
4849 bb = w;
4850 continue;
4851 }
4852 w = bb;
4853 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4854 ct, err, false)
4855 - this->__months_;
4856 if (i < 24)
4857 {
4858 result.push_back('%');
4859 if (i < 12)
4860 result.push_back('B');
4861 else
4862 result.push_back('b');
4863 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4864 result.back() = 'm';
4865 bb = w;
4866 continue;
4867 }
4868 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4869 {
4870 w = bb;
4871 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4872 ct, err, false) - this->__am_pm_;
4873 if (i < 2)
4874 {
4875 result.push_back('%');
4876 result.push_back('p');
4877 bb = w;
4878 continue;
4879 }
4880 }
4881 w = bb;
4882 if (ct.is(ctype_base::digit, *bb))
4883 {
4884 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4885 {
4886 case 6:
4887 result.push_back('%');
4888 result.push_back('w');
4889 break;
4890 case 7:
4891 result.push_back('%');
4892 result.push_back('u');
4893 break;
4894 case 11:
4895 result.push_back('%');
4896 result.push_back('I');
4897 break;
4898 case 12:
4899 result.push_back('%');
4900 result.push_back('m');
4901 break;
4902 case 23:
4903 result.push_back('%');
4904 result.push_back('H');
4905 break;
4906 case 31:
4907 result.push_back('%');
4908 result.push_back('d');
4909 break;
4910 case 55:
4911 result.push_back('%');
4912 result.push_back('M');
4913 break;
4914 case 59:
4915 result.push_back('%');
4916 result.push_back('S');
4917 break;
4918 case 61:
4919 result.push_back('%');
4920 result.push_back('y');
4921 break;
4922 case 364:
4923 result.push_back('%');
4924 result.push_back('j');
4925 break;
4926 case 2061:
4927 result.push_back('%');
4928 result.push_back('Y');
4929 break;
4930 default:
4931 for (; w != bb; ++w)
4932 result.push_back(*w);
4933 break;
4934 }
4935 continue;
4936 }
4937 if (*bb == '%')
4938 {
4939 result.push_back('%');
4940 result.push_back('%');
4941 ++bb;
4942 continue;
4943 }
4944 result.push_back(*bb);
4945 ++bb;
4946 }
4947 return result;
4948}
4949
Marshall Clowa3645132013-10-21 15:07:28 +00004950#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +00004951#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowa3645132013-10-21 15:07:28 +00004952#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004953
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004954template <>
4955wstring
4956__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4957{
Howard Hinnant3074a052012-02-19 14:55:32 +00004958 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004959 t.tm_sec = 59;
4960 t.tm_min = 55;
4961 t.tm_hour = 23;
4962 t.tm_mday = 31;
4963 t.tm_mon = 11;
4964 t.tm_year = 161;
4965 t.tm_wday = 6;
4966 t.tm_yday = 364;
4967 t.tm_isdst = -1;
4968 char buf[100];
4969 char f[3] = {0};
4970 f[0] = '%';
4971 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004972 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004973 wchar_t wbuf[100];
4974 wchar_t* wbb = wbuf;
4975 mbstate_t mb = {0};
4976 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004977#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004978 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004979#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004980 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004981#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004982 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004983 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004984 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004985 wstring result;
4986 while (wbb != wbe)
4987 {
4988 if (ct.is(ctype_base::space, *wbb))
4989 {
4990 result.push_back(L' ');
4991 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4992 ;
4993 continue;
4994 }
4995 wchar_t* w = wbb;
4996 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004997 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004998 ct, err, false)
4999 - this->__weeks_;
5000 if (i < 14)
5001 {
5002 result.push_back(L'%');
5003 if (i < 7)
5004 result.push_back(L'A');
5005 else
5006 result.push_back(L'a');
5007 wbb = w;
5008 continue;
5009 }
5010 w = wbb;
5011 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5012 ct, err, false)
5013 - this->__months_;
5014 if (i < 24)
5015 {
5016 result.push_back(L'%');
5017 if (i < 12)
5018 result.push_back(L'B');
5019 else
5020 result.push_back(L'b');
5021 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5022 result.back() = L'm';
5023 wbb = w;
5024 continue;
5025 }
5026 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5027 {
5028 w = wbb;
5029 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5030 ct, err, false) - this->__am_pm_;
5031 if (i < 2)
5032 {
5033 result.push_back(L'%');
5034 result.push_back(L'p');
5035 wbb = w;
5036 continue;
5037 }
5038 }
5039 w = wbb;
5040 if (ct.is(ctype_base::digit, *wbb))
5041 {
5042 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5043 {
5044 case 6:
5045 result.push_back(L'%');
5046 result.push_back(L'w');
5047 break;
5048 case 7:
5049 result.push_back(L'%');
5050 result.push_back(L'u');
5051 break;
5052 case 11:
5053 result.push_back(L'%');
5054 result.push_back(L'I');
5055 break;
5056 case 12:
5057 result.push_back(L'%');
5058 result.push_back(L'm');
5059 break;
5060 case 23:
5061 result.push_back(L'%');
5062 result.push_back(L'H');
5063 break;
5064 case 31:
5065 result.push_back(L'%');
5066 result.push_back(L'd');
5067 break;
5068 case 55:
5069 result.push_back(L'%');
5070 result.push_back(L'M');
5071 break;
5072 case 59:
5073 result.push_back(L'%');
5074 result.push_back(L'S');
5075 break;
5076 case 61:
5077 result.push_back(L'%');
5078 result.push_back(L'y');
5079 break;
5080 case 364:
5081 result.push_back(L'%');
5082 result.push_back(L'j');
5083 break;
5084 case 2061:
5085 result.push_back(L'%');
5086 result.push_back(L'Y');
5087 break;
5088 default:
5089 for (; w != wbb; ++w)
5090 result.push_back(*w);
5091 break;
5092 }
5093 continue;
5094 }
5095 if (ct.narrow(*wbb, 0) == '%')
5096 {
5097 result.push_back(L'%');
5098 result.push_back(L'%');
5099 ++wbb;
5100 continue;
5101 }
5102 result.push_back(*wbb);
5103 ++wbb;
5104 }
5105 return result;
5106}
5107
5108template <>
5109void
5110__time_get_storage<char>::init(const ctype<char>& ct)
5111{
Howard Hinnantcd992362012-08-02 18:44:17 +00005112 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005113 char buf[100];
5114 // __weeks_
5115 for (int i = 0; i < 7; ++i)
5116 {
5117 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005118 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005119 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005120 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005121 __weeks_[i+7] = buf;
5122 }
5123 // __months_
5124 for (int i = 0; i < 12; ++i)
5125 {
5126 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005127 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005128 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005129 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005130 __months_[i+12] = buf;
5131 }
5132 // __am_pm_
5133 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005134 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005135 __am_pm_[0] = buf;
5136 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005137 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005138 __am_pm_[1] = buf;
5139 __c_ = __analyze('c', ct);
5140 __r_ = __analyze('r', ct);
5141 __x_ = __analyze('x', ct);
5142 __X_ = __analyze('X', ct);
5143}
5144
5145template <>
5146void
5147__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5148{
5149 tm t = {0};
5150 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005151 wchar_t wbuf[100];
5152 wchar_t* wbe;
5153 mbstate_t mb = {0};
5154 // __weeks_
5155 for (int i = 0; i < 7; ++i)
5156 {
5157 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005158 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005159 mb = mbstate_t();
5160 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005161#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005162 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005163#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005164 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005165#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005166 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005167 __throw_runtime_error("locale not supported");
5168 wbe = wbuf + j;
5169 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005170 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005171 mb = mbstate_t();
5172 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005173#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005174 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005175#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005176 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005177#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005178 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005179 __throw_runtime_error("locale not supported");
5180 wbe = wbuf + j;
5181 __weeks_[i+7].assign(wbuf, wbe);
5182 }
5183 // __months_
5184 for (int i = 0; i < 12; ++i)
5185 {
5186 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005187 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005188 mb = mbstate_t();
5189 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005190#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005191 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005192#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005193 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005194#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005195 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005196 __throw_runtime_error("locale not supported");
5197 wbe = wbuf + j;
5198 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005199 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005200 mb = mbstate_t();
5201 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005202#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005203 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005204#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005205 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005206#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005207 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005208 __throw_runtime_error("locale not supported");
5209 wbe = wbuf + j;
5210 __months_[i+12].assign(wbuf, wbe);
5211 }
5212 // __am_pm_
5213 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005214 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005215 mb = mbstate_t();
5216 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005217#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005218 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005219#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005220 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005221#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005222 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005223 __throw_runtime_error("locale not supported");
5224 wbe = wbuf + j;
5225 __am_pm_[0].assign(wbuf, wbe);
5226 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005227 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005228 mb = mbstate_t();
5229 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005230#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005231 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005232#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005233 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005234#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005235 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005236 __throw_runtime_error("locale not supported");
5237 wbe = wbuf + j;
5238 __am_pm_[1].assign(wbuf, wbe);
5239 __c_ = __analyze('c', ct);
5240 __r_ = __analyze('r', ct);
5241 __x_ = __analyze('x', ct);
5242 __X_ = __analyze('X', ct);
5243}
5244
5245template <class CharT>
5246struct _LIBCPP_HIDDEN __time_get_temp
5247 : public ctype_byname<CharT>
5248{
5249 explicit __time_get_temp(const char* nm)
5250 : ctype_byname<CharT>(nm, 1) {}
5251 explicit __time_get_temp(const string& nm)
5252 : ctype_byname<CharT>(nm, 1) {}
5253};
5254
5255template <>
5256__time_get_storage<char>::__time_get_storage(const char* __nm)
5257 : __time_get(__nm)
5258{
5259 const __time_get_temp<char> ct(__nm);
5260 init(ct);
5261}
5262
5263template <>
5264__time_get_storage<char>::__time_get_storage(const string& __nm)
5265 : __time_get(__nm)
5266{
5267 const __time_get_temp<char> ct(__nm);
5268 init(ct);
5269}
5270
5271template <>
5272__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5273 : __time_get(__nm)
5274{
5275 const __time_get_temp<wchar_t> ct(__nm);
5276 init(ct);
5277}
5278
5279template <>
5280__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5281 : __time_get(__nm)
5282{
5283 const __time_get_temp<wchar_t> ct(__nm);
5284 init(ct);
5285}
5286
5287template <>
5288time_base::dateorder
5289__time_get_storage<char>::__do_date_order() const
5290{
5291 unsigned i;
5292 for (i = 0; i < __x_.size(); ++i)
5293 if (__x_[i] == '%')
5294 break;
5295 ++i;
5296 switch (__x_[i])
5297 {
5298 case 'y':
5299 case 'Y':
5300 for (++i; i < __x_.size(); ++i)
5301 if (__x_[i] == '%')
5302 break;
5303 if (i == __x_.size())
5304 break;
5305 ++i;
5306 switch (__x_[i])
5307 {
5308 case 'm':
5309 for (++i; i < __x_.size(); ++i)
5310 if (__x_[i] == '%')
5311 break;
5312 if (i == __x_.size())
5313 break;
5314 ++i;
5315 if (__x_[i] == 'd')
5316 return time_base::ymd;
5317 break;
5318 case 'd':
5319 for (++i; i < __x_.size(); ++i)
5320 if (__x_[i] == '%')
5321 break;
5322 if (i == __x_.size())
5323 break;
5324 ++i;
5325 if (__x_[i] == 'm')
5326 return time_base::ydm;
5327 break;
5328 }
5329 break;
5330 case 'm':
5331 for (++i; i < __x_.size(); ++i)
5332 if (__x_[i] == '%')
5333 break;
5334 if (i == __x_.size())
5335 break;
5336 ++i;
5337 if (__x_[i] == 'd')
5338 {
5339 for (++i; i < __x_.size(); ++i)
5340 if (__x_[i] == '%')
5341 break;
5342 if (i == __x_.size())
5343 break;
5344 ++i;
5345 if (__x_[i] == 'y' || __x_[i] == 'Y')
5346 return time_base::mdy;
5347 break;
5348 }
5349 break;
5350 case 'd':
5351 for (++i; i < __x_.size(); ++i)
5352 if (__x_[i] == '%')
5353 break;
5354 if (i == __x_.size())
5355 break;
5356 ++i;
5357 if (__x_[i] == 'm')
5358 {
5359 for (++i; i < __x_.size(); ++i)
5360 if (__x_[i] == '%')
5361 break;
5362 if (i == __x_.size())
5363 break;
5364 ++i;
5365 if (__x_[i] == 'y' || __x_[i] == 'Y')
5366 return time_base::dmy;
5367 break;
5368 }
5369 break;
5370 }
5371 return time_base::no_order;
5372}
5373
5374template <>
5375time_base::dateorder
5376__time_get_storage<wchar_t>::__do_date_order() const
5377{
5378 unsigned i;
5379 for (i = 0; i < __x_.size(); ++i)
5380 if (__x_[i] == L'%')
5381 break;
5382 ++i;
5383 switch (__x_[i])
5384 {
5385 case L'y':
5386 case L'Y':
5387 for (++i; i < __x_.size(); ++i)
5388 if (__x_[i] == L'%')
5389 break;
5390 if (i == __x_.size())
5391 break;
5392 ++i;
5393 switch (__x_[i])
5394 {
5395 case L'm':
5396 for (++i; i < __x_.size(); ++i)
5397 if (__x_[i] == L'%')
5398 break;
5399 if (i == __x_.size())
5400 break;
5401 ++i;
5402 if (__x_[i] == L'd')
5403 return time_base::ymd;
5404 break;
5405 case L'd':
5406 for (++i; i < __x_.size(); ++i)
5407 if (__x_[i] == L'%')
5408 break;
5409 if (i == __x_.size())
5410 break;
5411 ++i;
5412 if (__x_[i] == L'm')
5413 return time_base::ydm;
5414 break;
5415 }
5416 break;
5417 case L'm':
5418 for (++i; i < __x_.size(); ++i)
5419 if (__x_[i] == L'%')
5420 break;
5421 if (i == __x_.size())
5422 break;
5423 ++i;
5424 if (__x_[i] == L'd')
5425 {
5426 for (++i; i < __x_.size(); ++i)
5427 if (__x_[i] == L'%')
5428 break;
5429 if (i == __x_.size())
5430 break;
5431 ++i;
5432 if (__x_[i] == L'y' || __x_[i] == L'Y')
5433 return time_base::mdy;
5434 break;
5435 }
5436 break;
5437 case L'd':
5438 for (++i; i < __x_.size(); ++i)
5439 if (__x_[i] == L'%')
5440 break;
5441 if (i == __x_.size())
5442 break;
5443 ++i;
5444 if (__x_[i] == L'm')
5445 {
5446 for (++i; i < __x_.size(); ++i)
5447 if (__x_[i] == L'%')
5448 break;
5449 if (i == __x_.size())
5450 break;
5451 ++i;
5452 if (__x_[i] == L'y' || __x_[i] == L'Y')
5453 return time_base::dmy;
5454 break;
5455 }
5456 break;
5457 }
5458 return time_base::no_order;
5459}
5460
5461// time_put
5462
5463__time_put::__time_put(const char* nm)
5464 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5465{
Howard Hinnantd4444702010-08-11 17:04:31 +00005466#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005467 if (__loc_ == 0)
5468 throw runtime_error("time_put_byname"
5469 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005470#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005471}
5472
5473__time_put::__time_put(const string& nm)
5474 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5475{
Howard Hinnantd4444702010-08-11 17:04:31 +00005476#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005477 if (__loc_ == 0)
5478 throw runtime_error("time_put_byname"
5479 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005480#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005481}
5482
5483__time_put::~__time_put()
5484{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005485 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005486 freelocale(__loc_);
5487}
5488
5489void
5490__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5491 char __fmt, char __mod) const
5492{
5493 char fmt[] = {'%', __fmt, __mod, 0};
5494 if (__mod != 0)
5495 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005496 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005497 __ne = __nb + n;
5498}
5499
5500void
5501__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5502 char __fmt, char __mod) const
5503{
5504 char __nar[100];
5505 char* __ne = __nar + 100;
5506 __do_put(__nar, __ne, __tm, __fmt, __mod);
5507 mbstate_t mb = {0};
5508 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005509#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005510 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005511#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005512 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005513#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005514 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005515 __throw_runtime_error("locale not supported");
5516 __we = __wb + j;
5517}
5518
5519// moneypunct_byname
5520
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005521template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005522static
5523void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005524__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5525 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5526 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005527{
5528 const char sign = static_cast<char>(money_base::sign);
5529 const char space = static_cast<char>(money_base::space);
5530 const char none = static_cast<char>(money_base::none);
5531 const char symbol = static_cast<char>(money_base::symbol);
5532 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005533 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5534
5535 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5536 // function'. "Space between sign and symbol or value" means that
5537 // if the sign is adjacent to the symbol, there's a space between
5538 // them, and otherwise there's a space between the sign and value.
5539 //
5540 // C11's localeconv specifies that the fourth character of an
5541 // international curr_symbol is used to separate the sign and
5542 // value when sep_by_space says to do so. C++ can't represent
5543 // that, so we just use a space. When sep_by_space says to
5544 // separate the symbol and value-or-sign with a space, we rearrange the
5545 // curr_symbol to put its spacing character on the correct side of
5546 // the symbol.
5547 //
5548 // We also need to avoid adding an extra space between the sign
5549 // and value when the currency symbol is suppressed (by not
5550 // setting showbase). We match glibc's strfmon by interpreting
5551 // sep_by_space==1 as "omit the space when the currency symbol is
5552 // absent".
5553 //
5554 // Users who want to get this right should use ICU instead.
5555
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005556 switch (cs_precedes)
5557 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005558 case 0: // value before curr_symbol
5559 if (symbol_contains_sep) {
5560 // Move the separator to before the symbol, to place it
5561 // between the value and symbol.
5562 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5563 __curr_symbol_.end());
5564 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005565 switch (sign_posn)
5566 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005567 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005568 pat.field[0] = sign;
5569 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005570 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 pat.field[3] = symbol;
5572 switch (sep_by_space)
5573 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005574 case 0: // No space separates the currency symbol and value.
5575 // This case may have changed between C99 and C11;
5576 // assume the currency symbol matches the intention.
5577 case 2: // Space between sign and currency or value.
5578 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005579 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005580 case 1: // Space between currency-and-sign or currency and value.
5581 if (!symbol_contains_sep) {
5582 // We insert the space into the symbol instead of
5583 // setting pat.field[2]=space so that when
5584 // showbase is not set, the space goes away too.
5585 __curr_symbol_.insert(0, 1, space_char);
5586 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005587 return;
5588 default:
5589 break;
5590 }
5591 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005592 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005593 pat.field[0] = sign;
5594 pat.field[3] = symbol;
5595 switch (sep_by_space)
5596 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005597 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005598 pat.field[1] = value;
5599 pat.field[2] = none;
5600 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005601 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005602 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005603 pat.field[2] = none;
5604 if (!symbol_contains_sep) {
5605 // We insert the space into the symbol instead of
5606 // setting pat.field[2]=space so that when
5607 // showbase is not set, the space goes away too.
5608 __curr_symbol_.insert(0, 1, space_char);
5609 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005610 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005611 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005612 pat.field[1] = space;
5613 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005614 if (symbol_contains_sep) {
5615 // Remove the separator from the symbol, since it
5616 // has already appeared after the sign.
5617 __curr_symbol_.erase(__curr_symbol_.begin());
5618 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005619 return;
5620 default:
5621 break;
5622 }
5623 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005624 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005625 pat.field[0] = value;
5626 pat.field[3] = sign;
5627 switch (sep_by_space)
5628 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005629 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005630 pat.field[1] = none;
5631 pat.field[2] = symbol;
5632 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005633 case 1: // Space between currency-and-sign or currency and value.
5634 if (!symbol_contains_sep) {
5635 // We insert the space into the symbol instead of
5636 // setting pat.field[1]=space so that when
5637 // showbase is not set, the space goes away too.
5638 __curr_symbol_.insert(0, 1, space_char);
5639 }
5640 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005641 pat.field[2] = symbol;
5642 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005643 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005644 pat.field[1] = symbol;
5645 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005646 if (symbol_contains_sep) {
5647 // Remove the separator from the symbol, since it
5648 // should not be removed if showbase is absent.
5649 __curr_symbol_.erase(__curr_symbol_.begin());
5650 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005651 return;
5652 default:
5653 break;
5654 }
5655 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005656 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005657 pat.field[0] = value;
5658 pat.field[3] = symbol;
5659 switch (sep_by_space)
5660 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005661 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005662 pat.field[1] = none;
5663 pat.field[2] = sign;
5664 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005665 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005666 pat.field[1] = space;
5667 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 if (symbol_contains_sep) {
5669 // Remove the separator from the symbol, since it
5670 // has already appeared before the sign.
5671 __curr_symbol_.erase(__curr_symbol_.begin());
5672 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005673 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005674 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005675 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005676 pat.field[2] = none;
5677 if (!symbol_contains_sep) {
5678 // We insert the space into the symbol instead of
5679 // setting pat.field[2]=space so that when
5680 // showbase is not set, the space goes away too.
5681 __curr_symbol_.insert(0, 1, space_char);
5682 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005683 return;
5684 default:
5685 break;
5686 }
5687 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005688 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005689 pat.field[0] = value;
5690 pat.field[3] = sign;
5691 switch (sep_by_space)
5692 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005693 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005694 pat.field[1] = none;
5695 pat.field[2] = symbol;
5696 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005697 case 1: // Space between currency-and-sign or currency and value.
5698 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005699 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005700 if (!symbol_contains_sep) {
5701 // We insert the space into the symbol instead of
5702 // setting pat.field[1]=space so that when
5703 // showbase is not set, the space goes away too.
5704 __curr_symbol_.insert(0, 1, space_char);
5705 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005706 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005707 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005708 pat.field[1] = symbol;
5709 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005710 if (symbol_contains_sep) {
5711 // Remove the separator from the symbol, since it
5712 // should not disappear when showbase is absent.
5713 __curr_symbol_.erase(__curr_symbol_.begin());
5714 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005715 return;
5716 default:
5717 break;
5718 }
5719 break;
5720 default:
5721 break;
5722 }
5723 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005724 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005725 switch (sign_posn)
5726 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005727 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005728 pat.field[0] = sign;
5729 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005730 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731 pat.field[3] = value;
5732 switch (sep_by_space)
5733 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005734 case 0: // No space separates the currency symbol and value.
5735 // This case may have changed between C99 and C11;
5736 // assume the currency symbol matches the intention.
5737 case 2: // Space between sign and currency or value.
5738 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005739 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005740 case 1: // Space between currency-and-sign or currency and value.
5741 if (!symbol_contains_sep) {
5742 // We insert the space into the symbol instead of
5743 // setting pat.field[2]=space so that when
5744 // showbase is not set, the space goes away too.
5745 __curr_symbol_.insert(0, 1, space_char);
5746 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005747 return;
5748 default:
5749 break;
5750 }
5751 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005752 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005753 pat.field[0] = sign;
5754 pat.field[3] = value;
5755 switch (sep_by_space)
5756 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005757 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005758 pat.field[1] = symbol;
5759 pat.field[2] = none;
5760 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005761 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005762 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005763 pat.field[2] = none;
5764 if (!symbol_contains_sep) {
5765 // We insert the space into the symbol instead of
5766 // setting pat.field[2]=space so that when
5767 // showbase is not set, the space goes away too.
5768 __curr_symbol_.push_back(space_char);
5769 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005770 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005771 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005772 pat.field[1] = space;
5773 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005774 if (symbol_contains_sep) {
5775 // Remove the separator from the symbol, since it
5776 // has already appeared after the sign.
5777 __curr_symbol_.pop_back();
5778 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005779 return;
5780 default:
5781 break;
5782 }
5783 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005784 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005785 pat.field[0] = symbol;
5786 pat.field[3] = sign;
5787 switch (sep_by_space)
5788 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005789 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005790 pat.field[1] = none;
5791 pat.field[2] = value;
5792 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005793 case 1: // Space between currency-and-sign or currency and value.
5794 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005795 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005796 if (!symbol_contains_sep) {
5797 // We insert the space into the symbol instead of
5798 // setting pat.field[1]=space so that when
5799 // showbase is not set, the space goes away too.
5800 __curr_symbol_.push_back(space_char);
5801 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005802 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005803 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005804 pat.field[1] = value;
5805 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005806 if (symbol_contains_sep) {
5807 // Remove the separator from the symbol, since it
5808 // will appear before the sign.
5809 __curr_symbol_.pop_back();
5810 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005811 return;
5812 default:
5813 break;
5814 }
5815 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005816 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005817 pat.field[0] = sign;
5818 pat.field[3] = value;
5819 switch (sep_by_space)
5820 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005821 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005822 pat.field[1] = symbol;
5823 pat.field[2] = none;
5824 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005825 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005826 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005827 pat.field[2] = none;
5828 if (!symbol_contains_sep) {
5829 // We insert the space into the symbol instead of
5830 // setting pat.field[2]=space so that when
5831 // showbase is not set, the space goes away too.
5832 __curr_symbol_.push_back(space_char);
5833 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005834 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005835 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005836 pat.field[1] = space;
5837 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005838 if (symbol_contains_sep) {
5839 // Remove the separator from the symbol, since it
5840 // has already appeared after the sign.
5841 __curr_symbol_.pop_back();
5842 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005843 return;
5844 default:
5845 break;
5846 }
5847 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005848 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005849 pat.field[0] = symbol;
5850 pat.field[3] = value;
5851 switch (sep_by_space)
5852 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005853 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005854 pat.field[1] = sign;
5855 pat.field[2] = none;
5856 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005857 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005858 pat.field[1] = sign;
5859 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005860 if (symbol_contains_sep) {
5861 // Remove the separator from the symbol, since it
5862 // should not disappear when showbase is absent.
5863 __curr_symbol_.pop_back();
5864 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005865 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005866 case 2: // Space between sign and currency or value.
5867 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005868 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005869 if (!symbol_contains_sep) {
5870 // We insert the space into the symbol instead of
5871 // setting pat.field[1]=space so that when
5872 // showbase is not set, the space goes away too.
5873 __curr_symbol_.push_back(space_char);
5874 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005875 return;
5876 default:
5877 break;
5878 }
5879 break;
5880 default:
5881 break;
5882 }
5883 break;
5884 default:
5885 break;
5886 }
5887 pat.field[0] = symbol;
5888 pat.field[1] = sign;
5889 pat.field[2] = none;
5890 pat.field[3] = value;
5891}
5892
5893template<>
5894void
5895moneypunct_byname<char, false>::init(const char* nm)
5896{
5897 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005898 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005899#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005900 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005901 throw runtime_error("moneypunct_byname"
5902 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005903#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005904#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005905 lconv* lc = localeconv_l(loc.get());
5906#else
5907 lconv* lc = __localeconv_l(loc.get());
5908#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005909 if (*lc->mon_decimal_point)
5910 __decimal_point_ = *lc->mon_decimal_point;
5911 else
5912 __decimal_point_ = base::do_decimal_point();
5913 if (*lc->mon_thousands_sep)
5914 __thousands_sep_ = *lc->mon_thousands_sep;
5915 else
5916 __thousands_sep_ = base::do_thousands_sep();
5917 __grouping_ = lc->mon_grouping;
5918 __curr_symbol_ = lc->currency_symbol;
5919 if (lc->frac_digits != CHAR_MAX)
5920 __frac_digits_ = lc->frac_digits;
5921 else
5922 __frac_digits_ = base::do_frac_digits();
5923 if (lc->p_sign_posn == 0)
5924 __positive_sign_ = "()";
5925 else
5926 __positive_sign_ = lc->positive_sign;
5927 if (lc->n_sign_posn == 0)
5928 __negative_sign_ = "()";
5929 else
5930 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005931 // Assume the positive and negative formats will want spaces in
5932 // the same places in curr_symbol since there's no way to
5933 // represent anything else.
5934 string_type __dummy_curr_symbol = __curr_symbol_;
5935 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5936 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5937 __init_pat(__neg_format_, __curr_symbol_, false,
5938 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005939}
5940
5941template<>
5942void
5943moneypunct_byname<char, true>::init(const char* nm)
5944{
5945 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005946 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005947#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005948 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005949 throw runtime_error("moneypunct_byname"
5950 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005951#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005952#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005953 lconv* lc = localeconv_l(loc.get());
5954#else
5955 lconv* lc = __localeconv_l(loc.get());
5956#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005957 if (*lc->mon_decimal_point)
5958 __decimal_point_ = *lc->mon_decimal_point;
5959 else
5960 __decimal_point_ = base::do_decimal_point();
5961 if (*lc->mon_thousands_sep)
5962 __thousands_sep_ = *lc->mon_thousands_sep;
5963 else
5964 __thousands_sep_ = base::do_thousands_sep();
5965 __grouping_ = lc->mon_grouping;
5966 __curr_symbol_ = lc->int_curr_symbol;
5967 if (lc->int_frac_digits != CHAR_MAX)
5968 __frac_digits_ = lc->int_frac_digits;
5969 else
5970 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00005971#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005972 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005973#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005974 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005975#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005976 __positive_sign_ = "()";
5977 else
5978 __positive_sign_ = lc->positive_sign;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005979#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005980 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005981#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005982 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005983#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005984 __negative_sign_ = "()";
5985 else
5986 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005987 // Assume the positive and negative formats will want spaces in
5988 // the same places in curr_symbol since there's no way to
5989 // represent anything else.
5990 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005991#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005992 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5993 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5994 __init_pat(__neg_format_, __curr_symbol_, true,
5995 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005996#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005997 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5998 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5999 lc->int_p_sign_posn, ' ');
6000 __init_pat(__neg_format_, __curr_symbol_, true,
6001 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6002 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006003#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006004}
6005
6006template<>
6007void
6008moneypunct_byname<wchar_t, false>::init(const char* nm)
6009{
6010 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006011 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006012#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006013 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006014 throw runtime_error("moneypunct_byname"
6015 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006016#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006017#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006018 lconv* lc = localeconv_l(loc.get());
6019#else
6020 lconv* lc = __localeconv_l(loc.get());
6021#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006022 if (*lc->mon_decimal_point)
6023 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6024 else
6025 __decimal_point_ = base::do_decimal_point();
6026 if (*lc->mon_thousands_sep)
6027 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6028 else
6029 __thousands_sep_ = base::do_thousands_sep();
6030 __grouping_ = lc->mon_grouping;
6031 wchar_t wbuf[100];
6032 mbstate_t mb = {0};
6033 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006034#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006035 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006036#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006037 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006038#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006039 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006040 __throw_runtime_error("locale not supported");
6041 wchar_t* wbe = wbuf + j;
6042 __curr_symbol_.assign(wbuf, wbe);
6043 if (lc->frac_digits != CHAR_MAX)
6044 __frac_digits_ = lc->frac_digits;
6045 else
6046 __frac_digits_ = base::do_frac_digits();
6047 if (lc->p_sign_posn == 0)
6048 __positive_sign_ = L"()";
6049 else
6050 {
6051 mb = mbstate_t();
6052 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006053#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006054 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006055#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006056 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006057#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006058 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006059 __throw_runtime_error("locale not supported");
6060 wbe = wbuf + j;
6061 __positive_sign_.assign(wbuf, wbe);
6062 }
6063 if (lc->n_sign_posn == 0)
6064 __negative_sign_ = L"()";
6065 else
6066 {
6067 mb = mbstate_t();
6068 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006069#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006070 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006071#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006072 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006073#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006074 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006075 __throw_runtime_error("locale not supported");
6076 wbe = wbuf + j;
6077 __negative_sign_.assign(wbuf, wbe);
6078 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006079 // Assume the positive and negative formats will want spaces in
6080 // the same places in curr_symbol since there's no way to
6081 // represent anything else.
6082 string_type __dummy_curr_symbol = __curr_symbol_;
6083 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6084 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6085 __init_pat(__neg_format_, __curr_symbol_, false,
6086 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006087}
6088
6089template<>
6090void
6091moneypunct_byname<wchar_t, true>::init(const char* nm)
6092{
6093 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006094 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006095#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006096 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006097 throw runtime_error("moneypunct_byname"
6098 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006099#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006100#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006101 lconv* lc = localeconv_l(loc.get());
6102#else
6103 lconv* lc = __localeconv_l(loc.get());
6104#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006105 if (*lc->mon_decimal_point)
6106 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6107 else
6108 __decimal_point_ = base::do_decimal_point();
6109 if (*lc->mon_thousands_sep)
6110 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6111 else
6112 __thousands_sep_ = base::do_thousands_sep();
6113 __grouping_ = lc->mon_grouping;
6114 wchar_t wbuf[100];
6115 mbstate_t mb = {0};
6116 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006117#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006118 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006119#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006120 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006121#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006122 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006123 __throw_runtime_error("locale not supported");
6124 wchar_t* wbe = wbuf + j;
6125 __curr_symbol_.assign(wbuf, wbe);
6126 if (lc->int_frac_digits != CHAR_MAX)
6127 __frac_digits_ = lc->int_frac_digits;
6128 else
6129 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00006130#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006131 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006132#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006133 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006134#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006135 __positive_sign_ = L"()";
6136 else
6137 {
6138 mb = mbstate_t();
6139 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006140#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006141 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006142#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006143 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006144#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006145 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006146 __throw_runtime_error("locale not supported");
6147 wbe = wbuf + j;
6148 __positive_sign_.assign(wbuf, wbe);
6149 }
Howard Hinnantef5aa932013-09-17 01:34:47 +00006150#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006151 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006152#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006153 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006154#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006155 __negative_sign_ = L"()";
6156 else
6157 {
6158 mb = mbstate_t();
6159 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006160#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006161 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006162#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006163 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006164#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006165 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006166 __throw_runtime_error("locale not supported");
6167 wbe = wbuf + j;
6168 __negative_sign_.assign(wbuf, wbe);
6169 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006170 // Assume the positive and negative formats will want spaces in
6171 // the same places in curr_symbol since there's no way to
6172 // represent anything else.
6173 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00006174#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006175 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6176 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6177 __init_pat(__neg_format_, __curr_symbol_, true,
6178 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006179#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006180 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6181 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6182 lc->int_p_sign_posn, L' ');
6183 __init_pat(__neg_format_, __curr_symbol_, true,
6184 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6185 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006186#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006187}
6188
6189void __do_nothing(void*) {}
6190
6191void __throw_runtime_error(const char* msg)
6192{
Howard Hinnantd4444702010-08-11 17:04:31 +00006193#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006194 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006195#else
6196 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006197#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006198}
6199
6200template class collate<char>;
6201template class collate<wchar_t>;
6202
6203template class num_get<char>;
6204template class num_get<wchar_t>;
6205
Howard Hinnantec3773c2011-12-01 20:21:04 +00006206template struct __num_get<char>;
6207template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006208
6209template class num_put<char>;
6210template class num_put<wchar_t>;
6211
Howard Hinnantec3773c2011-12-01 20:21:04 +00006212template struct __num_put<char>;
6213template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006214
6215template class time_get<char>;
6216template class time_get<wchar_t>;
6217
6218template class time_get_byname<char>;
6219template class time_get_byname<wchar_t>;
6220
6221template class time_put<char>;
6222template class time_put<wchar_t>;
6223
6224template class time_put_byname<char>;
6225template class time_put_byname<wchar_t>;
6226
6227template class moneypunct<char, false>;
6228template class moneypunct<char, true>;
6229template class moneypunct<wchar_t, false>;
6230template class moneypunct<wchar_t, true>;
6231
6232template class moneypunct_byname<char, false>;
6233template class moneypunct_byname<char, true>;
6234template class moneypunct_byname<wchar_t, false>;
6235template class moneypunct_byname<wchar_t, true>;
6236
6237template class money_get<char>;
6238template class money_get<wchar_t>;
6239
6240template class __money_get<char>;
6241template class __money_get<wchar_t>;
6242
6243template class money_put<char>;
6244template class money_put<wchar_t>;
6245
6246template class __money_put<char>;
6247template class __money_put<wchar_t>;
6248
6249template class messages<char>;
6250template class messages<wchar_t>;
6251
6252template class messages_byname<char>;
6253template class messages_byname<wchar_t>;
6254
6255template class codecvt_byname<char, char, mbstate_t>;
6256template class codecvt_byname<wchar_t, char, mbstate_t>;
6257template class codecvt_byname<char16_t, char, mbstate_t>;
6258template class codecvt_byname<char32_t, char, mbstate_t>;
6259
6260template class __vector_base_common<true>;
6261
6262_LIBCPP_END_NAMESPACE_STD