blob: bdc73e1d537927fee482d64c6d1a81428b393cf9 [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__)
Marshall Clow8c42c8c2015-06-23 14:45:02 +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;
Ed Schouten7c1ebcf2015-07-06 15:39:36 +0000578#ifndef __CloudABI__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000579 if (g.name() != "*")
580 setlocale(LC_ALL, g.name().c_str());
Ed Schouten7c1ebcf2015-07-06 15:39:36 +0000581#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000582 return r;
583}
584
585bool
586locale::has_facet(id& x) const
587{
588 return __locale_->has_facet(x.__get());
589}
590
591const locale::facet*
592locale::use_facet(id& x) const
593{
594 return __locale_->use_facet(x.__get());
595}
596
597bool
598locale::operator==(const locale& y) const
599{
600 return (__locale_ == y.__locale_)
601 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
602}
603
604// locale::facet
605
606locale::facet::~facet()
607{
608}
609
610void
Howard Hinnant1694d232011-05-28 14:41:13 +0000611locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000612{
613 delete this;
614}
615
616// locale::id
617
618int32_t locale::id::__next_id = 0;
619
620namespace
621{
622
623class __fake_bind
624{
625 locale::id* id_;
626 void (locale::id::* pmf_)();
627public:
628 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
629 : id_(id), pmf_(pmf) {}
630
631 void operator()() const
632 {
633 (id_->*pmf_)();
634 }
635};
636
637}
638
639long
640locale::id::__get()
641{
642 call_once(__flag_, __fake_bind(&locale::id::__init, this));
643 return __id_ - 1;
644}
645
646void
647locale::id::__init()
648{
Howard Hinnantadff4892010-05-24 17:49:41 +0000649 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000650}
651
652// template <> class collate_byname<char>
653
654collate_byname<char>::collate_byname(const char* n, size_t refs)
655 : collate<char>(refs),
656 __l(newlocale(LC_ALL_MASK, n, 0))
657{
Howard Hinnantd4444702010-08-11 17:04:31 +0000658#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000659 if (__l == 0)
660 throw runtime_error("collate_byname<char>::collate_byname"
661 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000662#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000663}
664
665collate_byname<char>::collate_byname(const string& name, size_t refs)
666 : collate<char>(refs),
667 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
668{
Howard Hinnantd4444702010-08-11 17:04:31 +0000669#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000670 if (__l == 0)
671 throw runtime_error("collate_byname<char>::collate_byname"
672 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000673#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000674}
675
676collate_byname<char>::~collate_byname()
677{
678 freelocale(__l);
679}
680
681int
682collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
683 const char_type* __lo2, const char_type* __hi2) const
684{
685 string_type lhs(__lo1, __hi1);
686 string_type rhs(__lo2, __hi2);
687 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
688 if (r < 0)
689 return -1;
690 if (r > 0)
691 return 1;
692 return r;
693}
694
695collate_byname<char>::string_type
696collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
697{
698 const string_type in(lo, hi);
699 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
700 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
701 return out;
702}
703
704// template <> class collate_byname<wchar_t>
705
706collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
707 : collate<wchar_t>(refs),
708 __l(newlocale(LC_ALL_MASK, n, 0))
709{
Howard Hinnantd4444702010-08-11 17:04:31 +0000710#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000711 if (__l == 0)
712 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
713 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000714#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000715}
716
717collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
718 : collate<wchar_t>(refs),
719 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
720{
Howard Hinnantd4444702010-08-11 17:04:31 +0000721#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000722 if (__l == 0)
723 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
724 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000725#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000726}
727
728collate_byname<wchar_t>::~collate_byname()
729{
730 freelocale(__l);
731}
732
733int
734collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
735 const char_type* __lo2, const char_type* __hi2) const
736{
737 string_type lhs(__lo1, __hi1);
738 string_type rhs(__lo2, __hi2);
739 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
740 if (r < 0)
741 return -1;
742 if (r > 0)
743 return 1;
744 return r;
745}
746
747collate_byname<wchar_t>::string_type
748collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
749{
750 const string_type in(lo, hi);
751 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
752 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
753 return out;
754}
755
756// template <> class ctype<wchar_t>;
757
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000758const ctype_base::mask ctype_base::space;
759const ctype_base::mask ctype_base::print;
760const ctype_base::mask ctype_base::cntrl;
761const ctype_base::mask ctype_base::upper;
762const ctype_base::mask ctype_base::lower;
763const ctype_base::mask ctype_base::alpha;
764const ctype_base::mask ctype_base::digit;
765const ctype_base::mask ctype_base::punct;
766const ctype_base::mask ctype_base::xdigit;
767const ctype_base::mask ctype_base::blank;
768const ctype_base::mask ctype_base::alnum;
769const ctype_base::mask ctype_base::graph;
770
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000771locale::id ctype<wchar_t>::id;
772
773ctype<wchar_t>::~ctype()
774{
775}
776
777bool
778ctype<wchar_t>::do_is(mask m, char_type c) const
779{
Marshall Clowa3645132013-10-21 15:07:28 +0000780 return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000781}
782
783const wchar_t*
784ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
785{
786 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000787 *vec = static_cast<mask>(isascii(*low) ?
788 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000789 return low;
790}
791
792const wchar_t*
793ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
794{
795 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000796 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000797 break;
798 return low;
799}
800
801const wchar_t*
802ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
803{
804 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000805 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000806 break;
807 return low;
808}
809
810wchar_t
811ctype<wchar_t>::do_toupper(char_type c) const
812{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000813#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
814 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000815#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000816 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000817#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000818 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000819#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000820}
821
822const wchar_t*
823ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
824{
825 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000826#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
827 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000828#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000829 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
830 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000831#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000832 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000834 return low;
835}
836
837wchar_t
838ctype<wchar_t>::do_tolower(char_type c) const
839{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000840#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
841 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000842#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000843 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000844#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000845 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000846#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000847}
848
849const wchar_t*
850ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
851{
852 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000853#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
854 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Marshall Clow2ccffef2013-11-19 18:05:03 +0000855#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000856 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
857 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000858#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000859 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000860#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000861 return low;
862}
863
864wchar_t
865ctype<wchar_t>::do_widen(char c) const
866{
867 return c;
868}
869
870const char*
871ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
872{
873 for (; low != high; ++low, ++dest)
874 *dest = *low;
875 return low;
876}
877
878char
879ctype<wchar_t>::do_narrow(char_type c, char dfault) const
880{
881 if (isascii(c))
882 return static_cast<char>(c);
883 return dfault;
884}
885
886const wchar_t*
887ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
888{
889 for (; low != high; ++low, ++dest)
890 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000891 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000892 else
893 *dest = dfault;
894 return low;
895}
896
897// template <> class ctype<char>;
898
899locale::id ctype<char>::id;
900
901ctype<char>::ctype(const mask* tab, bool del, size_t refs)
902 : locale::facet(refs),
903 __tab_(tab),
904 __del_(del)
905{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000906 if (__tab_ == 0)
907 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000908}
909
910ctype<char>::~ctype()
911{
912 if (__tab_ && __del_)
913 delete [] __tab_;
914}
915
916char
917ctype<char>::do_toupper(char_type c) const
918{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000919#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000920 return isascii(c) ?
921 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000922#elif defined(__NetBSD__)
923 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000924#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000925 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000926 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000927#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000928 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000929#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000930}
931
932const char*
933ctype<char>::do_toupper(char_type* low, const char_type* high) const
934{
935 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000936#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000937 *low = isascii(*low) ?
938 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000939#elif defined(__NetBSD__)
940 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000941#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000942 *low = isascii(*low) ?
943 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000944#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000945 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000946#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000947 return low;
948}
949
950char
951ctype<char>::do_tolower(char_type c) const
952{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000953#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000954 return isascii(c) ?
955 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000956#elif defined(__NetBSD__)
957 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000958#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
Marshall Clow88c31902013-02-07 14:22:51 +0000959 return isascii(c) ?
960 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000961#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000962 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000963#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000964}
965
966const char*
967ctype<char>::do_tolower(char_type* low, const char_type* high) const
968{
969 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000970#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000971 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000972#elif defined(__NetBSD__)
973 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Marshall Clow2ccffef2013-11-19 18:05:03 +0000974#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__)
Marshall Clow88c31902013-02-07 14:22:51 +0000975 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000976#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000977 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000978#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000979 return low;
980}
981
982char
983ctype<char>::do_widen(char c) const
984{
985 return c;
986}
987
988const char*
989ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
990{
991 for (; low != high; ++low, ++dest)
992 *dest = *low;
993 return low;
994}
995
996char
997ctype<char>::do_narrow(char_type c, char dfault) const
998{
999 if (isascii(c))
1000 return static_cast<char>(c);
1001 return dfault;
1002}
1003
1004const char*
1005ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1006{
1007 for (; low != high; ++low, ++dest)
1008 if (isascii(*low))
1009 *dest = *low;
1010 else
1011 *dest = dfault;
1012 return low;
1013}
1014
Marshall Clow2ccffef2013-11-19 18:05:03 +00001015#ifdef __EMSCRIPTEN__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001016extern "C" const unsigned short ** __ctype_b_loc();
1017extern "C" const int ** __ctype_tolower_loc();
1018extern "C" const int ** __ctype_toupper_loc();
1019#endif
1020
Marshall Clowe917d802015-03-04 16:50:02 +00001021#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clow8291a762015-03-04 16:10:14 +00001022const ctype<char>::mask*
1023ctype<char>::classic_table() _NOEXCEPT
1024{
1025 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1026 cntrl, cntrl,
1027 cntrl, cntrl,
1028 cntrl, cntrl,
1029 cntrl, cntrl,
1030 cntrl, cntrl | space | blank,
1031 cntrl | space, cntrl | space,
1032 cntrl | space, cntrl | space,
1033 cntrl, cntrl,
1034 cntrl, cntrl,
1035 cntrl, cntrl,
1036 cntrl, cntrl,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl,
1040 cntrl, cntrl,
1041 cntrl, cntrl,
1042 space | blank | 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 punct | print, punct | print,
1049 punct | print, punct | print,
1050 digit | print | xdigit, digit | print | xdigit,
1051 digit | print | xdigit, digit | print | xdigit,
1052 digit | print | xdigit, digit | print | xdigit,
1053 digit | print | xdigit, digit | print | xdigit,
1054 digit | print | xdigit, digit | print | xdigit,
1055 punct | print, punct | print,
1056 punct | print, punct | print,
1057 punct | print, punct | print,
1058 punct | print, upper | xdigit | print | alpha,
1059 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1060 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1061 upper | xdigit | 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, upper | print | alpha,
1070 upper | print | alpha, upper | print | alpha,
1071 upper | print | alpha, punct | print,
1072 punct | print, punct | print,
1073 punct | print, punct | print,
1074 punct | print, lower | xdigit | print | alpha,
1075 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1076 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1077 lower | xdigit | 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, lower | print | alpha,
1086 lower | print | alpha, lower | print | alpha,
1087 lower | print | alpha, punct | print,
1088 punct | print, punct | print,
1089 punct | print, cntrl,
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1097 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1098 };
1099 return builtin_table;
1100}
1101#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001102const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001103ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001104{
David Chisnallc512df12011-09-21 08:39:44 +00001105#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001106 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001107#elif defined(__NetBSD__)
1108 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001109#elif defined(__GLIBC__)
Ed Schouten9e97eb82015-07-06 15:37:40 +00001110 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001111#elif __sun__
1112 return __ctype_mask;
Howard Hinnantef5aa932013-09-17 01:34:47 +00001113#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001114 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001115// This is assumed to be safe, which is a nonsense assumption because we're
1116// going to end up dereferencing it later...
Marshall Clow2ccffef2013-11-19 18:05:03 +00001117#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001118 return *__ctype_b_loc();
JF Bastiena14f7cb2015-02-25 22:16:46 +00001119#elif defined(_NEWLIB_VERSION)
1120 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1121 return _ctype_ + 1;
Howard Hinnant7f764502013-08-14 18:00:20 +00001122#elif defined(_AIX)
Marshall Clow016d4e82013-11-19 19:16:03 +00001123 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001124#else
David Chisnall997e4542012-02-29 13:05:08 +00001125 // Platform not supported: abort so the person doing the port knows what to
1126 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001127# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001128 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001129 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001130 return NULL;
1131#endif
1132}
Marshall Clow8291a762015-03-04 16:10:14 +00001133#endif
Sean Hunt62a6ac32011-07-09 00:56:23 +00001134
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001135#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001136const int*
1137ctype<char>::__classic_lower_table() _NOEXCEPT
1138{
Ed Schouten9e97eb82015-07-06 15:37:40 +00001139 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001140}
1141
1142const int*
1143ctype<char>::__classic_upper_table() _NOEXCEPT
1144{
Ed Schouten9e97eb82015-07-06 15:37:40 +00001145 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001146}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001147#elif __NetBSD__
1148const short*
1149ctype<char>::__classic_lower_table() _NOEXCEPT
1150{
1151 return _C_tolower_tab_ + 1;
1152}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001153
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001154const short*
1155ctype<char>::__classic_upper_table() _NOEXCEPT
1156{
1157 return _C_toupper_tab_ + 1;
1158}
1159
Marshall Clow2ccffef2013-11-19 18:05:03 +00001160#elif defined(__EMSCRIPTEN__)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001161const int*
1162ctype<char>::__classic_lower_table() _NOEXCEPT
1163{
1164 return *__ctype_tolower_loc();
1165}
1166
1167const int*
1168ctype<char>::__classic_upper_table() _NOEXCEPT
1169{
1170 return *__ctype_toupper_loc();
1171}
Marshall Clow2ccffef2013-11-19 18:05:03 +00001172#endif // __GLIBC__ || __EMSCRIPTEN__ || __NETBSD__
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001173
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001174// template <> class ctype_byname<char>
1175
1176ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1177 : ctype<char>(0, false, refs),
1178 __l(newlocale(LC_ALL_MASK, name, 0))
1179{
Howard Hinnantd4444702010-08-11 17:04:31 +00001180#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001181 if (__l == 0)
1182 throw runtime_error("ctype_byname<char>::ctype_byname"
1183 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001184#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001185}
1186
1187ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1188 : ctype<char>(0, false, refs),
1189 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1190{
Howard Hinnantd4444702010-08-11 17:04:31 +00001191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001192 if (__l == 0)
1193 throw runtime_error("ctype_byname<char>::ctype_byname"
1194 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001195#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001196}
1197
1198ctype_byname<char>::~ctype_byname()
1199{
1200 freelocale(__l);
1201}
1202
1203char
1204ctype_byname<char>::do_toupper(char_type c) const
1205{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001206 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001207}
1208
1209const char*
1210ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1211{
1212 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001213 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001214 return low;
1215}
1216
1217char
1218ctype_byname<char>::do_tolower(char_type c) const
1219{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001220 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001221}
1222
1223const char*
1224ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1225{
1226 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001227 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001228 return low;
1229}
1230
1231// template <> class ctype_byname<wchar_t>
1232
1233ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1234 : ctype<wchar_t>(refs),
1235 __l(newlocale(LC_ALL_MASK, name, 0))
1236{
Howard Hinnantd4444702010-08-11 17:04:31 +00001237#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001238 if (__l == 0)
1239 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1240 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001241#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001242}
1243
1244ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1245 : ctype<wchar_t>(refs),
1246 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1247{
Howard Hinnantd4444702010-08-11 17:04:31 +00001248#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001249 if (__l == 0)
1250 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1251 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001252#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001253}
1254
1255ctype_byname<wchar_t>::~ctype_byname()
1256{
1257 freelocale(__l);
1258}
1259
1260bool
1261ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1262{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001263#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001264 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001265#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001266 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001267 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001268 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1269 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1270 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1271 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1272 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1273 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1274 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1275 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1276 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1277 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001278 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001279#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001280}
1281
1282const wchar_t*
1283ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1284{
1285 for (; low != high; ++low, ++vec)
1286 {
1287 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001288 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001289 else
1290 {
1291 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001292 wint_t ch = static_cast<wint_t>(*low);
1293 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001294 *vec |= space;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001295#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clow88c31902013-02-07 14:22:51 +00001296 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001297 *vec |= print;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001298#endif
Marshall Clow88c31902013-02-07 14:22:51 +00001299 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001300 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001301 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001302 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001303 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001304 *vec |= lower;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001305#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clow88c31902013-02-07 14:22:51 +00001306 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001307 *vec |= alpha;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001308#endif
Marshall Clow88c31902013-02-07 14:22:51 +00001309 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001310 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001311 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001312 *vec |= punct;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001313#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clow88c31902013-02-07 14:22:51 +00001314 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001315 *vec |= xdigit;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001316#endif
Jonathan Roelofsf77031d2015-03-13 15:09:42 +00001317#if !defined(__sun__)
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001318 if (iswblank_l(ch, __l))
1319 *vec |= blank;
Jonathan Roelofsf77031d2015-03-13 15:09:42 +00001320#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001321 }
1322 }
1323 return low;
1324}
1325
1326const wchar_t*
1327ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1328{
1329 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001330 {
1331#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001332 if (iswctype_l(*low, m, __l))
1333 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001334#else
Marshall Clow88c31902013-02-07 14:22:51 +00001335 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001336 if ((m & space) == space && iswspace_l(ch, __l)) break;
1337 if ((m & print) == print && iswprint_l(ch, __l)) break;
1338 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1339 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1340 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1341 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1342 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1343 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1344 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1345 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001346#endif
1347 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001348 return low;
1349}
1350
1351const wchar_t*
1352ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1353{
1354 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001355 {
1356#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001357 if (!iswctype_l(*low, m, __l))
1358 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001359#else
Marshall Clow88c31902013-02-07 14:22:51 +00001360 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001361 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1362 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1363 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1364 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1365 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1366 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1367 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1368 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1369 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1370 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001371 break;
1372#endif
1373 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001374 return low;
1375}
1376
1377wchar_t
1378ctype_byname<wchar_t>::do_toupper(char_type c) const
1379{
1380 return towupper_l(c, __l);
1381}
1382
1383const wchar_t*
1384ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1385{
1386 for (; low != high; ++low)
1387 *low = towupper_l(*low, __l);
1388 return low;
1389}
1390
1391wchar_t
1392ctype_byname<wchar_t>::do_tolower(char_type c) const
1393{
1394 return towlower_l(c, __l);
1395}
1396
1397const wchar_t*
1398ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1399{
1400 for (; low != high; ++low)
1401 *low = towlower_l(*low, __l);
1402 return low;
1403}
1404
1405wchar_t
1406ctype_byname<wchar_t>::do_widen(char c) const
1407{
Howard Hinnant866569b2011-09-28 23:39:33 +00001408#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001409 return btowc_l(c, __l);
1410#else
1411 return __btowc_l(c, __l);
1412#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001413}
1414
1415const char*
1416ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1417{
1418 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001419#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001420 *dest = btowc_l(*low, __l);
1421#else
1422 *dest = __btowc_l(*low, __l);
1423#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001424 return low;
1425}
1426
1427char
1428ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1429{
Howard Hinnant866569b2011-09-28 23:39:33 +00001430#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001431 int r = wctob_l(c, __l);
1432#else
1433 int r = __wctob_l(c, __l);
1434#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001435 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001436}
1437
1438const wchar_t*
1439ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1440{
1441 for (; low != high; ++low, ++dest)
1442 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001443#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001444 int r = wctob_l(*low, __l);
1445#else
1446 int r = __wctob_l(*low, __l);
1447#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001448 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001449 }
1450 return low;
1451}
1452
1453// template <> class codecvt<char, char, mbstate_t>
1454
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001455locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001456
1457codecvt<char, char, mbstate_t>::~codecvt()
1458{
1459}
1460
1461codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001462codecvt<char, char, mbstate_t>::do_out(state_type&,
1463 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001464 extern_type* to, extern_type*, extern_type*& to_nxt) const
1465{
1466 frm_nxt = frm;
1467 to_nxt = to;
1468 return noconv;
1469}
1470
1471codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001472codecvt<char, char, mbstate_t>::do_in(state_type&,
1473 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001474 intern_type* to, intern_type*, intern_type*& to_nxt) const
1475{
1476 frm_nxt = frm;
1477 to_nxt = to;
1478 return noconv;
1479}
1480
1481codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001482codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001483 extern_type* to, extern_type*, extern_type*& to_nxt) const
1484{
1485 to_nxt = to;
1486 return noconv;
1487}
1488
1489int
Howard Hinnantc9834542011-05-31 15:34:58 +00001490codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001491{
1492 return 1;
1493}
1494
1495bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001496codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001497{
1498 return true;
1499}
1500
1501int
1502codecvt<char, char, mbstate_t>::do_length(state_type&,
1503 const extern_type* frm, const extern_type* end, size_t mx) const
1504{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001505 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001506}
1507
1508int
Howard Hinnantc9834542011-05-31 15:34:58 +00001509codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001510{
1511 return 1;
1512}
1513
1514// template <> class codecvt<wchar_t, char, mbstate_t>
1515
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001516locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001517
1518codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1519 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001520 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521{
1522}
1523
1524codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1525 : locale::facet(refs),
1526 __l(newlocale(LC_ALL_MASK, nm, 0))
1527{
Howard Hinnantd4444702010-08-11 17:04:31 +00001528#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001529 if (__l == 0)
1530 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1531 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001532#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001533}
1534
1535codecvt<wchar_t, char, mbstate_t>::~codecvt()
1536{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001537 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001538 freelocale(__l);
1539}
1540
1541codecvt<wchar_t, char, mbstate_t>::result
1542codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001543 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001544 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1545{
1546 // look for first internal null in frm
1547 const intern_type* fend = frm;
1548 for (; fend != frm_end; ++fend)
1549 if (*fend == 0)
1550 break;
1551 // loop over all null-terminated sequences in frm
1552 to_nxt = to;
1553 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1554 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001555 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001556 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001557#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001558 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1559 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001560#else
1561 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1562#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001563 if (n == size_t(-1))
1564 {
1565 // need to recover to_nxt
1566 for (to_nxt = to; frm != frm_nxt; ++frm)
1567 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001568#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001569 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1570#else
1571 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1572#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001573 if (n == size_t(-1))
1574 break;
1575 to_nxt += n;
1576 }
1577 frm_nxt = frm;
1578 return error;
1579 }
1580 if (n == 0)
1581 return partial;
1582 to_nxt += n;
1583 if (to_nxt == to_end)
1584 break;
1585 if (fend != frm_end) // set up next null terminated sequence
1586 {
1587 // Try to write the terminating null
1588 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001589#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001590 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1591#else
1592 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1593#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001594 if (n == size_t(-1)) // on error
1595 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001596 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001597 return partial;
1598 for (extern_type* p = tmp; n; --n) // write it
1599 *to_nxt++ = *p++;
1600 ++frm_nxt;
1601 // look for next null in frm
1602 for (fend = frm_nxt; fend != frm_end; ++fend)
1603 if (*fend == 0)
1604 break;
1605 }
1606 }
1607 return frm_nxt == frm_end ? ok : partial;
1608}
1609
1610codecvt<wchar_t, char, mbstate_t>::result
1611codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001612 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001613 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1614{
1615 // look for first internal null in frm
1616 const extern_type* fend = frm;
1617 for (; fend != frm_end; ++fend)
1618 if (*fend == 0)
1619 break;
1620 // loop over all null-terminated sequences in frm
1621 to_nxt = to;
1622 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1623 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001624 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001625 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001626#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001627 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1628 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001629#else
1630 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1631#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001632 if (n == size_t(-1))
1633 {
1634 // need to recover to_nxt
1635 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1636 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001637#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001638 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1639 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001640#else
1641 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1642#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001643 switch (n)
1644 {
1645 case 0:
1646 ++frm;
1647 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001648 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001649 frm_nxt = frm;
1650 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001651 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001652 frm_nxt = frm;
1653 return partial;
1654 default:
1655 frm += n;
1656 break;
1657 }
1658 }
1659 frm_nxt = frm;
1660 return frm_nxt == frm_end ? ok : partial;
1661 }
Joerg Sonnenberger64c62482015-06-05 15:54:26 +00001662 if (n == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001663 return error;
1664 to_nxt += n;
1665 if (to_nxt == to_end)
1666 break;
1667 if (fend != frm_end) // set up next null terminated sequence
1668 {
1669 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001670#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001671 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1672#else
1673 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1674#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001675 if (n != 0) // on error
1676 return error;
1677 ++to_nxt;
1678 ++frm_nxt;
1679 // look for next null in frm
1680 for (fend = frm_nxt; fend != frm_end; ++fend)
1681 if (*fend == 0)
1682 break;
1683 }
1684 }
1685 return frm_nxt == frm_end ? ok : partial;
1686}
1687
1688codecvt<wchar_t, char, mbstate_t>::result
1689codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1690 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1691{
1692 to_nxt = to;
1693 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001694#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001695 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1696#else
1697 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1698#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001699 if (n == size_t(-1) || n == 0) // on error
1700 return error;
1701 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001702 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001703 return partial;
1704 for (extern_type* p = tmp; n; --n) // write it
1705 *to_nxt++ = *p++;
1706 return ok;
1707}
1708
1709int
Howard Hinnantc9834542011-05-31 15:34:58 +00001710codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001711{
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001712#ifndef __CloudABI__
Howard Hinnant866569b2011-09-28 23:39:33 +00001713#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001714 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001715#else
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001716 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001717#endif
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001718 return -1;
1719#endif
1720
1721 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001722#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001723 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
Sean Huntf3907e62011-07-15 05:40:33 +00001724#else
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001725 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Sean Huntf3907e62011-07-15 05:40:33 +00001726#endif
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001727 return 1; // which take more than 1 char to form a wchar_t
1728 return 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001729}
1730
1731bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001732codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001733{
1734 return false;
1735}
1736
1737int
1738codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1739 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1740{
1741 int nbytes = 0;
1742 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1743 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001744#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001745 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001746#else
1747 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1748#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001749 switch (n)
1750 {
1751 case 0:
1752 ++nbytes;
1753 ++frm;
1754 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001755 case size_t(-1):
1756 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001757 return nbytes;
1758 default:
1759 nbytes += n;
1760 frm += n;
1761 break;
1762 }
1763 }
1764 return nbytes;
1765}
1766
1767int
Howard Hinnantc9834542011-05-31 15:34:58 +00001768codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001769{
Howard Hinnant866569b2011-09-28 23:39:33 +00001770#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001771 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001772#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001773 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001774#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001775}
1776
1777// Valid UTF ranges
1778// UTF-32 UTF-16 UTF-8 # of code points
1779// first second first second third fourth
1780// 000000 - 00007F 0000 - 007F 00 - 7F 127
1781// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1782// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1783// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1784// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1785// 00D800 - 00DFFF invalid
1786// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1787// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1788// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1789// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1790
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001791static
1792codecvt_base::result
1793utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1794 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1795 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1796{
1797 frm_nxt = frm;
1798 to_nxt = to;
1799 if (mode & generate_header)
1800 {
1801 if (to_end-to_nxt < 3)
1802 return codecvt_base::partial;
1803 *to_nxt++ = static_cast<uint8_t>(0xEF);
1804 *to_nxt++ = static_cast<uint8_t>(0xBB);
1805 *to_nxt++ = static_cast<uint8_t>(0xBF);
1806 }
1807 for (; frm_nxt < frm_end; ++frm_nxt)
1808 {
1809 uint16_t wc1 = *frm_nxt;
1810 if (wc1 > Maxcode)
1811 return codecvt_base::error;
1812 if (wc1 < 0x0080)
1813 {
1814 if (to_end-to_nxt < 1)
1815 return codecvt_base::partial;
1816 *to_nxt++ = static_cast<uint8_t>(wc1);
1817 }
1818 else if (wc1 < 0x0800)
1819 {
1820 if (to_end-to_nxt < 2)
1821 return codecvt_base::partial;
1822 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1823 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1824 }
1825 else if (wc1 < 0xD800)
1826 {
1827 if (to_end-to_nxt < 3)
1828 return codecvt_base::partial;
1829 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1830 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1831 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1832 }
1833 else if (wc1 < 0xDC00)
1834 {
1835 if (frm_end-frm_nxt < 2)
1836 return codecvt_base::partial;
1837 uint16_t wc2 = frm_nxt[1];
1838 if ((wc2 & 0xFC00) != 0xDC00)
1839 return codecvt_base::error;
1840 if (to_end-to_nxt < 4)
1841 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001842 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1843 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001844 return codecvt_base::error;
1845 ++frm_nxt;
1846 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1847 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1848 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1849 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1850 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1851 }
1852 else if (wc1 < 0xE000)
1853 {
1854 return codecvt_base::error;
1855 }
1856 else
1857 {
1858 if (to_end-to_nxt < 3)
1859 return codecvt_base::partial;
1860 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1861 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1862 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1863 }
1864 }
1865 return codecvt_base::ok;
1866}
1867
1868static
1869codecvt_base::result
1870utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1871 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1872 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1873{
1874 frm_nxt = frm;
1875 to_nxt = to;
1876 if (mode & generate_header)
1877 {
1878 if (to_end-to_nxt < 3)
1879 return codecvt_base::partial;
1880 *to_nxt++ = static_cast<uint8_t>(0xEF);
1881 *to_nxt++ = static_cast<uint8_t>(0xBB);
1882 *to_nxt++ = static_cast<uint8_t>(0xBF);
1883 }
1884 for (; frm_nxt < frm_end; ++frm_nxt)
1885 {
1886 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1887 if (wc1 > Maxcode)
1888 return codecvt_base::error;
1889 if (wc1 < 0x0080)
1890 {
1891 if (to_end-to_nxt < 1)
1892 return codecvt_base::partial;
1893 *to_nxt++ = static_cast<uint8_t>(wc1);
1894 }
1895 else if (wc1 < 0x0800)
1896 {
1897 if (to_end-to_nxt < 2)
1898 return codecvt_base::partial;
1899 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1900 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1901 }
1902 else if (wc1 < 0xD800)
1903 {
1904 if (to_end-to_nxt < 3)
1905 return codecvt_base::partial;
1906 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1907 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1908 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1909 }
1910 else if (wc1 < 0xDC00)
1911 {
1912 if (frm_end-frm_nxt < 2)
1913 return codecvt_base::partial;
1914 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1915 if ((wc2 & 0xFC00) != 0xDC00)
1916 return codecvt_base::error;
1917 if (to_end-to_nxt < 4)
1918 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001919 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1920 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001921 return codecvt_base::error;
1922 ++frm_nxt;
1923 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1924 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1925 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1926 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1927 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1928 }
1929 else if (wc1 < 0xE000)
1930 {
1931 return codecvt_base::error;
1932 }
1933 else
1934 {
1935 if (to_end-to_nxt < 3)
1936 return codecvt_base::partial;
1937 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1938 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1939 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1940 }
1941 }
1942 return codecvt_base::ok;
1943}
1944
1945static
1946codecvt_base::result
1947utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1948 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1949 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1950{
1951 frm_nxt = frm;
1952 to_nxt = to;
1953 if (mode & consume_header)
1954 {
1955 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1956 frm_nxt[2] == 0xBF)
1957 frm_nxt += 3;
1958 }
1959 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1960 {
1961 uint8_t c1 = *frm_nxt;
1962 if (c1 > Maxcode)
1963 return codecvt_base::error;
1964 if (c1 < 0x80)
1965 {
1966 *to_nxt = static_cast<uint16_t>(c1);
1967 ++frm_nxt;
1968 }
1969 else if (c1 < 0xC2)
1970 {
1971 return codecvt_base::error;
1972 }
1973 else if (c1 < 0xE0)
1974 {
1975 if (frm_end-frm_nxt < 2)
1976 return codecvt_base::partial;
1977 uint8_t c2 = frm_nxt[1];
1978 if ((c2 & 0xC0) != 0x80)
1979 return codecvt_base::error;
1980 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1981 if (t > Maxcode)
1982 return codecvt_base::error;
1983 *to_nxt = t;
1984 frm_nxt += 2;
1985 }
1986 else if (c1 < 0xF0)
1987 {
1988 if (frm_end-frm_nxt < 3)
1989 return codecvt_base::partial;
1990 uint8_t c2 = frm_nxt[1];
1991 uint8_t c3 = frm_nxt[2];
1992 switch (c1)
1993 {
1994 case 0xE0:
1995 if ((c2 & 0xE0) != 0xA0)
1996 return codecvt_base::error;
1997 break;
1998 case 0xED:
1999 if ((c2 & 0xE0) != 0x80)
2000 return codecvt_base::error;
2001 break;
2002 default:
2003 if ((c2 & 0xC0) != 0x80)
2004 return codecvt_base::error;
2005 break;
2006 }
2007 if ((c3 & 0xC0) != 0x80)
2008 return codecvt_base::error;
2009 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2010 | ((c2 & 0x3F) << 6)
2011 | (c3 & 0x3F));
2012 if (t > Maxcode)
2013 return codecvt_base::error;
2014 *to_nxt = t;
2015 frm_nxt += 3;
2016 }
2017 else if (c1 < 0xF5)
2018 {
2019 if (frm_end-frm_nxt < 4)
2020 return codecvt_base::partial;
2021 uint8_t c2 = frm_nxt[1];
2022 uint8_t c3 = frm_nxt[2];
2023 uint8_t c4 = frm_nxt[3];
2024 switch (c1)
2025 {
2026 case 0xF0:
2027 if (!(0x90 <= c2 && c2 <= 0xBF))
2028 return codecvt_base::error;
2029 break;
2030 case 0xF4:
2031 if ((c2 & 0xF0) != 0x80)
2032 return codecvt_base::error;
2033 break;
2034 default:
2035 if ((c2 & 0xC0) != 0x80)
2036 return codecvt_base::error;
2037 break;
2038 }
2039 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2040 return codecvt_base::error;
2041 if (to_end-to_nxt < 2)
2042 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002043 if ((((c1 & 7UL) << 18) +
2044 ((c2 & 0x3FUL) << 12) +
2045 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002046 return codecvt_base::error;
2047 *to_nxt = static_cast<uint16_t>(
2048 0xD800
2049 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2050 | ((c2 & 0x0F) << 2)
2051 | ((c3 & 0x30) >> 4));
2052 *++to_nxt = static_cast<uint16_t>(
2053 0xDC00
2054 | ((c3 & 0x0F) << 6)
2055 | (c4 & 0x3F));
2056 frm_nxt += 4;
2057 }
2058 else
2059 {
2060 return codecvt_base::error;
2061 }
2062 }
2063 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2064}
2065
2066static
2067codecvt_base::result
2068utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2069 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2070 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2071{
2072 frm_nxt = frm;
2073 to_nxt = to;
2074 if (mode & consume_header)
2075 {
2076 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2077 frm_nxt[2] == 0xBF)
2078 frm_nxt += 3;
2079 }
2080 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2081 {
2082 uint8_t c1 = *frm_nxt;
2083 if (c1 > Maxcode)
2084 return codecvt_base::error;
2085 if (c1 < 0x80)
2086 {
2087 *to_nxt = static_cast<uint32_t>(c1);
2088 ++frm_nxt;
2089 }
2090 else if (c1 < 0xC2)
2091 {
2092 return codecvt_base::error;
2093 }
2094 else if (c1 < 0xE0)
2095 {
2096 if (frm_end-frm_nxt < 2)
2097 return codecvt_base::partial;
2098 uint8_t c2 = frm_nxt[1];
2099 if ((c2 & 0xC0) != 0x80)
2100 return codecvt_base::error;
2101 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2102 if (t > Maxcode)
2103 return codecvt_base::error;
2104 *to_nxt = static_cast<uint32_t>(t);
2105 frm_nxt += 2;
2106 }
2107 else if (c1 < 0xF0)
2108 {
2109 if (frm_end-frm_nxt < 3)
2110 return codecvt_base::partial;
2111 uint8_t c2 = frm_nxt[1];
2112 uint8_t c3 = frm_nxt[2];
2113 switch (c1)
2114 {
2115 case 0xE0:
2116 if ((c2 & 0xE0) != 0xA0)
2117 return codecvt_base::error;
2118 break;
2119 case 0xED:
2120 if ((c2 & 0xE0) != 0x80)
2121 return codecvt_base::error;
2122 break;
2123 default:
2124 if ((c2 & 0xC0) != 0x80)
2125 return codecvt_base::error;
2126 break;
2127 }
2128 if ((c3 & 0xC0) != 0x80)
2129 return codecvt_base::error;
2130 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2131 | ((c2 & 0x3F) << 6)
2132 | (c3 & 0x3F));
2133 if (t > Maxcode)
2134 return codecvt_base::error;
2135 *to_nxt = static_cast<uint32_t>(t);
2136 frm_nxt += 3;
2137 }
2138 else if (c1 < 0xF5)
2139 {
2140 if (frm_end-frm_nxt < 4)
2141 return codecvt_base::partial;
2142 uint8_t c2 = frm_nxt[1];
2143 uint8_t c3 = frm_nxt[2];
2144 uint8_t c4 = frm_nxt[3];
2145 switch (c1)
2146 {
2147 case 0xF0:
2148 if (!(0x90 <= c2 && c2 <= 0xBF))
2149 return codecvt_base::error;
2150 break;
2151 case 0xF4:
2152 if ((c2 & 0xF0) != 0x80)
2153 return codecvt_base::error;
2154 break;
2155 default:
2156 if ((c2 & 0xC0) != 0x80)
2157 return codecvt_base::error;
2158 break;
2159 }
2160 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2161 return codecvt_base::error;
2162 if (to_end-to_nxt < 2)
2163 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002164 if ((((c1 & 7UL) << 18) +
2165 ((c2 & 0x3FUL) << 12) +
2166 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002167 return codecvt_base::error;
2168 *to_nxt = static_cast<uint32_t>(
2169 0xD800
2170 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2171 | ((c2 & 0x0F) << 2)
2172 | ((c3 & 0x30) >> 4));
2173 *++to_nxt = static_cast<uint32_t>(
2174 0xDC00
2175 | ((c3 & 0x0F) << 6)
2176 | (c4 & 0x3F));
2177 frm_nxt += 4;
2178 }
2179 else
2180 {
2181 return codecvt_base::error;
2182 }
2183 }
2184 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2185}
2186
2187static
2188int
2189utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2190 size_t mx, unsigned long Maxcode = 0x10FFFF,
2191 codecvt_mode mode = codecvt_mode(0))
2192{
2193 const uint8_t* frm_nxt = frm;
2194 if (mode & consume_header)
2195 {
2196 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2197 frm_nxt[2] == 0xBF)
2198 frm_nxt += 3;
2199 }
2200 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2201 {
2202 uint8_t c1 = *frm_nxt;
2203 if (c1 > Maxcode)
2204 break;
2205 if (c1 < 0x80)
2206 {
2207 ++frm_nxt;
2208 }
2209 else if (c1 < 0xC2)
2210 {
2211 break;
2212 }
2213 else if (c1 < 0xE0)
2214 {
2215 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2216 break;
2217 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2218 if (t > Maxcode)
2219 break;
2220 frm_nxt += 2;
2221 }
2222 else if (c1 < 0xF0)
2223 {
2224 if (frm_end-frm_nxt < 3)
2225 break;
2226 uint8_t c2 = frm_nxt[1];
2227 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002228 switch (c1)
2229 {
2230 case 0xE0:
2231 if ((c2 & 0xE0) != 0xA0)
2232 return static_cast<int>(frm_nxt - frm);
2233 break;
2234 case 0xED:
2235 if ((c2 & 0xE0) != 0x80)
2236 return static_cast<int>(frm_nxt - frm);
2237 break;
2238 default:
2239 if ((c2 & 0xC0) != 0x80)
2240 return static_cast<int>(frm_nxt - frm);
2241 break;
2242 }
2243 if ((c3 & 0xC0) != 0x80)
2244 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002245 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002246 break;
2247 frm_nxt += 3;
2248 }
2249 else if (c1 < 0xF5)
2250 {
2251 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2252 break;
2253 uint8_t c2 = frm_nxt[1];
2254 uint8_t c3 = frm_nxt[2];
2255 uint8_t c4 = frm_nxt[3];
2256 switch (c1)
2257 {
2258 case 0xF0:
2259 if (!(0x90 <= c2 && c2 <= 0xBF))
2260 return static_cast<int>(frm_nxt - frm);
2261 break;
2262 case 0xF4:
2263 if ((c2 & 0xF0) != 0x80)
2264 return static_cast<int>(frm_nxt - frm);
2265 break;
2266 default:
2267 if ((c2 & 0xC0) != 0x80)
2268 return static_cast<int>(frm_nxt - frm);
2269 break;
2270 }
2271 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2272 break;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002273 if ((((c1 & 7UL) << 18) +
2274 ((c2 & 0x3FUL) << 12) +
2275 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002276 break;
2277 ++nchar16_t;
2278 frm_nxt += 4;
2279 }
2280 else
2281 {
2282 break;
2283 }
2284 }
2285 return static_cast<int>(frm_nxt - frm);
2286}
2287
2288static
2289codecvt_base::result
2290ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2291 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2292 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2293{
2294 frm_nxt = frm;
2295 to_nxt = to;
2296 if (mode & generate_header)
2297 {
2298 if (to_end-to_nxt < 3)
2299 return codecvt_base::partial;
2300 *to_nxt++ = static_cast<uint8_t>(0xEF);
2301 *to_nxt++ = static_cast<uint8_t>(0xBB);
2302 *to_nxt++ = static_cast<uint8_t>(0xBF);
2303 }
2304 for (; frm_nxt < frm_end; ++frm_nxt)
2305 {
2306 uint32_t wc = *frm_nxt;
2307 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2308 return codecvt_base::error;
2309 if (wc < 0x000080)
2310 {
2311 if (to_end-to_nxt < 1)
2312 return codecvt_base::partial;
2313 *to_nxt++ = static_cast<uint8_t>(wc);
2314 }
2315 else if (wc < 0x000800)
2316 {
2317 if (to_end-to_nxt < 2)
2318 return codecvt_base::partial;
2319 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2320 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2321 }
2322 else if (wc < 0x010000)
2323 {
2324 if (to_end-to_nxt < 3)
2325 return codecvt_base::partial;
2326 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2327 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2328 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2329 }
2330 else // if (wc < 0x110000)
2331 {
2332 if (to_end-to_nxt < 4)
2333 return codecvt_base::partial;
2334 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2335 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2336 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2337 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2338 }
2339 }
2340 return codecvt_base::ok;
2341}
2342
2343static
2344codecvt_base::result
2345utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2346 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2347 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2348{
2349 frm_nxt = frm;
2350 to_nxt = to;
2351 if (mode & consume_header)
2352 {
2353 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2354 frm_nxt[2] == 0xBF)
2355 frm_nxt += 3;
2356 }
2357 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2358 {
2359 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2360 if (c1 < 0x80)
2361 {
2362 if (c1 > Maxcode)
2363 return codecvt_base::error;
2364 *to_nxt = static_cast<uint32_t>(c1);
2365 ++frm_nxt;
2366 }
2367 else if (c1 < 0xC2)
2368 {
2369 return codecvt_base::error;
2370 }
2371 else if (c1 < 0xE0)
2372 {
2373 if (frm_end-frm_nxt < 2)
2374 return codecvt_base::partial;
2375 uint8_t c2 = frm_nxt[1];
2376 if ((c2 & 0xC0) != 0x80)
2377 return codecvt_base::error;
2378 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2379 | (c2 & 0x3F));
2380 if (t > Maxcode)
2381 return codecvt_base::error;
2382 *to_nxt = t;
2383 frm_nxt += 2;
2384 }
2385 else if (c1 < 0xF0)
2386 {
2387 if (frm_end-frm_nxt < 3)
2388 return codecvt_base::partial;
2389 uint8_t c2 = frm_nxt[1];
2390 uint8_t c3 = frm_nxt[2];
2391 switch (c1)
2392 {
2393 case 0xE0:
2394 if ((c2 & 0xE0) != 0xA0)
2395 return codecvt_base::error;
2396 break;
2397 case 0xED:
2398 if ((c2 & 0xE0) != 0x80)
2399 return codecvt_base::error;
2400 break;
2401 default:
2402 if ((c2 & 0xC0) != 0x80)
2403 return codecvt_base::error;
2404 break;
2405 }
2406 if ((c3 & 0xC0) != 0x80)
2407 return codecvt_base::error;
2408 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2409 | ((c2 & 0x3F) << 6)
2410 | (c3 & 0x3F));
2411 if (t > Maxcode)
2412 return codecvt_base::error;
2413 *to_nxt = t;
2414 frm_nxt += 3;
2415 }
2416 else if (c1 < 0xF5)
2417 {
2418 if (frm_end-frm_nxt < 4)
2419 return codecvt_base::partial;
2420 uint8_t c2 = frm_nxt[1];
2421 uint8_t c3 = frm_nxt[2];
2422 uint8_t c4 = frm_nxt[3];
2423 switch (c1)
2424 {
2425 case 0xF0:
2426 if (!(0x90 <= c2 && c2 <= 0xBF))
2427 return codecvt_base::error;
2428 break;
2429 case 0xF4:
2430 if ((c2 & 0xF0) != 0x80)
2431 return codecvt_base::error;
2432 break;
2433 default:
2434 if ((c2 & 0xC0) != 0x80)
2435 return codecvt_base::error;
2436 break;
2437 }
2438 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2439 return codecvt_base::error;
2440 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2441 | ((c2 & 0x3F) << 12)
2442 | ((c3 & 0x3F) << 6)
2443 | (c4 & 0x3F));
2444 if (t > Maxcode)
2445 return codecvt_base::error;
2446 *to_nxt = t;
2447 frm_nxt += 4;
2448 }
2449 else
2450 {
2451 return codecvt_base::error;
2452 }
2453 }
2454 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2455}
2456
2457static
2458int
2459utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2460 size_t mx, unsigned long Maxcode = 0x10FFFF,
2461 codecvt_mode mode = codecvt_mode(0))
2462{
2463 const uint8_t* frm_nxt = frm;
2464 if (mode & consume_header)
2465 {
2466 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2467 frm_nxt[2] == 0xBF)
2468 frm_nxt += 3;
2469 }
2470 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2471 {
2472 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2473 if (c1 < 0x80)
2474 {
2475 if (c1 > Maxcode)
2476 break;
2477 ++frm_nxt;
2478 }
2479 else if (c1 < 0xC2)
2480 {
2481 break;
2482 }
2483 else if (c1 < 0xE0)
2484 {
2485 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2486 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002487 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002488 break;
2489 frm_nxt += 2;
2490 }
2491 else if (c1 < 0xF0)
2492 {
2493 if (frm_end-frm_nxt < 3)
2494 break;
2495 uint8_t c2 = frm_nxt[1];
2496 uint8_t c3 = frm_nxt[2];
2497 switch (c1)
2498 {
2499 case 0xE0:
2500 if ((c2 & 0xE0) != 0xA0)
2501 return static_cast<int>(frm_nxt - frm);
2502 break;
2503 case 0xED:
2504 if ((c2 & 0xE0) != 0x80)
2505 return static_cast<int>(frm_nxt - frm);
2506 break;
2507 default:
2508 if ((c2 & 0xC0) != 0x80)
2509 return static_cast<int>(frm_nxt - frm);
2510 break;
2511 }
2512 if ((c3 & 0xC0) != 0x80)
2513 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002514 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002515 break;
2516 frm_nxt += 3;
2517 }
2518 else if (c1 < 0xF5)
2519 {
2520 if (frm_end-frm_nxt < 4)
2521 break;
2522 uint8_t c2 = frm_nxt[1];
2523 uint8_t c3 = frm_nxt[2];
2524 uint8_t c4 = frm_nxt[3];
2525 switch (c1)
2526 {
2527 case 0xF0:
2528 if (!(0x90 <= c2 && c2 <= 0xBF))
2529 return static_cast<int>(frm_nxt - frm);
2530 break;
2531 case 0xF4:
2532 if ((c2 & 0xF0) != 0x80)
2533 return static_cast<int>(frm_nxt - frm);
2534 break;
2535 default:
2536 if ((c2 & 0xC0) != 0x80)
2537 return static_cast<int>(frm_nxt - frm);
2538 break;
2539 }
2540 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2541 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002542 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2543 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002544 break;
2545 frm_nxt += 4;
2546 }
2547 else
2548 {
2549 break;
2550 }
2551 }
2552 return static_cast<int>(frm_nxt - frm);
2553}
2554
2555static
2556codecvt_base::result
2557ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2558 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2559 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2560{
2561 frm_nxt = frm;
2562 to_nxt = to;
2563 if (mode & generate_header)
2564 {
2565 if (to_end-to_nxt < 3)
2566 return codecvt_base::partial;
2567 *to_nxt++ = static_cast<uint8_t>(0xEF);
2568 *to_nxt++ = static_cast<uint8_t>(0xBB);
2569 *to_nxt++ = static_cast<uint8_t>(0xBF);
2570 }
2571 for (; frm_nxt < frm_end; ++frm_nxt)
2572 {
2573 uint16_t wc = *frm_nxt;
2574 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2575 return codecvt_base::error;
2576 if (wc < 0x0080)
2577 {
2578 if (to_end-to_nxt < 1)
2579 return codecvt_base::partial;
2580 *to_nxt++ = static_cast<uint8_t>(wc);
2581 }
2582 else if (wc < 0x0800)
2583 {
2584 if (to_end-to_nxt < 2)
2585 return codecvt_base::partial;
2586 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2587 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2588 }
2589 else // if (wc <= 0xFFFF)
2590 {
2591 if (to_end-to_nxt < 3)
2592 return codecvt_base::partial;
2593 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2594 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2595 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2596 }
2597 }
2598 return codecvt_base::ok;
2599}
2600
2601static
2602codecvt_base::result
2603utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2604 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2605 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2606{
2607 frm_nxt = frm;
2608 to_nxt = to;
2609 if (mode & consume_header)
2610 {
2611 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2612 frm_nxt[2] == 0xBF)
2613 frm_nxt += 3;
2614 }
2615 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2616 {
2617 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2618 if (c1 < 0x80)
2619 {
2620 if (c1 > Maxcode)
2621 return codecvt_base::error;
2622 *to_nxt = static_cast<uint16_t>(c1);
2623 ++frm_nxt;
2624 }
2625 else if (c1 < 0xC2)
2626 {
2627 return codecvt_base::error;
2628 }
2629 else if (c1 < 0xE0)
2630 {
2631 if (frm_end-frm_nxt < 2)
2632 return codecvt_base::partial;
2633 uint8_t c2 = frm_nxt[1];
2634 if ((c2 & 0xC0) != 0x80)
2635 return codecvt_base::error;
2636 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2637 | (c2 & 0x3F));
2638 if (t > Maxcode)
2639 return codecvt_base::error;
2640 *to_nxt = t;
2641 frm_nxt += 2;
2642 }
2643 else if (c1 < 0xF0)
2644 {
2645 if (frm_end-frm_nxt < 3)
2646 return codecvt_base::partial;
2647 uint8_t c2 = frm_nxt[1];
2648 uint8_t c3 = frm_nxt[2];
2649 switch (c1)
2650 {
2651 case 0xE0:
2652 if ((c2 & 0xE0) != 0xA0)
2653 return codecvt_base::error;
2654 break;
2655 case 0xED:
2656 if ((c2 & 0xE0) != 0x80)
2657 return codecvt_base::error;
2658 break;
2659 default:
2660 if ((c2 & 0xC0) != 0x80)
2661 return codecvt_base::error;
2662 break;
2663 }
2664 if ((c3 & 0xC0) != 0x80)
2665 return codecvt_base::error;
2666 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2667 | ((c2 & 0x3F) << 6)
2668 | (c3 & 0x3F));
2669 if (t > Maxcode)
2670 return codecvt_base::error;
2671 *to_nxt = t;
2672 frm_nxt += 3;
2673 }
2674 else
2675 {
2676 return codecvt_base::error;
2677 }
2678 }
2679 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2680}
2681
2682static
2683int
2684utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2685 size_t mx, unsigned long Maxcode = 0x10FFFF,
2686 codecvt_mode mode = codecvt_mode(0))
2687{
2688 const uint8_t* frm_nxt = frm;
2689 if (mode & consume_header)
2690 {
2691 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2692 frm_nxt[2] == 0xBF)
2693 frm_nxt += 3;
2694 }
2695 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2696 {
2697 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2698 if (c1 < 0x80)
2699 {
2700 if (c1 > Maxcode)
2701 break;
2702 ++frm_nxt;
2703 }
2704 else if (c1 < 0xC2)
2705 {
2706 break;
2707 }
2708 else if (c1 < 0xE0)
2709 {
2710 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2711 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002712 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002713 break;
2714 frm_nxt += 2;
2715 }
2716 else if (c1 < 0xF0)
2717 {
2718 if (frm_end-frm_nxt < 3)
2719 break;
2720 uint8_t c2 = frm_nxt[1];
2721 uint8_t c3 = frm_nxt[2];
2722 switch (c1)
2723 {
2724 case 0xE0:
2725 if ((c2 & 0xE0) != 0xA0)
2726 return static_cast<int>(frm_nxt - frm);
2727 break;
2728 case 0xED:
2729 if ((c2 & 0xE0) != 0x80)
2730 return static_cast<int>(frm_nxt - frm);
2731 break;
2732 default:
2733 if ((c2 & 0xC0) != 0x80)
2734 return static_cast<int>(frm_nxt - frm);
2735 break;
2736 }
2737 if ((c3 & 0xC0) != 0x80)
2738 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002739 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002740 break;
2741 frm_nxt += 3;
2742 }
2743 else
2744 {
2745 break;
2746 }
2747 }
2748 return static_cast<int>(frm_nxt - frm);
2749}
2750
2751static
2752codecvt_base::result
2753ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2754 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2755 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2756{
2757 frm_nxt = frm;
2758 to_nxt = to;
2759 if (mode & generate_header)
2760 {
2761 if (to_end-to_nxt < 2)
2762 return codecvt_base::partial;
2763 *to_nxt++ = static_cast<uint8_t>(0xFE);
2764 *to_nxt++ = static_cast<uint8_t>(0xFF);
2765 }
2766 for (; frm_nxt < frm_end; ++frm_nxt)
2767 {
2768 uint32_t wc = *frm_nxt;
2769 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2770 return codecvt_base::error;
2771 if (wc < 0x010000)
2772 {
2773 if (to_end-to_nxt < 2)
2774 return codecvt_base::partial;
2775 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2776 *to_nxt++ = static_cast<uint8_t>(wc);
2777 }
2778 else
2779 {
2780 if (to_end-to_nxt < 4)
2781 return codecvt_base::partial;
2782 uint16_t t = static_cast<uint16_t>(
2783 0xD800
2784 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2785 | ((wc & 0x00FC00) >> 10));
2786 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2787 *to_nxt++ = static_cast<uint8_t>(t);
2788 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2789 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2790 *to_nxt++ = static_cast<uint8_t>(t);
2791 }
2792 }
2793 return codecvt_base::ok;
2794}
2795
2796static
2797codecvt_base::result
2798utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2799 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2800 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2801{
2802 frm_nxt = frm;
2803 to_nxt = to;
2804 if (mode & consume_header)
2805 {
2806 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2807 frm_nxt += 2;
2808 }
2809 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2810 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002811 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002812 if ((c1 & 0xFC00) == 0xDC00)
2813 return codecvt_base::error;
2814 if ((c1 & 0xFC00) != 0xD800)
2815 {
2816 if (c1 > Maxcode)
2817 return codecvt_base::error;
2818 *to_nxt = static_cast<uint32_t>(c1);
2819 frm_nxt += 2;
2820 }
2821 else
2822 {
2823 if (frm_end-frm_nxt < 4)
2824 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002825 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002826 if ((c2 & 0xFC00) != 0xDC00)
2827 return codecvt_base::error;
2828 uint32_t t = static_cast<uint32_t>(
2829 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2830 | ((c1 & 0x003F) << 10)
2831 | (c2 & 0x03FF));
2832 if (t > Maxcode)
2833 return codecvt_base::error;
2834 *to_nxt = t;
2835 frm_nxt += 4;
2836 }
2837 }
2838 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2839}
2840
2841static
2842int
2843utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2844 size_t mx, unsigned long Maxcode = 0x10FFFF,
2845 codecvt_mode mode = codecvt_mode(0))
2846{
2847 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002848 if (mode & consume_header)
2849 {
2850 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2851 frm_nxt += 2;
2852 }
2853 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2854 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002855 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002856 if ((c1 & 0xFC00) == 0xDC00)
2857 break;
2858 if ((c1 & 0xFC00) != 0xD800)
2859 {
2860 if (c1 > Maxcode)
2861 break;
2862 frm_nxt += 2;
2863 }
2864 else
2865 {
2866 if (frm_end-frm_nxt < 4)
2867 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002868 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002869 if ((c2 & 0xFC00) != 0xDC00)
2870 break;
2871 uint32_t t = static_cast<uint32_t>(
2872 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2873 | ((c1 & 0x003F) << 10)
2874 | (c2 & 0x03FF));
2875 if (t > Maxcode)
2876 break;
2877 frm_nxt += 4;
2878 }
2879 }
2880 return static_cast<int>(frm_nxt - frm);
2881}
2882
2883static
2884codecvt_base::result
2885ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2886 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2887 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2888{
2889 frm_nxt = frm;
2890 to_nxt = to;
2891 if (mode & generate_header)
2892 {
2893 if (to_end-to_nxt < 2)
2894 return codecvt_base::partial;
2895 *to_nxt++ = static_cast<uint8_t>(0xFF);
2896 *to_nxt++ = static_cast<uint8_t>(0xFE);
2897 }
2898 for (; frm_nxt < frm_end; ++frm_nxt)
2899 {
2900 uint32_t wc = *frm_nxt;
2901 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2902 return codecvt_base::error;
2903 if (wc < 0x010000)
2904 {
2905 if (to_end-to_nxt < 2)
2906 return codecvt_base::partial;
2907 *to_nxt++ = static_cast<uint8_t>(wc);
2908 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2909 }
2910 else
2911 {
2912 if (to_end-to_nxt < 4)
2913 return codecvt_base::partial;
2914 uint16_t t = static_cast<uint16_t>(
2915 0xD800
2916 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2917 | ((wc & 0x00FC00) >> 10));
2918 *to_nxt++ = static_cast<uint8_t>(t);
2919 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2920 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2921 *to_nxt++ = static_cast<uint8_t>(t);
2922 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2923 }
2924 }
2925 return codecvt_base::ok;
2926}
2927
2928static
2929codecvt_base::result
2930utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2931 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2932 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2933{
2934 frm_nxt = frm;
2935 to_nxt = to;
2936 if (mode & consume_header)
2937 {
2938 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2939 frm_nxt += 2;
2940 }
2941 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2942 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002943 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002944 if ((c1 & 0xFC00) == 0xDC00)
2945 return codecvt_base::error;
2946 if ((c1 & 0xFC00) != 0xD800)
2947 {
2948 if (c1 > Maxcode)
2949 return codecvt_base::error;
2950 *to_nxt = static_cast<uint32_t>(c1);
2951 frm_nxt += 2;
2952 }
2953 else
2954 {
2955 if (frm_end-frm_nxt < 4)
2956 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002957 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002958 if ((c2 & 0xFC00) != 0xDC00)
2959 return codecvt_base::error;
2960 uint32_t t = static_cast<uint32_t>(
2961 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2962 | ((c1 & 0x003F) << 10)
2963 | (c2 & 0x03FF));
2964 if (t > Maxcode)
2965 return codecvt_base::error;
2966 *to_nxt = t;
2967 frm_nxt += 4;
2968 }
2969 }
2970 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2971}
2972
2973static
2974int
2975utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2976 size_t mx, unsigned long Maxcode = 0x10FFFF,
2977 codecvt_mode mode = codecvt_mode(0))
2978{
2979 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002980 if (mode & consume_header)
2981 {
2982 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2983 frm_nxt += 2;
2984 }
2985 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2986 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002987 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002988 if ((c1 & 0xFC00) == 0xDC00)
2989 break;
2990 if ((c1 & 0xFC00) != 0xD800)
2991 {
2992 if (c1 > Maxcode)
2993 break;
2994 frm_nxt += 2;
2995 }
2996 else
2997 {
2998 if (frm_end-frm_nxt < 4)
2999 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003000 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003001 if ((c2 & 0xFC00) != 0xDC00)
3002 break;
3003 uint32_t t = static_cast<uint32_t>(
3004 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3005 | ((c1 & 0x003F) << 10)
3006 | (c2 & 0x03FF));
3007 if (t > Maxcode)
3008 break;
3009 frm_nxt += 4;
3010 }
3011 }
3012 return static_cast<int>(frm_nxt - frm);
3013}
3014
3015static
3016codecvt_base::result
3017ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3018 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3019 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3020{
3021 frm_nxt = frm;
3022 to_nxt = to;
3023 if (mode & generate_header)
3024 {
3025 if (to_end-to_nxt < 2)
3026 return codecvt_base::partial;
3027 *to_nxt++ = static_cast<uint8_t>(0xFE);
3028 *to_nxt++ = static_cast<uint8_t>(0xFF);
3029 }
3030 for (; frm_nxt < frm_end; ++frm_nxt)
3031 {
3032 uint16_t wc = *frm_nxt;
3033 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3034 return codecvt_base::error;
3035 if (to_end-to_nxt < 2)
3036 return codecvt_base::partial;
3037 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3038 *to_nxt++ = static_cast<uint8_t>(wc);
3039 }
3040 return codecvt_base::ok;
3041}
3042
3043static
3044codecvt_base::result
3045utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3046 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3047 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3048{
3049 frm_nxt = frm;
3050 to_nxt = to;
3051 if (mode & consume_header)
3052 {
3053 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3054 frm_nxt += 2;
3055 }
3056 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3057 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003058 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003059 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3060 return codecvt_base::error;
3061 *to_nxt = c1;
3062 frm_nxt += 2;
3063 }
3064 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3065}
3066
3067static
3068int
3069utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3070 size_t mx, unsigned long Maxcode = 0x10FFFF,
3071 codecvt_mode mode = codecvt_mode(0))
3072{
3073 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003074 if (mode & consume_header)
3075 {
3076 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3077 frm_nxt += 2;
3078 }
3079 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3080 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003081 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003082 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3083 break;
3084 frm_nxt += 2;
3085 }
3086 return static_cast<int>(frm_nxt - frm);
3087}
3088
3089static
3090codecvt_base::result
3091ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3092 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3093 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3094{
3095 frm_nxt = frm;
3096 to_nxt = to;
3097 if (mode & generate_header)
3098 {
3099 if (to_end-to_nxt < 2)
3100 return codecvt_base::partial;
3101 *to_nxt++ = static_cast<uint8_t>(0xFF);
3102 *to_nxt++ = static_cast<uint8_t>(0xFE);
3103 }
3104 for (; frm_nxt < frm_end; ++frm_nxt)
3105 {
3106 uint16_t wc = *frm_nxt;
3107 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3108 return codecvt_base::error;
3109 if (to_end-to_nxt < 2)
3110 return codecvt_base::partial;
3111 *to_nxt++ = static_cast<uint8_t>(wc);
3112 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3113 }
3114 return codecvt_base::ok;
3115}
3116
3117static
3118codecvt_base::result
3119utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3120 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3121 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3122{
3123 frm_nxt = frm;
3124 to_nxt = to;
3125 if (mode & consume_header)
3126 {
3127 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3128 frm_nxt += 2;
3129 }
3130 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3131 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003132 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003133 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3134 return codecvt_base::error;
3135 *to_nxt = c1;
3136 frm_nxt += 2;
3137 }
3138 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3139}
3140
3141static
3142int
3143utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3144 size_t mx, unsigned long Maxcode = 0x10FFFF,
3145 codecvt_mode mode = codecvt_mode(0))
3146{
3147 const uint8_t* frm_nxt = frm;
3148 frm_nxt = frm;
3149 if (mode & consume_header)
3150 {
3151 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3152 frm_nxt += 2;
3153 }
3154 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3155 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003156 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003157 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3158 break;
3159 frm_nxt += 2;
3160 }
3161 return static_cast<int>(frm_nxt - frm);
3162}
3163
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003164// template <> class codecvt<char16_t, char, mbstate_t>
3165
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003166locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003167
3168codecvt<char16_t, char, mbstate_t>::~codecvt()
3169{
3170}
3171
3172codecvt<char16_t, char, mbstate_t>::result
3173codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003174 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003175 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3176{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003177 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3178 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3179 const uint16_t* _frm_nxt = _frm;
3180 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3181 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3182 uint8_t* _to_nxt = _to;
3183 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3184 frm_nxt = frm + (_frm_nxt - _frm);
3185 to_nxt = to + (_to_nxt - _to);
3186 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003187}
3188
3189codecvt<char16_t, char, mbstate_t>::result
3190codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003191 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003192 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3193{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003194 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3195 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3196 const uint8_t* _frm_nxt = _frm;
3197 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3198 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3199 uint16_t* _to_nxt = _to;
3200 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3201 frm_nxt = frm + (_frm_nxt - _frm);
3202 to_nxt = to + (_to_nxt - _to);
3203 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003204}
3205
3206codecvt<char16_t, char, mbstate_t>::result
3207codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3208 extern_type* to, extern_type*, extern_type*& to_nxt) const
3209{
3210 to_nxt = to;
3211 return noconv;
3212}
3213
3214int
Howard Hinnantc9834542011-05-31 15:34:58 +00003215codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003216{
3217 return 0;
3218}
3219
3220bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003221codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003222{
3223 return false;
3224}
3225
3226int
3227codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3228 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3229{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003230 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3231 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3232 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003233}
3234
3235int
Howard Hinnantc9834542011-05-31 15:34:58 +00003236codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003237{
3238 return 4;
3239}
3240
3241// template <> class codecvt<char32_t, char, mbstate_t>
3242
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003243locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003244
3245codecvt<char32_t, char, mbstate_t>::~codecvt()
3246{
3247}
3248
3249codecvt<char32_t, char, mbstate_t>::result
3250codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003251 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003252 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3253{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003254 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3255 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3256 const uint32_t* _frm_nxt = _frm;
3257 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3258 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3259 uint8_t* _to_nxt = _to;
3260 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3261 frm_nxt = frm + (_frm_nxt - _frm);
3262 to_nxt = to + (_to_nxt - _to);
3263 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003264}
3265
3266codecvt<char32_t, char, mbstate_t>::result
3267codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003268 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003269 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3270{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003271 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3272 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3273 const uint8_t* _frm_nxt = _frm;
3274 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3275 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3276 uint32_t* _to_nxt = _to;
3277 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3278 frm_nxt = frm + (_frm_nxt - _frm);
3279 to_nxt = to + (_to_nxt - _to);
3280 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003281}
3282
3283codecvt<char32_t, char, mbstate_t>::result
3284codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3285 extern_type* to, extern_type*, extern_type*& to_nxt) const
3286{
3287 to_nxt = to;
3288 return noconv;
3289}
3290
3291int
Howard Hinnantc9834542011-05-31 15:34:58 +00003292codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003293{
3294 return 0;
3295}
3296
3297bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003298codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003299{
3300 return false;
3301}
3302
3303int
3304codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3305 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3306{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003307 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3308 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3309 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003310}
3311
3312int
Howard Hinnantc9834542011-05-31 15:34:58 +00003313codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003314{
3315 return 4;
3316}
3317
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003318// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003319
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003320__codecvt_utf8<wchar_t>::result
3321__codecvt_utf8<wchar_t>::do_out(state_type&,
3322 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003323 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3324{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003325#if _WIN32
3326 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3327 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3328 const uint16_t* _frm_nxt = _frm;
3329#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003330 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3331 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3332 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003333#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003334 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3335 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3336 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003337#if _WIN32
3338 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3339 _Maxcode_, _Mode_);
3340#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003341 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3342 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003343#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003344 frm_nxt = frm + (_frm_nxt - _frm);
3345 to_nxt = to + (_to_nxt - _to);
3346 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003347}
3348
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003349__codecvt_utf8<wchar_t>::result
3350__codecvt_utf8<wchar_t>::do_in(state_type&,
3351 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003352 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3353{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003354 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3355 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3356 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003357#if _WIN32
3358 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3359 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3360 uint16_t* _to_nxt = _to;
3361 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3362 _Maxcode_, _Mode_);
3363#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003364 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3365 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3366 uint32_t* _to_nxt = _to;
3367 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3368 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003369#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003370 frm_nxt = frm + (_frm_nxt - _frm);
3371 to_nxt = to + (_to_nxt - _to);
3372 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003373}
3374
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003375__codecvt_utf8<wchar_t>::result
3376__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003377 extern_type* to, extern_type*, extern_type*& to_nxt) const
3378{
3379 to_nxt = to;
3380 return noconv;
3381}
3382
3383int
Howard Hinnantc9834542011-05-31 15:34:58 +00003384__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003385{
3386 return 0;
3387}
3388
3389bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003390__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003391{
3392 return false;
3393}
3394
3395int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003396__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003397 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3398{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003399 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3400 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3401 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003402}
3403
3404int
Howard Hinnantc9834542011-05-31 15:34:58 +00003405__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003406{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003407 if (_Mode_ & consume_header)
3408 return 7;
3409 return 4;
3410}
3411
3412// __codecvt_utf8<char16_t>
3413
3414__codecvt_utf8<char16_t>::result
3415__codecvt_utf8<char16_t>::do_out(state_type&,
3416 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3417 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3418{
3419 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3420 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3421 const uint16_t* _frm_nxt = _frm;
3422 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3423 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3424 uint8_t* _to_nxt = _to;
3425 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3426 _Maxcode_, _Mode_);
3427 frm_nxt = frm + (_frm_nxt - _frm);
3428 to_nxt = to + (_to_nxt - _to);
3429 return r;
3430}
3431
3432__codecvt_utf8<char16_t>::result
3433__codecvt_utf8<char16_t>::do_in(state_type&,
3434 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3435 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3436{
3437 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3438 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3439 const uint8_t* _frm_nxt = _frm;
3440 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3441 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3442 uint16_t* _to_nxt = _to;
3443 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3444 _Maxcode_, _Mode_);
3445 frm_nxt = frm + (_frm_nxt - _frm);
3446 to_nxt = to + (_to_nxt - _to);
3447 return r;
3448}
3449
3450__codecvt_utf8<char16_t>::result
3451__codecvt_utf8<char16_t>::do_unshift(state_type&,
3452 extern_type* to, extern_type*, extern_type*& to_nxt) const
3453{
3454 to_nxt = to;
3455 return noconv;
3456}
3457
3458int
Howard Hinnantc9834542011-05-31 15:34:58 +00003459__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003460{
3461 return 0;
3462}
3463
3464bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003465__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003466{
3467 return false;
3468}
3469
3470int
3471__codecvt_utf8<char16_t>::do_length(state_type&,
3472 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3473{
3474 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3475 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3476 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3477}
3478
3479int
Howard Hinnantc9834542011-05-31 15:34:58 +00003480__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003481{
3482 if (_Mode_ & consume_header)
3483 return 6;
3484 return 3;
3485}
3486
3487// __codecvt_utf8<char32_t>
3488
3489__codecvt_utf8<char32_t>::result
3490__codecvt_utf8<char32_t>::do_out(state_type&,
3491 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3492 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3493{
3494 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3495 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3496 const uint32_t* _frm_nxt = _frm;
3497 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3498 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3499 uint8_t* _to_nxt = _to;
3500 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3501 _Maxcode_, _Mode_);
3502 frm_nxt = frm + (_frm_nxt - _frm);
3503 to_nxt = to + (_to_nxt - _to);
3504 return r;
3505}
3506
3507__codecvt_utf8<char32_t>::result
3508__codecvt_utf8<char32_t>::do_in(state_type&,
3509 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3510 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3511{
3512 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3513 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3514 const uint8_t* _frm_nxt = _frm;
3515 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3516 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3517 uint32_t* _to_nxt = _to;
3518 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3519 _Maxcode_, _Mode_);
3520 frm_nxt = frm + (_frm_nxt - _frm);
3521 to_nxt = to + (_to_nxt - _to);
3522 return r;
3523}
3524
3525__codecvt_utf8<char32_t>::result
3526__codecvt_utf8<char32_t>::do_unshift(state_type&,
3527 extern_type* to, extern_type*, extern_type*& to_nxt) const
3528{
3529 to_nxt = to;
3530 return noconv;
3531}
3532
3533int
Howard Hinnantc9834542011-05-31 15:34:58 +00003534__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003535{
3536 return 0;
3537}
3538
3539bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003540__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003541{
3542 return false;
3543}
3544
3545int
3546__codecvt_utf8<char32_t>::do_length(state_type&,
3547 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3548{
3549 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3550 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3551 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3552}
3553
3554int
Howard Hinnantc9834542011-05-31 15:34:58 +00003555__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003556{
3557 if (_Mode_ & consume_header)
3558 return 7;
3559 return 4;
3560}
3561
3562// __codecvt_utf16<wchar_t, false>
3563
3564__codecvt_utf16<wchar_t, false>::result
3565__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3566 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3567 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3568{
3569 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3570 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3571 const uint32_t* _frm_nxt = _frm;
3572 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3573 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3574 uint8_t* _to_nxt = _to;
3575 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3576 _Maxcode_, _Mode_);
3577 frm_nxt = frm + (_frm_nxt - _frm);
3578 to_nxt = to + (_to_nxt - _to);
3579 return r;
3580}
3581
3582__codecvt_utf16<wchar_t, false>::result
3583__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3584 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3585 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3586{
3587 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3588 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3589 const uint8_t* _frm_nxt = _frm;
3590 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3591 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3592 uint32_t* _to_nxt = _to;
3593 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3594 _Maxcode_, _Mode_);
3595 frm_nxt = frm + (_frm_nxt - _frm);
3596 to_nxt = to + (_to_nxt - _to);
3597 return r;
3598}
3599
3600__codecvt_utf16<wchar_t, false>::result
3601__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3602 extern_type* to, extern_type*, extern_type*& to_nxt) const
3603{
3604 to_nxt = to;
3605 return noconv;
3606}
3607
3608int
Howard Hinnantc9834542011-05-31 15:34:58 +00003609__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003610{
3611 return 0;
3612}
3613
3614bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003615__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003616{
3617 return false;
3618}
3619
3620int
3621__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3622 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3623{
3624 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3625 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3626 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3627}
3628
3629int
Howard Hinnantc9834542011-05-31 15:34:58 +00003630__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003631{
3632 if (_Mode_ & consume_header)
3633 return 6;
3634 return 4;
3635}
3636
3637// __codecvt_utf16<wchar_t, true>
3638
3639__codecvt_utf16<wchar_t, true>::result
3640__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3641 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3642 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3643{
3644 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3645 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3646 const uint32_t* _frm_nxt = _frm;
3647 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3648 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3649 uint8_t* _to_nxt = _to;
3650 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3651 _Maxcode_, _Mode_);
3652 frm_nxt = frm + (_frm_nxt - _frm);
3653 to_nxt = to + (_to_nxt - _to);
3654 return r;
3655}
3656
3657__codecvt_utf16<wchar_t, true>::result
3658__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3659 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3660 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3661{
3662 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3663 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3664 const uint8_t* _frm_nxt = _frm;
3665 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3666 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3667 uint32_t* _to_nxt = _to;
3668 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3669 _Maxcode_, _Mode_);
3670 frm_nxt = frm + (_frm_nxt - _frm);
3671 to_nxt = to + (_to_nxt - _to);
3672 return r;
3673}
3674
3675__codecvt_utf16<wchar_t, true>::result
3676__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3677 extern_type* to, extern_type*, extern_type*& to_nxt) const
3678{
3679 to_nxt = to;
3680 return noconv;
3681}
3682
3683int
Howard Hinnantc9834542011-05-31 15:34:58 +00003684__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003685{
3686 return 0;
3687}
3688
3689bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003690__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003691{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003692 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003693}
3694
3695int
3696__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3697 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3698{
3699 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3700 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3701 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3702}
3703
3704int
Howard Hinnantc9834542011-05-31 15:34:58 +00003705__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003706{
3707 if (_Mode_ & consume_header)
3708 return 6;
3709 return 4;
3710}
3711
3712// __codecvt_utf16<char16_t, false>
3713
3714__codecvt_utf16<char16_t, false>::result
3715__codecvt_utf16<char16_t, false>::do_out(state_type&,
3716 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3717 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3718{
3719 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3720 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3721 const uint16_t* _frm_nxt = _frm;
3722 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3723 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3724 uint8_t* _to_nxt = _to;
3725 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3726 _Maxcode_, _Mode_);
3727 frm_nxt = frm + (_frm_nxt - _frm);
3728 to_nxt = to + (_to_nxt - _to);
3729 return r;
3730}
3731
3732__codecvt_utf16<char16_t, false>::result
3733__codecvt_utf16<char16_t, false>::do_in(state_type&,
3734 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3735 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3736{
3737 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3738 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3739 const uint8_t* _frm_nxt = _frm;
3740 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3741 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3742 uint16_t* _to_nxt = _to;
3743 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3744 _Maxcode_, _Mode_);
3745 frm_nxt = frm + (_frm_nxt - _frm);
3746 to_nxt = to + (_to_nxt - _to);
3747 return r;
3748}
3749
3750__codecvt_utf16<char16_t, false>::result
3751__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3752 extern_type* to, extern_type*, extern_type*& to_nxt) const
3753{
3754 to_nxt = to;
3755 return noconv;
3756}
3757
3758int
Howard Hinnantc9834542011-05-31 15:34:58 +00003759__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003760{
3761 return 0;
3762}
3763
3764bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003765__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003766{
3767 return false;
3768}
3769
3770int
3771__codecvt_utf16<char16_t, false>::do_length(state_type&,
3772 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3773{
3774 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3775 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3776 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3777}
3778
3779int
Howard Hinnantc9834542011-05-31 15:34:58 +00003780__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003781{
3782 if (_Mode_ & consume_header)
3783 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003784 return 2;
3785}
3786
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003787// __codecvt_utf16<char16_t, true>
3788
3789__codecvt_utf16<char16_t, true>::result
3790__codecvt_utf16<char16_t, true>::do_out(state_type&,
3791 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3792 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3793{
3794 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3795 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3796 const uint16_t* _frm_nxt = _frm;
3797 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3798 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3799 uint8_t* _to_nxt = _to;
3800 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3801 _Maxcode_, _Mode_);
3802 frm_nxt = frm + (_frm_nxt - _frm);
3803 to_nxt = to + (_to_nxt - _to);
3804 return r;
3805}
3806
3807__codecvt_utf16<char16_t, true>::result
3808__codecvt_utf16<char16_t, true>::do_in(state_type&,
3809 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3810 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3811{
3812 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3813 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3814 const uint8_t* _frm_nxt = _frm;
3815 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3816 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3817 uint16_t* _to_nxt = _to;
3818 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3819 _Maxcode_, _Mode_);
3820 frm_nxt = frm + (_frm_nxt - _frm);
3821 to_nxt = to + (_to_nxt - _to);
3822 return r;
3823}
3824
3825__codecvt_utf16<char16_t, true>::result
3826__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3827 extern_type* to, extern_type*, extern_type*& to_nxt) const
3828{
3829 to_nxt = to;
3830 return noconv;
3831}
3832
3833int
Howard Hinnantc9834542011-05-31 15:34:58 +00003834__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003835{
3836 return 0;
3837}
3838
3839bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003840__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003841{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003842 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003843}
3844
3845int
3846__codecvt_utf16<char16_t, true>::do_length(state_type&,
3847 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3848{
3849 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3850 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3851 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3852}
3853
3854int
Howard Hinnantc9834542011-05-31 15:34:58 +00003855__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003856{
3857 if (_Mode_ & consume_header)
3858 return 4;
3859 return 2;
3860}
3861
3862// __codecvt_utf16<char32_t, false>
3863
3864__codecvt_utf16<char32_t, false>::result
3865__codecvt_utf16<char32_t, false>::do_out(state_type&,
3866 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3867 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3868{
3869 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3870 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3871 const uint32_t* _frm_nxt = _frm;
3872 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3873 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3874 uint8_t* _to_nxt = _to;
3875 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3876 _Maxcode_, _Mode_);
3877 frm_nxt = frm + (_frm_nxt - _frm);
3878 to_nxt = to + (_to_nxt - _to);
3879 return r;
3880}
3881
3882__codecvt_utf16<char32_t, false>::result
3883__codecvt_utf16<char32_t, false>::do_in(state_type&,
3884 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3885 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3886{
3887 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3888 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3889 const uint8_t* _frm_nxt = _frm;
3890 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3891 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3892 uint32_t* _to_nxt = _to;
3893 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3894 _Maxcode_, _Mode_);
3895 frm_nxt = frm + (_frm_nxt - _frm);
3896 to_nxt = to + (_to_nxt - _to);
3897 return r;
3898}
3899
3900__codecvt_utf16<char32_t, false>::result
3901__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3902 extern_type* to, extern_type*, extern_type*& to_nxt) const
3903{
3904 to_nxt = to;
3905 return noconv;
3906}
3907
3908int
Howard Hinnantc9834542011-05-31 15:34:58 +00003909__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003910{
3911 return 0;
3912}
3913
3914bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003915__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003916{
3917 return false;
3918}
3919
3920int
3921__codecvt_utf16<char32_t, false>::do_length(state_type&,
3922 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3923{
3924 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3925 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3926 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3927}
3928
3929int
Howard Hinnantc9834542011-05-31 15:34:58 +00003930__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003931{
3932 if (_Mode_ & consume_header)
3933 return 6;
3934 return 4;
3935}
3936
3937// __codecvt_utf16<char32_t, true>
3938
3939__codecvt_utf16<char32_t, true>::result
3940__codecvt_utf16<char32_t, true>::do_out(state_type&,
3941 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3942 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3943{
3944 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3945 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3946 const uint32_t* _frm_nxt = _frm;
3947 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3948 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3949 uint8_t* _to_nxt = _to;
3950 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3951 _Maxcode_, _Mode_);
3952 frm_nxt = frm + (_frm_nxt - _frm);
3953 to_nxt = to + (_to_nxt - _to);
3954 return r;
3955}
3956
3957__codecvt_utf16<char32_t, true>::result
3958__codecvt_utf16<char32_t, true>::do_in(state_type&,
3959 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3960 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3961{
3962 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3963 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3964 const uint8_t* _frm_nxt = _frm;
3965 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3966 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3967 uint32_t* _to_nxt = _to;
3968 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3969 _Maxcode_, _Mode_);
3970 frm_nxt = frm + (_frm_nxt - _frm);
3971 to_nxt = to + (_to_nxt - _to);
3972 return r;
3973}
3974
3975__codecvt_utf16<char32_t, true>::result
3976__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3977 extern_type* to, extern_type*, extern_type*& to_nxt) const
3978{
3979 to_nxt = to;
3980 return noconv;
3981}
3982
3983int
Howard Hinnantc9834542011-05-31 15:34:58 +00003984__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003985{
3986 return 0;
3987}
3988
3989bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003990__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003991{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003992 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003993}
3994
3995int
3996__codecvt_utf16<char32_t, true>::do_length(state_type&,
3997 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3998{
3999 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4000 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4001 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4002}
4003
4004int
Howard Hinnantc9834542011-05-31 15:34:58 +00004005__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004006{
4007 if (_Mode_ & consume_header)
4008 return 6;
4009 return 4;
4010}
4011
4012// __codecvt_utf8_utf16<wchar_t>
4013
4014__codecvt_utf8_utf16<wchar_t>::result
4015__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4016 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4017 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4018{
4019 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4020 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4021 const uint32_t* _frm_nxt = _frm;
4022 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4023 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4024 uint8_t* _to_nxt = _to;
4025 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4026 _Maxcode_, _Mode_);
4027 frm_nxt = frm + (_frm_nxt - _frm);
4028 to_nxt = to + (_to_nxt - _to);
4029 return r;
4030}
4031
4032__codecvt_utf8_utf16<wchar_t>::result
4033__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4034 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4035 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4036{
4037 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4038 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4039 const uint8_t* _frm_nxt = _frm;
4040 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4041 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4042 uint32_t* _to_nxt = _to;
4043 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4044 _Maxcode_, _Mode_);
4045 frm_nxt = frm + (_frm_nxt - _frm);
4046 to_nxt = to + (_to_nxt - _to);
4047 return r;
4048}
4049
4050__codecvt_utf8_utf16<wchar_t>::result
4051__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4052 extern_type* to, extern_type*, extern_type*& to_nxt) const
4053{
4054 to_nxt = to;
4055 return noconv;
4056}
4057
4058int
Howard Hinnantc9834542011-05-31 15:34:58 +00004059__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004060{
4061 return 0;
4062}
4063
4064bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004065__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004066{
4067 return false;
4068}
4069
4070int
4071__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4072 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4073{
4074 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4075 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4076 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4077}
4078
4079int
Howard Hinnantc9834542011-05-31 15:34:58 +00004080__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004081{
4082 if (_Mode_ & consume_header)
4083 return 7;
4084 return 4;
4085}
4086
4087// __codecvt_utf8_utf16<char16_t>
4088
4089__codecvt_utf8_utf16<char16_t>::result
4090__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4091 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4092 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4093{
4094 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4095 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4096 const uint16_t* _frm_nxt = _frm;
4097 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4098 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4099 uint8_t* _to_nxt = _to;
4100 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4101 _Maxcode_, _Mode_);
4102 frm_nxt = frm + (_frm_nxt - _frm);
4103 to_nxt = to + (_to_nxt - _to);
4104 return r;
4105}
4106
4107__codecvt_utf8_utf16<char16_t>::result
4108__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4109 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4110 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4111{
4112 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4113 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4114 const uint8_t* _frm_nxt = _frm;
4115 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4116 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4117 uint16_t* _to_nxt = _to;
4118 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4119 _Maxcode_, _Mode_);
4120 frm_nxt = frm + (_frm_nxt - _frm);
4121 to_nxt = to + (_to_nxt - _to);
4122 return r;
4123}
4124
4125__codecvt_utf8_utf16<char16_t>::result
4126__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4127 extern_type* to, extern_type*, extern_type*& to_nxt) const
4128{
4129 to_nxt = to;
4130 return noconv;
4131}
4132
4133int
Howard Hinnantc9834542011-05-31 15:34:58 +00004134__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004135{
4136 return 0;
4137}
4138
4139bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004140__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004141{
4142 return false;
4143}
4144
4145int
4146__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4147 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4148{
4149 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4150 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4151 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4152}
4153
4154int
Howard Hinnantc9834542011-05-31 15:34:58 +00004155__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004156{
4157 if (_Mode_ & consume_header)
4158 return 7;
4159 return 4;
4160}
4161
4162// __codecvt_utf8_utf16<char32_t>
4163
4164__codecvt_utf8_utf16<char32_t>::result
4165__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4166 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4167 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4168{
4169 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4170 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4171 const uint32_t* _frm_nxt = _frm;
4172 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4173 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4174 uint8_t* _to_nxt = _to;
4175 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4176 _Maxcode_, _Mode_);
4177 frm_nxt = frm + (_frm_nxt - _frm);
4178 to_nxt = to + (_to_nxt - _to);
4179 return r;
4180}
4181
4182__codecvt_utf8_utf16<char32_t>::result
4183__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4184 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4185 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4186{
4187 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4188 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4189 const uint8_t* _frm_nxt = _frm;
4190 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4191 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4192 uint32_t* _to_nxt = _to;
4193 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4194 _Maxcode_, _Mode_);
4195 frm_nxt = frm + (_frm_nxt - _frm);
4196 to_nxt = to + (_to_nxt - _to);
4197 return r;
4198}
4199
4200__codecvt_utf8_utf16<char32_t>::result
4201__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4202 extern_type* to, extern_type*, extern_type*& to_nxt) const
4203{
4204 to_nxt = to;
4205 return noconv;
4206}
4207
4208int
Howard Hinnantc9834542011-05-31 15:34:58 +00004209__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004210{
4211 return 0;
4212}
4213
4214bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004215__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004216{
4217 return false;
4218}
4219
4220int
4221__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4222 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4223{
4224 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4225 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4226 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4227}
4228
4229int
Howard Hinnantc9834542011-05-31 15:34:58 +00004230__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004231{
4232 if (_Mode_ & consume_header)
4233 return 7;
4234 return 4;
4235}
4236
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004237// __narrow_to_utf8<16>
4238
4239__narrow_to_utf8<16>::~__narrow_to_utf8()
4240{
4241}
4242
4243// __narrow_to_utf8<32>
4244
4245__narrow_to_utf8<32>::~__narrow_to_utf8()
4246{
4247}
4248
4249// __widen_from_utf8<16>
4250
4251__widen_from_utf8<16>::~__widen_from_utf8()
4252{
4253}
4254
4255// __widen_from_utf8<32>
4256
4257__widen_from_utf8<32>::~__widen_from_utf8()
4258{
4259}
4260
4261// numpunct<char> && numpunct<wchar_t>
4262
4263locale::id numpunct< char >::id;
4264locale::id numpunct<wchar_t>::id;
4265
4266numpunct<char>::numpunct(size_t refs)
4267 : locale::facet(refs),
4268 __decimal_point_('.'),
4269 __thousands_sep_(',')
4270{
4271}
4272
4273numpunct<wchar_t>::numpunct(size_t refs)
4274 : locale::facet(refs),
4275 __decimal_point_(L'.'),
4276 __thousands_sep_(L',')
4277{
4278}
4279
4280numpunct<char>::~numpunct()
4281{
4282}
4283
4284numpunct<wchar_t>::~numpunct()
4285{
4286}
4287
4288 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4289wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4290
4291 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4292wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4293
4294string numpunct< char >::do_grouping() const {return __grouping_;}
4295string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4296
4297 string numpunct< char >::do_truename() const {return "true";}
4298wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4299
4300 string numpunct< char >::do_falsename() const {return "false";}
4301wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4302
4303// numpunct_byname<char>
4304
4305numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4306 : numpunct<char>(refs)
4307{
4308 __init(nm);
4309}
4310
4311numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4312 : numpunct<char>(refs)
4313{
4314 __init(nm.c_str());
4315}
4316
4317numpunct_byname<char>::~numpunct_byname()
4318{
4319}
4320
4321void
4322numpunct_byname<char>::__init(const char* nm)
4323{
4324 if (strcmp(nm, "C") != 0)
4325 {
Sean Huntf3907e62011-07-15 05:40:33 +00004326 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004327#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004328 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004329 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4330 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004331#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004332#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004333 lconv* lc = localeconv_l(loc.get());
4334#else
4335 lconv* lc = __localeconv_l(loc.get());
4336#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004337 if (*lc->decimal_point)
4338 __decimal_point_ = *lc->decimal_point;
4339 if (*lc->thousands_sep)
4340 __thousands_sep_ = *lc->thousands_sep;
4341 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004342 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004343 }
4344}
4345
4346// numpunct_byname<wchar_t>
4347
4348numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4349 : numpunct<wchar_t>(refs)
4350{
4351 __init(nm);
4352}
4353
4354numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4355 : numpunct<wchar_t>(refs)
4356{
4357 __init(nm.c_str());
4358}
4359
4360numpunct_byname<wchar_t>::~numpunct_byname()
4361{
4362}
4363
4364void
4365numpunct_byname<wchar_t>::__init(const char* nm)
4366{
4367 if (strcmp(nm, "C") != 0)
4368 {
Sean Huntf3907e62011-07-15 05:40:33 +00004369 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004370#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004371 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004372 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4373 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004374#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004375#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004376 lconv* lc = localeconv_l(loc.get());
4377#else
4378 lconv* lc = __localeconv_l(loc.get());
4379#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004380 if (*lc->decimal_point)
4381 __decimal_point_ = *lc->decimal_point;
4382 if (*lc->thousands_sep)
4383 __thousands_sep_ = *lc->thousands_sep;
4384 __grouping_ = lc->grouping;
4385 // locallization for truename and falsename is not available
4386 }
4387}
4388
4389// num_get helpers
4390
4391int
4392__num_get_base::__get_base(ios_base& iob)
4393{
4394 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4395 if (__basefield == ios_base::oct)
4396 return 8;
4397 else if (__basefield == ios_base::hex)
4398 return 16;
4399 else if (__basefield == 0)
4400 return 0;
4401 return 10;
4402}
4403
4404const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4405
4406void
4407__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4408 ios_base::iostate& __err)
4409{
4410 if (__grouping.size() != 0)
4411 {
4412 reverse(__g, __g_end);
4413 const char* __ig = __grouping.data();
4414 const char* __eg = __ig + __grouping.size();
4415 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4416 {
4417 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4418 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004419 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004420 {
4421 __err = ios_base::failbit;
4422 return;
4423 }
4424 }
4425 if (__eg - __ig > 1)
4426 ++__ig;
4427 }
4428 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4429 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004430 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004431 __err = ios_base::failbit;
4432 }
4433 }
4434}
4435
4436void
4437__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4438 ios_base::fmtflags __flags)
4439{
4440 if (__flags & ios_base::showpos)
4441 *__fmtp++ = '+';
4442 if (__flags & ios_base::showbase)
4443 *__fmtp++ = '#';
4444 while(*__len)
4445 *__fmtp++ = *__len++;
4446 if ((__flags & ios_base::basefield) == ios_base::oct)
4447 *__fmtp = 'o';
4448 else if ((__flags & ios_base::basefield) == ios_base::hex)
4449 {
4450 if (__flags & ios_base::uppercase)
4451 *__fmtp = 'X';
4452 else
4453 *__fmtp = 'x';
4454 }
4455 else if (__signd)
4456 *__fmtp = 'd';
4457 else
4458 *__fmtp = 'u';
4459}
4460
4461bool
4462__num_put_base::__format_float(char* __fmtp, const char* __len,
4463 ios_base::fmtflags __flags)
4464{
4465 bool specify_precision = true;
4466 if (__flags & ios_base::showpos)
4467 *__fmtp++ = '+';
4468 if (__flags & ios_base::showpoint)
4469 *__fmtp++ = '#';
4470 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowa3645132013-10-21 15:07:28 +00004471 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004472 if (floatfield == (ios_base::fixed | ios_base::scientific))
4473 specify_precision = false;
4474 else
4475 {
4476 *__fmtp++ = '.';
4477 *__fmtp++ = '*';
4478 }
4479 while(*__len)
4480 *__fmtp++ = *__len++;
4481 if (floatfield == ios_base::fixed)
4482 {
4483 if (uppercase)
4484 *__fmtp = 'F';
4485 else
4486 *__fmtp = 'f';
4487 }
4488 else if (floatfield == ios_base::scientific)
4489 {
4490 if (uppercase)
4491 *__fmtp = 'E';
4492 else
4493 *__fmtp = 'e';
4494 }
4495 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4496 {
4497 if (uppercase)
4498 *__fmtp = 'A';
4499 else
4500 *__fmtp = 'a';
4501 }
4502 else
4503 {
4504 if (uppercase)
4505 *__fmtp = 'G';
4506 else
4507 *__fmtp = 'g';
4508 }
4509 return specify_precision;
4510}
4511
4512char*
4513__num_put_base::__identify_padding(char* __nb, char* __ne,
4514 const ios_base& __iob)
4515{
4516 switch (__iob.flags() & ios_base::adjustfield)
4517 {
4518 case ios_base::internal:
4519 if (__nb[0] == '-' || __nb[0] == '+')
4520 return __nb+1;
4521 if (__ne - __nb >= 2 && __nb[0] == '0'
4522 && (__nb[1] == 'x' || __nb[1] == 'X'))
4523 return __nb+2;
4524 break;
4525 case ios_base::left:
4526 return __ne;
4527 case ios_base::right:
4528 default:
4529 break;
4530 }
4531 return __nb;
4532}
4533
4534// time_get
4535
4536static
4537string*
4538init_weeks()
4539{
4540 static string weeks[14];
4541 weeks[0] = "Sunday";
4542 weeks[1] = "Monday";
4543 weeks[2] = "Tuesday";
4544 weeks[3] = "Wednesday";
4545 weeks[4] = "Thursday";
4546 weeks[5] = "Friday";
4547 weeks[6] = "Saturday";
4548 weeks[7] = "Sun";
4549 weeks[8] = "Mon";
4550 weeks[9] = "Tue";
4551 weeks[10] = "Wed";
4552 weeks[11] = "Thu";
4553 weeks[12] = "Fri";
4554 weeks[13] = "Sat";
4555 return weeks;
4556}
4557
4558static
4559wstring*
4560init_wweeks()
4561{
4562 static wstring weeks[14];
4563 weeks[0] = L"Sunday";
4564 weeks[1] = L"Monday";
4565 weeks[2] = L"Tuesday";
4566 weeks[3] = L"Wednesday";
4567 weeks[4] = L"Thursday";
4568 weeks[5] = L"Friday";
4569 weeks[6] = L"Saturday";
4570 weeks[7] = L"Sun";
4571 weeks[8] = L"Mon";
4572 weeks[9] = L"Tue";
4573 weeks[10] = L"Wed";
4574 weeks[11] = L"Thu";
4575 weeks[12] = L"Fri";
4576 weeks[13] = L"Sat";
4577 return weeks;
4578}
4579
4580template <>
4581const string*
4582__time_get_c_storage<char>::__weeks() const
4583{
4584 static const string* weeks = init_weeks();
4585 return weeks;
4586}
4587
4588template <>
4589const wstring*
4590__time_get_c_storage<wchar_t>::__weeks() const
4591{
4592 static const wstring* weeks = init_wweeks();
4593 return weeks;
4594}
4595
4596static
4597string*
4598init_months()
4599{
4600 static string months[24];
4601 months[0] = "January";
4602 months[1] = "February";
4603 months[2] = "March";
4604 months[3] = "April";
4605 months[4] = "May";
4606 months[5] = "June";
4607 months[6] = "July";
4608 months[7] = "August";
4609 months[8] = "September";
4610 months[9] = "October";
4611 months[10] = "November";
4612 months[11] = "December";
4613 months[12] = "Jan";
4614 months[13] = "Feb";
4615 months[14] = "Mar";
4616 months[15] = "Apr";
4617 months[16] = "May";
4618 months[17] = "Jun";
4619 months[18] = "Jul";
4620 months[19] = "Aug";
4621 months[20] = "Sep";
4622 months[21] = "Oct";
4623 months[22] = "Nov";
4624 months[23] = "Dec";
4625 return months;
4626}
4627
4628static
4629wstring*
4630init_wmonths()
4631{
4632 static wstring months[24];
4633 months[0] = L"January";
4634 months[1] = L"February";
4635 months[2] = L"March";
4636 months[3] = L"April";
4637 months[4] = L"May";
4638 months[5] = L"June";
4639 months[6] = L"July";
4640 months[7] = L"August";
4641 months[8] = L"September";
4642 months[9] = L"October";
4643 months[10] = L"November";
4644 months[11] = L"December";
4645 months[12] = L"Jan";
4646 months[13] = L"Feb";
4647 months[14] = L"Mar";
4648 months[15] = L"Apr";
4649 months[16] = L"May";
4650 months[17] = L"Jun";
4651 months[18] = L"Jul";
4652 months[19] = L"Aug";
4653 months[20] = L"Sep";
4654 months[21] = L"Oct";
4655 months[22] = L"Nov";
4656 months[23] = L"Dec";
4657 return months;
4658}
4659
4660template <>
4661const string*
4662__time_get_c_storage<char>::__months() const
4663{
4664 static const string* months = init_months();
4665 return months;
4666}
4667
4668template <>
4669const wstring*
4670__time_get_c_storage<wchar_t>::__months() const
4671{
4672 static const wstring* months = init_wmonths();
4673 return months;
4674}
4675
4676static
4677string*
4678init_am_pm()
4679{
4680 static string am_pm[24];
4681 am_pm[0] = "AM";
4682 am_pm[1] = "PM";
4683 return am_pm;
4684}
4685
4686static
4687wstring*
4688init_wam_pm()
4689{
4690 static wstring am_pm[24];
4691 am_pm[0] = L"AM";
4692 am_pm[1] = L"PM";
4693 return am_pm;
4694}
4695
4696template <>
4697const string*
4698__time_get_c_storage<char>::__am_pm() const
4699{
4700 static const string* am_pm = init_am_pm();
4701 return am_pm;
4702}
4703
4704template <>
4705const wstring*
4706__time_get_c_storage<wchar_t>::__am_pm() const
4707{
4708 static const wstring* am_pm = init_wam_pm();
4709 return am_pm;
4710}
4711
4712template <>
4713const string&
4714__time_get_c_storage<char>::__x() const
4715{
4716 static string s("%m/%d/%y");
4717 return s;
4718}
4719
4720template <>
4721const wstring&
4722__time_get_c_storage<wchar_t>::__x() const
4723{
4724 static wstring s(L"%m/%d/%y");
4725 return s;
4726}
4727
4728template <>
4729const string&
4730__time_get_c_storage<char>::__X() const
4731{
4732 static string s("%H:%M:%S");
4733 return s;
4734}
4735
4736template <>
4737const wstring&
4738__time_get_c_storage<wchar_t>::__X() const
4739{
4740 static wstring s(L"%H:%M:%S");
4741 return s;
4742}
4743
4744template <>
4745const string&
4746__time_get_c_storage<char>::__c() const
4747{
4748 static string s("%a %b %d %H:%M:%S %Y");
4749 return s;
4750}
4751
4752template <>
4753const wstring&
4754__time_get_c_storage<wchar_t>::__c() const
4755{
4756 static wstring s(L"%a %b %d %H:%M:%S %Y");
4757 return s;
4758}
4759
4760template <>
4761const string&
4762__time_get_c_storage<char>::__r() const
4763{
4764 static string s("%I:%M:%S %p");
4765 return s;
4766}
4767
4768template <>
4769const wstring&
4770__time_get_c_storage<wchar_t>::__r() const
4771{
4772 static wstring s(L"%I:%M:%S %p");
4773 return s;
4774}
4775
4776// time_get_byname
4777
4778__time_get::__time_get(const char* nm)
4779 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4780{
Howard Hinnantd4444702010-08-11 17:04:31 +00004781#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004782 if (__loc_ == 0)
4783 throw runtime_error("time_get_byname"
4784 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004785#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004786}
4787
4788__time_get::__time_get(const string& nm)
4789 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4790{
Howard Hinnantd4444702010-08-11 17:04:31 +00004791#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004792 if (__loc_ == 0)
4793 throw runtime_error("time_get_byname"
4794 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004795#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004796}
4797
4798__time_get::~__time_get()
4799{
4800 freelocale(__loc_);
4801}
Marshall Clowa3645132013-10-21 15:07:28 +00004802#if defined(__clang__)
Howard Hinnant335b1512012-02-20 16:51:43 +00004803#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004804#endif
4805#if defined(__GNUG__)
Howard Hinnant21772ec2012-12-28 18:15:01 +00004806#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004807#endif
Howard Hinnant335b1512012-02-20 16:51:43 +00004808
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004809template <>
4810string
4811__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4812{
Howard Hinnant3074a052012-02-19 14:55:32 +00004813 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004814 t.tm_sec = 59;
4815 t.tm_min = 55;
4816 t.tm_hour = 23;
4817 t.tm_mday = 31;
4818 t.tm_mon = 11;
4819 t.tm_year = 161;
4820 t.tm_wday = 6;
4821 t.tm_yday = 364;
4822 t.tm_isdst = -1;
4823 char buf[100];
4824 char f[3] = {0};
4825 f[0] = '%';
4826 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004827 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004828 char* bb = buf;
4829 char* be = buf + n;
4830 string result;
4831 while (bb != be)
4832 {
4833 if (ct.is(ctype_base::space, *bb))
4834 {
4835 result.push_back(' ');
4836 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4837 ;
4838 continue;
4839 }
4840 char* w = bb;
4841 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004842 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004843 ct, err, false)
4844 - this->__weeks_;
4845 if (i < 14)
4846 {
4847 result.push_back('%');
4848 if (i < 7)
4849 result.push_back('A');
4850 else
4851 result.push_back('a');
4852 bb = w;
4853 continue;
4854 }
4855 w = bb;
4856 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4857 ct, err, false)
4858 - this->__months_;
4859 if (i < 24)
4860 {
4861 result.push_back('%');
4862 if (i < 12)
4863 result.push_back('B');
4864 else
4865 result.push_back('b');
4866 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4867 result.back() = 'm';
4868 bb = w;
4869 continue;
4870 }
4871 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4872 {
4873 w = bb;
4874 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4875 ct, err, false) - this->__am_pm_;
4876 if (i < 2)
4877 {
4878 result.push_back('%');
4879 result.push_back('p');
4880 bb = w;
4881 continue;
4882 }
4883 }
4884 w = bb;
4885 if (ct.is(ctype_base::digit, *bb))
4886 {
4887 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4888 {
4889 case 6:
4890 result.push_back('%');
4891 result.push_back('w');
4892 break;
4893 case 7:
4894 result.push_back('%');
4895 result.push_back('u');
4896 break;
4897 case 11:
4898 result.push_back('%');
4899 result.push_back('I');
4900 break;
4901 case 12:
4902 result.push_back('%');
4903 result.push_back('m');
4904 break;
4905 case 23:
4906 result.push_back('%');
4907 result.push_back('H');
4908 break;
4909 case 31:
4910 result.push_back('%');
4911 result.push_back('d');
4912 break;
4913 case 55:
4914 result.push_back('%');
4915 result.push_back('M');
4916 break;
4917 case 59:
4918 result.push_back('%');
4919 result.push_back('S');
4920 break;
4921 case 61:
4922 result.push_back('%');
4923 result.push_back('y');
4924 break;
4925 case 364:
4926 result.push_back('%');
4927 result.push_back('j');
4928 break;
4929 case 2061:
4930 result.push_back('%');
4931 result.push_back('Y');
4932 break;
4933 default:
4934 for (; w != bb; ++w)
4935 result.push_back(*w);
4936 break;
4937 }
4938 continue;
4939 }
4940 if (*bb == '%')
4941 {
4942 result.push_back('%');
4943 result.push_back('%');
4944 ++bb;
4945 continue;
4946 }
4947 result.push_back(*bb);
4948 ++bb;
4949 }
4950 return result;
4951}
4952
Marshall Clowa3645132013-10-21 15:07:28 +00004953#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +00004954#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowa3645132013-10-21 15:07:28 +00004955#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004956
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004957template <>
4958wstring
4959__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4960{
Howard Hinnant3074a052012-02-19 14:55:32 +00004961 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004962 t.tm_sec = 59;
4963 t.tm_min = 55;
4964 t.tm_hour = 23;
4965 t.tm_mday = 31;
4966 t.tm_mon = 11;
4967 t.tm_year = 161;
4968 t.tm_wday = 6;
4969 t.tm_yday = 364;
4970 t.tm_isdst = -1;
4971 char buf[100];
4972 char f[3] = {0};
4973 f[0] = '%';
4974 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004975 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004976 wchar_t wbuf[100];
4977 wchar_t* wbb = wbuf;
4978 mbstate_t mb = {0};
4979 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004980#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004981 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004982#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004983 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004984#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004985 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004986 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004987 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004988 wstring result;
4989 while (wbb != wbe)
4990 {
4991 if (ct.is(ctype_base::space, *wbb))
4992 {
4993 result.push_back(L' ');
4994 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4995 ;
4996 continue;
4997 }
4998 wchar_t* w = wbb;
4999 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00005000 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005001 ct, err, false)
5002 - this->__weeks_;
5003 if (i < 14)
5004 {
5005 result.push_back(L'%');
5006 if (i < 7)
5007 result.push_back(L'A');
5008 else
5009 result.push_back(L'a');
5010 wbb = w;
5011 continue;
5012 }
5013 w = wbb;
5014 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5015 ct, err, false)
5016 - this->__months_;
5017 if (i < 24)
5018 {
5019 result.push_back(L'%');
5020 if (i < 12)
5021 result.push_back(L'B');
5022 else
5023 result.push_back(L'b');
5024 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5025 result.back() = L'm';
5026 wbb = w;
5027 continue;
5028 }
5029 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5030 {
5031 w = wbb;
5032 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5033 ct, err, false) - this->__am_pm_;
5034 if (i < 2)
5035 {
5036 result.push_back(L'%');
5037 result.push_back(L'p');
5038 wbb = w;
5039 continue;
5040 }
5041 }
5042 w = wbb;
5043 if (ct.is(ctype_base::digit, *wbb))
5044 {
5045 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5046 {
5047 case 6:
5048 result.push_back(L'%');
5049 result.push_back(L'w');
5050 break;
5051 case 7:
5052 result.push_back(L'%');
5053 result.push_back(L'u');
5054 break;
5055 case 11:
5056 result.push_back(L'%');
5057 result.push_back(L'I');
5058 break;
5059 case 12:
5060 result.push_back(L'%');
5061 result.push_back(L'm');
5062 break;
5063 case 23:
5064 result.push_back(L'%');
5065 result.push_back(L'H');
5066 break;
5067 case 31:
5068 result.push_back(L'%');
5069 result.push_back(L'd');
5070 break;
5071 case 55:
5072 result.push_back(L'%');
5073 result.push_back(L'M');
5074 break;
5075 case 59:
5076 result.push_back(L'%');
5077 result.push_back(L'S');
5078 break;
5079 case 61:
5080 result.push_back(L'%');
5081 result.push_back(L'y');
5082 break;
5083 case 364:
5084 result.push_back(L'%');
5085 result.push_back(L'j');
5086 break;
5087 case 2061:
5088 result.push_back(L'%');
5089 result.push_back(L'Y');
5090 break;
5091 default:
5092 for (; w != wbb; ++w)
5093 result.push_back(*w);
5094 break;
5095 }
5096 continue;
5097 }
5098 if (ct.narrow(*wbb, 0) == '%')
5099 {
5100 result.push_back(L'%');
5101 result.push_back(L'%');
5102 ++wbb;
5103 continue;
5104 }
5105 result.push_back(*wbb);
5106 ++wbb;
5107 }
5108 return result;
5109}
5110
5111template <>
5112void
5113__time_get_storage<char>::init(const ctype<char>& ct)
5114{
Howard Hinnantcd992362012-08-02 18:44:17 +00005115 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005116 char buf[100];
5117 // __weeks_
5118 for (int i = 0; i < 7; ++i)
5119 {
5120 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005121 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005122 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005123 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005124 __weeks_[i+7] = buf;
5125 }
5126 // __months_
5127 for (int i = 0; i < 12; ++i)
5128 {
5129 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005130 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005131 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005132 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005133 __months_[i+12] = buf;
5134 }
5135 // __am_pm_
5136 t.tm_hour = 1;
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_[0] = buf;
5139 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005140 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005141 __am_pm_[1] = buf;
5142 __c_ = __analyze('c', ct);
5143 __r_ = __analyze('r', ct);
5144 __x_ = __analyze('x', ct);
5145 __X_ = __analyze('X', ct);
5146}
5147
5148template <>
5149void
5150__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5151{
5152 tm t = {0};
5153 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005154 wchar_t wbuf[100];
5155 wchar_t* wbe;
5156 mbstate_t mb = {0};
5157 // __weeks_
5158 for (int i = 0; i < 7; ++i)
5159 {
5160 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005161 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005162 mb = mbstate_t();
5163 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005164#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005165 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005166#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005167 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005168#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005169 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005170 __throw_runtime_error("locale not supported");
5171 wbe = wbuf + j;
5172 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005173 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005174 mb = mbstate_t();
5175 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005176#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005177 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005178#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005179 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005180#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005181 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005182 __throw_runtime_error("locale not supported");
5183 wbe = wbuf + j;
5184 __weeks_[i+7].assign(wbuf, wbe);
5185 }
5186 // __months_
5187 for (int i = 0; i < 12; ++i)
5188 {
5189 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005190 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005191 mb = mbstate_t();
5192 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005193#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005194 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005195#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005196 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005197#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005198 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005199 __throw_runtime_error("locale not supported");
5200 wbe = wbuf + j;
5201 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005202 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005203 mb = mbstate_t();
5204 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005205#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005206 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005207#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005208 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005209#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005210 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005211 __throw_runtime_error("locale not supported");
5212 wbe = wbuf + j;
5213 __months_[i+12].assign(wbuf, wbe);
5214 }
5215 // __am_pm_
5216 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005217 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005218 mb = mbstate_t();
5219 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005220#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005221 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005222#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005223 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005224#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005225 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005226 __throw_runtime_error("locale not supported");
5227 wbe = wbuf + j;
5228 __am_pm_[0].assign(wbuf, wbe);
5229 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005230 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005231 mb = mbstate_t();
5232 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005233#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005234 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005235#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005236 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005237#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005238 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005239 __throw_runtime_error("locale not supported");
5240 wbe = wbuf + j;
5241 __am_pm_[1].assign(wbuf, wbe);
5242 __c_ = __analyze('c', ct);
5243 __r_ = __analyze('r', ct);
5244 __x_ = __analyze('x', ct);
5245 __X_ = __analyze('X', ct);
5246}
5247
5248template <class CharT>
5249struct _LIBCPP_HIDDEN __time_get_temp
5250 : public ctype_byname<CharT>
5251{
5252 explicit __time_get_temp(const char* nm)
5253 : ctype_byname<CharT>(nm, 1) {}
5254 explicit __time_get_temp(const string& nm)
5255 : ctype_byname<CharT>(nm, 1) {}
5256};
5257
5258template <>
5259__time_get_storage<char>::__time_get_storage(const char* __nm)
5260 : __time_get(__nm)
5261{
5262 const __time_get_temp<char> ct(__nm);
5263 init(ct);
5264}
5265
5266template <>
5267__time_get_storage<char>::__time_get_storage(const string& __nm)
5268 : __time_get(__nm)
5269{
5270 const __time_get_temp<char> ct(__nm);
5271 init(ct);
5272}
5273
5274template <>
5275__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5276 : __time_get(__nm)
5277{
5278 const __time_get_temp<wchar_t> ct(__nm);
5279 init(ct);
5280}
5281
5282template <>
5283__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5284 : __time_get(__nm)
5285{
5286 const __time_get_temp<wchar_t> ct(__nm);
5287 init(ct);
5288}
5289
5290template <>
5291time_base::dateorder
5292__time_get_storage<char>::__do_date_order() const
5293{
5294 unsigned i;
5295 for (i = 0; i < __x_.size(); ++i)
5296 if (__x_[i] == '%')
5297 break;
5298 ++i;
5299 switch (__x_[i])
5300 {
5301 case 'y':
5302 case 'Y':
5303 for (++i; i < __x_.size(); ++i)
5304 if (__x_[i] == '%')
5305 break;
5306 if (i == __x_.size())
5307 break;
5308 ++i;
5309 switch (__x_[i])
5310 {
5311 case 'm':
5312 for (++i; i < __x_.size(); ++i)
5313 if (__x_[i] == '%')
5314 break;
5315 if (i == __x_.size())
5316 break;
5317 ++i;
5318 if (__x_[i] == 'd')
5319 return time_base::ymd;
5320 break;
5321 case 'd':
5322 for (++i; i < __x_.size(); ++i)
5323 if (__x_[i] == '%')
5324 break;
5325 if (i == __x_.size())
5326 break;
5327 ++i;
5328 if (__x_[i] == 'm')
5329 return time_base::ydm;
5330 break;
5331 }
5332 break;
5333 case 'm':
5334 for (++i; i < __x_.size(); ++i)
5335 if (__x_[i] == '%')
5336 break;
5337 if (i == __x_.size())
5338 break;
5339 ++i;
5340 if (__x_[i] == 'd')
5341 {
5342 for (++i; i < __x_.size(); ++i)
5343 if (__x_[i] == '%')
5344 break;
5345 if (i == __x_.size())
5346 break;
5347 ++i;
5348 if (__x_[i] == 'y' || __x_[i] == 'Y')
5349 return time_base::mdy;
5350 break;
5351 }
5352 break;
5353 case 'd':
5354 for (++i; i < __x_.size(); ++i)
5355 if (__x_[i] == '%')
5356 break;
5357 if (i == __x_.size())
5358 break;
5359 ++i;
5360 if (__x_[i] == 'm')
5361 {
5362 for (++i; i < __x_.size(); ++i)
5363 if (__x_[i] == '%')
5364 break;
5365 if (i == __x_.size())
5366 break;
5367 ++i;
5368 if (__x_[i] == 'y' || __x_[i] == 'Y')
5369 return time_base::dmy;
5370 break;
5371 }
5372 break;
5373 }
5374 return time_base::no_order;
5375}
5376
5377template <>
5378time_base::dateorder
5379__time_get_storage<wchar_t>::__do_date_order() const
5380{
5381 unsigned i;
5382 for (i = 0; i < __x_.size(); ++i)
5383 if (__x_[i] == L'%')
5384 break;
5385 ++i;
5386 switch (__x_[i])
5387 {
5388 case L'y':
5389 case L'Y':
5390 for (++i; i < __x_.size(); ++i)
5391 if (__x_[i] == L'%')
5392 break;
5393 if (i == __x_.size())
5394 break;
5395 ++i;
5396 switch (__x_[i])
5397 {
5398 case L'm':
5399 for (++i; i < __x_.size(); ++i)
5400 if (__x_[i] == L'%')
5401 break;
5402 if (i == __x_.size())
5403 break;
5404 ++i;
5405 if (__x_[i] == L'd')
5406 return time_base::ymd;
5407 break;
5408 case L'd':
5409 for (++i; i < __x_.size(); ++i)
5410 if (__x_[i] == L'%')
5411 break;
5412 if (i == __x_.size())
5413 break;
5414 ++i;
5415 if (__x_[i] == L'm')
5416 return time_base::ydm;
5417 break;
5418 }
5419 break;
5420 case L'm':
5421 for (++i; i < __x_.size(); ++i)
5422 if (__x_[i] == L'%')
5423 break;
5424 if (i == __x_.size())
5425 break;
5426 ++i;
5427 if (__x_[i] == L'd')
5428 {
5429 for (++i; i < __x_.size(); ++i)
5430 if (__x_[i] == L'%')
5431 break;
5432 if (i == __x_.size())
5433 break;
5434 ++i;
5435 if (__x_[i] == L'y' || __x_[i] == L'Y')
5436 return time_base::mdy;
5437 break;
5438 }
5439 break;
5440 case L'd':
5441 for (++i; i < __x_.size(); ++i)
5442 if (__x_[i] == L'%')
5443 break;
5444 if (i == __x_.size())
5445 break;
5446 ++i;
5447 if (__x_[i] == L'm')
5448 {
5449 for (++i; i < __x_.size(); ++i)
5450 if (__x_[i] == L'%')
5451 break;
5452 if (i == __x_.size())
5453 break;
5454 ++i;
5455 if (__x_[i] == L'y' || __x_[i] == L'Y')
5456 return time_base::dmy;
5457 break;
5458 }
5459 break;
5460 }
5461 return time_base::no_order;
5462}
5463
5464// time_put
5465
5466__time_put::__time_put(const char* nm)
5467 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5468{
Howard Hinnantd4444702010-08-11 17:04:31 +00005469#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005470 if (__loc_ == 0)
5471 throw runtime_error("time_put_byname"
5472 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005473#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005474}
5475
5476__time_put::__time_put(const string& nm)
5477 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5478{
Howard Hinnantd4444702010-08-11 17:04:31 +00005479#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005480 if (__loc_ == 0)
5481 throw runtime_error("time_put_byname"
5482 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005483#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005484}
5485
5486__time_put::~__time_put()
5487{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005488 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005489 freelocale(__loc_);
5490}
5491
5492void
5493__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5494 char __fmt, char __mod) const
5495{
5496 char fmt[] = {'%', __fmt, __mod, 0};
5497 if (__mod != 0)
5498 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005499 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005500 __ne = __nb + n;
5501}
5502
5503void
5504__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5505 char __fmt, char __mod) const
5506{
5507 char __nar[100];
5508 char* __ne = __nar + 100;
5509 __do_put(__nar, __ne, __tm, __fmt, __mod);
5510 mbstate_t mb = {0};
5511 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005512#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005513 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005514#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005515 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005516#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005517 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005518 __throw_runtime_error("locale not supported");
5519 __we = __wb + j;
5520}
5521
5522// moneypunct_byname
5523
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005524template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005525static
5526void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005527__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5528 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5529 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005530{
5531 const char sign = static_cast<char>(money_base::sign);
5532 const char space = static_cast<char>(money_base::space);
5533 const char none = static_cast<char>(money_base::none);
5534 const char symbol = static_cast<char>(money_base::symbol);
5535 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005536 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5537
5538 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5539 // function'. "Space between sign and symbol or value" means that
5540 // if the sign is adjacent to the symbol, there's a space between
5541 // them, and otherwise there's a space between the sign and value.
5542 //
5543 // C11's localeconv specifies that the fourth character of an
5544 // international curr_symbol is used to separate the sign and
5545 // value when sep_by_space says to do so. C++ can't represent
5546 // that, so we just use a space. When sep_by_space says to
5547 // separate the symbol and value-or-sign with a space, we rearrange the
5548 // curr_symbol to put its spacing character on the correct side of
5549 // the symbol.
5550 //
5551 // We also need to avoid adding an extra space between the sign
5552 // and value when the currency symbol is suppressed (by not
5553 // setting showbase). We match glibc's strfmon by interpreting
5554 // sep_by_space==1 as "omit the space when the currency symbol is
5555 // absent".
5556 //
5557 // Users who want to get this right should use ICU instead.
5558
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005559 switch (cs_precedes)
5560 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005561 case 0: // value before curr_symbol
5562 if (symbol_contains_sep) {
5563 // Move the separator to before the symbol, to place it
5564 // between the value and symbol.
5565 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5566 __curr_symbol_.end());
5567 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005568 switch (sign_posn)
5569 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005570 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 pat.field[0] = sign;
5572 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005573 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005574 pat.field[3] = symbol;
5575 switch (sep_by_space)
5576 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 case 0: // No space separates the currency symbol and value.
5578 // This case may have changed between C99 and C11;
5579 // assume the currency symbol matches the intention.
5580 case 2: // Space between sign and currency or value.
5581 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005582 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005583 case 1: // Space between currency-and-sign or currency and value.
5584 if (!symbol_contains_sep) {
5585 // We insert the space into the symbol instead of
5586 // setting pat.field[2]=space so that when
5587 // showbase is not set, the space goes away too.
5588 __curr_symbol_.insert(0, 1, space_char);
5589 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005590 return;
5591 default:
5592 break;
5593 }
5594 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005595 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005596 pat.field[0] = sign;
5597 pat.field[3] = symbol;
5598 switch (sep_by_space)
5599 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005600 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005601 pat.field[1] = value;
5602 pat.field[2] = none;
5603 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005605 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005606 pat.field[2] = none;
5607 if (!symbol_contains_sep) {
5608 // We insert the space into the symbol instead of
5609 // setting pat.field[2]=space so that when
5610 // showbase is not set, the space goes away too.
5611 __curr_symbol_.insert(0, 1, space_char);
5612 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005613 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005614 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005615 pat.field[1] = space;
5616 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005617 if (symbol_contains_sep) {
5618 // Remove the separator from the symbol, since it
5619 // has already appeared after the sign.
5620 __curr_symbol_.erase(__curr_symbol_.begin());
5621 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005622 return;
5623 default:
5624 break;
5625 }
5626 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005627 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005628 pat.field[0] = value;
5629 pat.field[3] = sign;
5630 switch (sep_by_space)
5631 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005632 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005633 pat.field[1] = none;
5634 pat.field[2] = symbol;
5635 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005636 case 1: // Space between currency-and-sign or currency and value.
5637 if (!symbol_contains_sep) {
5638 // We insert the space into the symbol instead of
5639 // setting pat.field[1]=space so that when
5640 // showbase is not set, the space goes away too.
5641 __curr_symbol_.insert(0, 1, space_char);
5642 }
5643 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005644 pat.field[2] = symbol;
5645 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005646 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005647 pat.field[1] = symbol;
5648 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005649 if (symbol_contains_sep) {
5650 // Remove the separator from the symbol, since it
5651 // should not be removed if showbase is absent.
5652 __curr_symbol_.erase(__curr_symbol_.begin());
5653 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005654 return;
5655 default:
5656 break;
5657 }
5658 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005659 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005660 pat.field[0] = value;
5661 pat.field[3] = symbol;
5662 switch (sep_by_space)
5663 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005664 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005665 pat.field[1] = none;
5666 pat.field[2] = sign;
5667 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 pat.field[1] = space;
5670 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005671 if (symbol_contains_sep) {
5672 // Remove the separator from the symbol, since it
5673 // has already appeared before the sign.
5674 __curr_symbol_.erase(__curr_symbol_.begin());
5675 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005676 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005677 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005678 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005679 pat.field[2] = none;
5680 if (!symbol_contains_sep) {
5681 // We insert the space into the symbol instead of
5682 // setting pat.field[2]=space so that when
5683 // showbase is not set, the space goes away too.
5684 __curr_symbol_.insert(0, 1, space_char);
5685 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005686 return;
5687 default:
5688 break;
5689 }
5690 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005691 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005692 pat.field[0] = value;
5693 pat.field[3] = sign;
5694 switch (sep_by_space)
5695 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005696 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005697 pat.field[1] = none;
5698 pat.field[2] = symbol;
5699 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005700 case 1: // Space between currency-and-sign or currency and value.
5701 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005702 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005703 if (!symbol_contains_sep) {
5704 // We insert the space into the symbol instead of
5705 // setting pat.field[1]=space so that when
5706 // showbase is not set, the space goes away too.
5707 __curr_symbol_.insert(0, 1, space_char);
5708 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005709 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005710 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005711 pat.field[1] = symbol;
5712 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005713 if (symbol_contains_sep) {
5714 // Remove the separator from the symbol, since it
5715 // should not disappear when showbase is absent.
5716 __curr_symbol_.erase(__curr_symbol_.begin());
5717 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005718 return;
5719 default:
5720 break;
5721 }
5722 break;
5723 default:
5724 break;
5725 }
5726 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005727 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005728 switch (sign_posn)
5729 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005730 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005731 pat.field[0] = sign;
5732 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005733 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005734 pat.field[3] = value;
5735 switch (sep_by_space)
5736 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005737 case 0: // No space separates the currency symbol and value.
5738 // This case may have changed between C99 and C11;
5739 // assume the currency symbol matches the intention.
5740 case 2: // Space between sign and currency or value.
5741 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005742 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005743 case 1: // Space between currency-and-sign or currency and value.
5744 if (!symbol_contains_sep) {
5745 // We insert the space into the symbol instead of
5746 // setting pat.field[2]=space so that when
5747 // showbase is not set, the space goes away too.
5748 __curr_symbol_.insert(0, 1, space_char);
5749 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005750 return;
5751 default:
5752 break;
5753 }
5754 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005755 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005756 pat.field[0] = sign;
5757 pat.field[3] = value;
5758 switch (sep_by_space)
5759 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005760 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005761 pat.field[1] = symbol;
5762 pat.field[2] = none;
5763 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005764 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005765 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005766 pat.field[2] = none;
5767 if (!symbol_contains_sep) {
5768 // We insert the space into the symbol instead of
5769 // setting pat.field[2]=space so that when
5770 // showbase is not set, the space goes away too.
5771 __curr_symbol_.push_back(space_char);
5772 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005773 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005774 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005775 pat.field[1] = space;
5776 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005777 if (symbol_contains_sep) {
5778 // Remove the separator from the symbol, since it
5779 // has already appeared after the sign.
5780 __curr_symbol_.pop_back();
5781 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005782 return;
5783 default:
5784 break;
5785 }
5786 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005787 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005788 pat.field[0] = symbol;
5789 pat.field[3] = sign;
5790 switch (sep_by_space)
5791 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005792 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005793 pat.field[1] = none;
5794 pat.field[2] = value;
5795 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005796 case 1: // Space between currency-and-sign or currency and value.
5797 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005798 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005799 if (!symbol_contains_sep) {
5800 // We insert the space into the symbol instead of
5801 // setting pat.field[1]=space so that when
5802 // showbase is not set, the space goes away too.
5803 __curr_symbol_.push_back(space_char);
5804 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005805 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005806 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005807 pat.field[1] = value;
5808 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005809 if (symbol_contains_sep) {
5810 // Remove the separator from the symbol, since it
5811 // will appear before the sign.
5812 __curr_symbol_.pop_back();
5813 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005814 return;
5815 default:
5816 break;
5817 }
5818 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005819 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005820 pat.field[0] = sign;
5821 pat.field[3] = value;
5822 switch (sep_by_space)
5823 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005824 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005825 pat.field[1] = symbol;
5826 pat.field[2] = none;
5827 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005828 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005829 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005830 pat.field[2] = none;
5831 if (!symbol_contains_sep) {
5832 // We insert the space into the symbol instead of
5833 // setting pat.field[2]=space so that when
5834 // showbase is not set, the space goes away too.
5835 __curr_symbol_.push_back(space_char);
5836 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005837 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005838 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005839 pat.field[1] = space;
5840 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005841 if (symbol_contains_sep) {
5842 // Remove the separator from the symbol, since it
5843 // has already appeared after the sign.
5844 __curr_symbol_.pop_back();
5845 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005846 return;
5847 default:
5848 break;
5849 }
5850 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005851 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005852 pat.field[0] = symbol;
5853 pat.field[3] = value;
5854 switch (sep_by_space)
5855 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005856 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005857 pat.field[1] = sign;
5858 pat.field[2] = none;
5859 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005860 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005861 pat.field[1] = sign;
5862 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005863 if (symbol_contains_sep) {
5864 // Remove the separator from the symbol, since it
5865 // should not disappear when showbase is absent.
5866 __curr_symbol_.pop_back();
5867 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005868 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005869 case 2: // Space between sign and currency or value.
5870 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005871 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005872 if (!symbol_contains_sep) {
5873 // We insert the space into the symbol instead of
5874 // setting pat.field[1]=space so that when
5875 // showbase is not set, the space goes away too.
5876 __curr_symbol_.push_back(space_char);
5877 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005878 return;
5879 default:
5880 break;
5881 }
5882 break;
5883 default:
5884 break;
5885 }
5886 break;
5887 default:
5888 break;
5889 }
5890 pat.field[0] = symbol;
5891 pat.field[1] = sign;
5892 pat.field[2] = none;
5893 pat.field[3] = value;
5894}
5895
5896template<>
5897void
5898moneypunct_byname<char, false>::init(const char* nm)
5899{
5900 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005901 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005902#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005903 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005904 throw runtime_error("moneypunct_byname"
5905 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005906#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005907#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005908 lconv* lc = localeconv_l(loc.get());
5909#else
5910 lconv* lc = __localeconv_l(loc.get());
5911#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005912 if (*lc->mon_decimal_point)
5913 __decimal_point_ = *lc->mon_decimal_point;
5914 else
5915 __decimal_point_ = base::do_decimal_point();
5916 if (*lc->mon_thousands_sep)
5917 __thousands_sep_ = *lc->mon_thousands_sep;
5918 else
5919 __thousands_sep_ = base::do_thousands_sep();
5920 __grouping_ = lc->mon_grouping;
5921 __curr_symbol_ = lc->currency_symbol;
5922 if (lc->frac_digits != CHAR_MAX)
5923 __frac_digits_ = lc->frac_digits;
5924 else
5925 __frac_digits_ = base::do_frac_digits();
5926 if (lc->p_sign_posn == 0)
5927 __positive_sign_ = "()";
5928 else
5929 __positive_sign_ = lc->positive_sign;
5930 if (lc->n_sign_posn == 0)
5931 __negative_sign_ = "()";
5932 else
5933 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005934 // Assume the positive and negative formats will want spaces in
5935 // the same places in curr_symbol since there's no way to
5936 // represent anything else.
5937 string_type __dummy_curr_symbol = __curr_symbol_;
5938 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5939 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5940 __init_pat(__neg_format_, __curr_symbol_, false,
5941 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005942}
5943
5944template<>
5945void
5946moneypunct_byname<char, true>::init(const char* nm)
5947{
5948 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005949 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005950#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005951 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005952 throw runtime_error("moneypunct_byname"
5953 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005954#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005955#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005956 lconv* lc = localeconv_l(loc.get());
5957#else
5958 lconv* lc = __localeconv_l(loc.get());
5959#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005960 if (*lc->mon_decimal_point)
5961 __decimal_point_ = *lc->mon_decimal_point;
5962 else
5963 __decimal_point_ = base::do_decimal_point();
5964 if (*lc->mon_thousands_sep)
5965 __thousands_sep_ = *lc->mon_thousands_sep;
5966 else
5967 __thousands_sep_ = base::do_thousands_sep();
5968 __grouping_ = lc->mon_grouping;
5969 __curr_symbol_ = lc->int_curr_symbol;
5970 if (lc->int_frac_digits != CHAR_MAX)
5971 __frac_digits_ = lc->int_frac_digits;
5972 else
5973 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00005974#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005975 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005976#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005977 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005978#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005979 __positive_sign_ = "()";
5980 else
5981 __positive_sign_ = lc->positive_sign;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005982#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005983 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005984#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005985 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005986#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005987 __negative_sign_ = "()";
5988 else
5989 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005990 // Assume the positive and negative formats will want spaces in
5991 // the same places in curr_symbol since there's no way to
5992 // represent anything else.
5993 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005994#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005995 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5996 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5997 __init_pat(__neg_format_, __curr_symbol_, true,
5998 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00005999#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006000 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6001 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6002 lc->int_p_sign_posn, ' ');
6003 __init_pat(__neg_format_, __curr_symbol_, true,
6004 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6005 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006006#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006007}
6008
6009template<>
6010void
6011moneypunct_byname<wchar_t, false>::init(const char* nm)
6012{
6013 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006014 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006015#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006016 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006017 throw runtime_error("moneypunct_byname"
6018 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006019#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006020#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006021 lconv* lc = localeconv_l(loc.get());
6022#else
6023 lconv* lc = __localeconv_l(loc.get());
6024#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006025 if (*lc->mon_decimal_point)
6026 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6027 else
6028 __decimal_point_ = base::do_decimal_point();
6029 if (*lc->mon_thousands_sep)
6030 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6031 else
6032 __thousands_sep_ = base::do_thousands_sep();
6033 __grouping_ = lc->mon_grouping;
6034 wchar_t wbuf[100];
6035 mbstate_t mb = {0};
6036 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006037#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006038 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006039#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006040 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006041#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006042 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006043 __throw_runtime_error("locale not supported");
6044 wchar_t* wbe = wbuf + j;
6045 __curr_symbol_.assign(wbuf, wbe);
6046 if (lc->frac_digits != CHAR_MAX)
6047 __frac_digits_ = lc->frac_digits;
6048 else
6049 __frac_digits_ = base::do_frac_digits();
6050 if (lc->p_sign_posn == 0)
6051 __positive_sign_ = L"()";
6052 else
6053 {
6054 mb = mbstate_t();
6055 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006056#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006057 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006058#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006059 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006060#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006061 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006062 __throw_runtime_error("locale not supported");
6063 wbe = wbuf + j;
6064 __positive_sign_.assign(wbuf, wbe);
6065 }
6066 if (lc->n_sign_posn == 0)
6067 __negative_sign_ = L"()";
6068 else
6069 {
6070 mb = mbstate_t();
6071 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006072#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006073 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006074#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006075 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006076#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006077 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006078 __throw_runtime_error("locale not supported");
6079 wbe = wbuf + j;
6080 __negative_sign_.assign(wbuf, wbe);
6081 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006082 // Assume the positive and negative formats will want spaces in
6083 // the same places in curr_symbol since there's no way to
6084 // represent anything else.
6085 string_type __dummy_curr_symbol = __curr_symbol_;
6086 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6087 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6088 __init_pat(__neg_format_, __curr_symbol_, false,
6089 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006090}
6091
6092template<>
6093void
6094moneypunct_byname<wchar_t, true>::init(const char* nm)
6095{
6096 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006097 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006098#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006099 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006100 throw runtime_error("moneypunct_byname"
6101 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006102#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006103#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006104 lconv* lc = localeconv_l(loc.get());
6105#else
6106 lconv* lc = __localeconv_l(loc.get());
6107#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006108 if (*lc->mon_decimal_point)
6109 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6110 else
6111 __decimal_point_ = base::do_decimal_point();
6112 if (*lc->mon_thousands_sep)
6113 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6114 else
6115 __thousands_sep_ = base::do_thousands_sep();
6116 __grouping_ = lc->mon_grouping;
6117 wchar_t wbuf[100];
6118 mbstate_t mb = {0};
6119 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006120#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006121 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006122#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006123 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006124#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006125 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006126 __throw_runtime_error("locale not supported");
6127 wchar_t* wbe = wbuf + j;
6128 __curr_symbol_.assign(wbuf, wbe);
6129 if (lc->int_frac_digits != CHAR_MAX)
6130 __frac_digits_ = lc->int_frac_digits;
6131 else
6132 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00006133#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006134 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006135#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006136 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006137#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006138 __positive_sign_ = L"()";
6139 else
6140 {
6141 mb = mbstate_t();
6142 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006143#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006144 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006145#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006146 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006147#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006148 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006149 __throw_runtime_error("locale not supported");
6150 wbe = wbuf + j;
6151 __positive_sign_.assign(wbuf, wbe);
6152 }
Howard Hinnantef5aa932013-09-17 01:34:47 +00006153#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006154 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006155#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006156 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006157#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006158 __negative_sign_ = L"()";
6159 else
6160 {
6161 mb = mbstate_t();
6162 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006163#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006164 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006165#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006166 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006167#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006168 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006169 __throw_runtime_error("locale not supported");
6170 wbe = wbuf + j;
6171 __negative_sign_.assign(wbuf, wbe);
6172 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006173 // Assume the positive and negative formats will want spaces in
6174 // the same places in curr_symbol since there's no way to
6175 // represent anything else.
6176 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00006177#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006178 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6179 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6180 __init_pat(__neg_format_, __curr_symbol_, true,
6181 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006182#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006183 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6184 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6185 lc->int_p_sign_posn, L' ');
6186 __init_pat(__neg_format_, __curr_symbol_, true,
6187 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6188 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006189#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006190}
6191
6192void __do_nothing(void*) {}
6193
6194void __throw_runtime_error(const char* msg)
6195{
Howard Hinnantd4444702010-08-11 17:04:31 +00006196#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006197 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006198#else
6199 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006200#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006201}
6202
6203template class collate<char>;
6204template class collate<wchar_t>;
6205
6206template class num_get<char>;
6207template class num_get<wchar_t>;
6208
Howard Hinnantec3773c2011-12-01 20:21:04 +00006209template struct __num_get<char>;
6210template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006211
6212template class num_put<char>;
6213template class num_put<wchar_t>;
6214
Howard Hinnantec3773c2011-12-01 20:21:04 +00006215template struct __num_put<char>;
6216template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006217
6218template class time_get<char>;
6219template class time_get<wchar_t>;
6220
6221template class time_get_byname<char>;
6222template class time_get_byname<wchar_t>;
6223
6224template class time_put<char>;
6225template class time_put<wchar_t>;
6226
6227template class time_put_byname<char>;
6228template class time_put_byname<wchar_t>;
6229
6230template class moneypunct<char, false>;
6231template class moneypunct<char, true>;
6232template class moneypunct<wchar_t, false>;
6233template class moneypunct<wchar_t, true>;
6234
6235template class moneypunct_byname<char, false>;
6236template class moneypunct_byname<char, true>;
6237template class moneypunct_byname<wchar_t, false>;
6238template class moneypunct_byname<wchar_t, true>;
6239
6240template class money_get<char>;
6241template class money_get<wchar_t>;
6242
6243template class __money_get<char>;
6244template class __money_get<wchar_t>;
6245
6246template class money_put<char>;
6247template class money_put<wchar_t>;
6248
6249template class __money_put<char>;
6250template class __money_put<wchar_t>;
6251
6252template class messages<char>;
6253template class messages<wchar_t>;
6254
6255template class messages_byname<char>;
6256template class messages_byname<wchar_t>;
6257
6258template class codecvt_byname<char, char, mbstate_t>;
6259template class codecvt_byname<wchar_t, char, mbstate_t>;
6260template class codecvt_byname<char16_t, char, mbstate_t>;
6261template class codecvt_byname<char32_t, char, mbstate_t>;
6262
6263template class __vector_base_common<true>;
6264
6265_LIBCPP_END_NAMESPACE_STD